[MSPAINT] Make selection window-less (#5208)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Sat, 1 Apr 2023 13:01:04 +0000 (22:01 +0900)
committerGitHub <noreply@github.com>
Sat, 1 Apr 2023 13:01:04 +0000 (22:01 +0900)
- Delete selection.cpp and selection.h and selectionWindow.
- Extend ColorKeyedMaskBlt function.
- Implement selection resizing.
CORE-18867

23 files changed:
base/applications/mspaint/CMakeLists.txt
base/applications/mspaint/canvas.cpp
base/applications/mspaint/common.h
base/applications/mspaint/dib.cpp
base/applications/mspaint/dib.h
base/applications/mspaint/drawing.cpp
base/applications/mspaint/drawing.h
base/applications/mspaint/globalvar.h
base/applications/mspaint/history.cpp
base/applications/mspaint/history.h
base/applications/mspaint/imgarea.cpp
base/applications/mspaint/imgarea.h
base/applications/mspaint/mouse.cpp
base/applications/mspaint/palettemodel.cpp
base/applications/mspaint/precomp.h
base/applications/mspaint/selection.cpp [deleted file]
base/applications/mspaint/selection.h [deleted file]
base/applications/mspaint/selectionmodel.cpp
base/applications/mspaint/selectionmodel.h
base/applications/mspaint/toolbox.cpp
base/applications/mspaint/toolsmodel.cpp
base/applications/mspaint/toolsmodel.h
base/applications/mspaint/winproc.cpp

index 2d6e24d..57532cb 100644 (file)
@@ -20,7 +20,6 @@ list(APPEND SOURCE
     palette.cpp
     palettemodel.cpp
     registry.cpp
     palette.cpp
     palettemodel.cpp
     registry.cpp
-    selection.cpp
     selectionmodel.cpp
     sizebox.cpp
     textedit.cpp
     selectionmodel.cpp
     sizebox.cpp
     textedit.cpp
index d538925..c0fc4ad 100644 (file)
@@ -150,14 +150,25 @@ LRESULT CCanvasWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
 
     if (hit == HIT_NONE || hit == HIT_BORDER)
     {
 
     if (hit == HIT_NONE || hit == HIT_BORDER)
     {
-        if (toolsModel.GetActiveTool() == TOOL_BEZIER ||
-            toolsModel.GetActiveTool() == TOOL_SHAPE)
+        switch (toolsModel.GetActiveTool())
         {
         {
-            if (ToolBase::pointSP != 0)
-            {
-                toolsModel.OnCancelDraw();
+            case TOOL_BEZIER:
+            case TOOL_SHAPE:
+                if (ToolBase::pointSP != 0)
+                {
+                    toolsModel.OnCancelDraw();
+                    imageArea.Invalidate();
+                }
+                break;
+
+            case TOOL_FREESEL:
+            case TOOL_RECTSEL:
+                toolsModel.OnFinishDraw();
                 imageArea.Invalidate();
                 imageArea.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
index 619133f..0b9890d 100644 (file)
@@ -56,6 +56,5 @@ enum CANVAS_HITTEST // hit
 
 BOOL zoomTo(int newZoom, int mouseX, int mouseY);
 BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1);
 
 BOOL zoomTo(int newZoom, int mouseX, int mouseY);
 BOOL nearlyEqualPoints(INT x0, INT y0, INT x1, INT y1);
-void placeSelWin(void);
 void updateStartAndLast(LONG x, LONG y);
 void updateLast(LONG x, LONG y);
 void updateStartAndLast(LONG x, LONG y);
 void updateLast(LONG x, LONG y);
index 96218a8..f46ef41 100644 (file)
@@ -220,9 +220,13 @@ HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile)
     return hBitmap;
 }
 
     return hBitmap;
 }
 
-HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight)
+HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono)
 {
 {
-    HBITMAP hbm2 = CreateDIBWithProperties(cy, cx);
+    HBITMAP hbm2;
+    if (bMono)
+        hbm2 = ::CreateBitmap(cy, cx, 1, 1, NULL);
+    else
+        hbm2 = CreateDIBWithProperties(cy, cx);
     if (!hbm2)
         return NULL;
 
     if (!hbm2)
         return NULL;
 
index 82ccde6..f9eb7d3 100644 (file)
@@ -28,7 +28,7 @@ void ShowFileLoadError(LPCTSTR name);
 
 HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile);
 
 
 HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile);
 
-HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight);
+HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight, BOOL bMono);
 
 HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical);
 
 
 HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical);
 
index f94da43..86711c0 100644 (file)
@@ -290,33 +290,76 @@ Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCT
 
 BOOL
 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
 
 BOOL
 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
-                  HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask,
-                  DWORD dwRop, COLORREF keyColor)
+                  HDC hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight,
+                  HBITMAP hbmMask, COLORREF keyColor)
 {
 {
-    HDC hTempDC;
-    HDC hTempDC2;
-    HBITMAP hTempBm;
-    HBRUSH hTempBrush;
-    HBITMAP hTempMask;
-
-    hTempDC = CreateCompatibleDC(hdcSrc);
-    hTempDC2 = CreateCompatibleDC(hdcSrc);
-    hTempBm = CreateCompatibleBitmap(hTempDC, nWidth, nHeight);
-    SelectObject(hTempDC, hTempBm);
-    hTempBrush = CreateSolidBrush(keyColor);
-    SelectObject(hTempDC, hTempBrush);
-    BitBlt(hTempDC, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
-    PatBlt(hTempDC, 0, 0, nWidth, nHeight, PATINVERT);
-    hTempMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
-    SelectObject(hTempDC2, hTempMask);
-    BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, 0, 0, SRCCOPY);
-    SelectObject(hTempDC, hbmMask);
-    BitBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC, xMask, yMask, SRCAND);
-    MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, hTempMask, xMask, yMask, dwRop);
-    DeleteDC(hTempDC);
-    DeleteDC(hTempDC2);
-    DeleteObject(hTempBm);
-    DeleteObject(hTempBrush);
-    DeleteObject(hTempMask);
+    HDC hTempDC1, hTempDC2;
+    HBITMAP hbmTempColor, hbmTempMask;
+    HGDIOBJ hbmOld1, hbmOld2;
+
+    if (hbmMask == NULL)
+    {
+        if (keyColor == CLR_INVALID)
+        {
+            ::StretchBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                         hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, SRCCOPY);
+        }
+        else
+        {
+            ::GdiTransparentBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                                hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, keyColor);
+        }
+        return TRUE;
+    }
+    else if (nWidth == nSrcWidth && nHeight == nSrcHeight && keyColor == CLR_INVALID)
+    {
+        ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,
+                  hdcSrc, nXSrc, nYSrc, hbmMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029));
+        return TRUE;
+    }
+
+    hTempDC1 = ::CreateCompatibleDC(hdcDest);
+    hTempDC2 = ::CreateCompatibleDC(hdcDest);
+    hbmTempMask = ::CreateBitmap(nWidth, nHeight, 1, 1, NULL);
+    hbmTempColor = CreateColorDIB(nWidth, nHeight, RGB(255, 255, 255));
+
+    // hbmTempMask <-- hbmMask (stretched)
+    hbmOld1 = ::SelectObject(hTempDC1, hbmMask);
+    hbmOld2 = ::SelectObject(hTempDC2, hbmTempMask);
+    ::StretchBlt(hTempDC2, 0, 0, nWidth, nHeight, hTempDC1, 0, 0, nSrcWidth, nSrcHeight, SRCCOPY);
+    ::SelectObject(hTempDC2, hbmOld2);
+    ::SelectObject(hTempDC1, hbmOld1);
+
+    hbmOld1 = ::SelectObject(hTempDC1, hbmTempColor);
+    if (keyColor == CLR_INVALID)
+    {
+        // hbmTempColor <-- hdcSrc (stretched)
+        ::StretchBlt(hTempDC1, 0, 0, nWidth, nHeight,
+                     hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, SRCCOPY);
+
+        // hdcDest <-- hbmTempColor (masked)
+        ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hTempDC1, 0, 0,
+                  hbmTempMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029));
+    }
+    else
+    {
+        // hbmTempColor <-- hdcDest
+        ::BitBlt(hTempDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
+
+        // hbmTempColor <-- hdcSrc (color key)
+        ::GdiTransparentBlt(hTempDC1, 0, 0, nWidth, nHeight,
+                            hdcSrc, nXSrc, nYSrc, nSrcWidth, nSrcHeight, keyColor);
+
+        // hdcDest <-- hbmTempColor (masked)
+        ::MaskBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hTempDC1, 0, 0,
+                  hbmTempMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0029));
+    }
+    ::SelectObject(hTempDC1, hbmOld1);
+
+    ::DeleteObject(hbmTempColor);
+    ::DeleteObject(hbmTempMask);
+    ::DeleteDC(hTempDC2);
+    ::DeleteDC(hTempDC1);
+
     return TRUE;
 }
     return TRUE;
 }
index 5401168..8fb0f54 100644 (file)
@@ -34,7 +34,7 @@ void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2);
 
 void Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style);
 
 
 void Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style);
 
-extern BOOL
+BOOL
 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
 ColorKeyedMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
-                  HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask,
-                  DWORD dwRop, COLORREF keyColor);
+                  HDC hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight,
+                  HBITMAP hbmMask, COLORREF keyColor);
index fe9e47f..058117f 100644 (file)
@@ -52,6 +52,5 @@ extern CToolBox toolBoxContainer;
 extern CToolSettingsWindow toolSettingsWindow;
 extern CPaletteWindow paletteWindow;
 extern CCanvasWindow canvasWindow;
 extern CToolSettingsWindow toolSettingsWindow;
 extern CPaletteWindow paletteWindow;
 extern CCanvasWindow canvasWindow;
-extern CSelectionWindow selectionWindow;
 extern CImgAreaWindow imageArea;
 extern CTextEditWindow textEditWindow;
 extern CImgAreaWindow imageArea;
 extern CTextEditWindow textEditWindow;
index 847e6c6..0680865 100644 (file)
@@ -64,7 +64,7 @@ void ImageModel::Undo(BOOL bClearRedo)
     {
         int oldWidth = GetWidth();
         int oldHeight = GetHeight();
     {
         int oldWidth = GetWidth();
         int oldHeight = GetHeight();
-        selectionWindow.ShowWindow(SW_HIDE);
+        selectionModel.m_bShow = FALSE;
         currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE;
         SelectObject(hDrawingDC, hBms[currInd]);
         undoSteps--;
         currInd = (currInd + HISTORYSIZE - 1) % HISTORYSIZE;
         SelectObject(hDrawingDC, hBms[currInd]);
         undoSteps--;
@@ -85,7 +85,7 @@ void ImageModel::Redo()
     {
         int oldWidth = GetWidth();
         int oldHeight = GetHeight();
     {
         int oldWidth = GetWidth();
         int oldHeight = GetHeight();
-        selectionWindow.ShowWindow(SW_HIDE);
+        selectionModel.m_bShow = FALSE;
         currInd = (currInd + 1) % HISTORYSIZE;
         SelectObject(hDrawingDC, hBms[currInd]);
         redoSteps--;
         currInd = (currInd + 1) % HISTORYSIZE;
         SelectObject(hDrawingDC, hBms[currInd]);
         redoSteps--;
@@ -264,7 +264,7 @@ void ImageModel::RotateNTimes90Degrees(int iN)
     case 1:
     case 3:
         DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
     case 1:
     case 3:
         DeleteObject(hBms[(currInd + 1) % HISTORYSIZE]);
-        hBms[(currInd + 1) % HISTORYSIZE] = Rotate90DegreeBlt(hDrawingDC, GetWidth(), GetHeight(), iN == 1);
+        hBms[(currInd + 1) % HISTORYSIZE] = Rotate90DegreeBlt(hDrawingDC, GetWidth(), GetHeight(), iN == 1, FALSE);
         currInd = (currInd + 1) % HISTORYSIZE;
         if (undoSteps < HISTORYSIZE - 1)
             undoSteps++;
         currInd = (currInd + 1) % HISTORYSIZE;
         if (undoSteps < HISTORYSIZE - 1)
             undoSteps++;
@@ -282,23 +282,15 @@ void ImageModel::RotateNTimes90Degrees(int iN)
     NotifyImageChanged();
 }
 
     NotifyImageChanged();
 }
 
-void ImageModel::DrawSelectionBackground(COLORREF rgbBG)
-{
-    if (toolsModel.GetActiveTool() == TOOL_FREESEL)
-        selectionModel.DrawBackgroundPoly(hDrawingDC, rgbBG);
-    else
-        selectionModel.DrawBackgroundRect(hDrawingDC, rgbBG);
-}
-
 void ImageModel::DeleteSelection()
 {
 void ImageModel::DeleteSelection()
 {
-    if (selectionWindow.IsWindowVisible())
-        ResetToPrevious();
-    CopyPrevious();
-    if (selectionWindow.IsWindowVisible())
-        Undo(TRUE);
-    DrawSelectionBackground(paletteModel.GetBgColor());
-    selectionWindow.ShowWindow(SW_HIDE);
+    if (!selectionModel.m_bShow)
+        return;
+
+    selectionModel.TakeOff();
+    selectionModel.m_bShow = FALSE;
+    selectionModel.ClearColor();
+    selectionModel.ClearMask();
     NotifyImageChanged();
 }
 
     NotifyImageChanged();
 }
 
index 17ef43b..40792f8 100644 (file)
@@ -45,7 +45,6 @@ public:
     void FlipHorizontally();
     void FlipVertically();
     void RotateNTimes90Degrees(int iN);
     void FlipHorizontally();
     void FlipVertically();
     void RotateNTimes90Degrees(int iN);
-    void DrawSelectionBackground(COLORREF rgbBG);
     void DeleteSelection();
     void Bound(POINT& pt);
 };
     void DeleteSelection();
     void Bound(POINT& pt);
 };
index dfb9345..abae54c 100644 (file)
@@ -21,7 +21,6 @@ LRESULT CImgAreaWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
     m_hCurZoom     = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_ZOOM));
     m_hCurPen      = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_PEN));
     m_hCurAirbrush = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_AIRBRUSH));
     m_hCurZoom     = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_ZOOM));
     m_hCurPen      = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_PEN));
     m_hCurAirbrush = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDC_AIRBRUSH));
-
     return 0;
 }
 
     return 0;
 }
 
@@ -71,49 +70,61 @@ LRESULT CImgAreaWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
 
 LRESULT CImgAreaWindow::OnEraseBkGnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
 
 LRESULT CImgAreaWindow::OnEraseBkGnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    HDC hdc = (HDC)wParam;
-
-    if (toolsModel.GetActiveTool() == TOOL_TEXT && !toolsModel.IsBackgroundTransparent() &&
-        ::IsWindowVisible(textEditWindow))
-    {
-        // Do clipping
-        HWND hChild = textEditWindow;
-        RECT rcChild;
-        ::GetWindowRect(hChild, &rcChild);
-        ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcChild, 2);
-        ExcludeClipRect(hdc, rcChild.left, rcChild.top, rcChild.right, rcChild.bottom);
-    }
-
-    return DefWindowProc(nMsg, wParam, lParam);
+    return TRUE; // Don't fill background
 }
 
 LRESULT CImgAreaWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
 }
 
 LRESULT CImgAreaWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
+    RECT rcClient;
+    GetClientRect(&rcClient);
+
     PAINTSTRUCT ps;
     HDC hdc = BeginPaint(&ps);
     PAINTSTRUCT ps;
     HDC hdc = BeginPaint(&ps);
-    int imgXRes = imageModel.GetWidth();
-    int imgYRes = imageModel.GetHeight();
-    StretchBlt(hdc, 0, 0, Zoomed(imgXRes), Zoomed(imgYRes), imageModel.GetDC(), 0, 0, imgXRes,
-               imgYRes, SRCCOPY);
+
+    // 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))
     {
     if (showGrid && (toolsModel.GetZoom() >= 4000))
     {
-        HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, 0x00a0a0a0));
-        int counter;
-        for(counter = 0; counter <= imgYRes; counter++)
+        HPEN oldPen = (HPEN) SelectObject(hdcMem, CreatePen(PS_SOLID, 1, 0x00a0a0a0));
+        for (int counter = 0; counter <= size.cy; counter++)
         {
         {
-            MoveToEx(hdc, 0, Zoomed(counter), NULL);
-            LineTo(hdc, Zoomed(imgXRes), Zoomed(counter));
+            ::MoveToEx(hdcMem, 0, ::Zoomed(counter), NULL);
+            ::LineTo(hdcMem, ::Zoomed(size.cx), ::Zoomed(counter));
         }
         }
-        for(counter = 0; counter <= imgXRes; counter++)
+        for (int counter = 0; counter <= size.cx; counter++)
         {
         {
-            MoveToEx(hdc, Zoomed(counter), 0, NULL);
-            LineTo(hdc, Zoomed(counter), Zoomed(imgYRes));
+            ::MoveToEx(hdcMem, ::Zoomed(counter), 0, NULL);
+            ::LineTo(hdcMem, ::Zoomed(counter), ::Zoomed(size.cy));
         }
         }
-        DeleteObject(SelectObject(hdc, oldPen));
+        ::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);
     EndPaint(&ps);
-    if (selectionWindow.IsWindow())
-        selectionWindow.Invalidate(FALSE);
+
     if (miniature.IsWindow())
         miniature.Invalidate(FALSE);
     if (textEditWindow.IsWindow())
     if (miniature.IsWindow())
         miniature.Invalidate(FALSE);
     if (textEditWindow.IsWindow())
@@ -121,8 +132,57 @@ LRESULT CImgAreaWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& b
     return 0;
 }
 
     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)
 {
 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:
     switch (toolsModel.GetActiveTool())
     {
         case TOOL_FILL:
@@ -148,20 +208,31 @@ LRESULT CImgAreaWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
 
 LRESULT CImgAreaWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
 
 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();
     drawing = TRUE;
     SetCapture();
-    INT x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
-    toolsModel.OnButtonDown(TRUE, UnZoomed(x), UnZoomed(y), FALSE);
+    toolsModel.OnButtonDown(TRUE, pt.x, pt.y, FALSE);
     Invalidate(FALSE);
     return 0;
 }
 
 LRESULT CImgAreaWindow::OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
     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();
     drawing = FALSE;
     ReleaseCapture();
-    INT x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
-    toolsModel.OnButtonDown(TRUE, UnZoomed(x), UnZoomed(y), TRUE);
+    toolsModel.OnButtonDown(TRUE, pt.x, pt.y, TRUE);
     toolsModel.resetTool();
     Invalidate(FALSE);
     return 0;
     toolsModel.resetTool();
     Invalidate(FALSE);
     return 0;
@@ -169,20 +240,22 @@ LRESULT CImgAreaWindow::OnLButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam,
 
 LRESULT CImgAreaWindow::OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
 
 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();
     drawing = TRUE;
     SetCapture();
-    INT x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
-    toolsModel.OnButtonDown(FALSE, UnZoomed(x), UnZoomed(y), FALSE);
+    toolsModel.OnButtonDown(FALSE, pt.x, pt.y, FALSE);
     Invalidate(FALSE);
     return 0;
 }
 
 LRESULT CImgAreaWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
     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();
     drawing = FALSE;
     ReleaseCapture();
-    INT x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
-    toolsModel.OnButtonDown(FALSE, UnZoomed(x), UnZoomed(y), TRUE);
+    toolsModel.OnButtonDown(FALSE, pt.x, pt.y, TRUE);
     toolsModel.resetTool();
     Invalidate(FALSE);
     return 0;
     toolsModel.resetTool();
     Invalidate(FALSE);
     return 0;
@@ -190,20 +263,28 @@ LRESULT CImgAreaWindow::OnRButtonDblClk(UINT nMsg, WPARAM wParam, LPARAM lParam,
 
 LRESULT CImgAreaWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
 
 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;
     if (drawing)
     {
         drawing = FALSE;
-        INT x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
-        toolsModel.OnButtonUp(TRUE, UnZoomed(x), UnZoomed(y));
+        toolsModel.OnButtonUp(TRUE, pt.x, pt.y);
         Invalidate(FALSE);
         SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
     }
         Invalidate(FALSE);
         SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
     }
+    else if (m_hitSelection != HIT_NONE)
+    {
+        EndSelectionDrag(pt);
+    }
     ReleaseCapture();
     return 0;
 }
 
 void CImgAreaWindow::cancelDrawing()
 {
     ReleaseCapture();
     return 0;
 }
 
 void CImgAreaWindow::cancelDrawing()
 {
+    selectionModel.ClearColor();
+    selectionModel.ClearMask();
+    m_hitSelection = HIT_NONE;
     drawing = FALSE;
     toolsModel.OnCancelDraw();
     Invalidate(FALSE);
     drawing = FALSE;
     toolsModel.OnCancelDraw();
     Invalidate(FALSE);
@@ -226,7 +307,7 @@ LRESULT CImgAreaWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
         }
         else
         {
         }
         else
         {
-            if (drawing || ToolBase::pointSP != 0 || selectionWindow.IsWindowVisible())
+            if (drawing || ToolBase::pointSP != 0 || selectionModel.m_bShow)
                 cancelDrawing();
         }
     }
                 cancelDrawing();
         }
     }
@@ -235,22 +316,34 @@ LRESULT CImgAreaWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
 
 LRESULT CImgAreaWindow::OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
 
 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;
     if (drawing)
     {
         drawing = FALSE;
-        INT x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
-        toolsModel.OnButtonUp(FALSE, UnZoomed(x), UnZoomed(y));
+        toolsModel.OnButtonUp(FALSE, pt.x, pt.y);
         Invalidate(FALSE);
         SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
     }
         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)
 {
     ReleaseCapture();
     return 0;
 }
 
 LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    LONG xNow = UnZoomed(GET_X_LPARAM(lParam));
-    LONG yNow = UnZoomed(GET_Y_LPARAM(lParam));
+    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 ((!drawing) || (toolsModel.GetActiveTool() <= TOOL_AIRBRUSH))
     {
         TRACKMOUSEEVENT tme;
@@ -271,26 +364,26 @@ LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         if (!drawing)
         {
             CString strCoord;
         if (!drawing)
         {
             CString strCoord;
-            strCoord.Format(_T("%ld, %ld"), xNow, yNow);
+            strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
             SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
         }
     }
     if (drawing)
     {
         /* values displayed in statusbar */
             SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
         }
     }
     if (drawing)
     {
         /* values displayed in statusbar */
-        LONG xRel = xNow - start.x;
-        LONG yRel = yNow - start.y;
+        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)
         /* 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 = (xNow < 0) ? -start.x : xRel;
-            else if (xNow > imageModel.GetWidth())
+                xRel = (pt.x < 0) ? -start.x : xRel;
+            else if (pt.x > imageModel.GetWidth())
                 xRel = imageModel.GetWidth() - start.x;
             if (yRel < 0)
                 xRel = imageModel.GetWidth() - start.x;
             if (yRel < 0)
-                yRel = (yNow < 0) ? -start.y : yRel;
-            else if (yNow > imageModel.GetHeight())
-                 yRel = imageModel.GetHeight() - start.y;
+                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))
         }
         /* rectsel and shape tools always show non-negative numbers when drawing */
         if ((toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_SHAPE))
@@ -310,7 +403,7 @@ LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
             case TOOL_SHAPE:
             {
                 CString strCoord;
             case TOOL_SHAPE:
             {
                 CString strCoord;
-                strCoord.Format(_T("%ld, %ld"), xNow, yNow);
+                strCoord.Format(_T("%ld, %ld"), pt.x, pt.y);
                 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
                 break;
             }
                 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
                 break;
             }
@@ -319,7 +412,7 @@ LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         }
         if (wParam & MK_LBUTTON)
         {
         }
         if (wParam & MK_LBUTTON)
         {
-            toolsModel.OnMouseMove(TRUE, xNow, yNow);
+            toolsModel.OnMouseMove(TRUE, pt.x, pt.y);
             Invalidate(FALSE);
             if ((toolsModel.GetActiveTool() >= TOOL_TEXT) || (toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_FREESEL))
             {
             Invalidate(FALSE);
             if ((toolsModel.GetActiveTool() >= TOOL_TEXT) || (toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_FREESEL))
             {
@@ -332,7 +425,7 @@ LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
         }
         if (wParam & MK_RBUTTON)
         {
         }
         if (wParam & MK_RBUTTON)
         {
-            toolsModel.OnMouseMove(FALSE, xNow, yNow);
+            toolsModel.OnMouseMove(FALSE, pt.x, pt.y);
             Invalidate(FALSE);
             if (toolsModel.GetActiveTool() >= TOOL_TEXT)
             {
             Invalidate(FALSE);
             if (toolsModel.GetActiveTool() >= TOOL_TEXT)
             {
index daef656..941424d 100644 (file)
 class CImgAreaWindow : public CWindowImpl<CImgAreaWindow>
 {
 public:
 class CImgAreaWindow : public CWindowImpl<CImgAreaWindow>
 {
 public:
-    CImgAreaWindow() : drawing(FALSE) { }
+    CImgAreaWindow()
+        : drawing(FALSE)
+        , m_hitSelection(HIT_NONE)
+    {
+    }
 
     BOOL drawing;
 
     BOOL drawing;
+    CANVAS_HITTEST m_hitSelection;
+
     void cancelDrawing();
     void finishDrawing();
 
     void cancelDrawing();
     void finishDrawing();
 
@@ -71,4 +77,8 @@ private:
     LRESULT OnCtlColorEdit(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 
     void drawZoomFrame(int mouseX, int mouseY);
     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);
 };
 };
index 57f2894..5d1c4fc 100644 (file)
@@ -16,20 +16,6 @@ POINT ToolBase::pointStack[256] = { { 0 } };
 
 /* FUNCTIONS ********************************************************/
 
 
 /* FUNCTIONS ********************************************************/
 
-void
-placeSelWin()
-{
-    CRect rc;
-    rc.left = Zoomed(selectionModel.GetDestRectLeft());
-    rc.top = Zoomed(selectionModel.GetDestRectTop());
-    rc.right = rc.left + Zoomed(selectionModel.GetDestRectWidth());
-    rc.bottom = rc.top + Zoomed(selectionModel.GetDestRectHeight());
-    ::InflateRect(&rc, GRIP_SIZE, GRIP_SIZE);
-    selectionWindow.MoveWindow(rc.left, rc.top, rc.Width(), rc.Height(), TRUE);
-    selectionWindow.BringWindowToTop();
-    imageArea.InvalidateRect(NULL, FALSE);
-}
-
 void
 regularize(LONG x0, LONG y0, LONG& x1, LONG& y1)
 {
 void
 regularize(LONG x0, LONG y0, LONG& x1, LONG& y1)
 {
@@ -82,8 +68,11 @@ void ToolBase::reset()
     pointSP = 0;
     start.x = start.y = last.x = last.y = -1;
     selectionModel.ResetPtStack();
     pointSP = 0;
     start.x = start.y = last.x = last.y = -1;
     selectionModel.ResetPtStack();
-    if (selectionWindow.IsWindow())
-        selectionWindow.ShowWindow(SW_HIDE);
+    if (selectionModel.m_bShow)
+    {
+        selectionModel.Landing();
+        selectionModel.m_bShow = FALSE;
+    }
 }
 
 void ToolBase::OnCancelDraw()
 }
 
 void ToolBase::OnCancelDraw()
@@ -121,12 +110,14 @@ struct FreeSelTool : ToolBase
 
     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
     {
 
     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
     {
+        selectionModel.Landing();
         if (bLeftButton)
         {
             imageModel.CopyPrevious();
         if (bLeftButton)
         {
             imageModel.CopyPrevious();
-            selectionWindow.ShowWindow(SW_HIDE);
+            selectionModel.m_bShow = FALSE;
             selectionModel.ResetPtStack();
             selectionModel.ResetPtStack();
-            selectionModel.PushToPtStack(x, y);
+            POINT pt = { x, y };
+            selectionModel.PushToPtStack(pt);
         }
         m_bLeftButton = bLeftButton;
     }
         }
         m_bLeftButton = bLeftButton;
     }
@@ -137,7 +128,7 @@ struct FreeSelTool : ToolBase
         {
             POINT pt = { x, y };
             imageModel.Bound(pt);
         {
             POINT pt = { x, y };
             imageModel.Bound(pt);
-            selectionModel.PushToPtStack(pt.x, pt.y);
+            selectionModel.PushToPtStack(pt);
             imageModel.ResetToPrevious();
             selectionModel.DrawFramePoly(m_hdc);
         }
             imageModel.ResetToPrevious();
             selectionModel.DrawFramePoly(m_hdc);
         }
@@ -150,28 +141,25 @@ struct FreeSelTool : ToolBase
             imageModel.ResetToPrevious();
             if (selectionModel.PtStackSize() > 2)
             {
             imageModel.ResetToPrevious();
             if (selectionModel.PtStackSize() > 2)
             {
-                selectionModel.CalculateBoundingBoxAndContents(m_hdc);
-                placeSelWin();
-                selectionWindow.IsMoved(FALSE);
-                selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
+                selectionModel.BuildMaskFromPtStack();
+                selectionModel.TakeOff();
+                selectionModel.m_bShow = TRUE;
             }
             else
             {
                 imageModel.Undo(TRUE);
             }
             else
             {
                 imageModel.Undo(TRUE);
-                selectionWindow.IsMoved(FALSE);
                 selectionModel.ResetPtStack();
                 selectionModel.ResetPtStack();
-                selectionWindow.ShowWindow(SW_HIDE);
+                selectionModel.m_bShow = FALSE;
             }
             }
+            imageArea.Invalidate(FALSE);
         }
     }
 
     void OnFinishDraw()
     {
         if (m_bLeftButton)
         }
     }
 
     void OnFinishDraw()
     {
         if (m_bLeftButton)
-        {
-            selectionWindow.IsMoved(FALSE);
-            selectionWindow.ForceRefreshSelectionContents();
-        }
+            imageArea.Invalidate(FALSE);
+
         m_bLeftButton = FALSE;
         ToolBase::OnFinishDraw();
     }
         m_bLeftButton = FALSE;
         ToolBase::OnFinishDraw();
     }
@@ -181,7 +169,6 @@ struct FreeSelTool : ToolBase
         if (m_bLeftButton)
             imageModel.Undo(TRUE);
         m_bLeftButton = FALSE;
         if (m_bLeftButton)
             imageModel.Undo(TRUE);
         m_bLeftButton = FALSE;
-        selectionWindow.IsMoved(FALSE);
         ToolBase::OnCancelDraw();
     }
 };
         ToolBase::OnCancelDraw();
     }
 };
@@ -197,11 +184,12 @@ struct RectSelTool : ToolBase
 
     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
     {
 
     void OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
     {
+        selectionModel.Landing();
         if (bLeftButton)
         {
             imageModel.CopyPrevious();
         if (bLeftButton)
         {
             imageModel.CopyPrevious();
-            selectionWindow.ShowWindow(SW_HIDE);
-            selectionModel.SetSrcRectSizeToZero();
+            selectionModel.m_bShow = FALSE;
+            ::SetRectEmpty(&selectionModel.m_rc);
         }
         m_bLeftButton = bLeftButton;
     }
         }
         m_bLeftButton = bLeftButton;
     }
@@ -213,7 +201,7 @@ struct RectSelTool : ToolBase
             imageModel.ResetToPrevious();
             POINT pt = { x, y };
             imageModel.Bound(pt);
             imageModel.ResetToPrevious();
             POINT pt = { x, y };
             imageModel.Bound(pt);
-            selectionModel.SetSrcAndDestRectFromPoints(start, pt);
+            selectionModel.SetRectFromPoints(start, pt);
             RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
         }
     }
             RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
         }
     }
@@ -225,23 +213,16 @@ struct RectSelTool : ToolBase
             imageModel.ResetToPrevious();
             if (start.x == x && start.y == y)
                 imageModel.Undo(TRUE);
             imageModel.ResetToPrevious();
             if (start.x == x && start.y == y)
                 imageModel.Undo(TRUE);
-            selectionModel.CalculateContents(m_hdc);
-            placeSelWin();
-            selectionWindow.IsMoved(FALSE);
-            if (selectionModel.IsSrcRectSizeNonzero())
-                selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
-            else
-                selectionWindow.ShowWindow(SW_HIDE);
+            selectionModel.m_bShow = !selectionModel.m_rc.IsRectEmpty();
+            imageArea.Invalidate(FALSE);
         }
     }
 
     void OnFinishDraw()
     {
         if (m_bLeftButton)
         }
     }
 
     void OnFinishDraw()
     {
         if (m_bLeftButton)
-        {
-            selectionWindow.IsMoved(FALSE);
-            selectionWindow.ForceRefreshSelectionContents();
-        }
+            imageArea.Invalidate(FALSE);
+
         m_bLeftButton = FALSE;
         ToolBase::OnFinishDraw();
     }
         m_bLeftButton = FALSE;
         ToolBase::OnFinishDraw();
     }
@@ -251,7 +232,6 @@ struct RectSelTool : ToolBase
         if (m_bLeftButton)
             imageModel.Undo(TRUE);
         m_bLeftButton = FALSE;
         if (m_bLeftButton)
             imageModel.Undo(TRUE);
         m_bLeftButton = FALSE;
-        selectionWindow.IsMoved(FALSE);
         ToolBase::OnCancelDraw();
     }
 };
         ToolBase::OnCancelDraw();
     }
 };
@@ -430,7 +410,7 @@ struct TextTool : ToolBase
         imageModel.ResetToPrevious();
         POINT pt = { x, y };
         imageModel.Bound(pt);
         imageModel.ResetToPrevious();
         POINT pt = { x, y };
         imageModel.Bound(pt);
-        selectionModel.SetSrcAndDestRectFromPoints(start, pt);
+        selectionModel.SetRectFromPoints(start, pt);
         RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
     }
 
         RectSel(m_hdc, start.x, start.y, pt.x, pt.y);
     }
 
@@ -452,6 +432,10 @@ struct TextTool : ToolBase
     {
         imageModel.Undo(TRUE);
 
     {
         imageModel.Undo(TRUE);
 
+        POINT pt = { x, y };
+        imageModel.Bound(pt);
+        selectionModel.SetRectFromPoints(start, pt);
+
         BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow);
         if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0)
         {
         BOOL bTextBoxShown = ::IsWindowVisible(textEditWindow);
         if (bTextBoxShown && textEditWindow.GetWindowTextLength() > 0)
         {
@@ -466,6 +450,13 @@ struct TextTool : ToolBase
             imageModel.CopyPrevious();
             Text(m_hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText,
                  textEditWindow.GetFont(), style);
             imageModel.CopyPrevious();
             Text(m_hdc, rc.left, rc.top, rc.right, rc.bottom, m_fg, m_bg, szText,
                  textEditWindow.GetFont(), style);
+
+            if (selectionModel.m_rc.IsRectEmpty())
+            {
+                textEditWindow.ShowWindow(SW_HIDE);
+                textEditWindow.SetWindowText(NULL);
+                return;
+            }
         }
 
         if (registrySettings.ShowTextTool)
         }
 
         if (registrySettings.ShowTextTool)
@@ -476,45 +467,35 @@ struct TextTool : ToolBase
             fontsDialog.ShowWindow(SW_SHOWNOACTIVATE);
         }
 
             fontsDialog.ShowWindow(SW_SHOWNOACTIVATE);
         }
 
-        if (!bTextBoxShown || selectionModel.IsSrcRectSizeNonzero())
-        {
-            RECT rc;
-            selectionModel.GetRect(&rc);
+        RECT rc = selectionModel.m_rc;
 
 
-            // Enlarge if tool small
-            INT cxMin = CX_MINTEXTEDIT, cyMin = CY_MINTEXTEDIT;
-            if (selectionModel.IsSrcRectSizeNonzero())
-            {
-                if (rc.right - rc.left < cxMin)
-                    rc.right = rc.left + cxMin;
-                if (rc.bottom - rc.top < cyMin)
-                    rc.bottom = rc.top + cyMin;
-            }
-            else
-            {
-                SetRect(&rc, x, y, x + cxMin, y + cyMin);
-            }
-
-            if (!textEditWindow.IsWindow())
-                textEditWindow.Create(imageArea);
-
-            textEditWindow.SetWindowText(NULL);
-            textEditWindow.ValidateEditRect(&rc);
-            textEditWindow.ShowWindow(SW_SHOWNOACTIVATE);
-            textEditWindow.SetFocus();
+        // Enlarge if tool small
+        INT cxMin = CX_MINTEXTEDIT, cyMin = CY_MINTEXTEDIT;
+        if (selectionModel.m_rc.IsRectEmpty())
+        {
+            SetRect(&rc, x, y, x + cxMin, y + cyMin);
         }
         else
         {
         }
         else
         {
-            textEditWindow.ShowWindow(SW_HIDE);
-            textEditWindow.SetWindowText(NULL);
+            if (rc.right - rc.left < cxMin)
+                rc.right = rc.left + cxMin;
+            if (rc.bottom - rc.top < cyMin)
+                rc.bottom = rc.top + cyMin;
         }
         }
+
+        if (!textEditWindow.IsWindow())
+            textEditWindow.Create(imageArea);
+
+        textEditWindow.SetWindowText(NULL);
+        textEditWindow.ValidateEditRect(&rc);
+        textEditWindow.ShowWindow(SW_SHOWNOACTIVATE);
+        textEditWindow.SetFocus();
     }
 
     void OnFinishDraw()
     {
         toolsModel.OnButtonDown(TRUE, -1, -1, TRUE);
         toolsModel.OnButtonUp(TRUE, -1, -1);
     }
 
     void OnFinishDraw()
     {
         toolsModel.OnButtonDown(TRUE, -1, -1, TRUE);
         toolsModel.OnButtonUp(TRUE, -1, -1);
-        selectionWindow.IsMoved(FALSE);
         ToolBase::OnFinishDraw();
     }
 };
         ToolBase::OnFinishDraw();
     }
 };
index b4ae440..cf920bc 100644 (file)
@@ -97,8 +97,8 @@ void PaletteModel::NotifyColorChanged()
 {
     if (paletteWindow.IsWindow())
         paletteWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
 {
     if (paletteWindow.IsWindow())
         paletteWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
-    if (selectionWindow.IsWindow())
-        selectionWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
+    if (imageArea.IsWindow())
+        imageArea.SendMessage(WM_PALETTEMODELCOLORCHANGED);
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
 }
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_PALETTEMODELCOLORCHANGED);
 }
index 5dda7a9..ae4e584 100644 (file)
@@ -43,7 +43,6 @@
 #include "palette.h"
 #include "palettemodel.h"
 #include "registry.h"
 #include "palette.h"
 #include "palettemodel.h"
 #include "registry.h"
-#include "selection.h"
 #include "selectionmodel.h"
 #include "sizebox.h"
 #include "canvas.h"
 #include "selectionmodel.h"
 #include "sizebox.h"
 #include "canvas.h"
diff --git a/base/applications/mspaint/selection.cpp b/base/applications/mspaint/selection.cpp
deleted file mode 100644 (file)
index 1426e08..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * PROJECT:     PAINT for ReactOS
- * LICENSE:     LGPL
- * FILE:        base/applications/mspaint/selection.cpp
- * PURPOSE:     Window procedure of the selection window
- * PROGRAMMERS: Benedikt Freisen
- *              Katayama Hirofumi MZ
- */
-
-#include "precomp.h"
-
-CSelectionWindow selectionWindow;
-
-/* FUNCTIONS ********************************************************/
-
-const LPCTSTR CSelectionWindow::m_lpszCursorLUT[9] = { /* action to mouse cursor lookup table */
-    IDC_SIZEALL,
-
-    IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
-    IDC_SIZEWE,               IDC_SIZEWE,
-    IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE
-};
-
-void CSelectionWindow::ForceRefreshSelectionContents()
-{
-    if (::IsWindowVisible(selectionWindow))
-    {
-        imageModel.ResetToPrevious();
-        imageModel.DrawSelectionBackground(m_rgbBack);
-        selectionModel.DrawSelection(imageModel.GetDC(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
-    }
-}
-
-int CSelectionWindow::IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight)
-{
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    PAINTSTRUCT ps;
-    HDC hDC = BeginPaint(&ps);
-    if (!m_bMoving)
-    {
-        RECT rcClient;
-        GetClientRect(&rcClient);
-        drawSizeBoxes(hDC, &rcClient, TRUE, &ps.rcPaint);
-    }
-    EndPaint(&ps);
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    // do nothing => transparent background
-    return TRUE;
-}
-
-LRESULT CSelectionWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    m_bMoving = FALSE;
-    m_iAction = ACTION_MOVE;
-    /* update the system selection color */
-    Invalidate();
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    /* update the system selection color */
-    Invalidate();
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    RECT rcClient;
-    GetClientRect(&rcClient);
-
-    POINT pt;
-    ::GetCursorPos(&pt);
-    ScreenToClient(&pt);
-
-    if (!setCursorOnSizeBox(getSizeBoxHitTest(pt, &rcClient)))
-        ::SetCursor(::LoadCursor(NULL, IDC_SIZEALL));
-
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    m_ptPos.x = GET_X_LPARAM(lParam);
-    m_ptPos.y = GET_Y_LPARAM(lParam);
-    m_ptDelta.x = 0;
-    m_ptDelta.y = 0;
-    SetCapture();
-    if (m_iAction != ACTION_MOVE)
-        SetCursor(LoadCursor(NULL, m_lpszCursorLUT[m_iAction]));
-    m_bMoving = TRUE;
-    imageArea.InvalidateRect(NULL, FALSE);
-    imageArea.SendMessage(WM_PAINT, 0, 0);
-    m_rgbBack = paletteModel.GetBgColor();
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    if (m_bMoving)
-    {
-        imageModel.ResetToPrevious();
-        imageModel.DrawSelectionBackground(m_rgbBack);
-        m_ptFrac.x += GET_X_LPARAM(lParam) - m_ptPos.x;
-        m_ptFrac.y += GET_Y_LPARAM(lParam) - m_ptPos.y;
-        m_ptDelta.x += UnZoomed(m_ptFrac.x);
-        m_ptDelta.y += UnZoomed(m_ptFrac.y);
-        if (toolsModel.GetZoom() < 1000)
-        {
-            m_ptFrac.x = 0;
-            m_ptFrac.y = 0;
-        }
-        else
-        {
-            m_ptFrac.x -= Zoomed(UnZoomed(m_ptFrac.x));
-            m_ptFrac.y -= Zoomed(UnZoomed(m_ptFrac.y));
-        }
-        selectionModel.ModifyDestRect(m_ptDelta, m_iAction);
-
-        CString strSize;
-        strSize.Format(_T("%ld x %ld"), selectionModel.GetDestRectWidth(), selectionModel.GetDestRectHeight());
-        SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
-
-        if (m_iAction != ACTION_MOVE)
-            selectionModel.DrawSelectionStretched(imageModel.GetDC());
-        else
-            selectionModel.DrawSelection(imageModel.GetDC(), paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
-        imageArea.InvalidateRect(NULL, FALSE);
-        imageArea.SendMessage(WM_PAINT, 0, 0);
-        m_ptPos.x = GET_X_LPARAM(lParam);
-        m_ptPos.y = GET_Y_LPARAM(lParam);
-    }
-    else
-    {
-        int w = Zoomed(selectionModel.GetDestRectWidth()) + 2 * GRIP_SIZE;
-        int h = Zoomed(selectionModel.GetDestRectHeight()) + 2 * GRIP_SIZE;
-        m_ptPos.x = GET_X_LPARAM(lParam);
-        m_ptPos.y = GET_Y_LPARAM(lParam);
-        SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) NULL);
-        m_iAction = IdentifyCorner(m_ptPos.x, m_ptPos.y, w, h);
-        if (m_iAction != ACTION_MOVE)
-            SetCursor(LoadCursor(NULL, m_lpszCursorLUT[m_iAction]));
-    }
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    m_bMoved = TRUE;
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    if (m_bMoving)
-    {
-        m_bMoving = FALSE;
-        ReleaseCapture();
-        if (m_iAction != ACTION_MOVE && toolsModel.GetActiveTool() != TOOL_TEXT)
-        {
-            imageModel.Undo();
-            imageModel.DrawSelectionBackground(m_rgbBack);
-            selectionModel.ScaleContentsToFit();
-            imageModel.CopyPrevious();
-        }
-        placeSelWin();
-    }
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    if (m_bMoving)
-    {
-        m_bMoving = FALSE;
-        if (m_iAction == ACTION_MOVE)
-        {
-            if (toolsModel.GetActiveTool() == TOOL_RECTSEL)
-                imageArea.cancelDrawing();
-            else
-                placeSelWin();
-        }
-        else
-        {
-            m_iAction = ACTION_MOVE;
-        }
-        ShowWindow(SW_HIDE);
-    }
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    if (wParam == VK_ESCAPE)
-    {
-        if (GetCapture() == m_hWnd)
-        {
-            ReleaseCapture();
-        }
-    }
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnToolsModelSettingsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnSelectionModelRefreshNeeded(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    ForceRefreshSelectionContents();
-    return 0;
-}
-
-LRESULT CSelectionWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    return ::SendMessage(GetParent(), nMsg, wParam, lParam);
-}
-
-LRESULT CSelectionWindow::OnToolsModelZoomChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    placeSelWin();
-    return 0;
-}
diff --git a/base/applications/mspaint/selection.h b/base/applications/mspaint/selection.h
deleted file mode 100644 (file)
index 8e61b77..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * PROJECT:     PAINT for ReactOS
- * LICENSE:     LGPL
- * FILE:        base/applications/mspaint/selection.h
- * PURPOSE:     Window procedure of the selection window
- * PROGRAMMERS: Benedikt Freisen
- *              Katayama Hirofumi MZ
- */
-
-#pragma once
-
-class CSelectionWindow : public CWindowImpl<CSelectionWindow>
-{
-public:
-    CSelectionWindow() : m_bMoved(FALSE)
-    {
-    }
-
-    BOOL IsMoved() const        { return m_bMoved; }
-    void IsMoved(BOOL bMoved)   { m_bMoved = bMoved; }
-
-    void ForceRefreshSelectionContents();
-
-    DECLARE_WND_CLASS_EX(_T("Selection"), CS_DBLCLKS, COLOR_BTNFACE)
-
-    BEGIN_MSG_MAP(CSelectionWindow)
-        MESSAGE_HANDLER(WM_PAINT, OnPaint)
-        MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
-        MESSAGE_HANDLER(WM_CREATE, OnCreate)
-        MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange)
-        MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
-        MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
-        MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
-        MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
-        MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
-        MESSAGE_HANDLER(WM_MOVE, OnMove)
-        MESSAGE_HANDLER(WM_PALETTEMODELCOLORCHANGED, OnPaletteModelColorChanged)
-        MESSAGE_HANDLER(WM_TOOLSMODELSETTINGSCHANGED, OnToolsModelSettingsChanged)
-        MESSAGE_HANDLER(WM_TOOLSMODELZOOMCHANGED, OnToolsModelZoomChanged)
-        MESSAGE_HANDLER(WM_SELECTIONMODELREFRESHNEEDED, OnSelectionModelRefreshNeeded)
-        MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
-        MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
-    END_MSG_MAP()
-
-    LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnSysColorChange(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 OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnPaletteModelColorChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnToolsModelSettingsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnToolsModelZoomChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-    LRESULT OnSelectionModelRefreshNeeded(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 OnMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
-
-private:
-    static const LPCTSTR m_lpszCursorLUT[9];
-    BOOL m_bMoved;
-    BOOL m_bMoving;
-    int m_iAction;
-    POINT m_ptPos;
-    POINT m_ptFrac;
-    POINT m_ptDelta;
-    COLORREF m_rgbBack;
-
-    int IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight);
-};
-
-void ForceRefreshSelectionContents();
index 2079f7a..f7c61d1 100644 (file)
@@ -14,225 +14,295 @@ SelectionModel selectionModel;
 /* FUNCTIONS ********************************************************/
 
 SelectionModel::SelectionModel()
 /* FUNCTIONS ********************************************************/
 
 SelectionModel::SelectionModel()
-    : m_hDC(CreateCompatibleDC(NULL))
-    , m_hBm(NULL)
-    , m_hMask(NULL)
+    : m_hbmColor(NULL)
+    , m_hbmMask(NULL)
     , m_ptStack(NULL)
     , m_iPtSP(0)
     , m_ptStack(NULL)
     , m_iPtSP(0)
+    , m_bShow(FALSE)
 {
 {
-    SetRectEmpty(&m_rcSrc);
-    SetRectEmpty(&m_rcDest);
+    ::SetRectEmpty(&m_rc);
+    m_ptHit.x = m_ptHit.y = -1;
 }
 
 SelectionModel::~SelectionModel()
 {
 }
 
 SelectionModel::~SelectionModel()
 {
-    DeleteDC(m_hDC);
+    ClearColor();
+    ClearMask();
     ResetPtStack();
     ResetPtStack();
-    if (m_hBm)
-    {
-        DeleteObject(m_hBm);
-    }
-    if (m_hMask)
-    {
-        DeleteObject(m_hMask);
-    }
 }
 
 void SelectionModel::ResetPtStack()
 {
 }
 
 void SelectionModel::ResetPtStack()
 {
-    if (m_ptStack != NULL)
-        HeapFree(GetProcessHeap(), 0, m_ptStack);
-    m_ptStack = NULL;
+    if (m_ptStack)
+    {
+        free(m_ptStack);
+        m_ptStack = NULL;
+    }
     m_iPtSP = 0;
 }
 
     m_iPtSP = 0;
 }
 
-void SelectionModel::PushToPtStack(LONG x, LONG y)
+void SelectionModel::PushToPtStack(POINT pt)
 {
 {
-    if (m_iPtSP % 1024 == 0)
+#define GROW_COUNT 256
+    if (m_iPtSP % GROW_COUNT == 0)
     {
     {
-        if (m_ptStack)
-            m_ptStack = (POINT*) HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, m_ptStack, sizeof(POINT) * (m_iPtSP + 1024));
-        else
-            m_ptStack = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * 1024);
+        INT nNewCount = m_iPtSP + GROW_COUNT;
+        LPPOINT pptNew = (LPPOINT)realloc(m_ptStack, sizeof(POINT) * nNewCount);
+        if (pptNew == NULL)
+            return;
+        m_ptStack = pptNew;
     }
     }
-    m_ptStack[m_iPtSP].x = x;
-    m_ptStack[m_iPtSP].y = y;
+    m_ptStack[m_iPtSP] = pt;
     m_iPtSP++;
     m_iPtSP++;
+#undef GROW_COUNT
 }
 
 }
 
-void SelectionModel::CalculateBoundingBoxAndContents(HDC hDCImage)
+void SelectionModel::ShiftPtStack(BOOL bPlus)
 {
 {
-    int i;
-    m_rcSrc.left = m_rcSrc.top = MAXLONG;
-    m_rcSrc.right = m_rcSrc.bottom = 0;
-    for (i = 0; i < m_iPtSP; i++)
+    if (bPlus)
     {
     {
-        if (m_ptStack[i].x < m_rcSrc.left)
-            m_rcSrc.left = m_ptStack[i].x;
-        if (m_ptStack[i].y < m_rcSrc.top)
-            m_rcSrc.top = m_ptStack[i].y;
-        if (m_ptStack[i].x > m_rcSrc.right)
-            m_rcSrc.right = m_ptStack[i].x;
-        if (m_ptStack[i].y > m_rcSrc.bottom)
-            m_rcSrc.bottom = m_ptStack[i].y;
+        for (INT i = 0; i < m_iPtSP; ++i)
+        {
+            POINT& pt = m_ptStack[i];
+            pt.x += m_rc.left;
+            pt.y += m_rc.top;
+        }
     }
     }
-    m_rcSrc.right  += 1;
-    m_rcSrc.bottom += 1;
-    m_rcDest.left   = m_rcSrc.left;
-    m_rcDest.top    = m_rcSrc.top;
-    m_rcDest.right  = m_rcSrc.right;
-    m_rcDest.bottom = m_rcSrc.bottom;
-
-    if (m_iPtSP > 1)
+    else
     {
     {
-        DeleteObject(m_hMask);
-        m_hMask = CreateBitmap(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 1, 1, NULL);
-        DeleteObject(SelectObject(m_hDC, m_hMask));
-        POINT *m_ptStackCopy = (POINT*) HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(POINT) * m_iPtSP);
-        for (i = 0; i < m_iPtSP; i++)
+        for (INT i = 0; i < m_iPtSP; ++i)
         {
         {
-            m_ptStackCopy[i].x = m_ptStack[i].x - m_rcSrc.left;
-            m_ptStackCopy[i].y = m_ptStack[i].y - m_rcSrc.top;
+            POINT& pt = m_ptStack[i];
+            pt.x -= m_rc.left;
+            pt.y -= m_rc.top;
         }
         }
-        Poly(m_hDC, m_ptStackCopy, m_iPtSP, 0x00ffffff, 0x00ffffff, 1, 2, TRUE, FALSE);
-        HeapFree(GetProcessHeap(), 0, m_ptStackCopy);
-        SelectObject(m_hDC, m_hBm = CreateDIBWithProperties(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc)));
-        imageModel.ResetToPrevious();
-        MaskBlt(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), hDCImage, m_rcSrc.left,
-                m_rcSrc.top, m_hMask, 0, 0, MAKEROP4(SRCCOPY, WHITENESS));
     }
 }
 
     }
 }
 
-void SelectionModel::CalculateContents(HDC hDCImage)
+void SelectionModel::BuildMaskFromPtStack()
 {
 {
-    DeleteObject(m_hMask);
-    m_hMask = CreateBitmap(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 1, 1, NULL);
-    DeleteObject(SelectObject(m_hDC, m_hMask));
-    Rect(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), 0x00ffffff, 0x00ffffff, 1, 2);
-    SelectObject(m_hDC, m_hBm = CreateDIBWithProperties(RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc)));
-    BitBlt(m_hDC, 0, 0, RECT_WIDTH(m_rcSrc), RECT_HEIGHT(m_rcSrc), hDCImage, m_rcSrc.left,
-           m_rcSrc.top, SRCCOPY);
+    CRect rc = { MAXLONG, MAXLONG, 0, 0 };
+    for (INT i = 0; i < m_iPtSP; ++i)
+    {
+        POINT& pt = m_ptStack[i];
+        rc.left = min(pt.x, rc.left);
+        rc.top = min(pt.y, rc.top);
+        rc.right = max(pt.x, rc.right);
+        rc.bottom = max(pt.y, rc.bottom);
+    }
+    rc.right += 1;
+    rc.bottom += 1;
+
+    m_rc = rc;
+
+    ShiftPtStack(FALSE);
+
+    ClearMask();
+
+    HDC hdcMem = ::CreateCompatibleDC(NULL);
+    m_hbmMask = ::CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL);
+    HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_hbmMask);
+    FillRect(hdcMem, &rc, (HBRUSH)::GetStockObject(BLACK_BRUSH));
+    HGDIOBJ hPenOld = ::SelectObject(hdcMem, GetStockObject(NULL_PEN));
+    HGDIOBJ hbrOld = ::SelectObject(hdcMem, GetStockObject(WHITE_BRUSH));
+    ::Polygon(hdcMem, m_ptStack, m_iPtSP);
+    ::SelectObject(hdcMem, hbrOld);
+    ::SelectObject(hdcMem, hPenOld);
+    ::SelectObject(hdcMem, hbmOld);
+    ::DeleteDC(hdcMem);
 }
 
 void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
 {
 }
 
 void SelectionModel::DrawBackgroundPoly(HDC hDCImage, COLORREF crBg)
 {
-    Poly(hDCImage, m_ptStack, m_iPtSP, crBg, crBg, 1, 2, TRUE, FALSE);
+    ShiftPtStack(TRUE);
+
+    HGDIOBJ hPenOld = ::SelectObject(hDCImage, ::GetStockObject(NULL_PEN));
+    HGDIOBJ hbrOld = ::SelectObject(hDCImage, ::CreateSolidBrush(crBg));
+    ::Polygon(hDCImage, m_ptStack, m_iPtSP);
+    ::DeleteObject(::SelectObject(hDCImage, hbrOld));
+    ::SelectObject(hDCImage, hPenOld);
+
+    ShiftPtStack(FALSE);
 }
 
 void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
 {
 }
 
 void SelectionModel::DrawBackgroundRect(HDC hDCImage, COLORREF crBg)
 {
-    Rect(hDCImage, m_rcSrc.left, m_rcSrc.top, m_rcSrc.right, m_rcSrc.bottom, crBg, crBg, 0, 1);
+    Rect(hDCImage, m_rc.left, m_rc.top, m_rc.right, m_rc.bottom, crBg, crBg, 0, 1);
 }
 
 }
 
-void SelectionModel::DrawSelection(HDC hDCImage, COLORREF crBg, BOOL bBgTransparent)
+void SelectionModel::DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg, BOOL bBgTransparent)
 {
 {
-    if (!bBgTransparent)
-        MaskBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest),
-                m_hDC, 0, 0, m_hMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND));
-    else
-        ColorKeyedMaskBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest),
-                          m_hDC, 0, 0, m_hMask, 0, 0, MAKEROP4(SRCCOPY, SRCAND), crBg);
+    CRect rc = *prc;
+    if (::IsRectEmpty(&rc))
+        return;
+
+    BITMAP bm;
+    GetObject(m_hbmColor, sizeof(BITMAP), &bm);
+
+    COLORREF keyColor = (bBgTransparent ? crBg : CLR_INVALID);
+
+    HDC hMemDC = CreateCompatibleDC(hDCImage);
+    HGDIOBJ hbmOld = SelectObject(hMemDC, m_hbmColor);
+    ColorKeyedMaskBlt(hDCImage, rc.left, rc.top, rc.Width(), rc.Height(),
+                      hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, m_hbmMask, keyColor);
+    SelectObject(hMemDC, hbmOld);
+    DeleteDC(hMemDC);
+}
+
+void SelectionModel::GetSelectionContents(HDC hDCImage)
+{
+    ClearColor();
+
+    HDC hMemDC = ::CreateCompatibleDC(NULL);
+    m_hbmColor = CreateColorDIB(m_rc.Width(), m_rc.Height(), RGB(255, 255, 255));
+    HGDIOBJ hbmOld = ::SelectObject(hMemDC, m_hbmColor);
+    ::BitBlt(hMemDC, 0, 0, m_rc.Width(), m_rc.Height(), hDCImage, m_rc.left, m_rc.top, SRCCOPY);
+    ::SelectObject(hMemDC, hbmOld);
+    ::DeleteDC(hMemDC);
 }
 
 }
 
-void SelectionModel::DrawSelectionStretched(HDC hDCImage)
+BOOL SelectionModel::TakeOff()
 {
 {
-    StretchBlt(hDCImage, m_rcDest.left, m_rcDest.top, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0, GetDIBWidth(m_hBm), GetDIBHeight(m_hBm), SRCCOPY);
+    if (m_hbmColor || ::IsRectEmpty(&m_rc))
+        return FALSE;
+
+    HDC hDCImage = imageModel.GetDC();
+    GetSelectionContents(hDCImage);
+
+    if (toolsModel.GetActiveTool() == TOOL_FREESEL)
+    {
+        DrawBackgroundPoly(hDCImage, paletteModel.GetBgColor());
+    }
+    else
+    {
+        ClearMask();
+        DrawBackgroundRect(hDCImage, paletteModel.GetBgColor());
+    }
+
+    imageArea.Invalidate(FALSE);
+    return TRUE;
 }
 
 }
 
-void SelectionModel::ScaleContentsToFit()
+void SelectionModel::Landing()
 {
 {
-    HDC hTempDC;
-    HBITMAP hTempBm;
-    hTempDC = CreateCompatibleDC(m_hDC);
-    hTempBm = CreateDIBWithProperties(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest));
-    SelectObject(hTempDC, hTempBm);
-    SelectObject(m_hDC, m_hBm);
-    StretchBlt(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0,
-               GetDIBWidth(m_hBm), GetDIBHeight(m_hBm), SRCCOPY);
-    DeleteObject(m_hBm);
-    m_hBm = hTempBm;
-    hTempBm = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL);
-    SelectObject(hTempDC, hTempBm);
-    SelectObject(m_hDC, m_hMask);
-    StretchBlt(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC, 0, 0,
-               GetDIBWidth(m_hMask), GetDIBHeight(m_hMask), SRCCOPY);
-    DeleteObject(m_hMask);
-    m_hMask = hTempBm;
-    SelectObject(m_hDC, m_hBm);
-    DeleteDC(hTempDC);
+    if (!m_hbmColor)
+        return;
+
+    DrawSelection(imageModel.GetDC(), &m_rc, paletteModel.GetBgColor(), toolsModel.IsBackgroundTransparent());
+
+    ::SetRectEmpty(&m_rc);
+    ClearMask();
+    ClearColor();
+
+    imageModel.CopyPrevious();
 }
 
 void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
 {
 }
 
 void SelectionModel::InsertFromHBITMAP(HBITMAP hBm, INT x, INT y)
 {
-    HDC hTempDC;
-    HBITMAP hTempMask;
-
-    m_hBm = CopyDIBImage(hBm);
-    DeleteObject(SelectObject(m_hDC, m_hBm));
-
-    SetRectEmpty(&m_rcSrc);
-    m_rcDest.left = x;
-    m_rcDest.top = y;
-    m_rcDest.right = m_rcDest.left + GetDIBWidth(m_hBm);
-    m_rcDest.bottom = m_rcDest.top + GetDIBHeight(m_hBm);
-
-    hTempDC = CreateCompatibleDC(m_hDC);
-    hTempMask = CreateBitmap(RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 1, 1, NULL);
-    SelectObject(hTempDC, hTempMask);
-    Rect(hTempDC, 0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), 0x00ffffff, 0x00ffffff, 1, 1);
-    DeleteObject(m_hMask);
-    m_hMask = hTempMask;
-    DeleteDC(hTempDC);
+    m_hbmColor = CopyDIBImage(hBm);
+    ::DeleteObject(m_hbmColor);
+
+    m_rc.left = x;
+    m_rc.top = y;
+    m_rc.right = m_rc.left + GetDIBWidth(hBm);
+    m_rc.bottom = m_rc.top + GetDIBHeight(hBm);
+
+    ClearMask();
 }
 
 void SelectionModel::FlipHorizontally()
 {
 }
 
 void SelectionModel::FlipHorizontally()
 {
-    SelectObject(m_hDC, m_hMask);
-    StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, 0, -RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC,
-               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
-    SelectObject(m_hDC, m_hBm);
-    StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, 0, -RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), m_hDC,
-               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+    TakeOff();
+
+    HDC hdcMem = ::CreateCompatibleDC(NULL);
+    if (m_hbmMask)
+    {
+        ::SelectObject(hdcMem, m_hbmMask);
+        ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
+                     hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
+    }
+    if (m_hbmColor)
+    {
+        ::SelectObject(hdcMem, m_hbmColor);
+        ::StretchBlt(hdcMem, m_rc.Width() - 1, 0, -m_rc.Width(), m_rc.Height(),
+                     hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
+    }
+    ::DeleteDC(hdcMem);
+
     NotifyRefreshNeeded();
 }
 
 void SelectionModel::FlipVertically()
 {
     NotifyRefreshNeeded();
 }
 
 void SelectionModel::FlipVertically()
 {
-    SelectObject(m_hDC, m_hMask);
-    StretchBlt(m_hDC, 0, RECT_HEIGHT(m_rcDest) - 1, RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
-               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
-    SelectObject(m_hDC, m_hBm);
-    StretchBlt(m_hDC, 0, RECT_HEIGHT(m_rcDest) - 1, RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
-               0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
+    TakeOff();
+
+    HDC hdcMem = ::CreateCompatibleDC(NULL);
+    if (m_hbmMask)
+    {
+        ::SelectObject(hdcMem, m_hbmMask);
+        ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
+                     hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
+    }
+    if (m_hbmColor)
+    {
+        ::SelectObject(hdcMem, m_hbmColor);
+        ::StretchBlt(hdcMem, 0, m_rc.Height() - 1, m_rc.Width(), -m_rc.Height(),
+                     hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
+    }
+    ::DeleteDC(hdcMem);
+
     NotifyRefreshNeeded();
 }
 
 void SelectionModel::RotateNTimes90Degrees(int iN)
 {
     HBITMAP hbm;
     NotifyRefreshNeeded();
 }
 
 void SelectionModel::RotateNTimes90Degrees(int iN)
 {
     HBITMAP hbm;
+    HGDIOBJ hbmOld;
+    HDC hdcMem = ::CreateCompatibleDC(NULL);
+
     switch (iN)
     {
     switch (iN)
     {
-    case 1:
-    case 3:
-        imageModel.DeleteSelection();
-        imageModel.CopyPrevious();
-        SelectObject(m_hDC, m_hBm);
-        hbm = Rotate90DegreeBlt(m_hDC, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), iN == 1);
-        InsertFromHBITMAP(hbm, m_rcDest.left, m_rcDest.top);
-        DeleteObject(hbm);
-        selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
-        selectionWindow.ForceRefreshSelectionContents();
-        placeSelWin();
-        break;
-    case 2:
-        SelectObject(m_hDC, m_hMask);
-        StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
-                   0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
-        SelectObject(m_hDC, m_hBm);
-        StretchBlt(m_hDC, RECT_WIDTH(m_rcDest) - 1, RECT_HEIGHT(m_rcDest) - 1, -RECT_WIDTH(m_rcDest), -RECT_HEIGHT(m_rcDest), m_hDC,
-                   0, 0, RECT_WIDTH(m_rcDest), RECT_HEIGHT(m_rcDest), SRCCOPY);
-        break;
+        case 1:
+        case 3:
+            TakeOff();
+            if (m_hbmColor)
+            {
+                hbmOld = ::SelectObject(hdcMem, m_hbmColor);
+                hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, FALSE);
+                ::SelectObject(hdcMem, hbmOld);
+                ::DeleteObject(m_hbmColor);
+                m_hbmColor = hbm;
+            }
+            if (m_hbmMask)
+            {
+                hbmOld = ::SelectObject(hdcMem, m_hbmMask);
+                hbm = Rotate90DegreeBlt(hdcMem, m_rc.Width(), m_rc.Height(), iN == 1, TRUE);
+                ::SelectObject(hdcMem, hbmOld);
+                ::DeleteObject(m_hbmMask);
+                m_hbmMask = hbm;
+            }
+            break;
+
+        case 2:
+            TakeOff();
+            if (m_hbmColor)
+            {
+                hbmOld = ::SelectObject(hdcMem, m_hbmColor);
+                ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
+                             hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
+                ::SelectObject(hdcMem, hbmOld);
+            }
+            if (m_hbmMask)
+            {
+                hbmOld = ::SelectObject(hdcMem, m_hbmMask);
+                ::StretchBlt(hdcMem, m_rc.Width() - 1, m_rc.Height() - 1, -m_rc.Width(), -m_rc.Height(),
+                             hdcMem, 0, 0, m_rc.Width(), m_rc.Height(), SRCCOPY);
+                ::SelectObject(hdcMem, hbmOld);
+            }
+            break;
     }
     }
+
+    ::DeleteDC(hdcMem);
     NotifyRefreshNeeded();
 }
 
     NotifyRefreshNeeded();
 }
 
@@ -241,47 +311,47 @@ void SelectionModel::StretchSkew(int nStretchPercentX, int nStretchPercentY, int
     if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0)
         return;
 
     if (nStretchPercentX == 100 && nStretchPercentY == 100 && nSkewDegX == 0 && nSkewDegY == 0)
         return;
 
-    imageModel.DeleteSelection();
-    imageModel.CopyPrevious();
+    TakeOff();
 
 
-    INT oldWidth = RECT_WIDTH(m_rcDest);
-    INT oldHeight = RECT_HEIGHT(m_rcDest);
+    INT oldWidth = m_rc.Width();
+    INT oldHeight = m_rc.Height();
     INT newWidth = oldWidth * nStretchPercentX / 100;
     INT newHeight = oldHeight * nStretchPercentY / 100;
 
     if (oldWidth != newWidth || oldHeight != newHeight)
     {
     INT newWidth = oldWidth * nStretchPercentX / 100;
     INT newHeight = oldHeight * nStretchPercentY / 100;
 
     if (oldWidth != newWidth || oldHeight != newHeight)
     {
-        SelectObject(m_hDC, m_hBm);
-        HBITMAP hbm0 = CopyDIBImage(m_hBm, newWidth, newHeight);
-        InsertFromHBITMAP(hbm0, m_rcDest.left, m_rcDest.top);
-        DeleteObject(hbm0);
+        HBITMAP hbm0 = CopyDIBImage(m_hbmColor, newWidth, newHeight);
+        InsertFromHBITMAP(hbm0, m_rc.left, m_rc.top);
+        ::DeleteObject(hbm0);
     }
 
     }
 
+    HDC hDC = ::CreateCompatibleDC(NULL);
+
     if (nSkewDegX)
     {
     if (nSkewDegX)
     {
-        SelectObject(m_hDC, m_hBm);
-        HBITMAP hbm1 = SkewDIB(m_hDC, m_hBm, nSkewDegX, FALSE);
-        InsertFromHBITMAP(hbm1, m_rcDest.left, m_rcDest.top);
-        DeleteObject(hbm1);
+        ::SelectObject(hDC, m_hbmColor);
+        HBITMAP hbm1 = SkewDIB(hDC, m_hbmColor, nSkewDegX, FALSE);
+        InsertFromHBITMAP(hbm1, m_rc.left, m_rc.top);
+        ::DeleteObject(hbm1);
     }
 
     if (nSkewDegY)
     {
     }
 
     if (nSkewDegY)
     {
-        SelectObject(m_hDC, m_hBm);
-        HBITMAP hbm2 = SkewDIB(m_hDC, m_hBm, nSkewDegY, TRUE);
-        InsertFromHBITMAP(hbm2, m_rcDest.left, m_rcDest.top);
-        DeleteObject(hbm2);
+        ::SelectObject(hDC, m_hbmColor);
+        HBITMAP hbm2 = SkewDIB(hDC, m_hbmColor, nSkewDegY, TRUE);
+        InsertFromHBITMAP(hbm2, m_rc.left, m_rc.top);
+        ::DeleteObject(hbm2);
     }
 
     }
 
-    selectionWindow.ShowWindow(SW_SHOWNOACTIVATE);
-    selectionWindow.ForceRefreshSelectionContents();
-    placeSelWin();
+    ::DeleteDC(hDC);
+
+    m_bShow = TRUE;
     NotifyRefreshNeeded();
 }
 
 HBITMAP SelectionModel::GetBitmap() const
 {
     NotifyRefreshNeeded();
 }
 
 HBITMAP SelectionModel::GetBitmap() const
 {
-    return m_hBm;
+    return m_hbmColor;
 }
 
 int SelectionModel::PtStackSize() const
 }
 
 int SelectionModel::PtStackSize() const
@@ -291,114 +361,92 @@ int SelectionModel::PtStackSize() const
 
 void SelectionModel::DrawFramePoly(HDC hDCImage)
 {
 
 void SelectionModel::DrawFramePoly(HDC hDCImage)
 {
-    Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE); /* draw the freehand selection inverted/xored */
-}
-
-void SelectionModel::SetSrcAndDestRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
-{
-    m_rcDest.left = m_rcSrc.left = min(ptFrom.x, ptTo.x);
-    m_rcDest.top = m_rcSrc.top = min(ptFrom.y, ptTo.y);
-    m_rcDest.right = m_rcSrc.right = max(ptFrom.x, ptTo.x);
-    m_rcDest.bottom = m_rcSrc.bottom = max(ptFrom.y, ptTo.y);
-}
-
-void SelectionModel::SetSrcRectSizeToZero()
-{
-    m_rcSrc.right = m_rcSrc.left;
-    m_rcSrc.bottom = m_rcSrc.top;
+    /* draw the freehand selection inverted/xored */
+    Poly(hDCImage, m_ptStack, m_iPtSP, 0, 0, 2, 0, FALSE, TRUE);
 }
 
 }
 
-BOOL SelectionModel::IsSrcRectSizeNonzero() const
+void SelectionModel::SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo)
 {
 {
-    return (RECT_WIDTH(m_rcSrc) != 0) && (RECT_HEIGHT(m_rcSrc) != 0);
+    m_rc.left = min(ptFrom.x, ptTo.x);
+    m_rc.top = min(ptFrom.y, ptTo.y);
+    m_rc.right = max(ptFrom.x, ptTo.x);
+    m_rc.bottom = max(ptFrom.y, ptTo.y);
 }
 
 }
 
-void SelectionModel::ModifyDestRect(POINT& ptDelta, int iAction)
+void SelectionModel::Dragging(CANVAS_HITTEST hit, POINT pt)
 {
 {
-    POINT ptDeltaUsed;
-
-    switch (iAction)
+    switch (hit)
     {
     {
-        case ACTION_MOVE:                /* move selection */
-            ptDeltaUsed.x = ptDelta.x;
-            ptDeltaUsed.y = ptDelta.y;
-            OffsetRect(&m_rcDest, ptDeltaUsed.x, ptDeltaUsed.y);
+        case HIT_NONE:
+            break;
+        case HIT_UPPER_LEFT:
+            m_rc.left += pt.x - m_ptHit.x;
+            m_rc.top += pt.y - m_ptHit.y;
             break;
             break;
-        case ACTION_RESIZE_TOP_LEFT:     /* resize at upper left corner */
-            ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
-            ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
-            m_rcDest.left += ptDeltaUsed.x;
-            m_rcDest.top  += ptDeltaUsed.y;
+        case HIT_UPPER_CENTER:
+            m_rc.top += pt.y - m_ptHit.y;
             break;
             break;
-        case ACTION_RESIZE_TOP:          /* resize at top edge */
-            ptDeltaUsed.x = ptDelta.x;
-            ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
-            m_rcDest.top += ptDeltaUsed.y;
+        case HIT_UPPER_RIGHT:
+            m_rc.right += pt.x - m_ptHit.x;
+            m_rc.top += pt.y - m_ptHit.y;
             break;
             break;
-        case ACTION_RESIZE_TOP_RIGHT:    /* resize at upper right corner */
-            ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
-            ptDeltaUsed.y = min(ptDelta.y, RECT_HEIGHT(m_rcDest) - 1);
-            m_rcDest.top   += ptDeltaUsed.y;
-            m_rcDest.right += ptDeltaUsed.x;
+        case HIT_MIDDLE_LEFT:
+            m_rc.left += pt.x - m_ptHit.x;
             break;
             break;
-        case ACTION_RESIZE_LEFT:         /* resize at left edge */
-            ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
-            ptDeltaUsed.y = ptDelta.y;
-            m_rcDest.left += ptDeltaUsed.x;
+        case HIT_MIDDLE_RIGHT:
+            m_rc.right += pt.x - m_ptHit.x;
             break;
             break;
-        case ACTION_RESIZE_RIGHT:        /* resize at right edge */
-            ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
-            ptDeltaUsed.y = ptDelta.y;
-            m_rcDest.right += ptDeltaUsed.x;
+        case HIT_LOWER_LEFT:
+            m_rc.left += pt.x - m_ptHit.x;
+            m_rc.bottom += pt.y - m_ptHit.y;
             break;
             break;
-        case ACTION_RESIZE_BOTTOM_LEFT:  /* resize at lower left corner */
-            ptDeltaUsed.x = min(ptDelta.x, RECT_WIDTH(m_rcDest) - 1);
-            ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
-            m_rcDest.left   += ptDeltaUsed.x;
-            m_rcDest.bottom += ptDeltaUsed.y;
+        case HIT_LOWER_CENTER:
+            m_rc.bottom += pt.y - m_ptHit.y;
             break;
             break;
-        case ACTION_RESIZE_BOTTOM:       /* resize at bottom edge */
-            ptDeltaUsed.x = ptDelta.x;
-            ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
-            m_rcDest.bottom += ptDeltaUsed.y;
+        case HIT_LOWER_RIGHT:
+            m_rc.right += pt.x - m_ptHit.x;
+            m_rc.bottom += pt.y - m_ptHit.y;
             break;
             break;
-        case ACTION_RESIZE_BOTTOM_RIGHT: /* resize at lower right corner */
-            ptDeltaUsed.x = max(ptDelta.x, -(RECT_WIDTH(m_rcDest) - 1));
-            ptDeltaUsed.y = max(ptDelta.y, -(RECT_HEIGHT(m_rcDest) - 1));
-            m_rcDest.right  += ptDeltaUsed.x;
-            m_rcDest.bottom += ptDeltaUsed.y;
+        case HIT_BORDER:
+        case HIT_INNER:
+            OffsetRect(&m_rc, pt.x - m_ptHit.x, pt.y - m_ptHit.y);
             break;
     }
             break;
     }
-    ptDelta.x -= ptDeltaUsed.x;
-    ptDelta.y -= ptDeltaUsed.y;
+    m_ptHit = pt;
 }
 
 }
 
-LONG SelectionModel::GetDestRectWidth() const
+void SelectionModel::NotifyRefreshNeeded()
 {
 {
-    return m_rcDest.right - m_rcDest.left;
+    imageArea.Invalidate(FALSE);
 }
 
 }
 
-LONG SelectionModel::GetDestRectHeight() const
+void SelectionModel::ClearMask()
 {
 {
-    return m_rcDest.bottom - m_rcDest.top;
+    if (m_hbmMask)
+    {
+        ::DeleteObject(m_hbmMask);
+        m_hbmMask = NULL;
+    }
 }
 
 }
 
-LONG SelectionModel::GetDestRectLeft() const
+void SelectionModel::ClearColor()
 {
 {
-    return m_rcDest.left;
+    if (m_hbmColor)
+    {
+        ::DeleteObject(m_hbmColor);
+        m_hbmColor = NULL;
+    }
 }
 
 }
 
-LONG SelectionModel::GetDestRectTop() const
+void SelectionModel::CancelSelection()
 {
 {
-    return m_rcDest.top;
-}
+    if (!m_bShow)
+        return;
 
 
-void SelectionModel::NotifyRefreshNeeded()
-{
-    selectionWindow.SendMessage(WM_SELECTIONMODELREFRESHNEEDED);
-}
+    imageModel.CopyPrevious();
+    if (m_bShow)
+        imageModel.Undo(TRUE);
 
 
-void SelectionModel::GetRect(LPRECT prc) const
-{
-    *prc = m_rcDest;
+    m_bShow = FALSE;
+    imageArea.Invalidate(FALSE);
 }
 }
index fbb208f..fc1420d 100644 (file)
@@ -9,66 +9,54 @@
 
 #pragma once
 
 
 #pragma once
 
-/* DEFINES **********************************************************/
-
-#define ACTION_MOVE                 0
-#define ACTION_RESIZE_TOP_LEFT      1
-#define ACTION_RESIZE_TOP           2
-#define ACTION_RESIZE_TOP_RIGHT     3
-#define ACTION_RESIZE_LEFT          4
-#define ACTION_RESIZE_RIGHT         5
-#define ACTION_RESIZE_BOTTOM_LEFT   6
-#define ACTION_RESIZE_BOTTOM        7
-#define ACTION_RESIZE_BOTTOM_RIGHT  8
-
-/* CLASSES **********************************************************/
-
 class SelectionModel
 {
 private:
 class SelectionModel
 {
 private:
-    HDC m_hDC;
-    RECT m_rcSrc;
-    RECT m_rcDest;
-    HBITMAP m_hBm;
-    HBITMAP m_hMask;
+    HBITMAP m_hbmColor;
+    HBITMAP m_hbmMask;
     POINT *m_ptStack;
     int m_iPtSP;
 
     POINT *m_ptStack;
     int m_iPtSP;
 
-//     void NotifySelectionChanging();
-//     void NotifySelectionChanged();
-    void NotifyRefreshNeeded();
-
 public:
 public:
+    BOOL m_bShow;
+    CRect m_rc;    // in image pixel coordinates
+    POINT m_ptHit; // in image pixel coordinates
+
     SelectionModel();
     ~SelectionModel();
     SelectionModel();
     ~SelectionModel();
+
     void ResetPtStack();
     void ResetPtStack();
-    void PushToPtStack(LONG x, LONG y);
-    void CalculateBoundingBoxAndContents(HDC hDCImage);
-    void CalculateContents(HDC hDCImage);
+    void PushToPtStack(POINT pt);
+    int PtStackSize() const;
+    void SetRectFromPoints(const POINT& ptFrom, const POINT& ptTo);
+    void BuildMaskFromPtStack();
+
+    BOOL TakeOff();
+    void Landing();
+
+    HBITMAP GetBitmap() const;
+    void GetSelectionContents(HDC hDCImage);
+    void DrawFramePoly(HDC hDCImage);
     void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg);
     void DrawBackgroundRect(HDC hDCImage, COLORREF crBg);
     void DrawBackgroundPoly(HDC hDCImage, COLORREF crBg);
     void DrawBackgroundRect(HDC hDCImage, COLORREF crBg);
-    void DrawSelection(HDC hDCImage, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
-    void DrawSelectionStretched(HDC hDCImage);
-    void ScaleContentsToFit();
+    void DrawSelection(HDC hDCImage, LPCRECT prc, COLORREF crBg = 0, BOOL bBgTransparent = FALSE);
     void InsertFromHBITMAP(HBITMAP hBm, INT x = 0, INT y = 0);
     void InsertFromHBITMAP(HBITMAP hBm, INT x = 0, INT y = 0);
+
+    // operation
     void FlipHorizontally();
     void FlipVertically();
     void RotateNTimes90Degrees(int iN);
     void FlipHorizontally();
     void FlipVertically();
     void RotateNTimes90Degrees(int iN);
-    void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX = 0, int nSkewDegY = 0);
-    HBITMAP GetBitmap() const;
-    int PtStackSize() const;
-    void DrawFramePoly(HDC hDCImage);
-    void SetSrcAndDestRectFromPoints(const POINT& ptFrom, const POINT& ptTo);
-    void SetSrcRectSizeToZero();
-    BOOL IsSrcRectSizeNonzero() const;
-    void ModifyDestRect(POINT& ptDelta, int iAction);
-    LONG GetDestRectWidth() const;
-    LONG GetDestRectHeight() const;
-    LONG GetDestRectLeft() const;
-    LONG GetDestRectTop() const;
-    void GetRect(LPRECT prc) const;
+    void StretchSkew(int nStretchPercentX, int nStretchPercentY, int nSkewDegX, int nSkewDegY);
+
+    void CancelSelection();
+    void NotifyRefreshNeeded();
+    void Dragging(CANVAS_HITTEST hit, POINT pt);
+    void ClearMask();
+    void ClearColor();
 
 private:
     SelectionModel(const SelectionModel&);
     SelectionModel& operator=(const SelectionModel&);
 
 private:
     SelectionModel(const SelectionModel&);
     SelectionModel& operator=(const SelectionModel&);
+
+    void ShiftPtStack(BOOL bPlus);
 };
 };
index 6ba2337..64f90f9 100644 (file)
@@ -114,7 +114,7 @@ LRESULT CToolBox::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHand
 
 LRESULT CToolBox::OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
 
 LRESULT CToolBox::OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    selectionWindow.ShowWindow(SW_HIDE);
+    selectionModel.m_bShow = FALSE;
     toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
 
     // Check the toolbar button
     toolsModel.resetTool(); // resets the point-buffer of the polygon and bezier functions
 
     // Check the toolbar button
index 3434163..5f07ddf 100644 (file)
@@ -141,8 +141,8 @@ void ToolsModel::SetBackgroundTransparent(BOOL bTransparent)
 {
     m_transpBg = bTransparent;
     NotifyToolSettingsChanged();
 {
     m_transpBg = bTransparent;
     NotifyToolSettingsChanged();
-    if (selectionWindow.IsWindow())
-        selectionWindow.ForceRefreshSelectionContents();
+    if (imageArea.IsWindow())
+        imageArea.Invalidate(FALSE);
 }
 
 int ToolsModel::GetZoom() const
 }
 
 int ToolsModel::GetZoom() const
@@ -172,8 +172,6 @@ void ToolsModel::NotifyToolSettingsChanged()
 {
     if (toolSettingsWindow.IsWindow())
         toolSettingsWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
 {
     if (toolSettingsWindow.IsWindow())
         toolSettingsWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
-    if (selectionWindow.IsWindow())
-        selectionWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
 }
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_TOOLSMODELSETTINGSCHANGED);
 }
@@ -184,8 +182,8 @@ void ToolsModel::NotifyZoomChanged()
         toolSettingsWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
         toolSettingsWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
     if (textEditWindow.IsWindow())
         textEditWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
-    if (selectionWindow.IsWindow())
-        selectionWindow.SendMessage(WM_TOOLSMODELZOOMCHANGED);
+    if (imageArea.IsWindow())
+        imageArea.SendMessage(WM_TOOLSMODELZOOMCHANGED);
 }
 
 void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
 }
 
 void ToolsModel::OnButtonDown(BOOL bLeftButton, LONG x, LONG y, BOOL bDoubleClick)
index c7fc230..da0e06c 100644 (file)
@@ -132,3 +132,31 @@ static inline int UnZoomed(int xy)
 {
     return xy * 1000 / toolsModel.GetZoom();
 }
 {
     return xy * 1000 / toolsModel.GetZoom();
 }
+
+static inline void Zoomed(POINT& pt)
+{
+    pt.x = Zoomed(pt.x);
+    pt.y = Zoomed(pt.y);
+}
+
+static inline void Zoomed(RECT& rc)
+{
+    rc.left = Zoomed(rc.left);
+    rc.top = Zoomed(rc.top);
+    rc.right = Zoomed(rc.right);
+    rc.bottom = Zoomed(rc.bottom);
+}
+
+static inline void UnZoomed(POINT& pt)
+{
+    pt.x = UnZoomed(pt.x);
+    pt.y = UnZoomed(pt.y);
+}
+
+static inline void UnZoomed(RECT& rc)
+{
+    rc.left = UnZoomed(rc.left);
+    rc.top = UnZoomed(rc.top);
+    rc.right = UnZoomed(rc.right);
+    rc.bottom = UnZoomed(rc.bottom);
+}
index ee09d6f..b44534a 100644 (file)
@@ -182,11 +182,9 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window)
     toolBoxContainer.SendMessage(WM_COMMAND, ID_RECTSEL);
 
     imageModel.CopyPrevious();
     toolBoxContainer.SendMessage(WM_COMMAND, ID_RECTSEL);
 
     imageModel.CopyPrevious();
-    selectionModel.InsertFromHBITMAP(bitmap);
-
-    placeSelWin();
-    selectionWindow.ShowWindow(SW_SHOW);
-    selectionWindow.ForceRefreshSelectionContents();
+    selectionModel.InsertFromHBITMAP(bitmap, 0, 0);
+    selectionModel.m_bShow = TRUE;
+    imageArea.Invalidate(FALSE);
 }
 
 LRESULT CMainWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 }
 
 LRESULT CMainWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@@ -279,9 +277,6 @@ LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHa
     // Creating the window inside the canvas
     imageArea.Create(canvasWindow, rcEmpty, NULL, WS_CHILD | WS_VISIBLE);
 
     // Creating the window inside the canvas
     imageArea.Create(canvasWindow, rcEmpty, NULL, WS_CHILD | WS_VISIBLE);
 
-    // Create selection window (initially hidden)
-    selectionWindow.Create(imageArea, rcEmpty, NULL, WS_CHILD | BS_OWNERDRAW);
-
     // Create and show the miniature if necessary
     if (registrySettings.ShowThumbnail)
     {
     // Create and show the miniature if necessary
     if (registrySettings.ShowThumbnail)
     {
@@ -407,7 +402,7 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
 {
     HMENU menu = (HMENU)wParam;
     BOOL trueSelection =
 {
     HMENU menu = (HMENU)wParam;
     BOOL trueSelection =
-        (::IsWindowVisible(selectionWindow) &&
+        (selectionModel.m_bShow &&
          ((toolsModel.GetActiveTool() == TOOL_FREESEL) || (toolsModel.GetActiveTool() == TOOL_RECTSEL)));
 
     switch (lParam)
          ((toolsModel.GetActiveTool() == TOOL_FREESEL) || (toolsModel.GetActiveTool() == TOOL_RECTSEL)));
 
     switch (lParam)
@@ -438,7 +433,7 @@ LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BO
             CheckMenuItem(menu, IDM_VIEWSHOWMINIATURE, CHECKED_IF(registrySettings.ShowThumbnail));
             break;
         case 3: /* Image menu */
             CheckMenuItem(menu, IDM_VIEWSHOWMINIATURE, CHECKED_IF(registrySettings.ShowThumbnail));
             break;
         case 3: /* Image menu */
-            EnableMenuItem(menu, IDM_IMAGECROP, ENABLED_IF(::IsWindowVisible(selectionWindow)));
+            EnableMenuItem(menu, IDM_IMAGECROP, ENABLED_IF(selectionModel.m_bShow));
             CheckMenuItem(menu, IDM_IMAGEDRAWOPAQUE, CHECKED_IF(!toolsModel.IsBackgroundTransparent()));
             break;
     }
             CheckMenuItem(menu, IDM_IMAGEDRAWOPAQUE, CHECKED_IF(!toolsModel.IsBackgroundTransparent()));
             break;
     }
@@ -484,7 +479,6 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         if (hwndCapture)
         {
             if (canvasWindow.m_hWnd == hwndCapture ||
         if (hwndCapture)
         {
             if (canvasWindow.m_hWnd == hwndCapture ||
-                selectionWindow.m_hWnd == hwndCapture ||
                 imageArea.m_hWnd == hwndCapture ||
                 fullscreenWindow.m_hWnd == hwndCapture)
             {
                 imageArea.m_hWnd == hwndCapture ||
                 fullscreenWindow.m_hWnd == hwndCapture)
             {
@@ -610,7 +604,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         case IDM_EDITUNDO:
             if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
                 break;
         case IDM_EDITUNDO:
             if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
                 break;
-            if (selectionWindow.IsWindowVisible())
+            if (selectionModel.m_bShow)
             {
                 if (toolsModel.GetActiveTool() == TOOL_RECTSEL ||
                     toolsModel.GetActiveTool() == TOOL_FREESEL)
             {
                 if (toolsModel.GetActiveTool() == TOOL_RECTSEL ||
                     toolsModel.GetActiveTool() == TOOL_FREESEL)
@@ -736,31 +730,31 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
             switch (mirrorRotateDialog.DoModal(mainWindow.m_hWnd))
             {
                 case 1: /* flip horizontally */
             switch (mirrorRotateDialog.DoModal(mainWindow.m_hWnd))
             {
                 case 1: /* flip horizontally */
-                    if (::IsWindowVisible(selectionWindow))
+                    if (selectionModel.m_bShow)
                         selectionModel.FlipHorizontally();
                     else
                         imageModel.FlipHorizontally();
                     break;
                 case 2: /* flip vertically */
                         selectionModel.FlipHorizontally();
                     else
                         imageModel.FlipHorizontally();
                     break;
                 case 2: /* flip vertically */
-                    if (::IsWindowVisible(selectionWindow))
+                    if (selectionModel.m_bShow)
                         selectionModel.FlipVertically();
                     else
                         imageModel.FlipVertically();
                     break;
                 case 3: /* rotate 90 degrees */
                         selectionModel.FlipVertically();
                     else
                         imageModel.FlipVertically();
                     break;
                 case 3: /* rotate 90 degrees */
-                    if (::IsWindowVisible(selectionWindow))
+                    if (selectionModel.m_bShow)
                         selectionModel.RotateNTimes90Degrees(1);
                     else
                         imageModel.RotateNTimes90Degrees(1);
                     break;
                 case 4: /* rotate 180 degrees */
                         selectionModel.RotateNTimes90Degrees(1);
                     else
                         imageModel.RotateNTimes90Degrees(1);
                     break;
                 case 4: /* rotate 180 degrees */
-                    if (::IsWindowVisible(selectionWindow))
+                    if (selectionModel.m_bShow)
                         selectionModel.RotateNTimes90Degrees(2);
                     else
                         imageModel.RotateNTimes90Degrees(2);
                     break;
                 case 5: /* rotate 270 degrees */
                         selectionModel.RotateNTimes90Degrees(2);
                     else
                         imageModel.RotateNTimes90Degrees(2);
                     break;
                 case 5: /* rotate 270 degrees */
-                    if (::IsWindowVisible(selectionWindow))
+                    if (selectionModel.m_bShow)
                         selectionModel.RotateNTimes90Degrees(3);
                     else
                         imageModel.RotateNTimes90Degrees(3);
                         selectionModel.RotateNTimes90Degrees(3);
                     else
                         imageModel.RotateNTimes90Degrees(3);
@@ -779,7 +773,7 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         {
             if (stretchSkewDialog.DoModal(mainWindow.m_hWnd))
             {
         {
             if (stretchSkewDialog.DoModal(mainWindow.m_hWnd))
             {
-                if (::IsWindowVisible(selectionWindow))
+                if (selectionModel.m_bShow)
                 {
                     selectionModel.StretchSkew(stretchSkewDialog.percentage.x, stretchSkewDialog.percentage.y,
                                                stretchSkewDialog.angle.x, stretchSkewDialog.angle.y);
                 {
                     selectionModel.StretchSkew(stretchSkewDialog.percentage.x, stretchSkewDialog.percentage.y,
                                                stretchSkewDialog.angle.x, stretchSkewDialog.angle.y);