2 * PROJECT: PAINT for ReactOS
4 * FILE: base/applications/mspaint_new/selection.cpp
5 * PURPOSE: Window procedure of the selection window
6 * PROGRAMMERS: Benedikt Freisen
9 /* INCLUDES *********************************************************/
13 /* DEFINES **********************************************************/
16 #define ACTION_RESIZE_TOP_LEFT 1
17 #define ACTION_RESIZE_TOP 2
18 #define ACTION_RESIZE_TOP_RIGHT 3
19 #define ACTION_RESIZE_LEFT 4
20 #define ACTION_RESIZE_RIGHT 5
21 #define ACTION_RESIZE_BOTTOM_LEFT 6
22 #define ACTION_RESIZE_BOTTOM 7
23 #define ACTION_RESIZE_BOTTOM_RIGHT 8
25 /* FUNCTIONS ********************************************************/
27 LPCTSTR cursors
[9] = { /* action to mouse cursor lookup table */
30 IDC_SIZENWSE
, IDC_SIZENS
, IDC_SIZENESW
,
31 IDC_SIZEWE
, IDC_SIZEWE
,
32 IDC_SIZENESW
, IDC_SIZENS
, IDC_SIZENWSE
36 int action
= ACTION_MOVE
;
40 DWORD system_selection_color
;
43 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
)
51 hTempDC
= CreateCompatibleDC(hdcSrc
);
52 hTempDC2
= CreateCompatibleDC(hdcSrc
);
53 hTempBm
= CreateCompatibleBitmap(hTempDC
, nWidth
, nHeight
);
54 SelectObject(hTempDC
, hTempBm
);
55 hTempBrush
= CreateSolidBrush(keyColor
);
56 SelectObject(hTempDC
, hTempBrush
);
57 BitBlt(hTempDC
, 0, 0, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, SRCCOPY
);
58 PatBlt(hTempDC
, 0, 0, nWidth
, nHeight
, PATINVERT
);
59 hTempMask
= CreateBitmap(nWidth
, nHeight
, 1, 1, NULL
);
60 SelectObject(hTempDC2
, hTempMask
);
61 BitBlt(hTempDC2
, 0, 0, nWidth
, nHeight
, hTempDC
, 0, 0, SRCCOPY
);
62 SelectObject(hTempDC
, hbmMask
);
63 BitBlt(hTempDC2
, 0, 0, nWidth
, nHeight
, hTempDC
, xMask
, yMask
, SRCAND
);
64 MaskBlt(hdcDest
, nXDest
, nYDest
, nWidth
, nHeight
, hdcSrc
, nXSrc
, nYSrc
, hTempMask
, xMask
, yMask
, dwRop
);
67 DeleteObject(hTempBm
);
68 DeleteObject(hTempBrush
);
69 DeleteObject(hTempMask
);
74 ForceRefreshSelectionContents()
76 if (selectionWindow
.IsWindowVisible())
78 selectionWindow
.SendMessage(WM_LBUTTONDOWN
, 0, MAKELPARAM(0, 0));
79 selectionWindow
.SendMessage(WM_MOUSEMOVE
, 0, MAKELPARAM(0, 0));
80 selectionWindow
.SendMessage(WM_LBUTTONUP
, 0, MAKELPARAM(0, 0));
85 identifyCorner(short x
, short y
, short w
, short h
)
90 return ACTION_RESIZE_TOP_LEFT
;
91 if ((x
< w
/ 2 + 2) && (x
>= w
/ 2 - 1))
92 return ACTION_RESIZE_TOP
;
94 return ACTION_RESIZE_TOP_RIGHT
;
96 if ((y
< h
/ 2 + 2) && (y
>= h
/ 2 - 1))
99 return ACTION_RESIZE_LEFT
;
101 return ACTION_RESIZE_RIGHT
;
106 return ACTION_RESIZE_BOTTOM_LEFT
;
107 if ((x
< w
/ 2 + 2) && (x
>= w
/ 2 - 1))
108 return ACTION_RESIZE_BOTTOM
;
110 return ACTION_RESIZE_BOTTOM_RIGHT
;
115 LRESULT
CSelectionWindow::OnPaint(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
120 DefWindowProc(WM_PAINT
, wParam
, lParam
);
121 SelectionFrame(hDC
, 1, 1, RECT_WIDTH(rectSel_dest
) * toolsModel
.GetZoom() / 1000 + 5,
122 RECT_HEIGHT(rectSel_dest
) * toolsModel
.GetZoom() / 1000 + 5,
123 system_selection_color
);
129 LRESULT
CSelectionWindow::OnEraseBkgnd(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
131 // do nothing => transparent background
135 LRESULT
CSelectionWindow::OnCreate(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
137 /* update the system selection color */
138 system_selection_color
= GetSysColor(COLOR_HIGHLIGHT
);
139 SendMessage(WM_PAINT
, 0, MAKELPARAM(0, 0));
143 LRESULT
CSelectionWindow::OnSysColorChange(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
145 /* update the system selection color */
146 system_selection_color
= GetSysColor(COLOR_HIGHLIGHT
);
147 SendMessage(WM_PAINT
, 0, MAKELPARAM(0, 0));
151 LRESULT
CSelectionWindow::OnSetCursor(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
153 SetCursor(LoadCursor(NULL
, IDC_SIZEALL
));
157 LRESULT
CSelectionWindow::OnLButtonDown(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
159 pos
.x
= GET_X_LPARAM(lParam
);
160 pos
.y
= GET_Y_LPARAM(lParam
);
164 if (action
!= ACTION_MOVE
)
165 SetCursor(LoadCursor(NULL
, cursors
[action
]));
167 scrlClientWindow
.InvalidateRect(NULL
, TRUE
);
168 imageArea
.SendMessage(WM_PAINT
, 0, 0);
172 LRESULT
CSelectionWindow::OnMouseMove(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
179 frac
.x
+= GET_X_LPARAM(lParam
) - pos
.x
;
180 frac
.y
+= GET_Y_LPARAM(lParam
) - pos
.y
;
181 delta
.x
+= frac
.x
* 1000 / toolsModel
.GetZoom();
182 delta
.y
+= frac
.y
* 1000 / toolsModel
.GetZoom();
183 if (toolsModel
.GetZoom() < 1000)
190 frac
.x
-= (frac
.x
* 1000 / toolsModel
.GetZoom()) * toolsModel
.GetZoom() / 1000;
191 frac
.y
-= (frac
.y
* 1000 / toolsModel
.GetZoom()) * toolsModel
.GetZoom() / 1000;
195 case ACTION_MOVE
: /* move selection */
196 deltaUsed
.x
= delta
.x
;
197 deltaUsed
.y
= delta
.y
;
198 OffsetRect(&rectSel_dest
, deltaUsed
.x
, deltaUsed
.y
);
200 case ACTION_RESIZE_TOP_LEFT
: /* resize at upper left corner */
201 deltaUsed
.x
= min(delta
.x
, RECT_WIDTH(rectSel_dest
) - 1);
202 deltaUsed
.y
= min(delta
.y
, RECT_HEIGHT(rectSel_dest
) - 1);
203 rectSel_dest
.left
+= deltaUsed
.x
;
204 rectSel_dest
.top
+= deltaUsed
.y
;
206 case ACTION_RESIZE_TOP
: /* resize at top edge */
207 deltaUsed
.x
= delta
.x
;
208 deltaUsed
.y
= min(delta
.y
, RECT_HEIGHT(rectSel_dest
) - 1);
209 rectSel_dest
.top
+= deltaUsed
.y
;
211 case ACTION_RESIZE_TOP_RIGHT
: /* resize at upper right corner */
212 deltaUsed
.x
= max(delta
.x
, -(RECT_WIDTH(rectSel_dest
) - 1));
213 deltaUsed
.y
= min(delta
.y
, RECT_HEIGHT(rectSel_dest
) - 1);
214 rectSel_dest
.top
+= deltaUsed
.y
;
215 rectSel_dest
.right
+= deltaUsed
.x
;
217 case ACTION_RESIZE_LEFT
: /* resize at left edge */
218 deltaUsed
.x
= min(delta
.x
, RECT_WIDTH(rectSel_dest
) - 1);
219 deltaUsed
.y
= delta
.y
;
220 rectSel_dest
.left
+= deltaUsed
.x
;
222 case ACTION_RESIZE_RIGHT
: /* resize at right edge */
223 deltaUsed
.x
= max(delta
.x
, -(RECT_WIDTH(rectSel_dest
) - 1));
224 deltaUsed
.y
= delta
.y
;
225 rectSel_dest
.right
+= deltaUsed
.x
;
227 case ACTION_RESIZE_BOTTOM_LEFT
: /* resize at lower left corner */
228 deltaUsed
.x
= min(delta
.x
, RECT_WIDTH(rectSel_dest
) - 1);
229 deltaUsed
.y
= max(delta
.y
, -(RECT_HEIGHT(rectSel_dest
) - 1));
230 rectSel_dest
.left
+= deltaUsed
.x
;
231 rectSel_dest
.bottom
+= deltaUsed
.y
;
233 case ACTION_RESIZE_BOTTOM
: /* resize at bottom edge */
234 deltaUsed
.x
= delta
.x
;
235 deltaUsed
.y
= max(delta
.y
, -(RECT_HEIGHT(rectSel_dest
) - 1));
236 rectSel_dest
.bottom
+= deltaUsed
.y
;
238 case ACTION_RESIZE_BOTTOM_RIGHT
: /* resize at lower right corner */
239 deltaUsed
.x
= max(delta
.x
, -(RECT_WIDTH(rectSel_dest
) - 1));
240 deltaUsed
.y
= max(delta
.y
, -(RECT_HEIGHT(rectSel_dest
) - 1));
241 rectSel_dest
.right
+= deltaUsed
.x
;
242 rectSel_dest
.bottom
+= deltaUsed
.y
;
245 delta
.x
-= deltaUsed
.x
;
246 delta
.y
-= deltaUsed
.y
;
248 _stprintf(sizeStr
, _T("%d x %d"), RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
));
249 SendMessage(hStatusBar
, SB_SETTEXT
, 2, (LPARAM
) sizeStr
);
251 if (toolsModel
.GetActiveTool() == TOOL_TEXT
)
253 Text(hDrawingDC
, rectSel_dest
.left
, rectSel_dest
.top
, rectSel_dest
.right
, rectSel_dest
.bottom
, paletteModel
.GetFgColor(), paletteModel
.GetBgColor(), textToolText
, hfontTextFont
, toolsModel
.IsBackgroundTransparent());
257 if (action
!= ACTION_MOVE
)
258 StretchBlt(hDrawingDC
, rectSel_dest
.left
, rectSel_dest
.top
, RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
), hSelDC
, 0, 0, GetDIBWidth(hSelBm
), GetDIBHeight(hSelBm
), SRCCOPY
);
260 if (toolsModel
.IsBackgroundTransparent() == 0)
261 MaskBlt(hDrawingDC
, rectSel_dest
.left
, rectSel_dest
.top
, RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
),
262 hSelDC
, 0, 0, hSelMask
, 0, 0, MAKEROP4(SRCCOPY
, SRCAND
));
265 ColorKeyedMaskBlt(hDrawingDC
, rectSel_dest
.left
, rectSel_dest
.top
, RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
),
266 hSelDC
, 0, 0, hSelMask
, 0, 0, MAKEROP4(SRCCOPY
, SRCAND
), paletteModel
.GetBgColor());
269 imageArea
.InvalidateRect(NULL
, FALSE
);
270 imageArea
.SendMessage(WM_PAINT
, 0, 0);
271 pos
.x
= GET_X_LPARAM(lParam
);
272 pos
.y
= GET_Y_LPARAM(lParam
);
276 int w
= RECT_WIDTH(rectSel_dest
) * toolsModel
.GetZoom() / 1000 + 6;
277 int h
= RECT_HEIGHT(rectSel_dest
) * toolsModel
.GetZoom() / 1000 + 6;
278 pos
.x
= GET_X_LPARAM(lParam
);
279 pos
.y
= GET_Y_LPARAM(lParam
);
280 SendMessage(hStatusBar
, SB_SETTEXT
, 2, (LPARAM
) NULL
);
281 action
= identifyCorner(pos
.x
, pos
.y
, w
, h
);
282 if (action
!= ACTION_MOVE
)
283 SetCursor(LoadCursor(NULL
, cursors
[action
]));
288 LRESULT
CSelectionWindow::OnLButtonUp(UINT nMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
294 if (action
!= ACTION_MOVE
)
296 if (toolsModel
.GetActiveTool() == TOOL_TEXT
)
298 // FIXME: What to do?
304 hTempDC
= CreateCompatibleDC(hSelDC
);
305 hTempBm
= CreateDIBWithProperties(RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
));
306 SelectObject(hTempDC
, hTempBm
);
307 SelectObject(hSelDC
, hSelBm
);
308 StretchBlt(hTempDC
, 0, 0, RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
), hSelDC
, 0, 0,
309 GetDIBWidth(hSelBm
), GetDIBHeight(hSelBm
), SRCCOPY
);
310 DeleteObject(hSelBm
);
312 hTempBm
= CreateBitmap(RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
), 1, 1, NULL
);
313 SelectObject(hTempDC
, hTempBm
);
314 SelectObject(hSelDC
, hSelMask
);
315 StretchBlt(hTempDC
, 0, 0, RECT_WIDTH(rectSel_dest
), RECT_HEIGHT(rectSel_dest
), hSelDC
, 0, 0,
316 GetDIBWidth(hSelMask
), GetDIBHeight(hSelMask
), SRCCOPY
);
317 DeleteObject(hSelMask
);
319 SelectObject(hSelDC
, hSelBm
);