https://git.reactos.org/?p=reactos.git;a=commitdiff;h=8f1eb03ad28f6262b7322a637f775d7e1312351c

commit 8f1eb03ad28f6262b7322a637f775d7e1312351c
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Tue Oct 17 07:25:50 2023 +0900
Commit:     GitHub <nore...@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:

Reply via email to