https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8f1eb03ad28f6262b7322…
commit 8f1eb03ad28f6262b7322a637f775d7e1312351c
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Oct 17 07:25:50 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Oct 17 07:25:50 2023 +0900
[MSPAINT] Improve Zoom tool (#5798)
- Delete global zoomTo function.
- Add CCanvasWindow::zoomTo and
CCanvasWindow::getNewZoomRect functions.
- Rename CCanvasWindow::updateScrollInfo as
CCanvasWindow::updateScrollRange.
- Rename CCanvasWindow::resetScrollPos as
CCanvasWindow::updateScrollPos.
- Draw the proper zoom rectangle on mouse move.
- Revert the active tool on click when the tool
was Zoom.
CORE-19094
---
base/applications/mspaint/canvas.cpp | 57 ++++++++++++++++++++++++----
base/applications/mspaint/canvas.h | 6 ++-
base/applications/mspaint/common.h | 1 -
base/applications/mspaint/dib.cpp | 2 +-
base/applications/mspaint/history.cpp | 2 +-
base/applications/mspaint/mouse.cpp | 61 +++++++++++++++++++++---------
base/applications/mspaint/toolsettings.cpp | 2 +-
base/applications/mspaint/winproc.cpp | 55 ++++++---------------------
8 files changed, 113 insertions(+), 73 deletions(-)
diff --git a/base/applications/mspaint/canvas.cpp b/base/applications/mspaint/canvas.cpp
index 60aa29929b5..e19c4e6e306 100644
--- a/base/applications/mspaint/canvas.cpp
+++ b/base/applications/mspaint/canvas.cpp
@@ -89,6 +89,49 @@ HITTEST CCanvasWindow::CanvasHitTest(POINT pt)
return getSizeBoxHitTest(pt, &rcBase);
}
+VOID CCanvasWindow::getNewZoomRect(CRect& rcView, INT newZoom, CPoint ptTarget)
+{
+ CRect rcImage;
+ GetImageRect(rcImage);
+ ImageToCanvas(rcImage);
+
+ // Calculate the zoom rectangle
+ INT oldZoom = toolsModel.GetZoom();
+ GetClientRect(rcView);
+ LONG cxView = rcView.right * oldZoom / newZoom, cyView = rcView.bottom * oldZoom /
newZoom;
+ ::SetRect(&rcView, ptTarget.x - cxView / 2, ptTarget.y - cyView / 2,
+ ptTarget.x + cxView / 2, ptTarget.y + cyView / 2);
+
+ // Shift the rectangle if necessary
+ INT dx = 0, dy = 0;
+ if (rcView.left < rcImage.left)
+ dx = rcImage.left - rcView.left;
+ else if (rcImage.right < rcView.right)
+ dx = rcImage.right - rcView.right;
+ if (rcView.top < rcImage.top)
+ dy = rcImage.top - rcView.top;
+ else if (rcImage.bottom < rcView.bottom)
+ dy = rcImage.bottom - rcView.bottom;
+ rcView.OffsetRect(dx, dy);
+
+ rcView.IntersectRect(&rcView, &rcImage);
+}
+
+VOID CCanvasWindow::zoomTo(INT newZoom, LONG left, LONG top)
+{
+ POINT pt = { left, top };
+ CanvasToImage(pt);
+
+ toolsModel.SetZoom(newZoom);
+ ImageToCanvas(pt);
+ pt.x += GetScrollPos(SB_HORZ);
+ pt.y += GetScrollPos(SB_VERT);
+
+ updateScrollRange();
+ updateScrollPos(pt.x, pt.y);
+ Invalidate(TRUE);
+}
+
VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
{
// This is the target area we have to draw on
@@ -180,7 +223,7 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT&
rcPaint)
::DeleteDC(hdcMem0);
}
-VOID CCanvasWindow::updateScrollInfo()
+VOID CCanvasWindow::updateScrollRange()
{
CRect rcClient;
GetClientRect(&rcClient);
@@ -211,16 +254,16 @@ VOID CCanvasWindow::updateScrollInfo()
SetScrollInfo(SB_VERT, &si);
}
-VOID CCanvasWindow::resetScrollPos()
+VOID CCanvasWindow::updateScrollPos(INT x, INT y)
{
- SetScrollPos(SB_HORZ, 0);
- SetScrollPos(SB_VERT, 0);
+ SetScrollPos(SB_HORZ, x);
+ SetScrollPos(SB_VERT, y);
}
LRESULT CCanvasWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled)
{
if (m_hWnd)
- updateScrollInfo();
+ updateScrollRange();
return 0;
}
@@ -251,7 +294,7 @@ VOID CCanvasWindow::OnHVScroll(WPARAM wParam, INT fnBar)
break;
}
SetScrollInfo(fnBar, &si);
- updateScrollInfo();
+ updateScrollRange();
Invalidate(FALSE); // FIXME: Flicker
}
@@ -632,7 +675,7 @@ LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg,
WPARAM wParam,
m_hitCanvasSizeBox = HIT_NONE;
toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier
functions
- updateScrollInfo();
+ updateScrollRange();
Invalidate(TRUE);
return 0;
}
diff --git a/base/applications/mspaint/canvas.h b/base/applications/mspaint/canvas.h
index 193d7603abd..21a6e11ecfa 100644
--- a/base/applications/mspaint/canvas.h
+++ b/base/applications/mspaint/canvas.h
@@ -42,8 +42,8 @@ public:
VOID cancelDrawing();
VOID finishDrawing();
- VOID updateScrollInfo();
- VOID resetScrollPos();
+ VOID updateScrollRange();
+ VOID updateScrollPos(INT x = 0, INT y = 0);
VOID ImageToCanvas(POINT& pt);
VOID ImageToCanvas(RECT& rc);
@@ -51,6 +51,8 @@ public:
VOID CanvasToImage(RECT& rc, BOOL bZoomed = FALSE);
VOID GetImageRect(RECT& rc);
VOID MoveSelection(INT xDelta, INT yDelta);
+ VOID getNewZoomRect(CRect& rcView, INT newZoom, CPoint ptTarget);
+ VOID zoomTo(INT newZoom, LONG left = 0, LONG top = 0);
protected:
HITTEST m_hitSelection;
diff --git a/base/applications/mspaint/common.h b/base/applications/mspaint/common.h
index d2e862b0114..3dda6703441 100644
--- a/base/applications/mspaint/common.h
+++ b/base/applications/mspaint/common.h
@@ -43,7 +43,6 @@ enum HITTEST // hit
/* FUNCTIONS ********************************************************/
-BOOL zoomTo(int newZoom, int mouseX, int mouseY);
BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1);
BOOL OpenMailer(HWND hWnd, LPCWSTR pszPathName);
diff --git a/base/applications/mspaint/dib.cpp b/base/applications/mspaint/dib.cpp
index 7b458138618..eede3325c55 100644
--- a/base/applications/mspaint/dib.cpp
+++ b/base/applications/mspaint/dib.cpp
@@ -241,7 +241,7 @@ HBITMAP InitializeImage(LPCWSTR name, LPWIN32_FIND_DATAW pFound, BOOL
isFile)
HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCWSTR name, LPWIN32_FIND_DATAW pFound, BOOL
isFile)
{
// update image
- canvasWindow.resetScrollPos();
+ canvasWindow.updateScrollPos();
imageModel.PushImageForUndo(hBitmap);
imageModel.ClearHistory();
diff --git a/base/applications/mspaint/history.cpp
b/base/applications/mspaint/history.cpp
index 05990df42b8..2d28cb5def2 100644
--- a/base/applications/mspaint/history.cpp
+++ b/base/applications/mspaint/history.cpp
@@ -16,7 +16,7 @@ void ImageModel::NotifyImageChanged()
{
if (canvasWindow.IsWindow())
{
- canvasWindow.updateScrollInfo();
+ canvasWindow.updateScrollRange();
canvasWindow.Invalidate();
}
diff --git a/base/applications/mspaint/mouse.cpp b/base/applications/mspaint/mouse.cpp
index dc9ce6b89a2..c7c19e16544 100644
--- a/base/applications/mspaint/mouse.cpp
+++ b/base/applications/mspaint/mouse.cpp
@@ -563,40 +563,67 @@ struct ColorTool : ToolBase
// TOOL_ZOOM
struct ZoomTool : ToolBase
{
+ BOOL m_bZoomed = FALSE;
+
ZoomTool() : ToolBase(TOOL_ZOOM)
{
}
+ BOOL getNewZoomRect(CRect& rcView, INT newZoom);
+
void OnDrawOverlayOnCanvas(HDC hdc) override
{
- CRect rc;
- canvasWindow.GetImageRect(rc);
- canvasWindow.ImageToCanvas(rc);
-
- POINT pt;
- ::GetCursorPos(&pt);
- ::ScreenToClient(canvasWindow, &pt);
-
- // FIXME: Draw the border of the area that is to be zoomed in
- if (rc.PtInRect(pt))
- DrawXorRect(hdc, &rc);
+ CRect rcView;
+ INT oldZoom = toolsModel.GetZoom();
+ if (oldZoom < MAX_ZOOM && getNewZoomRect(rcView, oldZoom * 2))
+ DrawXorRect(hdc, &rcView);
}
void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick) override
{
+ INT newZoom, oldZoom = toolsModel.GetZoom();
if (bLeftButton)
- {
- if (toolsModel.GetZoom() < MAX_ZOOM)
- zoomTo(toolsModel.GetZoom() * 2, x, y);
- }
+ newZoom = (oldZoom < MAX_ZOOM) ? (oldZoom * 2) : MIN_ZOOM;
else
+ newZoom = (oldZoom > MIN_ZOOM) ? (oldZoom / 2) : MAX_ZOOM;
+
+ m_bZoomed = FALSE;
+
+ if (oldZoom != newZoom)
{
- if (toolsModel.GetZoom() > MIN_ZOOM)
- zoomTo(toolsModel.GetZoom() / 2, x, y);
+ CRect rcView;
+ if (getNewZoomRect(rcView, newZoom))
+ {
+ canvasWindow.zoomTo(newZoom, rcView.left, rcView.top);
+ m_bZoomed = TRUE;
+ }
}
}
+
+ BOOL OnButtonUp(BOOL bLeftButton, LONG& x, LONG& y) override
+ {
+ if (m_bZoomed)
+ toolsModel.SetActiveTool(toolsModel.GetOldActiveTool());
+
+ return TRUE;
+ }
};
+BOOL ZoomTool::getNewZoomRect(CRect& rcView, INT newZoom)
+{
+ CPoint pt;
+ ::GetCursorPos(&pt);
+ canvasWindow.ScreenToClient(&pt);
+
+ canvasWindow.getNewZoomRect(rcView, newZoom, pt);
+
+ CRect rc;
+ canvasWindow.GetImageRect(rc);
+ canvasWindow.ImageToCanvas(rc);
+
+ return rc.PtInRect(pt);
+}
+
// TOOL_PEN
struct PenTool : SmoothDrawTool
{
diff --git a/base/applications/mspaint/toolsettings.cpp
b/base/applications/mspaint/toolsettings.cpp
index 182862ec305..745f2afe3e0 100644
--- a/base/applications/mspaint/toolsettings.cpp
+++ b/base/applications/mspaint/toolsettings.cpp
@@ -309,7 +309,7 @@ LRESULT CToolSettingsWindow::OnDestroy(UINT nMsg, WPARAM wParam,
LPARAM lParam,
LRESULT CToolSettingsWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled)
{
INT trackPos = MAX_ZOOM_TRACK - (INT)trackbarZoom.SendMessage(TBM_GETPOS, 0, 0);
- zoomTo(MIN_ZOOM << trackPos, 0, 0);
+ canvasWindow.zoomTo(MIN_ZOOM << trackPos);
INT zoomRate = toolsModel.GetZoom();
diff --git a/base/applications/mspaint/winproc.cpp
b/base/applications/mspaint/winproc.cpp
index 58bf4a98909..c1cbff31b8c 100644
--- a/base/applications/mspaint/winproc.cpp
+++ b/base/applications/mspaint/winproc.cpp
@@ -41,37 +41,6 @@ static HWND DoHtmlHelpW(HWND hwndCaller, LPCWSTR pszFile, UINT
uCommand, DWORD_P
return s_pHtmlHelpW(hwndCaller, pszFile, uCommand, dwData);
}
-BOOL
-zoomTo(int newZoom, int mouseX, int mouseY)
-{
- int x, y, w, h;
- RECT clientRectScrollbox;
- canvasWindow.GetClientRect(&clientRectScrollbox);
-
- RECT clientRectImageArea;
- ::SetRect(&clientRectImageArea, 0, 0, imageModel.GetWidth(),
imageModel.GetHeight());
- Zoomed(clientRectImageArea);
-
- w = clientRectImageArea.right * newZoom / toolsModel.GetZoom();
- h = clientRectImageArea.bottom * newZoom / toolsModel.GetZoom();
- if (!w || !h)
- {
- return FALSE;
- }
- w = clientRectImageArea.right * clientRectScrollbox.right / w;
- h = clientRectImageArea.bottom * clientRectScrollbox.bottom / h;
- x = max(0, min(clientRectImageArea.right - w, mouseX - w / 2)) * newZoom /
toolsModel.GetZoom();
- y = max(0, min(clientRectImageArea.bottom - h, mouseY - h / 2)) * newZoom /
toolsModel.GetZoom();
-
- toolsModel.SetZoom(newZoom);
-
- canvasWindow.Invalidate(TRUE);
-
- canvasWindow.SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, x), 0);
- canvasWindow.SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, y), 0);
- return TRUE;
-}
-
void CMainWindow::alignChildrenToMainWindow()
{
RECT clientRect, rc;
@@ -216,20 +185,20 @@ LRESULT CMainWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM
lParam, BOOL&
{
INT zDelta = (SHORT)HIWORD(wParam);
- if (::GetAsyncKeyState(VK_CONTROL) < 0)
+ if (::GetKeyState(VK_CONTROL) < 0) // Ctrl+Wheel
{
if (zDelta < 0)
{
if (toolsModel.GetZoom() > MIN_ZOOM)
- zoomTo(toolsModel.GetZoom() / 2, 0, 0);
+ canvasWindow.zoomTo(toolsModel.GetZoom() / 2);
}
else if (zDelta > 0)
{
if (toolsModel.GetZoom() < MAX_ZOOM)
- zoomTo(toolsModel.GetZoom() * 2, 0, 0);
+ canvasWindow.zoomTo(toolsModel.GetZoom() * 2);
}
}
- else
+ else // Wheel only
{
UINT nCount = 3;
if (::GetAsyncKeyState(VK_SHIFT) < 0)
@@ -921,7 +890,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM
lParam, BOOL& bH
case IDM_IMAGEROTATEMIRROR:
{
CWaitCursor waitCursor;
- canvasWindow.resetScrollPos();
+ canvasWindow.updateScrollPos();
switch (mirrorRotateDialog.DoModal(mainWindow.m_hWnd))
{
case 1: /* flip horizontally */
@@ -1054,25 +1023,25 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM
lParam, BOOL& bH
break;
case IDM_VIEWZOOM125:
- zoomTo(125, 0, 0);
+ canvasWindow.zoomTo(125);
break;
case IDM_VIEWZOOM25:
- zoomTo(250, 0, 0);
+ canvasWindow.zoomTo(250);
break;
case IDM_VIEWZOOM50:
- zoomTo(500, 0, 0);
+ canvasWindow.zoomTo(500);
break;
case IDM_VIEWZOOM100:
- zoomTo(1000, 0, 0);
+ canvasWindow.zoomTo(1000);
break;
case IDM_VIEWZOOM200:
- zoomTo(2000, 0, 0);
+ canvasWindow.zoomTo(2000);
break;
case IDM_VIEWZOOM400:
- zoomTo(4000, 0, 0);
+ canvasWindow.zoomTo(4000);
break;
case IDM_VIEWZOOM800:
- zoomTo(8000, 0, 0);
+ canvasWindow.zoomTo(8000);
break;
case IDM_VIEWFULLSCREEN: