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

commit efe7368c46f910beb19b3500c989d7d947effcf6
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Sat Apr 8 22:25:27 2023 +0900
Commit:     GitHub <[email protected]>
CommitDate: Sat Apr 8 22:25:27 2023 +0900

    [MSPAINT] Make imageArea window-less (#5215)
    
    - Move imageArea code into canvasWindow.
    - Delete imgarea.cpp, imgarea.h, and imageArea.
    - Add CCanvasWindow::ImageToCanvas and CCanvasWindow::CanvasToImage to 
convert the coordinates.
    - Realize drawing of resizing image area.
    CORE-18867
---
 base/applications/mspaint/CMakeLists.txt     |   1 -
 base/applications/mspaint/canvas.cpp         | 483 ++++++++++++++++++++++++---
 base/applications/mspaint/canvas.h           |  34 +-
 base/applications/mspaint/drawing.cpp        |  11 +
 base/applications/mspaint/drawing.h          |   2 +
 base/applications/mspaint/globalvar.h        |   1 -
 base/applications/mspaint/history.cpp        |   8 +-
 base/applications/mspaint/imgarea.cpp        | 480 --------------------------
 base/applications/mspaint/imgarea.h          |  84 -----
 base/applications/mspaint/mouse.cpp          |  12 +-
 base/applications/mspaint/palettemodel.cpp   |   4 +-
 base/applications/mspaint/precomp.h          |   1 -
 base/applications/mspaint/selectionmodel.cpp |   6 +-
 base/applications/mspaint/textedit.cpp       |  30 +-
 base/applications/mspaint/toolsmodel.cpp     |   8 +-
 base/applications/mspaint/winproc.cpp        |  45 ++-
 16 files changed, 544 insertions(+), 666 deletions(-)

diff --git a/base/applications/mspaint/CMakeLists.txt 
b/base/applications/mspaint/CMakeLists.txt
index 57532cba22d..94b8e26c680 100644
--- a/base/applications/mspaint/CMakeLists.txt
+++ b/base/applications/mspaint/CMakeLists.txt
@@ -13,7 +13,6 @@ list(APPEND SOURCE
     drawing.cpp
     fullscreen.cpp
     history.cpp
-    imgarea.cpp
     main.cpp
     miniature.cpp
     mouse.cpp
diff --git a/base/applications/mspaint/canvas.cpp 
b/base/applications/mspaint/canvas.cpp
index c0fc4ad9210..000a44d7987 100644
--- a/base/applications/mspaint/canvas.cpp
+++ b/base/applications/mspaint/canvas.cpp
@@ -13,20 +13,79 @@ CCanvasWindow canvasWindow;
 /* FUNCTIONS ********************************************************/
 
 CCanvasWindow::CCanvasWindow()
-    : m_whereHit(HIT_NONE)
-    , m_ptOrig { 0, 0 }
+    : m_drawing(FALSE)
+    , m_hitSelection(HIT_NONE)
+    , m_whereHit(HIT_NONE)
+    , m_ptOrig { -1, -1 }
 {
+    ::SetRectEmpty(&m_rcNew);
+}
+
+VOID CCanvasWindow::drawZoomFrame(INT mouseX, INT mouseY)
+{
+    // FIXME: Draw the border of the area that is to be zoomed in
+    CRect rc;
+    GetImageRect(rc);
+    ImageToCanvas(rc);
+
+    HDC hdc = GetDC();
+    DrawXorRect(hdc, &rc);
+    ReleaseDC(hdc);
 }
 
 RECT CCanvasWindow::GetBaseRect()
 {
-    CRect rcBase = { 0, 0, Zoomed(imageModel.GetWidth()), 
Zoomed(imageModel.GetHeight()) };
+    CRect rcBase;
+    GetImageRect(rcBase);
+    ImageToCanvas(rcBase);
     ::InflateRect(&rcBase, GRIP_SIZE, GRIP_SIZE);
-    ::OffsetRect(&rcBase, GRIP_SIZE - GetScrollPos(SB_HORZ), GRIP_SIZE - 
GetScrollPos(SB_VERT));
     return rcBase;
 }
 
-CANVAS_HITTEST CCanvasWindow::HitTest(POINT pt)
+VOID CCanvasWindow::ImageToCanvas(POINT& pt)
+{
+    pt.x = Zoomed(pt.x);
+    pt.y = Zoomed(pt.y);
+    pt.x += GRIP_SIZE - GetScrollPos(SB_HORZ);
+    pt.y += GRIP_SIZE - GetScrollPos(SB_VERT);
+}
+
+VOID CCanvasWindow::ImageToCanvas(RECT& rc)
+{
+    rc.left = Zoomed(rc.left);
+    rc.top = Zoomed(rc.top);
+    rc.right = Zoomed(rc.right);
+    rc.bottom = Zoomed(rc.bottom);
+    ::OffsetRect(&rc, GRIP_SIZE - GetScrollPos(SB_HORZ), GRIP_SIZE - 
GetScrollPos(SB_VERT));
+}
+
+VOID CCanvasWindow::CanvasToImage(POINT& pt, BOOL bZoomed)
+{
+    pt.x -= GRIP_SIZE - GetScrollPos(SB_HORZ);
+    pt.y -= GRIP_SIZE - GetScrollPos(SB_VERT);
+    if (bZoomed)
+        return;
+    pt.x = UnZoomed(pt.x);
+    pt.y = UnZoomed(pt.y);
+}
+
+VOID CCanvasWindow::CanvasToImage(RECT& rc, BOOL bZoomed)
+{
+    ::OffsetRect(&rc, GetScrollPos(SB_HORZ) - GRIP_SIZE, GetScrollPos(SB_VERT) 
- GRIP_SIZE);
+    if (bZoomed)
+        return;
+    rc.left = UnZoomed(rc.left);
+    rc.top = UnZoomed(rc.top);
+    rc.right = UnZoomed(rc.right);
+    rc.bottom = UnZoomed(rc.bottom);
+}
+
+VOID CCanvasWindow::GetImageRect(RECT& rc)
+{
+    ::SetRect(&rc, 0, 0, imageModel.GetWidth(), imageModel.GetHeight());
+}
+
+CANVAS_HITTEST CCanvasWindow::CanvasHitTest(POINT pt)
 {
     RECT rcBase = GetBaseRect();
     return getSizeBoxHitTest(pt, &rcBase);
@@ -42,9 +101,62 @@ VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& 
rcPaint)
     // Fill the background
     ::FillRect(hdcMem, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1));
 
-    // Draw the sizeboxes
+    // Draw the sizeboxes if necessary
     RECT rcBase = GetBaseRect();
-    drawSizeBoxes(hdcMem, &rcBase, FALSE, &rcPaint);
+    if (!selectionModel.m_bShow)
+        drawSizeBoxes(hdcMem, &rcBase, FALSE, &rcPaint);
+
+    // Draw the image
+    CRect rcImage;
+    GetImageRect(rcImage);
+    ImageToCanvas(rcImage);
+    SIZE sizeImage = { imageModel.GetWidth(), imageModel.GetHeight() };
+    StretchBlt(hdcMem, rcImage.left, rcImage.top, rcImage.Width(), 
rcImage.Height(),
+               imageModel.GetDC(), 0, 0, sizeImage.cx, sizeImage.cy, SRCCOPY);
+
+    // Draw the grid
+    if (showGrid && toolsModel.GetZoom() >= 4000)
+    {
+        HPEN oldPen = (HPEN) SelectObject(hdcMem, CreatePen(PS_SOLID, 1, 
RGB(160, 160, 160)));
+        for (INT counter = 0; counter < sizeImage.cy; counter++)
+        {
+            POINT pt0 = { 0, counter }, pt1 = { sizeImage.cx, counter };
+            ImageToCanvas(pt0);
+            ImageToCanvas(pt1);
+            ::MoveToEx(hdcMem, pt0.x, pt0.y, NULL);
+            ::LineTo(hdcMem, pt1.x, pt1.y);
+        }
+        for (INT counter = 0; counter < sizeImage.cx; counter++)
+        {
+            POINT pt0 = { counter, 0 }, pt1 = { counter, sizeImage.cy };
+            ImageToCanvas(pt0);
+            ImageToCanvas(pt1);
+            ::MoveToEx(hdcMem, pt0.x, pt0.y, NULL);
+            ::LineTo(hdcMem, pt1.x, pt1.y);
+        }
+        ::DeleteObject(::SelectObject(hdcMem, oldPen));
+    }
+
+    // Draw selection
+    if (selectionModel.m_bShow)
+    {
+        RECT rcSelection = selectionModel.m_rc;
+        ImageToCanvas(rcSelection);
+
+        ::InflateRect(&rcSelection, GRIP_SIZE, GRIP_SIZE);
+        drawSizeBoxes(hdcMem, &rcSelection, TRUE, &rcPaint);
+        ::InflateRect(&rcSelection, -GRIP_SIZE, -GRIP_SIZE);
+
+        INT iSaveDC = ::SaveDC(hdcMem);
+        ::IntersectClipRect(hdcMem, rcImage.left, rcImage.top, rcImage.right, 
rcImage.bottom);
+        selectionModel.DrawSelection(hdcMem, &rcSelection, 
paletteModel.GetBgColor(),
+                                     toolsModel.IsBackgroundTransparent());
+        ::RestoreDC(hdcMem, iSaveDC);
+    }
+
+    // Draw new frame if any
+    if (!::IsRectEmpty(&m_rcNew))
+        DrawXorRect(hdcMem, &m_rcNew);
 
     // Transfer the bits
     ::BitBlt(hDC,
@@ -65,7 +177,7 @@ VOID CCanvasWindow::Update(HWND hwndFrom)
     CSize sizeZoomed = { Zoomed(imageModel.GetWidth()), 
Zoomed(imageModel.GetHeight()) };
     CSize sizeWhole = { sizeZoomed.cx + (GRIP_SIZE * 2), sizeZoomed.cy + 
(GRIP_SIZE * 2) };
 
-    /* show/hide the scrollbars */
+    // show/hide the scrollbars
     ShowScrollBar(SB_HORZ, sizePage.cx < sizeWhole.cx);
     ShowScrollBar(SB_VERT, sizePage.cy < sizeWhole.cy);
 
@@ -85,12 +197,6 @@ VOID CCanvasWindow::Update(HWND hwndFrom)
     si.nMax   = sizeWhole.cy;
     si.nPage  = sizePage.cy;
     SetScrollInfo(SB_VERT, &si);
-
-    if (imageArea.IsWindow() && hwndFrom != imageArea.m_hWnd)
-    {
-        INT dx = -GetScrollPos(SB_HORZ), dy = -GetScrollPos(SB_VERT);
-        imageArea.MoveWindow(dx + GRIP_SIZE, dy + GRIP_SIZE, sizeZoomed.cx, 
sizeZoomed.cy, TRUE);
-    }
 }
 
 LRESULT CCanvasWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
@@ -143,60 +249,221 @@ LRESULT CCanvasWindow::OnVScroll(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL&
     return 0;
 }
 
-LRESULT CCanvasWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+LRESULT CCanvasWindow::OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL& bHandled)
 {
     POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-    CANVAS_HITTEST hit = HitTest(pt);
 
+    CANVAS_HITTEST hitSelection = SelectionHitTest(pt);
+    if (hitSelection != HIT_NONE)
+    {
+        if (bLeftButton)
+        {
+            UnZoomed(pt);
+            StartSelectionDrag(hitSelection, pt);
+        }
+        return 0;
+    }
+
+    CANVAS_HITTEST hit = CanvasHitTest(pt);
     if (hit == HIT_NONE || hit == HIT_BORDER)
     {
         switch (toolsModel.GetActiveTool())
         {
             case TOOL_BEZIER:
             case TOOL_SHAPE:
-                if (ToolBase::pointSP != 0)
-                {
-                    toolsModel.OnCancelDraw();
-                    imageArea.Invalidate();
-                }
+                toolsModel.OnCancelDraw();
+                canvasWindow.Invalidate();
                 break;
 
             case TOOL_FREESEL:
             case TOOL_RECTSEL:
                 toolsModel.OnFinishDraw();
-                imageArea.Invalidate();
+                canvasWindow.Invalidate();
                 break;
 
             default:
                 break;
         }
 
-        toolsModel.resetTool();  // resets the point-buffer of the polygon and 
bezier functions
+        toolsModel.resetTool(); // resets the point-buffer of the polygon and 
bezier functions
         return 0;
     }
 
+    CanvasToImage(pt, TRUE);
+
     if (hit == HIT_INNER)
     {
-        // TODO: In the future, we handle the events of the window-less image 
area.
+        m_drawing = TRUE;
+        UnZoomed(pt);
+        SetCapture();
+        toolsModel.OnButtonDown(bLeftButton, pt.x, pt.y, FALSE);
+        Invalidate(FALSE);
         return 0;
     }
 
-    // Start dragging
-    m_whereHit = hit;
-    m_ptOrig = pt;
-    SetCapture();
+    if (bLeftButton)
+    {
+        m_whereHit = hit;
+        UnZoomed(pt);
+        m_ptOrig = pt;
+        SetCapture();
+    }
+    return 0;
+}
+
+LRESULT CCanvasWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+{
+    return OnLRButtonDown(TRUE, nMsg, wParam, lParam, bHandled);
+}
+
+LRESULT CCanvasWindow::OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+{
+    return OnLRButtonDown(FALSE, nMsg, wParam, lParam, bHandled);
+}
+
+LRESULT CCanvasWindow::OnLRButtonDblClk(BOOL bLeftButton, UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL& bHandled)
+{
+    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+    CanvasToImage(pt);
+
+    m_drawing = FALSE;
+    ReleaseCapture();
+
+    toolsModel.OnButtonDown(bLeftButton, pt.x, pt.y, TRUE);
+    toolsModel.resetTool();
+    Invalidate(FALSE);
     return 0;
 }
 
+LRESULT CCanvasWindow::OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled)
+{
+    return OnLRButtonDblClk(TRUE, nMsg, wParam, lParam, bHandled);
+}
+
+LRESULT CCanvasWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled)
+{
+    return OnLRButtonDblClk(FALSE, nMsg, wParam, lParam, bHandled);
+}
+
 LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
 {
+    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+    CanvasToImage(pt);
+
+    if (m_hitSelection != HIT_NONE)
+    {
+        SelectionDragging(pt);
+        return 0;
+    }
+
+    if (!m_drawing || toolsModel.GetActiveTool() <= TOOL_AIRBRUSH)
+    {
+        if (toolsModel.GetActiveTool() == TOOL_ZOOM)
+        {
+            Invalidate(FALSE);
+            UpdateWindow();
+            CanvasToImage(pt);
+            drawZoomFrame(pt.x, pt.y);
+        }
+
+        TRACKMOUSEEVENT tme = { sizeof(tme) };
+        tme.dwFlags = TME_LEAVE;
+        tme.hwndTrack = m_hWnd;
+        tme.dwHoverTime = 0;
+        ::TrackMouseEvent(&tme);
+
+        if (!m_drawing)
+        {
+            CString strCoord;
+            strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
+            SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) 
strCoord);
+        }
+    }
+
+    if (m_drawing)
+    {
+        // values displayed in statusbar
+        LONG xRel = pt.x - start.x;
+        LONG yRel = pt.y - start.y;
+
+        switch (toolsModel.GetActiveTool())
+        {
+            // freesel, rectsel and text tools always show numbers limited to 
fit into image area
+            case TOOL_FREESEL:
+            case TOOL_RECTSEL:
+            case TOOL_TEXT:
+                if (xRel < 0)
+                    xRel = (pt.x < 0) ? -start.x : xRel;
+                else if (pt.x > imageModel.GetWidth())
+                    xRel = imageModel.GetWidth() - start.x;
+                if (yRel < 0)
+                    yRel = (pt.y < 0) ? -start.y : yRel;
+                else if (pt.y > imageModel.GetHeight())
+                    yRel = imageModel.GetHeight() - start.y;
+                break;
+
+            // while drawing, update cursor coordinates only for tools 3, 7, 
8, 9, 14
+            case TOOL_RUBBER:
+            case TOOL_PEN:
+            case TOOL_BRUSH:
+            case TOOL_AIRBRUSH:
+            case TOOL_SHAPE:
+            {
+                CString strCoord;
+                strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
+                SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) 
strCoord);
+                break;
+            }
+            default:
+                break;
+        }
+
+        // rectsel and shape tools always show non-negative numbers when 
drawing
+        if (toolsModel.GetActiveTool() == TOOL_RECTSEL || 
toolsModel.GetActiveTool() == TOOL_SHAPE)
+        {
+            if (xRel < 0)
+                xRel = -xRel;
+            if (yRel < 0)
+                yRel =  -yRel;
+        }
+
+        if (wParam & MK_LBUTTON)
+        {
+            toolsModel.OnMouseMove(TRUE, pt.x, pt.y);
+            Invalidate(FALSE);
+            if ((toolsModel.GetActiveTool() >= TOOL_TEXT) || 
(toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == 
TOOL_FREESEL))
+            {
+                CString strSize;
+                if ((toolsModel.GetActiveTool() >= TOOL_LINE) && 
(GetAsyncKeyState(VK_SHIFT) < 0))
+                    yRel = xRel;
+                strSize.Format(_T("%ld x %ld"), xRel, yRel);
+                SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) 
strSize);
+            }
+        }
+
+        if (wParam & MK_RBUTTON)
+        {
+            toolsModel.OnMouseMove(FALSE, pt.x, pt.y);
+            Invalidate(FALSE);
+            if (toolsModel.GetActiveTool() >= TOOL_TEXT)
+            {
+                CString strSize;
+                if ((toolsModel.GetActiveTool() >= TOOL_LINE) && 
(GetAsyncKeyState(VK_SHIFT) < 0))
+                    yRel = xRel;
+                strSize.Format(_T("%ld x %ld"), xRel, yRel);
+                SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) 
strSize);
+            }
+        }
+        return 0;
+    }
+
     if (m_whereHit == HIT_NONE || ::GetCapture() != m_hWnd)
         return 0;
 
     // Dragging now... Calculate the new size
     INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
-    INT cxDelta = UnZoomed(GET_X_LPARAM(lParam) - m_ptOrig.x);
-    INT cyDelta = UnZoomed(GET_Y_LPARAM(lParam) - m_ptOrig.y);
+    INT cxDelta = pt.x - m_ptOrig.x;
+    INT cyDelta = pt.y - m_ptOrig.y;
     switch (m_whereHit)
     {
         case HIT_UPPER_LEFT:
@@ -242,20 +509,62 @@ LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL
     strSize.Format(_T("%d x %d"), cxImage, cyImage);
     SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
 
+    CRect rc = { 0, 0, cxImage, cyImage };
+    switch (m_whereHit)
+    {
+        case HIT_UPPER_LEFT:
+            ::OffsetRect(&rc, cxDelta, cyDelta);
+            break;
+        case HIT_UPPER_CENTER:
+            ::OffsetRect(&rc, 0, cyDelta);
+            break;
+        case HIT_UPPER_RIGHT:
+            ::OffsetRect(&rc, 0, cyDelta);
+            break;
+        case HIT_MIDDLE_LEFT:
+            ::OffsetRect(&rc, cxDelta, 0);
+            break;
+        case HIT_LOWER_LEFT:
+            ::OffsetRect(&rc, cxDelta, 0);
+            break;
+        default:
+            break;
+    }
+    ImageToCanvas(rc);
+    m_rcNew = rc;
+    Invalidate(TRUE);
+
     return 0;
 }
 
-LRESULT CCanvasWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+LRESULT CCanvasWindow::OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL& bHandled)
 {
+    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+    CanvasToImage(pt);
+
     ::ReleaseCapture();
 
-    if (m_whereHit == HIT_NONE)
+    if (m_drawing)
+    {
+        m_drawing = FALSE;
+        toolsModel.OnButtonUp(bLeftButton, pt.x, pt.y);
+        Invalidate(FALSE);
+        SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
+        return 0;
+    }
+    else if (m_hitSelection != HIT_NONE && bLeftButton)
+    {
+        EndSelectionDrag(pt);
+        return 0;
+    }
+
+    if (m_whereHit == HIT_NONE || !bLeftButton)
         return 0;
 
     // Resize the image
     INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
-    INT cxDelta = UnZoomed(GET_X_LPARAM(lParam) - m_ptOrig.x);
-    INT cyDelta = UnZoomed(GET_Y_LPARAM(lParam) - m_ptOrig.y);
+    INT cxDelta = pt.x - m_ptOrig.x;
+    INT cyDelta = pt.y - m_ptOrig.y;
     switch (m_whereHit)
     {
         case HIT_UPPER_LEFT:
@@ -285,23 +594,68 @@ LRESULT CCanvasWindow::OnLButtonUp(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL
         default:
             break;
     }
+    ::SetRectEmpty(&m_rcNew);
 
-    // Finish dragging
     m_whereHit = HIT_NONE;
-    toolsModel.resetTool();  // resets the point-buffer of the polygon and 
bezier functions
+    toolsModel.resetTool(); // resets the point-buffer of the polygon and 
bezier functions
     Update(NULL);
     Invalidate(TRUE);
-
     return 0;
 }
 
+LRESULT CCanvasWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+{
+    return OnLRButtonUp(TRUE, nMsg, wParam, lParam, bHandled);
+}
+
+LRESULT CCanvasWindow::OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
+{
+    return OnLRButtonUp(FALSE, nMsg, wParam, lParam, bHandled);
+}
+
 LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
 {
     POINT pt;
     ::GetCursorPos(&pt);
     ScreenToClient(&pt);
 
-    if (!setCursorOnSizeBox(HitTest(pt)))
+    CANVAS_HITTEST hitSelection = SelectionHitTest(pt);
+    if (hitSelection != HIT_NONE)
+    {
+        if (!setCursorOnSizeBox(hitSelection))
+            ::SetCursor(::LoadCursor(NULL, IDC_SIZEALL));
+        return 0;
+    }
+
+    CRect rcImage;
+    GetImageRect(rcImage);
+    ImageToCanvas(rcImage);
+    if (::PtInRect(&rcImage, pt))
+    {
+        switch (toolsModel.GetActiveTool())
+        {
+            case TOOL_FILL:
+                ::SetCursor(::LoadIcon(hProgInstance, 
MAKEINTRESOURCE(IDC_FILL)));
+                break;
+            case TOOL_COLOR:
+                ::SetCursor(::LoadIcon(hProgInstance, 
MAKEINTRESOURCE(IDC_COLOR)));
+                break;
+            case TOOL_ZOOM:
+                ::SetCursor(::LoadIcon(hProgInstance, 
MAKEINTRESOURCE(IDC_ZOOM)));
+                break;
+            case TOOL_PEN:
+                ::SetCursor(::LoadIcon(hProgInstance, 
MAKEINTRESOURCE(IDC_PEN)));
+                break;
+            case TOOL_AIRBRUSH:
+                ::SetCursor(::LoadIcon(hProgInstance, 
MAKEINTRESOURCE(IDC_AIRBRUSH)));
+                break;
+            default:
+                ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
+        }
+        return 0;
+    }
+
+    if (selectionModel.m_bShow || !setCursorOnSizeBox(CanvasHitTest(pt)))
         ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
 
     return 0;
@@ -354,3 +708,56 @@ LRESULT CCanvasWindow::OnPaint(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
     EndPaint(&ps);
     return 0;
 }
+
+VOID CCanvasWindow::cancelDrawing()
+{
+    selectionModel.ClearColor();
+    selectionModel.ClearMask();
+    m_hitSelection = HIT_NONE;
+    m_drawing = FALSE;
+    toolsModel.OnCancelDraw();
+    Invalidate(FALSE);
+}
+
+VOID CCanvasWindow::finishDrawing()
+{
+    toolsModel.OnFinishDraw();
+    m_drawing = FALSE;
+    Invalidate(FALSE);
+}
+
+CANVAS_HITTEST CCanvasWindow::SelectionHitTest(POINT ptZoomed)
+{
+    if (!selectionModel.m_bShow)
+        return HIT_NONE;
+
+    RECT rcSelection = selectionModel.m_rc;
+    Zoomed(rcSelection);
+    ::OffsetRect(&rcSelection, GRIP_SIZE - GetScrollPos(SB_HORZ), GRIP_SIZE - 
GetScrollPos(SB_VERT));
+    ::InflateRect(&rcSelection, GRIP_SIZE, GRIP_SIZE);
+
+    return getSizeBoxHitTest(ptZoomed, &rcSelection);
+}
+
+VOID CCanvasWindow::StartSelectionDrag(CANVAS_HITTEST hit, POINT ptUnZoomed)
+{
+    m_hitSelection = hit;
+    selectionModel.m_ptHit = ptUnZoomed;
+    selectionModel.TakeOff();
+
+    SetCapture();
+    Invalidate(FALSE);
+}
+
+VOID CCanvasWindow::SelectionDragging(POINT ptUnZoomed)
+{
+    selectionModel.Dragging(m_hitSelection, ptUnZoomed);
+    Invalidate(FALSE);
+}
+
+VOID CCanvasWindow::EndSelectionDrag(POINT ptUnZoomed)
+{
+    selectionModel.Dragging(m_hitSelection, ptUnZoomed);
+    m_hitSelection = HIT_NONE;
+    Invalidate(FALSE);
+}
diff --git a/base/applications/mspaint/canvas.h 
b/base/applications/mspaint/canvas.h
index fe2251ce05a..f932902b370 100644
--- a/base/applications/mspaint/canvas.h
+++ b/base/applications/mspaint/canvas.h
@@ -11,7 +11,7 @@
 class CCanvasWindow : public CWindowImpl<CCanvasWindow>
 {
 public:
-    DECLARE_WND_CLASS_EX(_T("ReactOSPaintCanvas"), 0, COLOR_APPWORKSPACE)
+    DECLARE_WND_CLASS_EX(_T("ReactOSPaintCanvas"), CS_DBLCLKS, 
COLOR_APPWORKSPACE)
 
     BEGIN_MSG_MAP(CCanvasWindow)
         MESSAGE_HANDLER(WM_SIZE, OnSize)
@@ -21,8 +21,12 @@ public:
         MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
         MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+        MESSAGE_HANDLER(WM_RBUTTONDOWN, OnRButtonDown)
+        MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
+        MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnRButtonDblClk)
         MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
         MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
+        MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
         MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
         MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
         MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode)
@@ -31,16 +35,34 @@ public:
 
     CCanvasWindow();
 
+    BOOL m_drawing;
+
+    VOID cancelDrawing();
+    VOID finishDrawing();
     VOID Update(HWND hwndFrom);
 
+    VOID ImageToCanvas(POINT& pt);
+    VOID ImageToCanvas(RECT& rc);
+    VOID CanvasToImage(POINT& pt, BOOL bZoomed = FALSE);
+    VOID CanvasToImage(RECT& rc, BOOL bZoomed = FALSE);
+    VOID GetImageRect(RECT& rc);
+
 protected:
+    CANVAS_HITTEST m_hitSelection;
     CANVAS_HITTEST m_whereHit;
     POINT m_ptOrig; // The origin of drag start
+    CRect m_rcNew;
 
-    CANVAS_HITTEST HitTest(POINT pt);
+    CANVAS_HITTEST CanvasHitTest(POINT pt);
     RECT GetBaseRect();
     VOID DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint);
     VOID OnHVScroll(WPARAM wParam, INT fnBar);
+    VOID drawZoomFrame(INT mouseX, INT mouseY);
+
+    CANVAS_HITTEST SelectionHitTest(POINT ptZoomed);
+    VOID StartSelectionDrag(CANVAS_HITTEST hit, POINT ptUnZoomed);
+    VOID SelectionDragging(POINT ptUnZoomed);
+    VOID EndSelectionDrag(POINT ptUnZoomed);
 
     LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
@@ -48,11 +70,19 @@ protected:
     LRESULT OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
     LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
+    LRESULT OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
+    LRESULT OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
+    LRESULT OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
     LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
     LRESULT OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
+    LRESULT OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
     LRESULT OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
     LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
     LRESULT OnCancelMode(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
     LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
+
+    LRESULT OnLRButtonDown(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled);
+    LRESULT OnLRButtonDblClk(BOOL bLeftButton, UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bHandled);
+    LRESULT OnLRButtonUp(BOOL bLeftButton, UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled);
 };
diff --git a/base/applications/mspaint/drawing.cpp 
b/base/applications/mspaint/drawing.cpp
index 86711c0f6f0..afcae889bc0 100644
--- a/base/applications/mspaint/drawing.cpp
+++ b/base/applications/mspaint/drawing.cpp
@@ -363,3 +363,14 @@ ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int 
nWidth, int nHeight,
 
     return TRUE;
 }
+
+void DrawXorRect(HDC hdc, const RECT *prc)
+{
+    HGDIOBJ oldPen = ::SelectObject(hdc, ::CreatePen(PS_SOLID, 0, RGB(255, 
255, 255)));
+    HGDIOBJ oldBrush = ::SelectObject(hdc, ::GetStockObject(NULL_BRUSH));
+    INT oldRop2 = SetROP2(hdc, R2_XORPEN);
+    ::Rectangle(hdc, prc->left, prc->top, prc->right, prc->bottom);
+    ::SetROP2(hdc, oldRop2);
+    ::SelectObject(hdc, oldBrush);
+    ::DeleteObject(::SelectObject(hdc, oldPen));
+}
diff --git a/base/applications/mspaint/drawing.h 
b/base/applications/mspaint/drawing.h
index 8fb0f54c6a6..11c0bcd6516 100644
--- a/base/applications/mspaint/drawing.h
+++ b/base/applications/mspaint/drawing.h
@@ -38,3 +38,5 @@ BOOL
 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
                   HDC hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int 
nSrcHeight,
                   HBITMAP hbmMask, COLORREF keyColor);
+
+void DrawXorRect(HDC hdc, const RECT *prc);
diff --git a/base/applications/mspaint/globalvar.h 
b/base/applications/mspaint/globalvar.h
index 058117f9390..4ed2cfc6a12 100644
--- a/base/applications/mspaint/globalvar.h
+++ b/base/applications/mspaint/globalvar.h
@@ -52,5 +52,4 @@ extern CToolBox toolBoxContainer;
 extern CToolSettingsWindow toolSettingsWindow;
 extern CPaletteWindow paletteWindow;
 extern CCanvasWindow canvasWindow;
-extern CImgAreaWindow imageArea;
 extern CTextEditWindow textEditWindow;
diff --git a/base/applications/mspaint/history.cpp 
b/base/applications/mspaint/history.cpp
index 0680865c2a6..5be421fdfa0 100644
--- a/base/applications/mspaint/history.cpp
+++ b/base/applications/mspaint/history.cpp
@@ -14,14 +14,14 @@ ImageModel imageModel;
 
 void ImageModel::NotifyDimensionsChanged()
 {
-    if (imageArea.IsWindow())
-        imageArea.SendMessage(WM_IMAGEMODELDIMENSIONSCHANGED);
+    if (canvasWindow.IsWindow())
+        canvasWindow.SendMessage(WM_IMAGEMODELDIMENSIONSCHANGED);
 }
 
 void ImageModel::NotifyImageChanged()
 {
-    if (imageArea.IsWindow())
-        imageArea.SendMessage(WM_IMAGEMODELIMAGECHANGED);
+    if (canvasWindow.IsWindow())
+        canvasWindow.SendMessage(WM_IMAGEMODELIMAGECHANGED);
 }
 
 ImageModel::ImageModel()
diff --git a/base/applications/mspaint/imgarea.cpp 
b/base/applications/mspaint/imgarea.cpp
deleted file mode 100644
index abae54c89a5..00000000000
--- a/base/applications/mspaint/imgarea.cpp
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * PROJECT:     PAINT for ReactOS
- * LICENSE:     LGPL
- * FILE:        base/applications/mspaint/imgarea.cpp
- * PURPOSE:     Window procedure of the main window and all children apart from
- *              hPalWin, hToolSettings and hSelection
- * PROGRAMMERS: Benedikt Freisen
- *              Katayama Hirofumi MZ
- */
-
-#include "precomp.h"
-
-CImgAreaWindow imageArea;
-
-/* FUNCTIONS ********************************************************/
-
-LRESULT CImgAreaWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    m_hCurFill     = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_FILL));
-    m_hCurColor    = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_COLOR));
-    m_hCurZoom     = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_ZOOM));
-    m_hCurPen      = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_PEN));
-    m_hCurAirbrush = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_AIRBRUSH));
-    return 0;
-}
-
-void CImgAreaWindow::drawZoomFrame(int mouseX, int mouseY)
-{
-    HDC hdc;
-    HPEN oldPen;
-    HBRUSH oldBrush;
-    LOGBRUSH logbrush;
-    int rop;
-
-    RECT clientRectCanvas;
-    RECT clientRectImageArea;
-    int x, y, w, h;
-    canvasWindow.GetClientRect(&clientRectCanvas);
-    GetClientRect(&clientRectImageArea);
-    w = clientRectImageArea.right * 2;
-    h = clientRectImageArea.bottom * 2;
-    if (!w || !h)
-    {
-        return;
-    }
-    w = clientRectImageArea.right * clientRectCanvas.right / w;
-    h = clientRectImageArea.bottom * clientRectCanvas.bottom / h;
-    x = max(0, min(clientRectImageArea.right - w, mouseX - w / 2));
-    y = max(0, min(clientRectImageArea.bottom - h, mouseY - h / 2));
-
-    hdc = GetDC();
-    oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 0, 0));
-    logbrush.lbStyle = BS_HOLLOW;
-    oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
-    rop = SetROP2(hdc, R2_NOT);
-    Rectangle(hdc, x, y, x + w, y + h);
-    SetROP2(hdc, rop);
-    DeleteObject(SelectObject(hdc, oldBrush));
-    DeleteObject(SelectObject(hdc, oldPen));
-    ReleaseDC(hdc);
-}
-
-LRESULT CImgAreaWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
-{
-    if (!IsWindow())
-        return 0;
-    canvasWindow.Update(NULL);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnEraseBkGnd(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    return TRUE; // Don't fill background
-}
-
-LRESULT CImgAreaWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
-{
-    RECT rcClient;
-    GetClientRect(&rcClient);
-
-    PAINTSTRUCT ps;
-    HDC hdc = BeginPaint(&ps);
-
-    // We use a memory bitmap to reduce flickering
-    HDC hdcMem = ::CreateCompatibleDC(hdc);
-    HBITMAP hbm = ::CreateCompatibleBitmap(hdc, rcClient.right, 
rcClient.bottom);
-    HGDIOBJ hbmOld = ::SelectObject(hdcMem, hbm);
-
-    // Draw the image
-    SIZE size = { imageModel.GetWidth(), imageModel.GetHeight() };
-    StretchBlt(hdcMem, 0, 0, ::Zoomed(size.cx), ::Zoomed(size.cy),
-               imageModel.GetDC(), 0, 0, size.cx, size.cy, SRCCOPY);
-
-    // Draw the grid
-    if (showGrid && (toolsModel.GetZoom() >= 4000))
-    {
-        HPEN oldPen = (HPEN) SelectObject(hdcMem, CreatePen(PS_SOLID, 1, 
0x00a0a0a0));
-        for (int counter = 0; counter <= size.cy; counter++)
-        {
-            ::MoveToEx(hdcMem, 0, ::Zoomed(counter), NULL);
-            ::LineTo(hdcMem, ::Zoomed(size.cx), ::Zoomed(counter));
-        }
-        for (int counter = 0; counter <= size.cx; counter++)
-        {
-            ::MoveToEx(hdcMem, ::Zoomed(counter), 0, NULL);
-            ::LineTo(hdcMem, ::Zoomed(counter), ::Zoomed(size.cy));
-        }
-        ::DeleteObject(::SelectObject(hdcMem, oldPen));
-    }
-
-    // Draw selection
-    if (selectionModel.m_bShow)
-    {
-        RECT rc = selectionModel.m_rc;
-        Zoomed(rc);
-        ::InflateRect(&rc, GRIP_SIZE, GRIP_SIZE);
-        drawSizeBoxes(hdcMem, &rc, TRUE, &ps.rcPaint);
-        ::InflateRect(&rc, -GRIP_SIZE, -GRIP_SIZE);
-        selectionModel.DrawSelection(hdcMem, &rc, paletteModel.GetBgColor(),
-                                     toolsModel.IsBackgroundTransparent());
-    }
-
-    // Transfer bits
-    ::BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcMem, 0, 0, 
SRCCOPY);
-    ::SelectObject(hdcMem, hbmOld);
-    EndPaint(&ps);
-
-    if (miniature.IsWindow())
-        miniature.Invalidate(FALSE);
-    if (textEditWindow.IsWindow())
-        textEditWindow.Invalidate(FALSE);
-    return 0;
-}
-
-CANVAS_HITTEST CImgAreaWindow::SelectionHitTest(POINT ptZoomed)
-{
-    if (!selectionModel.m_bShow)
-        return HIT_NONE;
-
-    RECT rcSelection = selectionModel.m_rc;
-    Zoomed(rcSelection);
-    ::InflateRect(&rcSelection, GRIP_SIZE, GRIP_SIZE);
-
-    return getSizeBoxHitTest(ptZoomed, &rcSelection);
-}
-
-void CImgAreaWindow::StartSelectionDrag(CANVAS_HITTEST hit, POINT ptUnZoomed)
-{
-    m_hitSelection = hit;
-    selectionModel.m_ptHit = ptUnZoomed;
-    selectionModel.TakeOff();
-
-    SetCapture();
-    Invalidate(FALSE);
-}
-
-void CImgAreaWindow::SelectionDragging(POINT ptUnZoomed)
-{
-    selectionModel.Dragging(m_hitSelection, ptUnZoomed);
-    Invalidate(FALSE);
-}
-
-void CImgAreaWindow::EndSelectionDrag(POINT ptUnZoomed)
-{
-    selectionModel.Dragging(m_hitSelection, ptUnZoomed);
-    m_hitSelection = HIT_NONE;
-    Invalidate(FALSE);
-}
-
-LRESULT CImgAreaWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    POINT pt;
-    ::GetCursorPos(&pt);
-    ScreenToClient(&pt);
-
-    CANVAS_HITTEST hit = SelectionHitTest(pt);
-    if (hit != HIT_NONE)
-    {
-        if (!setCursorOnSizeBox(hit))
-            ::SetCursor(::LoadCursor(NULL, IDC_SIZEALL));
-        return 0;
-    }
-
-    UnZoomed(pt);
-
-    switch (toolsModel.GetActiveTool())
-    {
-        case TOOL_FILL:
-            ::SetCursor(m_hCurFill);
-            break;
-        case TOOL_COLOR:
-            ::SetCursor(m_hCurColor);
-            break;
-        case TOOL_ZOOM:
-            ::SetCursor(m_hCurZoom);
-            break;
-        case TOOL_PEN:
-            ::SetCursor(m_hCurPen);
-            break;
-        case TOOL_AIRBRUSH:
-            ::SetCursor(m_hCurAirbrush);
-            break;
-        default:
-            ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
-    }
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-
-    CANVAS_HITTEST hit = SelectionHitTest(pt);
-    if (hit != HIT_NONE)
-    {
-        UnZoomed(pt);
-        StartSelectionDrag(hit, pt);
-        return 0;
-    }
-
-    UnZoomed(pt);
-    drawing = TRUE;
-    SetCapture();
-    toolsModel.OnButtonDown(TRUE, pt.x, pt.y, FALSE);
-    Invalidate(FALSE);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled)
-{
-    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-    UnZoomed(pt);
-    drawing = FALSE;
-    ReleaseCapture();
-    toolsModel.OnButtonDown(TRUE, pt.x, pt.y, TRUE);
-    toolsModel.resetTool();
-    Invalidate(FALSE);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-    UnZoomed(pt);
-    drawing = TRUE;
-    SetCapture();
-    toolsModel.OnButtonDown(FALSE, pt.x, pt.y, FALSE);
-    Invalidate(FALSE);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled)
-{
-    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-    UnZoomed(pt);
-    drawing = FALSE;
-    ReleaseCapture();
-    toolsModel.OnButtonDown(FALSE, pt.x, pt.y, TRUE);
-    toolsModel.resetTool();
-    Invalidate(FALSE);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-    UnZoomed(pt);
-    if (drawing)
-    {
-        drawing = FALSE;
-        toolsModel.OnButtonUp(TRUE, pt.x, pt.y);
-        Invalidate(FALSE);
-        SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
-    }
-    else if (m_hitSelection != HIT_NONE)
-    {
-        EndSelectionDrag(pt);
-    }
-    ReleaseCapture();
-    return 0;
-}
-
-void CImgAreaWindow::cancelDrawing()
-{
-    selectionModel.ClearColor();
-    selectionModel.ClearMask();
-    m_hitSelection = HIT_NONE;
-    drawing = FALSE;
-    toolsModel.OnCancelDraw();
-    Invalidate(FALSE);
-}
-
-LRESULT CImgAreaWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled)
-{
-    if (drawing)
-        cancelDrawing();
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    if (wParam == VK_ESCAPE)
-    {
-        if (GetCapture() == m_hWnd)
-        {
-            ReleaseCapture();
-        }
-        else
-        {
-            if (drawing || ToolBase::pointSP != 0 || selectionModel.m_bShow)
-                cancelDrawing();
-        }
-    }
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-    UnZoomed(pt);
-    if (drawing)
-    {
-        drawing = FALSE;
-        toolsModel.OnButtonUp(FALSE, pt.x, pt.y);
-        Invalidate(FALSE);
-        SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
-    }
-    else if (m_hitSelection != HIT_NONE)
-    {
-        EndSelectionDrag(pt);
-    }
-    ReleaseCapture();
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-    UnZoomed(pt);
-
-    if (m_hitSelection != HIT_NONE)
-    {
-        SelectionDragging(pt);
-        return 0;
-    }
-
-    if ((!drawing) || (toolsModel.GetActiveTool() <= TOOL_AIRBRUSH))
-    {
-        TRACKMOUSEEVENT tme;
-
-        if (toolsModel.GetActiveTool() == TOOL_ZOOM)
-        {
-            Invalidate(FALSE);
-            UpdateWindow();
-            drawZoomFrame(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
-        }
-
-        tme.cbSize = sizeof(TRACKMOUSEEVENT);
-        tme.dwFlags = TME_LEAVE;
-        tme.hwndTrack = m_hWnd;
-        tme.dwHoverTime = 0;
-        TrackMouseEvent(&tme);
-
-        if (!drawing)
-        {
-            CString strCoord;
-            strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
-            SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) 
strCoord);
-        }
-    }
-    if (drawing)
-    {
-        /* values displayed in statusbar */
-        LONG xRel = pt.x - start.x;
-        LONG yRel = pt.y - start.y;
-        /* freesel, rectsel and text tools always show numbers limited to fit 
into image area */
-        if ((toolsModel.GetActiveTool() == TOOL_FREESEL) || 
(toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == 
TOOL_TEXT))
-        {
-            if (xRel < 0)
-                xRel = (pt.x < 0) ? -start.x : xRel;
-            else if (pt.x > imageModel.GetWidth())
-                xRel = imageModel.GetWidth() - start.x;
-            if (yRel < 0)
-                yRel = (pt.y < 0) ? -start.y : yRel;
-            else if (pt.y > imageModel.GetHeight())
-                yRel = imageModel.GetHeight() - start.y;
-        }
-        /* rectsel and shape tools always show non-negative numbers when 
drawing */
-        if ((toolsModel.GetActiveTool() == TOOL_RECTSEL) || 
(toolsModel.GetActiveTool() == TOOL_SHAPE))
-        {
-            if (xRel < 0)
-                xRel = -xRel;
-            if (yRel < 0)
-                yRel =  -yRel;
-        }
-        /* while drawing, update cursor coordinates only for tools 3, 7, 8, 9, 
14 */
-        switch(toolsModel.GetActiveTool())
-        {
-            case TOOL_RUBBER:
-            case TOOL_PEN:
-            case TOOL_BRUSH:
-            case TOOL_AIRBRUSH:
-            case TOOL_SHAPE:
-            {
-                CString strCoord;
-                strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
-                SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) 
strCoord);
-                break;
-            }
-            default:
-                break;
-        }
-        if (wParam & MK_LBUTTON)
-        {
-            toolsModel.OnMouseMove(TRUE, pt.x, pt.y);
-            Invalidate(FALSE);
-            if ((toolsModel.GetActiveTool() >= TOOL_TEXT) || 
(toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == 
TOOL_FREESEL))
-            {
-                CString strSize;
-                if ((toolsModel.GetActiveTool() >= TOOL_LINE) && 
(GetAsyncKeyState(VK_SHIFT) < 0))
-                    yRel = xRel;
-                strSize.Format(_T("%ld x %ld"), xRel, yRel);
-                SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) 
strSize);
-            }
-        }
-        if (wParam & MK_RBUTTON)
-        {
-            toolsModel.OnMouseMove(FALSE, pt.x, pt.y);
-            Invalidate(FALSE);
-            if (toolsModel.GetActiveTool() >= TOOL_TEXT)
-            {
-                CString strSize;
-                if ((toolsModel.GetActiveTool() >= TOOL_LINE) && 
(GetAsyncKeyState(VK_SHIFT) < 0))
-                    yRel = xRel;
-                strSize.Format(_T("%ld x %ld"), xRel, yRel);
-                SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) 
strSize);
-            }
-        }
-    }
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnMouseLeave(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) _T(""));
-    if (toolsModel.GetActiveTool() == TOOL_ZOOM)
-        Invalidate(FALSE);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnImageModelDimensionsChanged(UINT nMsg, WPARAM 
wParam, LPARAM lParam, BOOL& bHandled)
-{
-    canvasWindow.Update(NULL);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnImageModelImageChanged(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bHandled)
-{
-    Invalidate(FALSE);
-    return 0;
-}
-
-LRESULT CImgAreaWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
-{
-    return ::SendMessage(GetParent(), nMsg, wParam, lParam);
-}
-
-LRESULT CImgAreaWindow::OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled)
-{
-    HDC hdc = (HDC)wParam;
-    SetBkMode(hdc, TRANSPARENT);
-    return (LRESULT)GetStockObject(NULL_BRUSH);
-}
-
-void CImgAreaWindow::finishDrawing()
-{
-    toolsModel.OnFinishDraw();
-    drawing = FALSE;
-    Invalidate(FALSE);
-}
diff --git a/base/applications/mspaint/imgarea.h 
b/base/applications/mspaint/imgarea.h
deleted file mode 100644
index 941424d0af9..00000000000
--- a/base/applications/mspaint/imgarea.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * PROJECT:     PAINT for ReactOS
- * LICENSE:     LGPL
- * FILE:        base/applications/mspaint/imgarea.h
- * PURPOSE:     Window procedure of the main window and all children apart from
- *              hPalWin, hToolSettings and hSelection
- * PROGRAMMERS: Benedikt Freisen
- *              Katayama Hirofumi MZ
- */
-
-#pragma once
-
-class CImgAreaWindow : public CWindowImpl<CImgAreaWindow>
-{
-public:
-    CImgAreaWindow()
-        : drawing(FALSE)
-        , m_hitSelection(HIT_NONE)
-    {
-    }
-
-    BOOL drawing;
-    CANVAS_HITTEST m_hitSelection;
-
-    void cancelDrawing();
-    void finishDrawing();
-
-    DECLARE_WND_CLASS_EX(_T("ImgAreaWindow"), CS_DBLCLKS, COLOR_BTNFACE)
-
-    BEGIN_MSG_MAP(CImgAreaWindow)
-        MESSAGE_HANDLER(WM_SIZE, OnSize)
-        MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkGnd)
-        MESSAGE_HANDLER(WM_PAINT, OnPaint)
-        MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
-        MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
-        MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)
-        MESSAGE_HANDLER(WM_RBUTTONDOWN, OnRButtonDown)
-        MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnRButtonDblClk)
-        MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
-        MESSAGE_HANDLER(WM_RBUTTONUP, OnRButtonUp)
-        MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
-        MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
-        MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
-        MESSAGE_HANDLER(WM_IMAGEMODELDIMENSIONSCHANGED, 
OnImageModelDimensionsChanged)
-        MESSAGE_HANDLER(WM_IMAGEMODELIMAGECHANGED, OnImageModelImageChanged)
-        MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
-        MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
-        MESSAGE_HANDLER(WM_CTLCOLOREDIT, OnCtlColorEdit)
-        MESSAGE_HANDLER(WM_CREATE, OnCreate)
-    END_MSG_MAP()
-
-private:
-    HCURSOR m_hCurFill;
-    HCURSOR m_hCurColor;
-    HCURSOR m_hCurZoom;
-    HCURSOR m_hCurPen;
-    HCURSOR m_hCurAirbrush;
-
-    LRESULT OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnEraseBkGnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnMouseLeave(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnImageModelDimensionsChanged(UINT nMsg, WPARAM wParam, LPARAM 
lParam, BOOL& bHandled);
-    LRESULT OnImageModelImageChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled);
-    LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-    LRESULT OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled);
-
-    void drawZoomFrame(int mouseX, int mouseY);
-    CANVAS_HITTEST SelectionHitTest(POINT ptZoomed);
-    void StartSelectionDrag(CANVAS_HITTEST hit, POINT ptUnZoomed);
-    void SelectionDragging(POINT ptUnZoomed);
-    void EndSelectionDrag(POINT ptUnZoomed);
-};
diff --git a/base/applications/mspaint/mouse.cpp 
b/base/applications/mspaint/mouse.cpp
index 5d1c4fcefea..a412219e0bb 100644
--- a/base/applications/mspaint/mouse.cpp
+++ b/base/applications/mspaint/mouse.cpp
@@ -151,14 +151,14 @@ struct FreeSelTool : ToolBase
                 selectionModel.ResetPtStack();
                 selectionModel.m_bShow = FALSE;
             }
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
         }
     }
 
     void OnFinishDraw()
     {
         if (m_bLeftButton)
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
 
         m_bLeftButton = FALSE;
         ToolBase::OnFinishDraw();
@@ -214,14 +214,14 @@ struct RectSelTool : ToolBase
             if (start.x == x && start.y == y)
                 imageModel.Undo(TRUE);
             selectionModel.m_bShow = !selectionModel.m_rc.IsRectEmpty();
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
         }
     }
 
     void OnFinishDraw()
     {
         if (m_bLeftButton)
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
 
         m_bLeftButton = FALSE;
         ToolBase::OnFinishDraw();
@@ -417,7 +417,7 @@ struct TextTool : ToolBase
     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
     {
         if (!textEditWindow.IsWindow())
-            textEditWindow.Create(imageArea);
+            textEditWindow.Create(canvasWindow);
 
         imageModel.CopyPrevious();
         UpdatePoint(x, y);
@@ -484,7 +484,7 @@ struct TextTool : ToolBase
         }
 
         if (!textEditWindow.IsWindow())
-            textEditWindow.Create(imageArea);
+            textEditWindow.Create(canvasWindow);
 
         textEditWindow.SetWindowText(NULL);
         textEditWindow.ValidateEditRect(&rc);
diff --git a/base/applications/mspaint/palettemodel.cpp 
b/base/applications/mspaint/palettemodel.cpp
index cf920bc43e0..8d18449fbee 100644
--- a/base/applications/mspaint/palettemodel.cpp
+++ b/base/applications/mspaint/palettemodel.cpp
@@ -97,8 +97,8 @@ void PaletteModel::NotifyColorChanged()
 {
     if (paletteWindow.IsWindow())
         paletteWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
-    if (imageArea.IsWindow())
-        imageArea.SendMessage(WM_PALETTEMODELCOLORCHANGED);
+    if (canvasWindow.IsWindow())
+        canvasWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
 }
diff --git a/base/applications/mspaint/precomp.h 
b/base/applications/mspaint/precomp.h
index ae4e584e229..368ce304461 100644
--- a/base/applications/mspaint/precomp.h
+++ b/base/applications/mspaint/precomp.h
@@ -38,7 +38,6 @@
 #include "dib.h"
 #include "fullscreen.h"
 #include "history.h"
-#include "imgarea.h"
 #include "miniature.h"
 #include "palette.h"
 #include "palettemodel.h"
diff --git a/base/applications/mspaint/selectionmodel.cpp 
b/base/applications/mspaint/selectionmodel.cpp
index f7c61d16c28..3609632f63b 100644
--- a/base/applications/mspaint/selectionmodel.cpp
+++ b/base/applications/mspaint/selectionmodel.cpp
@@ -179,7 +179,7 @@ BOOL SelectionModel::TakeOff()
         DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
     }
 
-    imageArea.Invalidate(FALSE);
+    canvasWindow.Invalidate(FALSE);
     return TRUE;
 }
 
@@ -417,7 +417,7 @@ void SelectionModel::Dragging(CANVAS_HITTEST hit, POINT pt)
 
 void SelectionModel::NotifyRefreshNeeded()
 {
-    imageArea.Invalidate(FALSE);
+    canvasWindow.Invalidate(FALSE);
 }
 
 void SelectionModel::ClearMask()
@@ -448,5 +448,5 @@ void SelectionModel::CancelSelection()
         imageModel.Undo(TRUE);
 
     m_bShow = FALSE;
-    imageArea.Invalidate(FALSE);
+    canvasWindow.Invalidate(FALSE);
 }
diff --git a/base/applications/mspaint/textedit.cpp 
b/base/applications/mspaint/textedit.cpp
index 6a05cebff90..3b679c61272 100644
--- a/base/applications/mspaint/textedit.cpp
+++ b/base/applications/mspaint/textedit.cpp
@@ -293,11 +293,8 @@ void CTextEditWindow::InvalidateEditRect()
     ::InvalidateRect(m_hwndParent, &rc, TRUE);
 
     GetClientRect(&rc);
-    MapWindowPoints(imageArea, (LPPOINT)&rc, 2);
-    rc.left = UnZoomed(rc.left);
-    rc.top = UnZoomed(rc.top);
-    rc.right = UnZoomed(rc.right);
-    rc.bottom = UnZoomed(rc.bottom);
+    MapWindowPoints(canvasWindow, (LPPOINT)&rc, 2);
+    canvasWindow.CanvasToImage(rc);
     m_rc = rc;
 }
 
@@ -394,27 +391,30 @@ void CTextEditWindow::ValidateEditRect(LPCRECT prc 
OPTIONAL)
 {
     if (prc)
         m_rc = *prc;
-    INT x0 = Zoomed(m_rc.left), y0 = Zoomed(m_rc.top);
-    INT x1 = Zoomed(m_rc.right), y1 = Zoomed(m_rc.bottom);
+
+    CRect rc = m_rc;
+    canvasWindow.ImageToCanvas(rc);
 
     ++m_nAppIsMovingOrSizing;
-    MoveWindow(x0, y0, x1 - x0, y1 - y0, TRUE);
+    MoveWindow(rc.left, rc.top, rc.Width(), rc.Height(), TRUE);
     --m_nAppIsMovingOrSizing;
 }
 
 void CTextEditWindow::Reposition()
 {
-    RECT rc, rcImage;
+    CRect rc;
     GetWindowRect(&rc);
+    ::MapWindowPoints(NULL, canvasWindow, (LPPOINT)&rc, 2);
+    canvasWindow.CanvasToImage(rc);
 
-    ::MapWindowPoints(NULL, imageArea, (LPPOINT)&rc, 2);
-    imageArea.GetClientRect(&rcImage);
+    CRect rcImage;
+    canvasWindow.GetImageRect(rcImage);
 
     if (rc.bottom > rcImage.bottom)
-        ::OffsetRect(&rc, 0, rcImage.bottom - rc.bottom);
+        ::OffsetRect(&rc, 0, rcImage.Height());
 
     if (rc.right > rcImage.right)
-        ::OffsetRect(&rc, rcImage.right - rc.right, 0);
+        ::OffsetRect(&rc, rcImage.Width(), 0);
 
     if (rc.left < 0)
         ::OffsetRect(&rc, -rc.left, 0);
@@ -422,8 +422,10 @@ void CTextEditWindow::Reposition()
     if (rc.top < 0)
         ::OffsetRect(&rc, 0, -rc.top);
 
+    canvasWindow.ImageToCanvas(rc);
+
     ++m_nAppIsMovingOrSizing;
-    MoveWindow(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
+    MoveWindow(rc.left, rc.top, rc.Width(), rc.Height(), TRUE);
     --m_nAppIsMovingOrSizing;
 }
 
diff --git a/base/applications/mspaint/toolsmodel.cpp 
b/base/applications/mspaint/toolsmodel.cpp
index 5f07ddf6132..bebb8687284 100644
--- a/base/applications/mspaint/toolsmodel.cpp
+++ b/base/applications/mspaint/toolsmodel.cpp
@@ -141,8 +141,8 @@ void ToolsModel::SetBackgroundTransparent(BOOL bTransparent)
 {
     m_transpBg = bTransparent;
     NotifyToolSettingsChanged();
-    if (imageArea.IsWindow())
-        imageArea.Invalidate(FALSE);
+    if (canvasWindow.IsWindow())
+        canvasWindow.Invalidate(FALSE);
 }
 
 int ToolsModel::GetZoom() const
@@ -182,8 +182,8 @@ void ToolsModel::NotifyZoomChanged()
         toolSettingsWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
-    if (imageArea.IsWindow())
-        imageArea.SendMessage(WM_TOOLSMODELZOOMCHANGED);
+    if (canvasWindow.IsWindow())
+        canvasWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
 }
 
 void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL 
bDoubleClick)
diff --git a/base/applications/mspaint/winproc.cpp 
b/base/applications/mspaint/winproc.cpp
index c709750b2e3..09fc9e4b139 100644
--- a/base/applications/mspaint/winproc.cpp
+++ b/base/applications/mspaint/winproc.cpp
@@ -45,11 +45,14 @@ static HWND DoHtmlHelpW(HWND hwndCaller, LPCWSTR pszFile, 
UINT uCommand, DWORD_P
 BOOL
 zoomTo(int newZoom, int mouseX, int mouseY)
 {
-    RECT clientRectScrollbox;
-    RECT clientRectImageArea;
     int x, y, w, h;
+    RECT clientRectScrollbox;
     canvasWindow.GetClientRect(&clientRectScrollbox);
-    imageArea.GetClientRect(&clientRectImageArea);
+
+    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)
@@ -63,9 +66,7 @@ zoomTo(int newZoom, int mouseX, int mouseY)
 
     toolsModel.SetZoom(newZoom);
 
-    imageArea.MoveWindow(GRIP_SIZE, GRIP_SIZE, Zoomed(imageModel.GetWidth()), 
Zoomed(imageModel.GetHeight()), FALSE);
     canvasWindow.Invalidate(TRUE);
-    imageArea.Invalidate(FALSE);
 
     canvasWindow.SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, x), 0);
     canvasWindow.SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, y), 0);
@@ -139,7 +140,7 @@ void CMainWindow::alignChildrenToMainWindow()
 
 void CMainWindow::saveImage(BOOL overwrite)
 {
-    imageArea.finishDrawing();
+    canvasWindow.finishDrawing();
 
     if (isAFile && overwrite)
     {
@@ -206,7 +207,7 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP 
bitmap, HWND window)
     imageModel.CopyPrevious();
     selectionModel.InsertFromHBITMAP(bitmap, 0, 0);
     selectionModel.m_bShow = TRUE;
-    imageArea.Invalidate(FALSE);
+    canvasWindow.Invalidate(FALSE);
 }
 
 LRESULT CMainWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, 
BOOL& bHandled)
@@ -296,9 +297,6 @@ LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bHa
     style = WS_CHILD | WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE;
     canvasWindow.Create(m_hWnd, rcEmpty, NULL, style, WS_EX_CLIENTEDGE);
 
-    // Creating the window inside the canvas
-    imageArea.Create(canvasWindow, rcEmpty, NULL, WS_CHILD | WS_VISIBLE);
-
     // Create and show the miniature if necessary
     if (registrySettings.ShowThumbnail)
     {
@@ -340,7 +338,7 @@ LRESULT CMainWindow::OnDestroy(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
 
 BOOL CMainWindow::ConfirmSave()
 {
-    imageArea.finishDrawing();
+    canvasWindow.finishDrawing();
 
     if (imageModel.IsImageSaved())
         return TRUE;
@@ -501,16 +499,11 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
         if (hwndCapture)
         {
             if (canvasWindow.m_hWnd == hwndCapture ||
-                imageArea.m_hWnd == hwndCapture ||
                 fullscreenWindow.m_hWnd == hwndCapture)
             {
                 SendMessage(hwndCapture, nMsg, wParam, lParam);
             }
         }
-        else
-        {
-            imageArea.SendMessage(nMsg, wParam, lParam);
-        }
     }
     return 0;
 }
@@ -526,7 +519,7 @@ LRESULT CMainWindow::OnSysColorChange(UINT nMsg, WPARAM 
wParam, LPARAM lParam, B
 LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
 {
     // Disable commands while dragging mouse
-    if (imageArea.drawing && ::GetCapture())
+    if (canvasWindow.m_drawing && ::GetCapture())
     {
         ATLTRACE("locking!\n");
         return 0;
@@ -631,28 +624,28 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
                 if (toolsModel.GetActiveTool() == TOOL_RECTSEL ||
                     toolsModel.GetActiveTool() == TOOL_FREESEL)
                 {
-                    imageArea.cancelDrawing();
+                    canvasWindow.cancelDrawing();
                     break;
                 }
             }
             if (ToolBase::pointSP != 0) // drawing something?
             {
-                imageArea.cancelDrawing();
+                canvasWindow.cancelDrawing();
                 break;
             }
             imageModel.Undo();
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
             break;
         case IDM_EDITREDO:
             if (toolsModel.GetActiveTool() == TOOL_TEXT && 
::IsWindowVisible(textEditWindow))
                 break;
             if (ToolBase::pointSP != 0) // drawing something?
             {
-                imageArea.finishDrawing();
+                canvasWindow.finishDrawing();
                 break;
             }
             imageModel.Redo();
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
             break;
         case IDM_EDITCOPY:
             OpenClipboard();
@@ -684,7 +677,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
                     break;
 
                 case TOOL_TEXT:
-                    imageArea.cancelDrawing();
+                    canvasWindow.cancelDrawing();
                     break;
                 default:
                     break;
@@ -701,7 +694,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
             HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, 
TOOLBARCLASSNAME, NULL);
             SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELPARAM(TRUE, 
0));
             toolsModel.selectAll();
-            imageArea.Invalidate(TRUE);
+            canvasWindow.Invalidate(TRUE);
             break;
         }
         case IDM_EDITCOPYTO:
@@ -746,7 +739,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
         case IDM_IMAGEDELETEIMAGE:
             imageModel.CopyPrevious();
             Rect(imageModel.GetDC(), 0, 0, imageModel.GetWidth(), 
imageModel.GetHeight(), paletteModel.GetBgColor(), paletteModel.GetBgColor(), 
0, TRUE);
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
             break;
         case IDM_IMAGEROTATEMIRROR:
             switch (mirrorRotateDialog.DoModal(mainWindow.m_hWnd))
@@ -844,7 +837,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, 
LPARAM lParam, BOOL& bH
             break;
         case IDM_VIEWSHOWGRID:
             showGrid = !showGrid;
-            imageArea.Invalidate(FALSE);
+            canvasWindow.Invalidate(FALSE);
             break;
         case IDM_VIEWSHOWMINIATURE:
             registrySettings.ShowThumbnail = !::IsWindowVisible(miniature);

Reply via email to