[MSPAINT] Make sizeboxes window-less (#5166)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Sun, 19 Mar 2023 01:42:10 +0000 (10:42 +0900)
committerGitHub <noreply@github.com>
Sun, 19 Mar 2023 01:42:10 +0000 (10:42 +0900)
Reduce window controls and integrate to the canvas window.
- The sizeboxes are absorbed by canvasWindow.
- class CSizeboxWindow is deleted.
- Add enum CANVAS_HITTEST.
- Add getSizeBoxRect, getSizeBoxHitTest, and drawSizeBoxes helper functions in sizebox.cpp.
CORE-18867

12 files changed:
base/applications/mspaint/canvas.cpp
base/applications/mspaint/canvas.h
base/applications/mspaint/drawing.cpp
base/applications/mspaint/drawing.h
base/applications/mspaint/globalvar.h
base/applications/mspaint/main.cpp
base/applications/mspaint/mouse.cpp
base/applications/mspaint/precomp.h
base/applications/mspaint/selection.cpp
base/applications/mspaint/sizebox.cpp
base/applications/mspaint/sizebox.h
base/applications/mspaint/winproc.cpp

index 4924937..591d1ba 100644 (file)
 /* INCLUDES *********************************************************/
 
 #include "precomp.h"
-#include <atltypes.h>
 
 /* FUNCTIONS ********************************************************/
 
+CCanvasWindow::CCanvasWindow()
+    : m_whereHit(HIT_NONE)
+    , m_ptOrig { 0, 0 }
+{
+}
+
+RECT CCanvasWindow::GetBaseRect()
+{
+    CRect rcBase = { 0, 0, Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()) };
+    ::InflateRect(&rcBase, GRIP_SIZE, GRIP_SIZE);
+    ::OffsetRect(&rcBase, GRIP_SIZE - GetScrollPos(SB_HORZ), GRIP_SIZE - GetScrollPos(SB_VERT));
+    return rcBase;
+}
+
+CANVAS_HITTEST CCanvasWindow::HitTest(POINT pt)
+{
+    RECT rcBase = GetBaseRect();
+    return getSizeBoxHitTest(pt, &rcBase);
+}
+
+VOID CCanvasWindow::DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint)
+{
+    // 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);
+
+    // Fill the background
+    ::FillRect(hdcMem, &rcPaint, (HBRUSH)(COLOR_APPWORKSPACE + 1));
+
+    // Draw the sizeboxes
+    RECT rcBase = GetBaseRect();
+    drawSizeBoxes(hdcMem, &rcBase, FALSE, &rcPaint);
+
+    // Transfer the bits
+    ::BitBlt(hDC,
+             rcPaint.left, rcPaint.top,
+             rcPaint.right - rcPaint.left, rcPaint.bottom - rcPaint.top,
+             hdcMem, rcPaint.left, rcPaint.top, SRCCOPY);
+
+    ::SelectObject(hdcMem, hbmOld);
+    ::DeleteDC(hdcMem);
+}
+
 VOID CCanvasWindow::Update(HWND hwndFrom)
 {
-    CRect tempRect;
-    GetClientRect(&tempRect);
-    CSize sizeScrollBox(tempRect.Width(), tempRect.Height());
+    CRect rcClient;
+    GetClientRect(&rcClient);
 
+    CSize sizePage(rcClient.right, rcClient.bottom);
     CSize sizeZoomed = { Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()) };
     CSize sizeWhole = { sizeZoomed.cx + (GRIP_SIZE * 2), sizeZoomed.cy + (GRIP_SIZE * 2) };
 
     /* show/hide the scrollbars */
-    ShowScrollBar(SB_HORZ, sizeScrollBox.cx < sizeWhole.cx);
-    ShowScrollBar(SB_VERT, sizeScrollBox.cy < sizeWhole.cy);
+    ShowScrollBar(SB_HORZ, sizePage.cx < sizeWhole.cx);
+    ShowScrollBar(SB_VERT, sizePage.cy < sizeWhole.cy);
 
-    if (sizeScrollBox.cx < sizeWhole.cx || sizeScrollBox.cy < sizeWhole.cy)
+    if (sizePage.cx < sizeWhole.cx || sizePage.cy < sizeWhole.cy)
     {
-        GetClientRect(&tempRect);
-        sizeScrollBox = CSize(tempRect.Width(), tempRect.Height());
+        GetClientRect(&rcClient); // Scrollbars might change, get client rectangle again
+        sizePage = CSize(rcClient.right, rcClient.bottom);
     }
 
     SCROLLINFO si = { sizeof(si), SIF_PAGE | SIF_RANGE };
     si.nMin   = 0;
 
     si.nMax   = sizeWhole.cx;
-    si.nPage  = sizeScrollBox.cx;
+    si.nPage  = sizePage.cx;
     SetScrollInfo(SB_HORZ, &si);
 
     si.nMax   = sizeWhole.cy;
-    si.nPage  = sizeScrollBox.cy;
+    si.nPage  = sizePage.cy;
     SetScrollInfo(SB_VERT, &si);
 
-    INT dx = -GetScrollPos(SB_HORZ);
-    INT dy = -GetScrollPos(SB_VERT);
-
-    if (sizeboxLeftTop.IsWindow())
-    {
-        sizeboxLeftTop.MoveWindow(dx, dy, GRIP_SIZE, GRIP_SIZE, TRUE);
-        sizeboxCenterTop.MoveWindow(dx + GRIP_SIZE + (sizeZoomed.cx - GRIP_SIZE) / 2,
-                                    dy,
-                                    GRIP_SIZE, GRIP_SIZE, TRUE);
-        sizeboxRightTop.MoveWindow(dx + GRIP_SIZE + sizeZoomed.cx,
-                                   dy,
-                                   GRIP_SIZE, GRIP_SIZE, TRUE);
-        sizeboxLeftCenter.MoveWindow(dx,
-                                     dy + GRIP_SIZE + (sizeZoomed.cy - GRIP_SIZE) / 2,
-                                     GRIP_SIZE, GRIP_SIZE, TRUE);
-        sizeboxRightCenter.MoveWindow(dx + GRIP_SIZE + sizeZoomed.cx,
-                                      dy + GRIP_SIZE + (sizeZoomed.cy - GRIP_SIZE) / 2,
-                                      GRIP_SIZE, GRIP_SIZE, TRUE);
-        sizeboxLeftBottom.MoveWindow(dx,
-                                     dy + GRIP_SIZE + sizeZoomed.cy,
-                                     GRIP_SIZE, GRIP_SIZE, TRUE);
-        sizeboxCenterBottom.MoveWindow(dx + GRIP_SIZE + (sizeZoomed.cx - GRIP_SIZE) / 2,
-                                       dy + GRIP_SIZE + sizeZoomed.cy,
-                                       GRIP_SIZE, GRIP_SIZE, TRUE);
-        sizeboxRightBottom.MoveWindow(dx + GRIP_SIZE + sizeZoomed.cx,
-                                      dy + GRIP_SIZE + sizeZoomed.cy,
-                                      GRIP_SIZE, GRIP_SIZE, TRUE);
-    }
-
     if (imageArea.IsWindow() && hwndFrom != imageArea.m_hWnd)
+    {
+        INT dx = -GetScrollPos(SB_HORZ), dy = -GetScrollPos(SB_VERT);
         imageArea.MoveWindow(dx + GRIP_SIZE, dy + GRIP_SIZE, sizeZoomed.cx, sizeZoomed.cy, TRUE);
+    }
 }
 
 LRESULT CCanvasWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
     if (m_hWnd)
-    {
         Update(m_hWnd);
-    }
+
     return 0;
 }
 
-LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+VOID CCanvasWindow::OnHVScroll(WPARAM wParam, INT fnBar)
 {
     SCROLLINFO si;
     si.cbSize = sizeof(SCROLLINFO);
     si.fMask = SIF_ALL;
-    GetScrollInfo(SB_HORZ, &si);
+    GetScrollInfo(fnBar, &si);
     switch (LOWORD(wParam))
     {
         case SB_THUMBTRACK:
@@ -110,59 +126,193 @@ LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
             si.nPos += si.nPage;
             break;
     }
-    SetScrollInfo(SB_HORZ, &si);
+    SetScrollInfo(fnBar, &si);
     Update(m_hWnd);
+    Invalidate(FALSE); // FIXME: Flicker
+}
+
+LRESULT CCanvasWindow::OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    OnHVScroll(wParam, SB_HORZ);
     return 0;
 }
 
 LRESULT CCanvasWindow::OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    SCROLLINFO si;
-    si.cbSize = sizeof(SCROLLINFO);
-    si.fMask = SIF_ALL;
-    GetScrollInfo(SB_VERT, &si);
-    switch (LOWORD(wParam))
-    {
-        case SB_THUMBTRACK:
-        case SB_THUMBPOSITION:
-            si.nPos = HIWORD(wParam);
-            break;
-        case SB_LINEUP:
-            si.nPos -= 5;
-            break;
-        case SB_LINEDOWN:
-            si.nPos += 5;
-            break;
-        case SB_PAGEUP:
-            si.nPos -= si.nPage;
-            break;
-        case SB_PAGEDOWN:
-            si.nPos += si.nPage;
-            break;
-    }
-    SetScrollInfo(SB_VERT, &si);
-    Update(m_hWnd);
+    OnHVScroll(wParam, SB_VERT);
     return 0;
 }
 
 LRESULT CCanvasWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    switch (toolsModel.GetActiveTool())
+    POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+    CANVAS_HITTEST hit = HitTest(pt);
+
+    if (hit == HIT_NONE || hit == HIT_BORDER)
     {
-        case TOOL_BEZIER:
-        case TOOL_SHAPE:
+        if (toolsModel.GetActiveTool() == TOOL_BEZIER ||
+            toolsModel.GetActiveTool() == TOOL_SHAPE)
+        {
             if (ToolBase::pointSP != 0)
             {
                 toolsModel.OnCancelDraw();
                 imageArea.Invalidate();
             }
+        }
+
+        toolsModel.resetTool();  // resets the point-buffer of the polygon and bezier functions
+        return 0;
+    }
+
+    if (hit == HIT_INNER)
+    {
+        // TODO: In the future, we handle the events of the window-less image area.
+        return 0;
+    }
+
+    // Start dragging
+    m_whereHit = hit;
+    m_ptOrig = pt;
+    SetCapture();
+    return 0;
+}
+
+LRESULT CCanvasWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    if (m_whereHit == HIT_NONE || ::GetCapture() != m_hWnd)
+        return 0;
+
+    // Dragging now... Calculate the new size
+    INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
+    INT cxDelta = UnZoomed(GET_X_LPARAM(lParam) - m_ptOrig.x);
+    INT cyDelta = UnZoomed(GET_Y_LPARAM(lParam) - m_ptOrig.y);
+    switch (m_whereHit)
+    {
+        case HIT_UPPER_LEFT:
+            cxImage -= cxDelta;
+            cyImage -= cyDelta;
+            break;
+        case HIT_UPPER_CENTER:
+            cyImage -= cyDelta;
+            break;
+        case HIT_UPPER_RIGHT:
+            cxImage += cxDelta;
+            cyImage -= cyDelta;
+            break;
+        case HIT_MIDDLE_LEFT:
+            cxImage -= cxDelta;
+            break;
+        case HIT_MIDDLE_RIGHT:
+            cxImage += cxDelta;
             break;
+        case HIT_LOWER_LEFT:
+            cxImage -= cxDelta;
+            cyImage += cyDelta;
+            break;
+        case HIT_LOWER_CENTER:
+            cyImage += cyDelta;
+            break;
+        case HIT_LOWER_RIGHT:
+            cxImage += cxDelta;
+            cyImage += cyDelta;
+            break;
+        default:
+            return 0;
+    }
+
+    // Limit bitmap size
+    cxImage = max(1, cxImage);
+    cyImage = max(1, cyImage);
+    cxImage = min(MAXWORD, cxImage);
+    cyImage = min(MAXWORD, cyImage);
+
+    // Display new size
+    CString strSize;
+    strSize.Format(_T("%d x %d"), cxImage, cyImage);
+    SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
 
+    return 0;
+}
+
+LRESULT CCanvasWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    ::ReleaseCapture();
+
+    if (m_whereHit == HIT_NONE)
+        return 0;
+
+    // Resize the image
+    INT cxImage = imageModel.GetWidth(), cyImage = imageModel.GetHeight();
+    INT cxDelta = UnZoomed(GET_X_LPARAM(lParam) - m_ptOrig.x);
+    INT cyDelta = UnZoomed(GET_Y_LPARAM(lParam) - m_ptOrig.y);
+    switch (m_whereHit)
+    {
+        case HIT_UPPER_LEFT:
+            imageModel.Crop(cxImage - cxDelta, cyImage - cyDelta, cxDelta, cyDelta);
+            break;
+        case HIT_UPPER_CENTER:
+            imageModel.Crop(cxImage, cyImage - cyDelta, 0, cyDelta);
+            break;
+        case HIT_UPPER_RIGHT:
+            imageModel.Crop(cxImage + cxDelta, cyImage - cyDelta, 0, cyDelta);
+            break;
+        case HIT_MIDDLE_LEFT:
+            imageModel.Crop(cxImage - cxDelta, cyImage, cxDelta, 0);
+            break;
+        case HIT_MIDDLE_RIGHT:
+            imageModel.Crop(cxImage + cxDelta, cyImage, 0, 0);
+            break;
+        case HIT_LOWER_LEFT:
+            imageModel.Crop(cxImage - cxDelta, cyImage + cyDelta, cxDelta, 0);
+            break;
+        case HIT_LOWER_CENTER:
+            imageModel.Crop(cxImage, cyImage + cyDelta, 0, 0);
+            break;
+        case HIT_LOWER_RIGHT:
+            imageModel.Crop(cxImage + cxDelta, cyImage + cyDelta, 0, 0);
+            break;
         default:
             break;
     }
 
+    // Finish dragging
+    m_whereHit = HIT_NONE;
     toolsModel.resetTool();  // resets the point-buffer of the polygon and bezier functions
+    Update(NULL);
+    Invalidate(TRUE);
+
+    return 0;
+}
+
+LRESULT CCanvasWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    POINT pt;
+    ::GetCursorPos(&pt);
+    ScreenToClient(&pt);
+
+    if (!setCursorOnSizeBox(HitTest(pt)))
+        ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
+
+    return 0;
+}
+
+LRESULT CCanvasWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    if (wParam == VK_ESCAPE && ::GetCapture() == m_hWnd)
+    {
+        // Cancel dragging
+        m_whereHit = HIT_NONE;
+        ::ReleaseCapture();
+    }
+
+    return 0;
+}
+
+LRESULT CCanvasWindow::OnCancelMode(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    // Cancel dragging
+    m_whereHit = HIT_NONE;
+    Invalidate(TRUE);
     return 0;
 }
 
@@ -170,3 +320,26 @@ LRESULT CCanvasWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOO
 {
     return ::SendMessage(GetParent(), nMsg, wParam, lParam);
 }
+
+LRESULT CCanvasWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM)_T(""));
+    return 0;
+}
+
+LRESULT CCanvasWindow::OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    return TRUE; // do nothing => transparent background
+}
+
+LRESULT CCanvasWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+    RECT rcClient;
+    GetClientRect(&rcClient);
+
+    PAINTSTRUCT ps;
+    HDC hDC = BeginPaint(&ps);
+    DoDraw(hDC, rcClient, ps.rcPaint);
+    EndPaint(&ps);
+    return 0;
+}
index 2261351..fe2251c 100644 (file)
@@ -15,18 +15,44 @@ public:
 
     BEGIN_MSG_MAP(CCanvasWindow)
         MESSAGE_HANDLER(WM_SIZE, OnSize)
+        MESSAGE_HANDLER(WM_PAINT, OnPaint)
+        MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
         MESSAGE_HANDLER(WM_HSCROLL, OnHScroll)
         MESSAGE_HANDLER(WM_VSCROLL, OnVScroll)
+        MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
         MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
+        MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
+        MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
+        MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
         MESSAGE_HANDLER(WM_MOUSEWHEEL, OnMouseWheel)
+        MESSAGE_HANDLER(WM_CANCELMODE, OnCancelMode)
+        MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
     END_MSG_MAP()
 
+    CCanvasWindow();
+
     VOID Update(HWND hwndFrom);
 
 protected:
+    CANVAS_HITTEST m_whereHit;
+    POINT m_ptOrig; // The origin of drag start
+
+    CANVAS_HITTEST HitTest(POINT pt);
+    RECT GetBaseRect();
+    VOID DoDraw(HDC hDC, RECT& rcClient, RECT& rcPaint);
+    VOID OnHVScroll(WPARAM wParam, INT fnBar);
+
     LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnHScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnVScroll(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
     LRESULT OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnCancelMode(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+    LRESULT OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 };
index 490ff9a..296a6f5 100644 (file)
@@ -245,34 +245,6 @@ RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2)
     SetROP2(hdc, oldRop);
 }
 
-void
-SelectionFrame(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF system_selection_color)
-{
-    HBRUSH oldBrush;
-    LOGBRUSH logbrush;
-    HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_DOT, 1, system_selection_color));
-
-    logbrush.lbStyle = BS_HOLLOW;
-    logbrush.lbColor = 0;
-    logbrush.lbHatch = 0;
-    oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
-    Rectangle(hdc, x1, y1, x2, y2); /* SEL BOX FRAME */
-    DeleteObject(SelectObject(hdc, oldBrush));
-    DeleteObject(SelectObject(hdc, oldPen));
-    oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, system_selection_color));
-    oldBrush = (HBRUSH) SelectObject(hdc, CreateSolidBrush(system_selection_color));
-    Rectangle(hdc, x1 - 1, y1 - 1, x1 + 2, y1 + 2);
-    Rectangle(hdc, x2 - 2, y1 - 1, x2 + 2, y1 + 2);
-    Rectangle(hdc, x1 - 1, y2 - 2, x1 + 2, y2 + 1);
-    Rectangle(hdc, x2 - 2, y2 - 2, x2 + 2, y2 + 1);
-    Rectangle(hdc, (x1 + x2) / 2 - 1, y1 - 1, (x1 + x2) / 2 + 2, y1 + 2);
-    Rectangle(hdc, (x1 + x2) / 2 - 1, y2 - 2, (x1 + x2) / 2 + 2, y2 + 1);
-    Rectangle(hdc, x1 - 1, (y1 + y2) / 2 - 1, x1 + 2, (y1 + y2) / 2 + 2);
-    Rectangle(hdc, x2 - 2, (y1 + y2) / 2 - 1, x2 + 1, (y1 + y2) / 2 + 2);
-    DeleteObject(SelectObject(hdc, oldBrush));
-    DeleteObject(SelectObject(hdc, oldPen));
-}
-
 void
 Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style)
 {
index 26178a8..5401168 100644 (file)
@@ -32,8 +32,6 @@ void Brush(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF color, LONG sty
 
 void RectSel(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2);
 
-void SelectionFrame(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF system_selection_color);
-
 void Text(HDC hdc, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF fg, COLORREF bg, LPCTSTR lpchText, HFONT font, LONG style);
 
 extern BOOL
index b0099e5..3a366c0 100644 (file)
@@ -70,14 +70,6 @@ extern CPaletteWindow paletteWindow;
 extern CCanvasWindow canvasWindow;
 extern CSelectionWindow selectionWindow;
 extern CImgAreaWindow imageArea;
-extern CSizeboxWindow sizeboxLeftTop;
-extern CSizeboxWindow sizeboxCenterTop;
-extern CSizeboxWindow sizeboxRightTop;
-extern CSizeboxWindow sizeboxLeftCenter;
-extern CSizeboxWindow sizeboxRightCenter;
-extern CSizeboxWindow sizeboxLeftBottom;
-extern CSizeboxWindow sizeboxCenterBottom;
-extern CSizeboxWindow sizeboxRightBottom;
 extern CTextEditWindow textEditWindow;
 
 /* VARIABLES declared in dialogs.cpp ********************************/
index 933ef86..82b70d9 100644 (file)
@@ -57,14 +57,6 @@ CPaletteWindow paletteWindow;
 CCanvasWindow canvasWindow;
 CSelectionWindow selectionWindow;
 CImgAreaWindow imageArea;
-CSizeboxWindow sizeboxLeftTop;
-CSizeboxWindow sizeboxCenterTop;
-CSizeboxWindow sizeboxRightTop;
-CSizeboxWindow sizeboxLeftCenter;
-CSizeboxWindow sizeboxRightCenter;
-CSizeboxWindow sizeboxLeftBottom;
-CSizeboxWindow sizeboxCenterBottom;
-CSizeboxWindow sizeboxRightBottom;
 CTextEditWindow textEditWindow;
 
 // get file name extension from filter string
@@ -289,16 +281,6 @@ _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument
         }
     }
 
-    /* creating the size boxes */
-    RECT sizeboxPos = {0, 0, GRIP_SIZE, GRIP_SIZE};
-    sizeboxLeftTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
-    sizeboxCenterTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
-    sizeboxRightTop.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
-    sizeboxLeftCenter.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
-    sizeboxRightCenter.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
-    sizeboxLeftBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
-    sizeboxCenterBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
-    sizeboxRightBottom.Create(canvasWindow, sizeboxPos, NULL, WS_CHILD | WS_VISIBLE);
     /* placing the size boxes around the image */
     imageArea.SendMessage(WM_SIZE, 0, 0);
 
index fda0bc6..57f2894 100644 (file)
@@ -19,9 +19,13 @@ POINT ToolBase::pointStack[256] = { { 0 } };
 void
 placeSelWin()
 {
-    selectionWindow.MoveWindow(Zoomed(selectionModel.GetDestRectLeft()), Zoomed(selectionModel.GetDestRectTop()),
-        Zoomed(selectionModel.GetDestRectWidth()) + 2 * GRIP_SIZE,
-        Zoomed(selectionModel.GetDestRectHeight()) + 2 * GRIP_SIZE, TRUE);
+    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);
 }
@@ -712,11 +716,6 @@ struct ShapeTool : ToolBase
             imageModel.ResetToPrevious();
             --pointSP;
             draw(m_bLeftButton, -1, -1, TRUE);
-            pointSP = 0;
-        }
-        else
-        {
-            imageModel.Undo(TRUE);
         }
         ToolBase::OnFinishDraw();
     }
index 7c1f23a..cd24f7f 100644 (file)
@@ -19,6 +19,7 @@
 #include <atlpath.h>
 #include <atlstr.h>
 #include <atlwin.h>
+#include <atltypes.h>
 #include <windowsx.h>
 #include <commdlg.h>
 #include <commctrl.h>
 #define WM_IMAGEMODELIMAGECHANGED        (WM_APP + 6)
 #define WM_SELECTIONMODELREFRESHNEEDED   (WM_APP + 7)
 
+enum CANVAS_HITTEST // hit
+{
+    HIT_NONE = 0, // Nothing hit or outside
+    HIT_UPPER_LEFT,
+    HIT_UPPER_CENTER,
+    HIT_UPPER_RIGHT,
+    HIT_MIDDLE_LEFT,
+    HIT_MIDDLE_RIGHT,
+    HIT_LOWER_LEFT,
+    HIT_LOWER_CENTER,
+    HIT_LOWER_RIGHT,
+    HIT_BORDER,
+    HIT_INNER,
+};
+
 #include "resource.h"
-#include "canvas.h"
 #include "drawing.h"
 #include "dib.h"
 #include "fullscreen.h"
@@ -53,6 +68,7 @@
 #include "selection.h"
 #include "selectionmodel.h"
 #include "sizebox.h"
+#include "canvas.h"
 #include "textedit.h"
 #include "toolbox.h"
 #include "toolsettings.h"
index 64d0153..4a328b0 100644 (file)
@@ -33,24 +33,6 @@ void CSelectionWindow::ForceRefreshSelectionContents()
 
 int CSelectionWindow::IdentifyCorner(int iXPos, int iYPos, int iWidth, int iHeight)
 {
-    POINT pt = { iXPos, iYPos };
-    HWND hwndChild = ChildWindowFromPointEx(pt, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
-    if (hwndChild == sizeboxLeftTop)
-        return ACTION_RESIZE_TOP_LEFT;
-    if (hwndChild == sizeboxCenterTop)
-        return ACTION_RESIZE_TOP;
-    if (hwndChild == sizeboxRightTop)
-        return ACTION_RESIZE_TOP_RIGHT;
-    if (hwndChild == sizeboxRightCenter)
-        return ACTION_RESIZE_RIGHT;
-    if (hwndChild == sizeboxLeftCenter)
-        return ACTION_RESIZE_LEFT;
-    if (hwndChild == sizeboxCenterBottom)
-        return ACTION_RESIZE_BOTTOM;
-    if (hwndChild == sizeboxRightBottom)
-        return ACTION_RESIZE_BOTTOM_RIGHT;
-    if (hwndChild == sizeboxLeftBottom)
-        return ACTION_RESIZE_BOTTOM_LEFT;
     return 0;
 }
 
@@ -60,10 +42,9 @@ LRESULT CSelectionWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL&
     HDC hDC = BeginPaint(&ps);
     if (!m_bMoving)
     {
-        SelectionFrame(hDC, 1, 1,
-                       Zoomed(selectionModel.GetDestRectWidth()) + (GRIP_SIZE * 2) - 1,
-                       Zoomed(selectionModel.GetDestRectHeight()) + (GRIP_SIZE * 2) - 1,
-                       GetSysColor(COLOR_HIGHLIGHT));
+        RECT rcClient;
+        GetClientRect(&rcClient);
+        drawSizeBoxes(hDC, &rcClient, TRUE, &ps.rcPaint);
     }
     EndPaint(&ps);
     return 0;
@@ -93,7 +74,16 @@ LRESULT CSelectionWindow::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lPar
 
 LRESULT CSelectionWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    SetCursor(LoadCursor(NULL, IDC_SIZEALL));
+    RECT rcClient;
+    GetClientRect(&rcClient);
+
+    POINT pt;
+    ::GetCursorPos(&pt);
+    ScreenToClient(&pt);
+
+    if (!setCursorOnSizeBox(getSizeBoxHitTest(pt, &rcClient)))
+        ::SetCursor(::LoadCursor(NULL, IDC_SIZEALL));
+
     return 0;
 }
 
index 2ebbbcc..8f3c502 100644 (file)
  *              Katayama Hirofumi MZ
  */
 
-/* INCLUDES *********************************************************/
-
 #include "precomp.h"
 
-/* FUNCTIONS ********************************************************/
-
-static BOOL resizing = FALSE;
-static short xOrig;
-static short yOrig;
-
-LRESULT CSizeboxWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+static LPCWSTR s_cursor_shapes[] =
 {
-    if ((m_hWnd == sizeboxLeftTop.m_hWnd) || (m_hWnd == sizeboxRightBottom.m_hWnd))
-        SetCursor(LoadCursor(NULL, IDC_SIZENWSE));
-    if ((m_hWnd == sizeboxLeftBottom.m_hWnd) || (m_hWnd == sizeboxRightTop.m_hWnd))
-        SetCursor(LoadCursor(NULL, IDC_SIZENESW));
-    if ((m_hWnd == sizeboxLeftCenter.m_hWnd) || (m_hWnd == sizeboxRightCenter.m_hWnd))
-        SetCursor(LoadCursor(NULL, IDC_SIZEWE));
-    if ((m_hWnd == sizeboxCenterTop.m_hWnd) || (m_hWnd == sizeboxCenterBottom.m_hWnd))
-        SetCursor(LoadCursor(NULL, IDC_SIZENS));
-    return 0;
-}
+    IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
+    IDC_SIZEWE,               IDC_SIZEWE,
+    IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE,
+};
 
-LRESULT CSizeboxWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
-{
-    resizing = TRUE;
-    xOrig = GET_X_LPARAM(lParam);
-    yOrig = GET_Y_LPARAM(lParam);
-    SetCapture();
-    return 0;
-}
+/* FUNCTIONS ********************************************************/
 
-LRESULT CSizeboxWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+BOOL setCursorOnSizeBox(CANVAS_HITTEST hit)
 {
-    if (resizing)
+    if (HIT_UPPER_LEFT <= hit && hit <= HIT_LOWER_RIGHT)
     {
-        CString strSize;
-        short xRel;
-        short yRel;
-        int imgXRes = imageModel.GetWidth();
-        int imgYRes = imageModel.GetHeight();
-        xRel = UnZoomed(GET_X_LPARAM(lParam) - xOrig);
-        yRel = UnZoomed(GET_Y_LPARAM(lParam) - yOrig);
-        if (m_hWnd == sizeboxLeftTop.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes - xRel, imgYRes - yRel);
-        if (m_hWnd == sizeboxCenterTop.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes, imgYRes - yRel);
-        if (m_hWnd == sizeboxRightTop.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes + xRel, imgYRes - yRel);
-        if (m_hWnd == sizeboxLeftCenter.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes - xRel, imgYRes);
-        if (m_hWnd == sizeboxRightCenter.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes + xRel, imgYRes);
-        if (m_hWnd == sizeboxLeftBottom.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes - xRel, imgYRes + yRel);
-        if (m_hWnd == sizeboxCenterBottom.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes, imgYRes + yRel);
-        if (m_hWnd == sizeboxRightBottom.m_hWnd)
-            strSize.Format(_T("%d x %d"), imgXRes + xRel, imgYRes + yRel);
-        SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
+        ::SetCursor(::LoadCursor(NULL, s_cursor_shapes[hit - HIT_UPPER_LEFT]));
+        return TRUE;
     }
-    return 0;
+    return FALSE;
 }
 
-LRESULT CSizeboxWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+BOOL getSizeBoxRect(LPRECT prc, CANVAS_HITTEST hit, LPCRECT prcBase)
 {
-    if (resizing)
+    switch (hit)
     {
-        short xRel;
-        short yRel;
-        int imgXRes = imageModel.GetWidth();
-        int imgYRes = imageModel.GetHeight();
-        xRel = (GET_X_LPARAM(lParam) - xOrig) * 1000 / toolsModel.GetZoom();
-        yRel = (GET_Y_LPARAM(lParam) - yOrig) * 1000 / toolsModel.GetZoom();
-        if (m_hWnd == sizeboxLeftTop)
-            imageModel.Crop(imgXRes - xRel, imgYRes - yRel, xRel, yRel);
-        if (m_hWnd == sizeboxCenterTop.m_hWnd)
-            imageModel.Crop(imgXRes, imgYRes - yRel, 0, yRel);
-        if (m_hWnd == sizeboxRightTop.m_hWnd)
-            imageModel.Crop(imgXRes + xRel, imgYRes - yRel, 0, yRel);
-        if (m_hWnd == sizeboxLeftCenter.m_hWnd)
-            imageModel.Crop(imgXRes - xRel, imgYRes, xRel, 0);
-        if (m_hWnd == sizeboxRightCenter.m_hWnd)
-            imageModel.Crop(imgXRes + xRel, imgYRes, 0, 0);
-        if (m_hWnd == sizeboxLeftBottom.m_hWnd)
-            imageModel.Crop(imgXRes - xRel, imgYRes + yRel, xRel, 0);
-        if (m_hWnd == sizeboxCenterBottom.m_hWnd)
-            imageModel.Crop(imgXRes, imgYRes + yRel, 0, 0);
-        if (m_hWnd == sizeboxRightBottom.m_hWnd)
-            imageModel.Crop(imgXRes + xRel, imgYRes + yRel, 0, 0);
-        SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) _T(""));
+        case HIT_UPPER_LEFT:
+            prc->left = prcBase->left;
+            prc->top = prcBase->top;
+            break;
+        case HIT_UPPER_CENTER:
+            prc->left = (prcBase->left + prcBase->right - GRIP_SIZE) / 2;
+            prc->top = prcBase->top;
+            break;
+        case HIT_UPPER_RIGHT:
+            prc->left = prcBase->right - GRIP_SIZE;
+            prc->top = prcBase->top;
+            break;
+        case HIT_MIDDLE_LEFT:
+            prc->left = prcBase->left;
+            prc->top = (prcBase->top + prcBase->bottom - GRIP_SIZE) / 2;
+            break;
+        case HIT_MIDDLE_RIGHT:
+            prc->left = prcBase->right - GRIP_SIZE;
+            prc->top = (prcBase->top + prcBase->bottom - GRIP_SIZE) / 2;
+            break;
+        case HIT_LOWER_LEFT:
+            prc->left = prcBase->left;
+            prc->top = prcBase->bottom - GRIP_SIZE;
+            break;
+        case HIT_LOWER_CENTER:
+            prc->left = (prcBase->left + prcBase->right - GRIP_SIZE) / 2;
+            prc->top = prcBase->bottom - GRIP_SIZE;
+            break;
+        case HIT_LOWER_RIGHT:
+            prc->left = prcBase->right - GRIP_SIZE;
+            prc->top = prcBase->bottom - GRIP_SIZE;
+            break;
+        case HIT_INNER:
+            *prc = *prcBase;
+            ::InflateRect(prc, -GRIP_SIZE, -GRIP_SIZE);
+            return TRUE;
+        default:
+            ::SetRectEmpty(prc);
+            return FALSE;
     }
-    resizing = FALSE;
-    ReleaseCapture();
-    return 0;
+
+    prc->right = prc->left + GRIP_SIZE;
+    prc->bottom = prc->top + GRIP_SIZE;
+    return TRUE;
 }
 
-LRESULT CSizeboxWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+CANVAS_HITTEST getSizeBoxHitTest(POINT pt, LPCRECT prcBase)
 {
-    resizing = FALSE;
-    return 0;
+    RECT rc;
+
+    if (!::PtInRect(prcBase, pt))
+        return HIT_NONE;
+
+    rc = *prcBase;
+    ::InflateRect(&rc, -GRIP_SIZE, -GRIP_SIZE);
+    if (::PtInRect(&rc, pt))
+        return HIT_INNER;
+
+    for (INT i = HIT_UPPER_LEFT; i <= HIT_LOWER_RIGHT; ++i)
+    {
+        CANVAS_HITTEST hit = (CANVAS_HITTEST)i;
+        getSizeBoxRect(&rc, hit, prcBase);
+        if (::PtInRect(&rc, pt))
+            return hit;
+    }
+
+    return HIT_BORDER;
 }
 
-LRESULT CSizeboxWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+VOID drawSizeBoxes(HDC hdc, LPCRECT prcBase, BOOL bDrawFrame, LPCRECT prcPaint)
 {
-    if (wParam == VK_ESCAPE)
+    CRect rc, rcIntersect;
+
+    if (prcPaint && !::IntersectRect(&rcIntersect, prcPaint, prcBase))
+        return;
+
+    if (bDrawFrame)
+    {
+        rc = *prcBase;
+        ::InflateRect(&rc, -GRIP_SIZE / 2, -GRIP_SIZE / 2);
+
+        LOGBRUSH logBrush = { BS_HOLLOW, 0, 0 };
+        COLORREF rgbHighlight = ::GetSysColor(COLOR_HIGHLIGHT);
+        HGDIOBJ oldPen = ::SelectObject(hdc, ::CreatePen(PS_DOT, 1, rgbHighlight));
+        HGDIOBJ oldBrush = ::SelectObject(hdc, ::CreateBrushIndirect(&logBrush));
+        ::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
+        ::DeleteObject(::SelectObject(hdc, oldBrush));
+        ::DeleteObject(::SelectObject(hdc, oldPen));
+    }
+
+    for (INT i = HIT_UPPER_LEFT; i <= HIT_LOWER_RIGHT; ++i)
     {
-        if (GetCapture() == m_hWnd)
-        {
-            ReleaseCapture();
-        }
+        getSizeBoxRect(&rc, (CANVAS_HITTEST)i, prcBase);
+        if (!prcPaint || ::IntersectRect(&rcIntersect, &rc, prcPaint))
+            ::FillRect(hdc, &rc, (HBRUSH)(COLOR_HIGHLIGHT + 1));
     }
-    return 0;
 }
index 551f0e6..9a6e423 100644 (file)
@@ -9,24 +9,7 @@
 
 #pragma once
 
-class CSizeboxWindow : public CWindowImpl<CSizeboxWindow>
-{
-public:
-    DECLARE_WND_CLASS_EX(_T("Sizebox"), CS_DBLCLKS, COLOR_HIGHLIGHT)
-
-    BEGIN_MSG_MAP(CSizeboxWindow)
-        MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
-        MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
-        MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
-        MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
-        MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
-        MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
-    END_MSG_MAP()
-
-    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 OnLButtonUp(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);
-};
+BOOL setCursorOnSizeBox(CANVAS_HITTEST hit);
+BOOL getSizeBoxRect(LPRECT prc, CANVAS_HITTEST hit, LPCRECT prcBase);
+CANVAS_HITTEST getSizeBoxHitTest(POINT pt, LPCRECT prcBase);
+VOID drawSizeBoxes(HDC hdc, LPCRECT prcBase, BOOL bDrawFrame = FALSE, LPCRECT prcPaint = NULL);
index e121a4f..ee4e9da 100644 (file)
@@ -437,17 +437,10 @@ LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH
         HWND hwndCapture = GetCapture();
         if (hwndCapture)
         {
-            if (selectionWindow.m_hWnd == hwndCapture ||
+            if (canvasWindow.m_hWnd == hwndCapture ||
+                selectionWindow.m_hWnd == hwndCapture ||
                 imageArea.m_hWnd == hwndCapture ||
-                fullscreenWindow.m_hWnd == hwndCapture ||
-                sizeboxLeftTop.m_hWnd == hwndCapture ||
-                sizeboxCenterTop.m_hWnd == hwndCapture ||
-                sizeboxRightTop.m_hWnd == hwndCapture ||
-                sizeboxLeftCenter.m_hWnd == hwndCapture ||
-                sizeboxRightCenter.m_hWnd == hwndCapture ||
-                sizeboxLeftBottom.m_hWnd == hwndCapture ||
-                sizeboxCenterBottom.m_hWnd == hwndCapture ||
-                sizeboxRightBottom.m_hWnd == hwndCapture)
+                fullscreenWindow.m_hWnd == hwndCapture)
             {
                 SendMessage(hwndCapture, nMsg, wParam, lParam);
             }