74bf84414f300c221e4be8b9d8dc69544d31d627
[reactos.git] / base / applications / mspaint / imgarea.cpp
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/imgarea.cpp
5 * PURPOSE: Window procedure of the main window and all children apart from
6 * hPalWin, hToolSettings and hSelection
7 * PROGRAMMERS: Benedikt Freisen
8 * Katayama Hirofumi MZ
9 */
10
11 /* INCLUDES *********************************************************/
12
13 #include "precomp.h"
14
15 #include "dialogs.h"
16
17 /* FUNCTIONS ********************************************************/
18
19 void
20 updateCanvasAndScrollbars()
21 {
22 selectionWindow.ShowWindow(SW_HIDE);
23 imageArea.MoveWindow(3, 3, imageModel.GetWidth() * toolsModel.GetZoom() / 1000, imageModel.GetHeight() * toolsModel.GetZoom() / 1000, FALSE);
24 scrollboxWindow.Invalidate(TRUE);
25 imageArea.Invalidate(FALSE);
26
27 scrollboxWindow.SetScrollPos(SB_HORZ, 0, TRUE);
28 scrollboxWindow.SetScrollPos(SB_VERT, 0, TRUE);
29 }
30
31 void CImgAreaWindow::drawZoomFrame(int mouseX, int mouseY)
32 {
33 HDC hdc;
34 HPEN oldPen;
35 HBRUSH oldBrush;
36 LOGBRUSH logbrush;
37 int rop;
38
39 RECT clientRectScrollbox;
40 RECT clientRectImageArea;
41 int x, y, w, h;
42 scrollboxWindow.GetClientRect(&clientRectScrollbox);
43 GetClientRect(&clientRectImageArea);
44 w = clientRectImageArea.right * 2;
45 h = clientRectImageArea.bottom * 2;
46 if (!w || !h)
47 {
48 return;
49 }
50 w = clientRectImageArea.right * clientRectScrollbox.right / w;
51 h = clientRectImageArea.bottom * clientRectScrollbox.bottom / h;
52 x = max(0, min(clientRectImageArea.right - w, mouseX - w / 2));
53 y = max(0, min(clientRectImageArea.bottom - h, mouseY - h / 2));
54
55 hdc = GetDC();
56 oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 0, 0));
57 logbrush.lbStyle = BS_HOLLOW;
58 oldBrush = (HBRUSH) SelectObject(hdc, CreateBrushIndirect(&logbrush));
59 rop = SetROP2(hdc, R2_NOT);
60 Rectangle(hdc, x, y, x + w, y + h);
61 SetROP2(hdc, rop);
62 DeleteObject(SelectObject(hdc, oldBrush));
63 DeleteObject(SelectObject(hdc, oldPen));
64 ReleaseDC(hdc);
65 }
66
67 LRESULT CImgAreaWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
68 {
69 int imgXRes = imageModel.GetWidth();
70 int imgYRes = imageModel.GetHeight();
71 sizeboxLeftTop.MoveWindow(
72 0,
73 0, 3, 3, TRUE);
74 sizeboxCenterTop.MoveWindow(
75 imgXRes * toolsModel.GetZoom() / 2000 + 3 * 3 / 4,
76 0, 3, 3, TRUE);
77 sizeboxRightTop.MoveWindow(
78 imgXRes * toolsModel.GetZoom() / 1000 + 3,
79 0, 3, 3, TRUE);
80 sizeboxLeftCenter.MoveWindow(
81 0,
82 imgYRes * toolsModel.GetZoom() / 2000 + 3 * 3 / 4, 3, 3, TRUE);
83 sizeboxRightCenter.MoveWindow(
84 imgXRes * toolsModel.GetZoom() / 1000 + 3,
85 imgYRes * toolsModel.GetZoom() / 2000 + 3 * 3 / 4, 3, 3, TRUE);
86 sizeboxLeftBottom.MoveWindow(
87 0,
88 imgYRes * toolsModel.GetZoom() / 1000 + 3, 3, 3, TRUE);
89 sizeboxCenterBottom.MoveWindow(
90 imgXRes * toolsModel.GetZoom() / 2000 + 3 * 3 / 4,
91 imgYRes * toolsModel.GetZoom() / 1000 + 3, 3, 3, TRUE);
92 sizeboxRightBottom.MoveWindow(
93 imgXRes * toolsModel.GetZoom() / 1000 + 3,
94 imgYRes * toolsModel.GetZoom() / 1000 + 3, 3, 3, TRUE);
95 UpdateScrollbox();
96 return 0;
97 }
98
99 LRESULT CImgAreaWindow::OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
100 {
101 DefWindowProc(WM_PAINT, wParam, lParam);
102 HDC hdc = GetDC();
103 int imgXRes = imageModel.GetWidth();
104 int imgYRes = imageModel.GetHeight();
105 StretchBlt(hdc, 0, 0, imgXRes * toolsModel.GetZoom() / 1000, imgYRes * toolsModel.GetZoom() / 1000, imageModel.GetDC(), 0, 0, imgXRes,
106 imgYRes, SRCCOPY);
107 if (showGrid && (toolsModel.GetZoom() >= 4000))
108 {
109 HPEN oldPen = (HPEN) SelectObject(hdc, CreatePen(PS_SOLID, 1, 0x00a0a0a0));
110 int counter;
111 for(counter = 0; counter <= imgYRes; counter++)
112 {
113 MoveToEx(hdc, 0, counter * toolsModel.GetZoom() / 1000, NULL);
114 LineTo(hdc, imgXRes * toolsModel.GetZoom() / 1000, counter * toolsModel.GetZoom() / 1000);
115 }
116 for(counter = 0; counter <= imgXRes; counter++)
117 {
118 MoveToEx(hdc, counter * toolsModel.GetZoom() / 1000, 0, NULL);
119 LineTo(hdc, counter * toolsModel.GetZoom() / 1000, imgYRes * toolsModel.GetZoom() / 1000);
120 }
121 DeleteObject(SelectObject(hdc, oldPen));
122 }
123 ReleaseDC(hdc);
124 selectionWindow.Invalidate(FALSE);
125 miniature.Invalidate(FALSE);
126 return 0;
127 }
128
129 LRESULT CImgAreaWindow::OnSetCursor(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
130 {
131 switch (toolsModel.GetActiveTool())
132 {
133 case TOOL_FILL:
134 SetCursor(hCurFill);
135 break;
136 case TOOL_COLOR:
137 SetCursor(hCurColor);
138 break;
139 case TOOL_ZOOM:
140 SetCursor(hCurZoom);
141 break;
142 case TOOL_PEN:
143 SetCursor(hCurPen);
144 break;
145 case TOOL_AIRBRUSH:
146 SetCursor(hCurAirbrush);
147 break;
148 default:
149 SetCursor(LoadCursor(NULL, IDC_CROSS));
150 }
151 return 0;
152 }
153
154 LRESULT CImgAreaWindow::OnLButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
155 {
156 if ((!drawing) || (toolsModel.GetActiveTool() == TOOL_COLOR))
157 {
158 SetCapture();
159 drawing = TRUE;
160 startPaintingL(imageModel.GetDC(), GET_X_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), GET_Y_LPARAM(lParam) * 1000 / toolsModel.GetZoom(),
161 paletteModel.GetFgColor(), paletteModel.GetBgColor());
162 }
163 else
164 {
165 SendMessage(WM_LBUTTONUP, wParam, lParam);
166 imageModel.Undo();
167 }
168 Invalidate(FALSE);
169 if ((toolsModel.GetActiveTool() == TOOL_ZOOM) && (toolsModel.GetZoom() < 8000))
170 zoomTo(toolsModel.GetZoom() * 2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
171 return 0;
172 }
173
174 LRESULT CImgAreaWindow::OnRButtonDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
175 {
176 if ((!drawing) || (toolsModel.GetActiveTool() == TOOL_COLOR))
177 {
178 SetCapture();
179 drawing = TRUE;
180 startPaintingR(imageModel.GetDC(), GET_X_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), GET_Y_LPARAM(lParam) * 1000 / toolsModel.GetZoom(),
181 paletteModel.GetFgColor(), paletteModel.GetBgColor());
182 }
183 else
184 {
185 SendMessage(WM_RBUTTONUP, wParam, lParam);
186 imageModel.Undo();
187 }
188 Invalidate(FALSE);
189 if ((toolsModel.GetActiveTool() == TOOL_ZOOM) && (toolsModel.GetZoom() > 125))
190 zoomTo(toolsModel.GetZoom() / 2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
191 return 0;
192 }
193
194 LRESULT CImgAreaWindow::OnLButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
195 {
196 if (drawing)
197 {
198 endPaintingL(imageModel.GetDC(), GET_X_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), GET_Y_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), paletteModel.GetFgColor(),
199 paletteModel.GetBgColor());
200 Invalidate(FALSE);
201 if (toolsModel.GetActiveTool() == TOOL_COLOR)
202 {
203 COLORREF tempColor =
204 GetPixel(imageModel.GetDC(), GET_X_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), GET_Y_LPARAM(lParam) * 1000 / toolsModel.GetZoom());
205 if (tempColor != CLR_INVALID)
206 paletteModel.SetFgColor(tempColor);
207 }
208 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
209 }
210 drawing = FALSE;
211 ReleaseCapture();
212 return 0;
213 }
214
215 void CImgAreaWindow::cancelDrawing()
216 {
217 POINT pt;
218 switch (toolsModel.GetActiveTool())
219 {
220 case TOOL_FREESEL: case TOOL_RECTSEL:
221 case TOOL_TEXT: case TOOL_ZOOM: case TOOL_SHAPE:
222 imageModel.ResetToPrevious();
223 selectionModel.ResetPtStack();
224 pointSP = 0;
225 Invalidate(FALSE);
226 break;
227 default:
228 GetCursorPos(&pt);
229 ScreenToClient(&pt);
230 // FIXME: dirty hack
231 if (GetKeyState(VK_LBUTTON) < 0)
232 {
233 endPaintingL(imageModel.GetDC(), pt.x * 1000 / toolsModel.GetZoom(), pt.y * 1000 / toolsModel.GetZoom(), paletteModel.GetFgColor(),
234 paletteModel.GetBgColor());
235 }
236 else if (GetKeyState(VK_RBUTTON) < 0)
237 {
238 endPaintingR(imageModel.GetDC(), pt.x * 1000 / toolsModel.GetZoom(), pt.y * 1000 / toolsModel.GetZoom(), paletteModel.GetFgColor(),
239 paletteModel.GetBgColor());
240 }
241 imageModel.Undo();
242 pointSP = 0;
243 selectionModel.ResetPtStack();
244 }
245 }
246
247 LRESULT CImgAreaWindow::OnCaptureChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
248 {
249 if (drawing)
250 {
251 cancelDrawing();
252 drawing = FALSE;
253 }
254 return 0;
255 }
256
257 LRESULT CImgAreaWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
258 {
259 if (wParam == VK_ESCAPE)
260 {
261 if (GetCapture() == m_hWnd)
262 {
263 ReleaseCapture();
264 }
265 else
266 {
267 switch (toolsModel.GetActiveTool())
268 {
269 case TOOL_SHAPE: case TOOL_BEZIER:
270 cancelDrawing();
271 break;
272 }
273 }
274 }
275 return 0;
276 }
277
278 LRESULT CImgAreaWindow::OnRButtonUp(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
279 {
280 if (drawing)
281 {
282 endPaintingR(imageModel.GetDC(), GET_X_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), GET_Y_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), paletteModel.GetFgColor(),
283 paletteModel.GetBgColor());
284 Invalidate(FALSE);
285 if (toolsModel.GetActiveTool() == TOOL_COLOR)
286 {
287 COLORREF tempColor =
288 GetPixel(imageModel.GetDC(), GET_X_LPARAM(lParam) * 1000 / toolsModel.GetZoom(), GET_Y_LPARAM(lParam) * 1000 / toolsModel.GetZoom());
289 if (tempColor != CLR_INVALID)
290 paletteModel.SetBgColor(tempColor);
291 }
292 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
293 }
294 drawing = FALSE;
295 ReleaseCapture();
296 return 0;
297 }
298
299 LRESULT CImgAreaWindow::OnMouseMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
300 {
301 LONG xNow = GET_X_LPARAM(lParam) * 1000 / toolsModel.GetZoom();
302 LONG yNow = GET_Y_LPARAM(lParam) * 1000 / toolsModel.GetZoom();
303 if ((!drawing) || (toolsModel.GetActiveTool() <= TOOL_AIRBRUSH))
304 {
305 TRACKMOUSEEVENT tme;
306
307 if (toolsModel.GetActiveTool() == TOOL_ZOOM)
308 {
309 Invalidate(FALSE);
310 UpdateWindow();
311 drawZoomFrame(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
312 }
313
314 tme.cbSize = sizeof(TRACKMOUSEEVENT);
315 tme.dwFlags = TME_LEAVE;
316 tme.hwndTrack = m_hWnd;
317 tme.dwHoverTime = 0;
318 TrackMouseEvent(&tme);
319
320 if (!drawing)
321 {
322 CString strCoord;
323 strCoord.Format(_T("%ld, %ld"), xNow, yNow);
324 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
325 }
326 }
327 if (drawing)
328 {
329 /* values displayed in statusbar */
330 LONG xRel = xNow - start.x;
331 LONG yRel = yNow - start.y;
332 /* freesel, rectsel and text tools always show numbers limited to fit into image area */
333 if ((toolsModel.GetActiveTool() == TOOL_FREESEL) || (toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_TEXT))
334 {
335 if (xRel < 0)
336 xRel = (xNow < 0) ? -start.x : xRel;
337 else if (xNow > imageModel.GetWidth())
338 xRel = imageModel.GetWidth() - start.x;
339 if (yRel < 0)
340 yRel = (yNow < 0) ? -start.y : yRel;
341 else if (yNow > imageModel.GetHeight())
342 yRel = imageModel.GetHeight() - start.y;
343 }
344 /* rectsel and shape tools always show non-negative numbers when drawing */
345 if ((toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_SHAPE))
346 {
347 if (xRel < 0)
348 xRel = -xRel;
349 if (yRel < 0)
350 yRel = -yRel;
351 }
352 /* while drawing, update cursor coordinates only for tools 3, 7, 8, 9, 14 */
353 switch(toolsModel.GetActiveTool())
354 {
355 case TOOL_RUBBER:
356 case TOOL_PEN:
357 case TOOL_BRUSH:
358 case TOOL_AIRBRUSH:
359 case TOOL_SHAPE:
360 {
361 CString strCoord;
362 strCoord.Format(_T("%ld, %ld"), xNow, yNow);
363 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) (LPCTSTR) strCoord);
364 break;
365 }
366 }
367 if ((wParam & MK_LBUTTON) != 0)
368 {
369 whilePaintingL(imageModel.GetDC(), xNow, yNow, paletteModel.GetFgColor(), paletteModel.GetBgColor());
370 Invalidate(FALSE);
371 if ((toolsModel.GetActiveTool() >= TOOL_TEXT) || (toolsModel.GetActiveTool() == TOOL_RECTSEL) || (toolsModel.GetActiveTool() == TOOL_FREESEL))
372 {
373 CString strSize;
374 if ((toolsModel.GetActiveTool() >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
375 yRel = xRel;
376 strSize.Format(_T("%ld x %ld"), xRel, yRel);
377 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
378 }
379 }
380 if ((wParam & MK_RBUTTON) != 0)
381 {
382 whilePaintingR(imageModel.GetDC(), xNow, yNow, paletteModel.GetFgColor(), paletteModel.GetBgColor());
383 Invalidate(FALSE);
384 if (toolsModel.GetActiveTool() >= TOOL_TEXT)
385 {
386 CString strSize;
387 if ((toolsModel.GetActiveTool() >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
388 yRel = xRel;
389 strSize.Format(_T("%ld x %ld"), xRel, yRel);
390 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) (LPCTSTR) strSize);
391 }
392 }
393 }
394 return 0;
395 }
396
397 LRESULT CImgAreaWindow::OnMouseLeave(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
398 {
399 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) _T(""));
400 if (toolsModel.GetActiveTool() == TOOL_ZOOM)
401 Invalidate(FALSE);
402 return 0;
403 }
404
405 LRESULT CImgAreaWindow::OnImageModelDimensionsChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
406 {
407 updateCanvasAndScrollbars();
408 return 0;
409 }
410
411 LRESULT CImgAreaWindow::OnImageModelImageChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
412 {
413 Invalidate(FALSE);
414 return 0;
415 }