1 /*
2  * PROJECT:    PAINT for ReactOS
3  * LICENSE:    LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:    Window procedure of the size boxes
5  * COPYRIGHT:  Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
6  *             Copyright 2017 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7  */
8 
9 #include "precomp.h"
10 
11 static LPCWSTR s_cursor_shapes[] =
12 {
13     IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW,
14     IDC_SIZEWE,               IDC_SIZEWE,
15     IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE,
16 };
17 
18 /* FUNCTIONS ********************************************************/
19 
20 BOOL setCursorOnSizeBox(HITTEST hit)
21 {
22     if (HIT_UPPER_LEFT <= hit && hit <= HIT_LOWER_RIGHT)
23     {
24         ::SetCursor(::LoadCursorW(NULL, s_cursor_shapes[hit - HIT_UPPER_LEFT]));
25         return TRUE;
26     }
27     return FALSE;
28 }
29 
30 BOOL getSizeBoxRect(LPRECT prc, HITTEST hit, LPCRECT prcBase)
31 {
32     switch (hit)
33     {
34         case HIT_UPPER_LEFT:
35             prc->left = prcBase->left;
36             prc->top = prcBase->top;
37             break;
38         case HIT_UPPER_CENTER:
39             prc->left = (prcBase->left + prcBase->right - GRIP_SIZE) / 2;
40             prc->top = prcBase->top;
41             break;
42         case HIT_UPPER_RIGHT:
43             prc->left = prcBase->right - GRIP_SIZE;
44             prc->top = prcBase->top;
45             break;
46         case HIT_MIDDLE_LEFT:
47             prc->left = prcBase->left;
48             prc->top = (prcBase->top + prcBase->bottom - GRIP_SIZE) / 2;
49             break;
50         case HIT_MIDDLE_RIGHT:
51             prc->left = prcBase->right - GRIP_SIZE;
52             prc->top = (prcBase->top + prcBase->bottom - GRIP_SIZE) / 2;
53             break;
54         case HIT_LOWER_LEFT:
55             prc->left = prcBase->left;
56             prc->top = prcBase->bottom - GRIP_SIZE;
57             break;
58         case HIT_LOWER_CENTER:
59             prc->left = (prcBase->left + prcBase->right - GRIP_SIZE) / 2;
60             prc->top = prcBase->bottom - GRIP_SIZE;
61             break;
62         case HIT_LOWER_RIGHT:
63             prc->left = prcBase->right - GRIP_SIZE;
64             prc->top = prcBase->bottom - GRIP_SIZE;
65             break;
66         case HIT_INNER:
67             *prc = *prcBase;
68             ::InflateRect(prc, -GRIP_SIZE, -GRIP_SIZE);
69             return TRUE;
70         default:
71             ::SetRectEmpty(prc);
72             return FALSE;
73     }
74 
75     prc->right = prc->left + GRIP_SIZE;
76     prc->bottom = prc->top + GRIP_SIZE;
77     return TRUE;
78 }
79 
80 HITTEST getSizeBoxHitTest(POINT pt, LPCRECT prcBase)
81 {
82     CRect rc;
83 
84     if (!::PtInRect(prcBase, pt))
85         return HIT_NONE;
86 
87     rc = *prcBase;
88     rc.InflateRect(-GRIP_SIZE, -GRIP_SIZE);
89     if (rc.PtInRect(pt))
90         return HIT_INNER;
91 
92     for (INT i = HIT_UPPER_LEFT; i <= HIT_LOWER_RIGHT; ++i)
93     {
94         HITTEST hit = (HITTEST)i;
95         getSizeBoxRect(&rc, hit, prcBase);
96         if (rc.PtInRect(pt))
97             return hit;
98     }
99 
100     return HIT_BORDER;
101 }
102 
103 VOID drawSizeBoxes(HDC hdc, LPCRECT prcBase, BOOL bDrawFrame, LPCRECT prcPaint)
104 {
105     CRect rc, rcIntersect;
106 
107     if (prcPaint && !::IntersectRect(&rcIntersect, prcPaint, prcBase))
108         return;
109 
110     if (bDrawFrame)
111     {
112         rc = *prcBase;
113         rc.InflateRect(-GRIP_SIZE / 2, -GRIP_SIZE / 2);
114 
115         LOGBRUSH logBrush = { BS_HOLLOW, 0, 0 };
116         COLORREF rgbHighlight = ::GetSysColor(COLOR_HIGHLIGHT);
117         HGDIOBJ oldPen = ::SelectObject(hdc, ::CreatePen(PS_DOT, 1, rgbHighlight));
118         HGDIOBJ oldBrush = ::SelectObject(hdc, ::CreateBrushIndirect(&logBrush));
119         ::Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
120         ::DeleteObject(::SelectObject(hdc, oldBrush));
121         ::DeleteObject(::SelectObject(hdc, oldPen));
122     }
123 
124     for (INT i = HIT_UPPER_LEFT; i <= HIT_LOWER_RIGHT; ++i)
125     {
126         getSizeBoxRect(&rc, (HITTEST)i, prcBase);
127         if (!prcPaint || ::IntersectRect(&rcIntersect, &rc, prcPaint))
128             ::FillRect(hdc, &rc, (HBRUSH)(COLOR_HIGHLIGHT + 1));
129     }
130 }
131