[KERNEL32]
[reactos.git] / base / applications / mspaint / winproc.c
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/paint/winproc.c
5 * PURPOSE: Window procedure of the main window and all children apart from
6 * hPalWin, hToolSettings and hSelection
7 * PROGRAMMERS: Benedikt Freisen
8 */
9
10 /* INCLUDES *********************************************************/
11
12 //#include <htmlhelp.h>
13 #include "precomp.h"
14
15 /* FUNCTIONS ********************************************************/
16
17 void
18 selectTool(int tool)
19 {
20 ShowWindow(hSelection, SW_HIDE);
21 activeTool = tool;
22 pointSP = 0; // resets the point-buffer of the polygon and bezier functions
23 SendMessage(hToolSettings, WM_PAINT, 0, 0);
24 ShowWindow(hTrackbarZoom, (tool == 6) ? SW_SHOW : SW_HIDE);
25 }
26
27 void
28 updateCanvasAndScrollbars()
29 {
30 ShowWindow(hSelection, SW_HIDE);
31 MoveWindow(hImageArea, 3, 3, imgXRes * zoom / 1000, imgYRes * zoom / 1000, FALSE);
32 InvalidateRect(hScrollbox, NULL, TRUE);
33 InvalidateRect(hImageArea, NULL, FALSE);
34
35 SetScrollPos(hScrollbox, SB_HORZ, 0, TRUE);
36 SetScrollPos(hScrollbox, SB_VERT, 0, TRUE);
37 }
38
39 void
40 zoomTo(int newZoom, int mouseX, int mouseY)
41 {
42 int tbPos = 0;
43 int tempZoom = newZoom;
44
45 long clientRectScrollbox[4];
46 long clientRectImageArea[4];
47 int x, y, w, h;
48 GetClientRect(hScrollbox, (LPRECT) &clientRectScrollbox);
49 GetClientRect(hImageArea, (LPRECT) &clientRectImageArea);
50 w = clientRectImageArea[2] * clientRectScrollbox[2] / (clientRectImageArea[2] * newZoom / zoom);
51 h = clientRectImageArea[3] * clientRectScrollbox[3] / (clientRectImageArea[3] * newZoom / zoom);
52 x = max(0, min(clientRectImageArea[2] - w, mouseX - w / 2)) * newZoom / zoom;
53 y = max(0, min(clientRectImageArea[3] - h, mouseY - h / 2)) * newZoom / zoom;
54
55 zoom = newZoom;
56
57 ShowWindow(hSelection, SW_HIDE);
58 MoveWindow(hImageArea, 3, 3, imgXRes * zoom / 1000, imgYRes * zoom / 1000, FALSE);
59 InvalidateRect(hScrollbox, NULL, TRUE);
60 InvalidateRect(hImageArea, NULL, FALSE);
61
62 SendMessage(hScrollbox, WM_HSCROLL, SB_THUMBPOSITION | (x << 16), 0);
63 SendMessage(hScrollbox, WM_VSCROLL, SB_THUMBPOSITION | (y << 16), 0);
64
65 while (tempZoom > 125)
66 {
67 tbPos++;
68 tempZoom = tempZoom >> 1;
69 }
70 SendMessage(hTrackbarZoom, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) tbPos);
71 }
72
73 void
74 drawZoomFrame(int mouseX, int mouseY)
75 {
76 HDC hdc;
77 HPEN oldPen;
78 HBRUSH oldBrush;
79 LOGBRUSH logbrush;
80 int rop;
81
82 long clientRectScrollbox[4];
83 long clientRectImageArea[4];
84 int x, y, w, h;
85 GetClientRect(hScrollbox, (LPRECT) &clientRectScrollbox);
86 GetClientRect(hImageArea, (LPRECT) &clientRectImageArea);
87 w = clientRectImageArea[2] * clientRectScrollbox[2] / (clientRectImageArea[2] * 2);
88 h = clientRectImageArea[3] * clientRectScrollbox[3] / (clientRectImageArea[3] * 2);
89 x = max(0, min(clientRectImageArea[2] - w, mouseX - w / 2));
90 y = max(0, min(clientRectImageArea[3] - h, mouseY - h / 2));
91
92 hdc = GetDC(hImageArea);
93 oldPen = SelectObject(hdc, CreatePen(PS_SOLID, 0, 0));
94 logbrush.lbStyle = BS_HOLLOW;
95 oldBrush = SelectObject(hdc, CreateBrushIndirect(&logbrush));
96 rop = SetROP2(hdc, R2_NOT);
97 Rectangle(hdc, x, y, x + w, y + h);
98 SetROP2(hdc, rop);
99 DeleteObject(SelectObject(hdc, oldBrush));
100 DeleteObject(SelectObject(hdc, oldPen));
101 ReleaseDC(hImageArea, hdc);
102 }
103
104 void
105 alignChildrenToMainWindow()
106 {
107 int x, y, w, h;
108 RECT clientRect;
109 GetClientRect(hMainWnd, &clientRect);
110
111 if (IsWindowVisible(hToolBoxContainer))
112 {
113 x = 56;
114 w = clientRect.right - 56;
115 }
116 else
117 {
118 x = 0;
119 w = clientRect.right;
120 }
121 if (IsWindowVisible(hPalWin))
122 {
123 y = 49;
124 h = clientRect.bottom - 49;
125 }
126 else
127 {
128 y = 3;
129 h = clientRect.bottom - 3;
130 }
131
132 MoveWindow(hScrollbox, x, y, w, IsWindowVisible(hStatusBar) ? h - 23 : h, TRUE);
133 MoveWindow(hPalWin, x, 9, 255, 32, TRUE);
134 }
135
136 BOOL drawing;
137
138 LRESULT CALLBACK
139 WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
140 {
141 switch (message) /* handle the messages */
142 {
143 case WM_CREATE:
144 ptStack = NULL;
145 ptSP = 0;
146 break;
147
148 case WM_DESTROY:
149 PostQuitMessage(0); /* send a WM_QUIT to the message queue */
150 break;
151
152 case WM_CLOSE:
153 if (hwnd == hwndMiniature)
154 {
155 ShowWindow(hwndMiniature, SW_HIDE);
156 showMiniature = FALSE;
157 break;
158 }
159 if (!imageSaved)
160 {
161 TCHAR programname[20];
162 TCHAR saveprompttext[100];
163 TCHAR temptext[500];
164 LoadString(hProgInstance, IDS_PROGRAMNAME, programname, SIZEOF(programname));
165 LoadString(hProgInstance, IDS_SAVEPROMPTTEXT, saveprompttext, SIZEOF(saveprompttext));
166 _stprintf(temptext, saveprompttext, filename);
167 switch (MessageBox(hwnd, temptext, programname, MB_YESNOCANCEL | MB_ICONQUESTION))
168 {
169 case IDNO:
170 DestroyWindow(hwnd);
171 break;
172 case IDYES:
173 SendMessage(hwnd, WM_COMMAND, IDM_FILESAVEAS, 0);
174 DestroyWindow(hwnd);
175 break;
176 }
177 }
178 else
179 {
180 DestroyWindow(hwnd);
181 }
182 break;
183
184 case WM_INITMENUPOPUP:
185 switch (lParam)
186 {
187 case 0:
188 if (isAFile)
189 {
190 EnableMenuItem(GetMenu(hMainWnd), IDM_FILEASWALLPAPERPLANE,
191 MF_ENABLED | MF_BYCOMMAND);
192 EnableMenuItem(GetMenu(hMainWnd), IDM_FILEASWALLPAPERCENTERED,
193 MF_ENABLED | MF_BYCOMMAND);
194 EnableMenuItem(GetMenu(hMainWnd), IDM_FILEASWALLPAPERSTRETCHED,
195 MF_ENABLED | MF_BYCOMMAND);
196 }
197 else
198 {
199 EnableMenuItem(GetMenu(hMainWnd), IDM_FILEASWALLPAPERPLANE,
200 MF_GRAYED | MF_BYCOMMAND);
201 EnableMenuItem(GetMenu(hMainWnd), IDM_FILEASWALLPAPERCENTERED,
202 MF_GRAYED | MF_BYCOMMAND);
203 EnableMenuItem(GetMenu(hMainWnd), IDM_FILEASWALLPAPERSTRETCHED,
204 MF_GRAYED | MF_BYCOMMAND);
205 }
206 break;
207 case 1:
208 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITUNDO,
209 (undoSteps > 0) ? (MF_ENABLED | MF_BYCOMMAND) : (MF_GRAYED | MF_BYCOMMAND));
210 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITREDO,
211 (redoSteps > 0) ? (MF_ENABLED | MF_BYCOMMAND) : (MF_GRAYED | MF_BYCOMMAND));
212 if (IsWindowVisible(hSelection))
213 {
214 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITCUT, MF_ENABLED | MF_BYCOMMAND);
215 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITCOPY, MF_ENABLED | MF_BYCOMMAND);
216 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITDELETESELECTION, MF_ENABLED | MF_BYCOMMAND);
217 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITINVERTSELECTION, MF_ENABLED | MF_BYCOMMAND);
218 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITCOPYTO, MF_ENABLED | MF_BYCOMMAND);
219 }
220 else
221 {
222 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITCUT, MF_GRAYED | MF_BYCOMMAND);
223 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITCOPY, MF_GRAYED | MF_BYCOMMAND);
224 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITDELETESELECTION, MF_GRAYED | MF_BYCOMMAND);
225 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITINVERTSELECTION, MF_GRAYED | MF_BYCOMMAND);
226 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITCOPYTO, MF_GRAYED | MF_BYCOMMAND);
227 }
228 OpenClipboard(hMainWnd);
229 if (GetClipboardData(CF_BITMAP) != NULL)
230 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITPASTE, MF_ENABLED | MF_BYCOMMAND);
231 else
232 EnableMenuItem(GetMenu(hMainWnd), IDM_EDITPASTE, MF_GRAYED | MF_BYCOMMAND);
233 CloseClipboard();
234 break;
235 case 3:
236 if (IsWindowVisible(hSelection))
237 EnableMenuItem(GetMenu(hMainWnd), IDM_IMAGECROP, MF_ENABLED | MF_BYCOMMAND);
238 else
239 EnableMenuItem(GetMenu(hMainWnd), IDM_IMAGECROP, MF_GRAYED | MF_BYCOMMAND);
240 CheckMenuItem(GetMenu(hMainWnd), IDM_IMAGEDRAWOPAQUE, (transpBg == 0) ?
241 (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
242 break;
243 }
244 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWTOOLBOX,
245 IsWindowVisible(hToolBoxContainer) ?
246 (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
247 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWCOLORPALETTE,
248 IsWindowVisible(hPalWin) ?
249 (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
250 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWSTATUSBAR,
251 IsWindowVisible(hStatusBar) ?
252 (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
253
254 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWSHOWGRID,
255 showGrid ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
256 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWSHOWMINIATURE,
257 showMiniature ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
258
259 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWZOOM125,
260 (zoom == 125) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
261 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWZOOM25,
262 (zoom == 250) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
263 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWZOOM50,
264 (zoom == 500) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
265 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWZOOM100,
266 (zoom == 1000) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
267 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWZOOM200,
268 (zoom == 2000) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
269 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWZOOM400,
270 (zoom == 4000) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
271 CheckMenuItem(GetMenu(hMainWnd), IDM_VIEWZOOM800,
272 (zoom == 8000) ? (MF_CHECKED | MF_BYCOMMAND) : (MF_UNCHECKED | MF_BYCOMMAND));
273
274 break;
275
276 case WM_SIZE:
277 if (hwnd == hMainWnd)
278 {
279 int test[] = { LOWORD(lParam) - 260, LOWORD(lParam) - 140, LOWORD(lParam) - 20 };
280 SendMessage(hStatusBar, WM_SIZE, wParam, lParam);
281 SendMessage(hStatusBar, SB_SETPARTS, 3, (LPARAM)&test);
282 alignChildrenToMainWindow();
283 }
284 if (hwnd == hImageArea)
285 {
286 MoveWindow(hSizeboxLeftTop,
287 0,
288 0, 3, 3, TRUE);
289 MoveWindow(hSizeboxCenterTop,
290 imgXRes * zoom / 2000 + 3 * 3 / 4,
291 0, 3, 3, TRUE);
292 MoveWindow(hSizeboxRightTop,
293 imgXRes * zoom / 1000 + 3,
294 0, 3, 3, TRUE);
295 MoveWindow(hSizeboxLeftCenter,
296 0,
297 imgYRes * zoom / 2000 + 3 * 3 / 4, 3, 3, TRUE);
298 MoveWindow(hSizeboxRightCenter,
299 imgXRes * zoom / 1000 + 3,
300 imgYRes * zoom / 2000 + 3 * 3 / 4, 3, 3, TRUE);
301 MoveWindow(hSizeboxLeftBottom,
302 0,
303 imgYRes * zoom / 1000 + 3, 3, 3, TRUE);
304 MoveWindow(hSizeboxCenterBottom,
305 imgXRes * zoom / 2000 + 3 * 3 / 4,
306 imgYRes * zoom / 1000 + 3, 3, 3, TRUE);
307 MoveWindow(hSizeboxRightBottom,
308 imgXRes * zoom / 1000 + 3,
309 imgYRes * zoom / 1000 + 3, 3, 3, TRUE);
310 }
311 if ((hwnd == hImageArea) || (hwnd == hScrollbox))
312 {
313 long clientRectScrollbox[4];
314 long clientRectImageArea[4];
315 SCROLLINFO si;
316 GetClientRect(hScrollbox, (LPRECT) &clientRectScrollbox);
317 GetClientRect(hImageArea, (LPRECT) &clientRectImageArea);
318 si.cbSize = sizeof(SCROLLINFO);
319 si.fMask = SIF_PAGE | SIF_RANGE;
320 si.nMax = clientRectImageArea[2] + 6 - 1;
321 si.nMin = 0;
322 si.nPage = clientRectScrollbox[2];
323 SetScrollInfo(hScrollbox, SB_HORZ, &si, TRUE);
324 GetClientRect(hScrollbox, (LPRECT) clientRectScrollbox);
325 si.nMax = clientRectImageArea[3] + 6 - 1;
326 si.nPage = clientRectScrollbox[3];
327 SetScrollInfo(hScrollbox, SB_VERT, &si, TRUE);
328 MoveWindow(hScrlClient,
329 -GetScrollPos(hScrollbox, SB_HORZ), -GetScrollPos(hScrollbox, SB_VERT),
330 max(clientRectImageArea[2] + 6, clientRectScrollbox[2]),
331 max(clientRectImageArea[3] + 6, clientRectScrollbox[3]), TRUE);
332 }
333 break;
334
335 case WM_HSCROLL:
336 if (hwnd == hScrollbox)
337 {
338 SCROLLINFO si;
339 si.cbSize = sizeof(SCROLLINFO);
340 si.fMask = SIF_ALL;
341 GetScrollInfo(hScrollbox, SB_HORZ, &si);
342 switch (LOWORD(wParam))
343 {
344 case SB_THUMBTRACK:
345 case SB_THUMBPOSITION:
346 si.nPos = HIWORD(wParam);
347 break;
348 case SB_LINELEFT:
349 si.nPos -= 5;
350 break;
351 case SB_LINERIGHT:
352 si.nPos += 5;
353 break;
354 case SB_PAGELEFT:
355 si.nPos -= si.nPage;
356 break;
357 case SB_PAGERIGHT:
358 si.nPos += si.nPage;
359 break;
360 }
361 SetScrollInfo(hScrollbox, SB_HORZ, &si, TRUE);
362 MoveWindow(hScrlClient, -GetScrollPos(hScrollbox, SB_HORZ),
363 -GetScrollPos(hScrollbox, SB_VERT), imgXRes * zoom / 1000 + 6,
364 imgYRes * zoom / 1000 + 6, TRUE);
365 }
366 break;
367
368 case WM_VSCROLL:
369 if (hwnd == hScrollbox)
370 {
371 SCROLLINFO si;
372 si.cbSize = sizeof(SCROLLINFO);
373 si.fMask = SIF_ALL;
374 GetScrollInfo(hScrollbox, SB_VERT, &si);
375 switch (LOWORD(wParam))
376 {
377 case SB_THUMBTRACK:
378 case SB_THUMBPOSITION:
379 si.nPos = HIWORD(wParam);
380 break;
381 case SB_LINEUP:
382 si.nPos -= 5;
383 break;
384 case SB_LINEDOWN:
385 si.nPos += 5;
386 break;
387 case SB_PAGEUP:
388 si.nPos -= si.nPage;
389 break;
390 case SB_PAGEDOWN:
391 si.nPos += si.nPage;
392 break;
393 }
394 SetScrollInfo(hScrollbox, SB_VERT, &si, TRUE);
395 MoveWindow(hScrlClient, -GetScrollPos(hScrollbox, SB_HORZ),
396 -GetScrollPos(hScrollbox, SB_VERT), imgXRes * zoom / 1000 + 6,
397 imgYRes * zoom / 1000 + 6, TRUE);
398 }
399 break;
400
401 case WM_GETMINMAXINFO:
402 if (hwnd == hMainWnd)
403 {
404 MINMAXINFO *mm = (LPMINMAXINFO) lParam;
405 (*mm).ptMinTrackSize.x = 330;
406 (*mm).ptMinTrackSize.y = 430;
407 }
408 break;
409
410 case WM_PAINT:
411 DefWindowProc(hwnd, message, wParam, lParam);
412 if (hwnd == hImageArea)
413 {
414 HDC hdc = GetDC(hImageArea);
415 StretchBlt(hdc, 0, 0, imgXRes * zoom / 1000, imgYRes * zoom / 1000, hDrawingDC, 0, 0, imgXRes,
416 imgYRes, SRCCOPY);
417 if (showGrid && (zoom >= 4000))
418 {
419 HPEN oldPen = SelectObject(hdc, CreatePen(PS_SOLID, 1, 0x00a0a0a0));
420 int counter;
421 for(counter = 0; counter <= imgYRes; counter++)
422 {
423 MoveToEx(hdc, 0, counter * zoom / 1000, NULL);
424 LineTo(hdc, imgXRes * zoom / 1000, counter * zoom / 1000);
425 }
426 for(counter = 0; counter <= imgXRes; counter++)
427 {
428 MoveToEx(hdc, counter * zoom / 1000, 0, NULL);
429 LineTo(hdc, counter * zoom / 1000, imgYRes * zoom / 1000);
430 }
431 DeleteObject(SelectObject(hdc, oldPen));
432 }
433 ReleaseDC(hImageArea, hdc);
434 SendMessage(hSelection, WM_PAINT, 0, 0);
435 SendMessage(hwndMiniature, WM_PAINT, 0, 0);
436 }
437 else if (hwnd == hwndMiniature)
438 {
439 RECT mclient;
440 HDC hdc;
441 GetClientRect(hwndMiniature, &mclient);
442 hdc = GetDC(hwndMiniature);
443 StretchBlt(hdc, 0, 0, mclient.right, mclient.bottom, hDrawingDC, 0, 0, imgXRes, imgYRes, SRCCOPY);
444 ReleaseDC(hwndMiniature, hdc);
445 }
446 break;
447
448 // mouse events used for drawing
449
450 case WM_SETCURSOR:
451 if (hwnd == hImageArea)
452 {
453 switch (activeTool)
454 {
455 case TOOL_FILL:
456 SetCursor(hCurFill);
457 break;
458 case TOOL_COLOR:
459 SetCursor(hCurColor);
460 break;
461 case TOOL_ZOOM:
462 SetCursor(hCurZoom);
463 break;
464 case TOOL_PEN:
465 SetCursor(hCurPen);
466 break;
467 case TOOL_AIRBRUSH:
468 SetCursor(hCurAirbrush);
469 break;
470 default:
471 SetCursor(LoadCursor(NULL, IDC_CROSS));
472 }
473 }
474 else
475 DefWindowProc(hwnd, message, wParam, lParam);
476 break;
477
478 case WM_LBUTTONDOWN:
479 if (hwnd == hImageArea)
480 {
481 if ((!drawing) || (activeTool == TOOL_COLOR))
482 {
483 SetCapture(hImageArea);
484 drawing = TRUE;
485 startPaintingL(hDrawingDC, GET_X_LPARAM(lParam) * 1000 / zoom, GET_Y_LPARAM(lParam) * 1000 / zoom,
486 fgColor, bgColor);
487 }
488 else
489 {
490 SendMessage(hwnd, WM_LBUTTONUP, wParam, lParam);
491 undo();
492 }
493 SendMessage(hImageArea, WM_PAINT, 0, 0);
494 if ((activeTool == TOOL_ZOOM) && (zoom < 8000))
495 zoomTo(zoom * 2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
496 }
497 break;
498
499 case WM_RBUTTONDOWN:
500 if (hwnd == hImageArea)
501 {
502 if ((!drawing) || (activeTool == TOOL_COLOR))
503 {
504 SetCapture(hImageArea);
505 drawing = TRUE;
506 startPaintingR(hDrawingDC, GET_X_LPARAM(lParam) * 1000 / zoom, GET_Y_LPARAM(lParam) * 1000 / zoom,
507 fgColor, bgColor);
508 }
509 else
510 {
511 SendMessage(hwnd, WM_RBUTTONUP, wParam, lParam);
512 undo();
513 }
514 SendMessage(hImageArea, WM_PAINT, 0, 0);
515 if ((activeTool == TOOL_ZOOM) && (zoom > 125))
516 zoomTo(zoom / 2, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
517 }
518 break;
519
520 case WM_LBUTTONUP:
521 if ((hwnd == hImageArea) && drawing)
522 {
523 ReleaseCapture();
524 drawing = FALSE;
525 endPaintingL(hDrawingDC, GET_X_LPARAM(lParam) * 1000 / zoom, GET_Y_LPARAM(lParam) * 1000 / zoom, fgColor,
526 bgColor);
527 SendMessage(hImageArea, WM_PAINT, 0, 0);
528 if (activeTool == TOOL_COLOR)
529 {
530 int tempColor =
531 GetPixel(hDrawingDC, GET_X_LPARAM(lParam) * 1000 / zoom, GET_Y_LPARAM(lParam) * 1000 / zoom);
532 if (tempColor != CLR_INVALID)
533 fgColor = tempColor;
534 SendMessage(hPalWin, WM_PAINT, 0, 0);
535 }
536 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
537 }
538 break;
539
540 case WM_RBUTTONUP:
541 if ((hwnd == hImageArea) && drawing)
542 {
543 ReleaseCapture();
544 drawing = FALSE;
545 endPaintingR(hDrawingDC, GET_X_LPARAM(lParam) * 1000 / zoom, GET_Y_LPARAM(lParam) * 1000 / zoom, fgColor,
546 bgColor);
547 SendMessage(hImageArea, WM_PAINT, 0, 0);
548 if (activeTool == TOOL_COLOR)
549 {
550 int tempColor =
551 GetPixel(hDrawingDC, GET_X_LPARAM(lParam) * 1000 / zoom, GET_Y_LPARAM(lParam) * 1000 / zoom);
552 if (tempColor != CLR_INVALID)
553 bgColor = tempColor;
554 SendMessage(hPalWin, WM_PAINT, 0, 0);
555 }
556 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) "");
557 }
558 break;
559
560 case WM_KEYDOWN:
561 if (wParam == VK_ESCAPE)
562 {
563 if (!drawing)
564 {
565 /* Deselect */
566 if ((activeTool == TOOL_RECTSEL) || (activeTool == TOOL_FREESEL))
567 {
568 startPaintingL(hDrawingDC, 0, 0, fgColor, bgColor);
569 whilePaintingL(hDrawingDC, 0, 0, fgColor, bgColor);
570 endPaintingL(hDrawingDC, 0, 0, fgColor, bgColor);
571 ShowWindow(hSelection, SW_HIDE);
572 }
573 }
574 /* FIXME: also cancel current drawing underway */
575 }
576 break;
577
578 case WM_MOUSEMOVE:
579 if (hwnd == hImageArea)
580 {
581 LONG xNow = GET_X_LPARAM(lParam) * 1000 / zoom;
582 LONG yNow = GET_Y_LPARAM(lParam) * 1000 / zoom;
583 if ((!drawing) || (activeTool <= TOOL_AIRBRUSH))
584 {
585 TRACKMOUSEEVENT tme;
586
587 if (activeTool == TOOL_ZOOM)
588 {
589 SendMessage(hImageArea, WM_PAINT, 0, 0);
590 drawZoomFrame(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
591 }
592
593 tme.cbSize = sizeof(TRACKMOUSEEVENT);
594 tme.dwFlags = TME_LEAVE;
595 tme.hwndTrack = hImageArea;
596 tme.dwHoverTime = 0;
597 TrackMouseEvent(&tme);
598
599 if (!drawing)
600 {
601 TCHAR coordStr[100];
602 _stprintf(coordStr, _T("%d, %d"), xNow, yNow);
603 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) coordStr);
604 }
605 }
606 if (drawing)
607 {
608 /* values displayed in statusbar */
609 LONG xRel = xNow - startX;
610 LONG yRel = yNow - startY;
611 /* freesel, rectsel and text tools always show numbers limited to fit into image area */
612 if ((activeTool == TOOL_FREESEL) || (activeTool == TOOL_RECTSEL) || (activeTool == TOOL_TEXT))
613 {
614 if (xRel < 0)
615 xRel = (xNow < 0) ? -startX : xRel;
616 else if (xNow > imgXRes)
617 xRel = imgXRes-startX;
618 if (yRel < 0)
619 yRel = (yNow < 0) ? -startY : yRel;
620 else if (yNow > imgYRes)
621 yRel = imgYRes-startY;
622 }
623 /* rectsel and shape tools always show non-negative numbers when drawing */
624 if ((activeTool == TOOL_RECTSEL) || (activeTool == TOOL_SHAPE))
625 {
626 if (xRel < 0)
627 xRel = -xRel;
628 if (yRel < 0)
629 yRel = -yRel;
630 }
631 /* while drawing, update cursor coordinates only for tools 3, 7, 8, 9, 14 */
632 switch(activeTool)
633 {
634 case TOOL_RUBBER:
635 case TOOL_PEN:
636 case TOOL_BRUSH:
637 case TOOL_AIRBRUSH:
638 case TOOL_SHAPE:
639 {
640 TCHAR coordStr[100];
641 _stprintf(coordStr, _T("%d, %d"), xNow, yNow);
642 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) coordStr);
643 break;
644 }
645 }
646 if ((wParam & MK_LBUTTON) != 0)
647 {
648 whilePaintingL(hDrawingDC, xNow, yNow, fgColor, bgColor);
649 SendMessage(hImageArea, WM_PAINT, 0, 0);
650 if ((activeTool >= TOOL_TEXT) || (activeTool == TOOL_RECTSEL) || (activeTool == TOOL_FREESEL))
651 {
652 TCHAR sizeStr[100];
653 if ((activeTool >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
654 yRel = xRel;
655 _stprintf(sizeStr, _T("%d x %d"), xRel, yRel);
656 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) sizeStr);
657 }
658 }
659 if ((wParam & MK_RBUTTON) != 0)
660 {
661 whilePaintingR(hDrawingDC, xNow, yNow, fgColor, bgColor);
662 SendMessage(hImageArea, WM_PAINT, 0, 0);
663 if (activeTool >= TOOL_TEXT)
664 {
665 TCHAR sizeStr[100];
666 if ((activeTool >= TOOL_LINE) && (GetAsyncKeyState(VK_SHIFT) < 0))
667 yRel = xRel;
668 _stprintf(sizeStr, _T("%d x %d"), xRel, yRel);
669 SendMessage(hStatusBar, SB_SETTEXT, 2, (LPARAM) sizeStr);
670 }
671 }
672 }
673 }
674 break;
675
676 case WM_MOUSELEAVE:
677 SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM) _T(""));
678 if (activeTool == TOOL_ZOOM)
679 SendMessage(hImageArea, WM_PAINT, 0, 0);
680 break;
681
682 // menu and button events
683
684 case WM_SYSCOLORCHANGE:
685 {
686 /* Redirect message to common controls */
687 HWND hToolbar = FindWindowEx(hToolBoxContainer, NULL, TOOLBARCLASSNAME, NULL);
688 SendMessage(hToolbar, WM_SYSCOLORCHANGE, 0, 0);
689 break;
690 }
691
692 case WM_COMMAND:
693 switch (LOWORD(wParam))
694 {
695 case IDM_HELPINFO:
696 {
697 HICON paintIcon = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON));
698 TCHAR infotitle[100];
699 TCHAR infotext[200];
700 LoadString(hProgInstance, IDS_INFOTITLE, infotitle, SIZEOF(infotitle));
701 LoadString(hProgInstance, IDS_INFOTEXT, infotext, SIZEOF(infotext));
702 ShellAbout(hMainWnd, infotitle, infotext, paintIcon);
703 DeleteObject(paintIcon);
704 break;
705 }
706 case IDM_HELPHELPTOPICS:
707 //HtmlHelp(hMainWnd, "help\\Paint.chm", 0, 0);
708 break;
709 case IDM_FILEEXIT:
710 SendMessage(hwnd, WM_CLOSE, wParam, lParam);
711 break;
712 case IDM_FILENEW:
713 ShowWindow(hSelection, SW_HIDE);
714 clearHistory();
715
716 Rectangle(hDrawingDC, 0 - 1, 0 - 1, imgXRes + 1, imgYRes + 1);
717 SendMessage(hImageArea, WM_PAINT, 0, 0);
718 break;
719 case IDM_FILEOPEN:
720 if (GetOpenFileName(&ofn) != 0)
721 {
722 HBITMAP bmNew = NULL;
723 LoadDIBFromFile(&bmNew, ofn.lpstrFile, &fileTime, &fileSize, &fileHPPM, &fileVPPM);
724 if (bmNew != NULL)
725 {
726 TCHAR tempstr[1000];
727 TCHAR resstr[100];
728 insertReversible(bmNew);
729 updateCanvasAndScrollbars();
730 CopyMemory(filename, ofn.lpstrFileTitle, sizeof(filename));
731 CopyMemory(filepathname, ofn.lpstrFileTitle, sizeof(filepathname));
732 LoadString(hProgInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
733 _stprintf(tempstr, resstr, filename);
734 SetWindowText(hMainWnd, tempstr);
735 clearHistory();
736 isAFile = TRUE;
737 }
738 }
739 break;
740 case IDM_FILESAVE:
741 if (isAFile)
742 {
743 SaveDIBToFile(hBms[currInd], filepathname, hDrawingDC, &fileTime, &fileSize, fileHPPM,
744 fileVPPM);
745 imageSaved = TRUE;
746 }
747 else
748 SendMessage(hwnd, WM_COMMAND, IDM_FILESAVEAS, 0);
749 break;
750 case IDM_FILESAVEAS:
751 if (GetSaveFileName(&sfn) != 0)
752 {
753 TCHAR tempstr[1000];
754 TCHAR resstr[100];
755 SaveDIBToFile(hBms[currInd], sfn.lpstrFile, hDrawingDC, &fileTime, &fileSize,
756 fileHPPM, fileVPPM);
757 CopyMemory(filename, sfn.lpstrFileTitle, sizeof(filename));
758 CopyMemory(filepathname, sfn.lpstrFile, sizeof(filepathname));
759 LoadString(hProgInstance, IDS_WINDOWTITLE, resstr, SIZEOF(resstr));
760 _stprintf(tempstr, resstr, filename);
761 SetWindowText(hMainWnd, tempstr);
762 isAFile = TRUE;
763 imageSaved = TRUE;
764 }
765 break;
766 case IDM_FILEASWALLPAPERPLANE:
767 SetWallpaper(filepathname, 1, 1);
768 break;
769 case IDM_FILEASWALLPAPERCENTERED:
770 SetWallpaper(filepathname, 1, 0);
771 break;
772 case IDM_FILEASWALLPAPERSTRETCHED:
773 SetWallpaper(filepathname, 2, 0);
774 break;
775 case IDM_EDITUNDO:
776 undo();
777 SendMessage(hImageArea, WM_PAINT, 0, 0);
778 break;
779 case IDM_EDITREDO:
780 redo();
781 SendMessage(hImageArea, WM_PAINT, 0, 0);
782 break;
783 case IDM_EDITCOPY:
784 OpenClipboard(hMainWnd);
785 EmptyClipboard();
786 SetClipboardData(CF_BITMAP, CopyImage(hSelBm, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
787 CloseClipboard();
788 break;
789 case IDM_EDITCUT:
790 /* Copy */
791 SendMessage(hwnd, WM_COMMAND, IDM_EDITCOPY, 0);
792 /* Delete selection */
793 SendMessage(hwnd, WM_COMMAND, IDM_EDITDELETESELECTION, 0);
794 break;
795 case IDM_EDITPASTE:
796 OpenClipboard(hMainWnd);
797 if (GetClipboardData(CF_BITMAP) != NULL)
798 {
799 HWND hToolbar = FindWindowEx(hToolBoxContainer, NULL, TOOLBARCLASSNAME, NULL);
800 SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELONG(TRUE, 0));
801 SendMessage(hwnd, WM_COMMAND, ID_RECTSEL, 0);
802
803 DeleteObject(SelectObject(hSelDC, hSelBm = CopyImage(GetClipboardData(CF_BITMAP),
804 IMAGE_BITMAP, 0, 0,
805 LR_COPYRETURNORG)));
806 newReversible();
807 rectSel_src[0] = rectSel_src[1] = rectSel_src[2] = rectSel_src[3] = 0;
808 rectSel_dest[0] = rectSel_dest[1] = 0;
809 rectSel_dest[2] = GetDIBWidth(hSelBm);
810 rectSel_dest[3] = GetDIBHeight(hSelBm);
811 BitBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
812 hSelDC, 0, 0, SRCCOPY);
813 placeSelWin();
814 ShowWindow(hSelection, SW_SHOW);
815 }
816 CloseClipboard();
817 break;
818 case IDM_EDITDELETESELECTION:
819 {
820 /* remove selection window and already painted content using undo(),
821 paint Rect for rectangular selections and Poly for freeform selections */
822 undo();
823 if (activeTool == TOOL_RECTSEL)
824 {
825 newReversible();
826 Rect(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2] + rectSel_dest[0],
827 rectSel_dest[3] + rectSel_dest[1], bgColor, bgColor, 0, TRUE);
828 }
829 if (activeTool == TOOL_FREESEL)
830 {
831 newReversible();
832 Poly(hDrawingDC, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE);
833 }
834 break;
835 }
836 case IDM_EDITSELECTALL:
837 {
838 HWND hToolbar = FindWindowEx(hToolBoxContainer, NULL, TOOLBARCLASSNAME, NULL);
839 SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELONG(TRUE, 0));
840 SendMessage(hwnd, WM_COMMAND, ID_RECTSEL, 0);
841 startPaintingL(hDrawingDC, 0, 0, fgColor, bgColor);
842 whilePaintingL(hDrawingDC, imgXRes, imgYRes, fgColor, bgColor);
843 endPaintingL(hDrawingDC, imgXRes, imgYRes, fgColor, bgColor);
844 break;
845 }
846 case IDM_EDITCOPYTO:
847 if (GetSaveFileName(&ofn) != 0)
848 SaveDIBToFile(hSelBm, ofn.lpstrFile, hDrawingDC, NULL, NULL, fileHPPM, fileVPPM);
849 break;
850 case IDM_COLORSEDITPALETTE:
851 if (ChooseColor(&choosecolor))
852 {
853 fgColor = choosecolor.rgbResult;
854 SendMessage(hPalWin, WM_PAINT, 0, 0);
855 }
856 break;
857 case IDM_IMAGEINVERTCOLORS:
858 {
859 RECT tempRect;
860 newReversible();
861 SetRect(&tempRect, 0, 0, imgXRes, imgYRes);
862 InvertRect(hDrawingDC, &tempRect);
863 SendMessage(hImageArea, WM_PAINT, 0, 0);
864 break;
865 }
866 case IDM_IMAGEDELETEIMAGE:
867 newReversible();
868 Rect(hDrawingDC, 0, 0, imgXRes, imgYRes, bgColor, bgColor, 0, TRUE);
869 SendMessage(hImageArea, WM_PAINT, 0, 0);
870 break;
871 case IDM_IMAGEROTATEMIRROR:
872 switch (mirrorRotateDlg())
873 {
874 case 1: /* flip horizontally */
875 if (IsWindowVisible(hSelection))
876 {
877 SelectObject(hSelDC, hSelMask);
878 StretchBlt(hSelDC, rectSel_dest[2] - 1, 0, -rectSel_dest[2], rectSel_dest[3], hSelDC,
879 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
880 SelectObject(hSelDC, hSelBm);
881 StretchBlt(hSelDC, rectSel_dest[2] - 1, 0, -rectSel_dest[2], rectSel_dest[3], hSelDC,
882 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
883 /* force refresh of selection contents, used also in case 2 and case 4 */
884 SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0);
885 SendMessage(hSelection, WM_MOUSEMOVE, 0, 0);
886 SendMessage(hSelection, WM_LBUTTONUP, 0, 0);
887 }
888 else
889 {
890 newReversible();
891 StretchBlt(hDrawingDC, imgXRes - 1, 0, -imgXRes, imgYRes, hDrawingDC, 0, 0,
892 imgXRes, imgYRes, SRCCOPY);
893 SendMessage(hImageArea, WM_PAINT, 0, 0);
894 }
895 break;
896 case 2: /* flip vertically */
897 if (IsWindowVisible(hSelection))
898 {
899 SelectObject(hSelDC, hSelMask);
900 StretchBlt(hSelDC, 0, rectSel_dest[3] - 1, rectSel_dest[2], -rectSel_dest[3], hSelDC,
901 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
902 SelectObject(hSelDC, hSelBm);
903 StretchBlt(hSelDC, 0, rectSel_dest[3] - 1, rectSel_dest[2], -rectSel_dest[3], hSelDC,
904 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
905 SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0);
906 SendMessage(hSelection, WM_MOUSEMOVE, 0, 0);
907 SendMessage(hSelection, WM_LBUTTONUP, 0, 0);
908 }
909 else
910 {
911 newReversible();
912 StretchBlt(hDrawingDC, 0, imgYRes - 1, imgXRes, -imgYRes, hDrawingDC, 0, 0,
913 imgXRes, imgYRes, SRCCOPY);
914 SendMessage(hImageArea, WM_PAINT, 0, 0);
915 }
916 break;
917 case 3: /* rotate 90 degrees */
918 break;
919 case 4: /* rotate 180 degrees */
920 if (IsWindowVisible(hSelection))
921 {
922 SelectObject(hSelDC, hSelMask);
923 StretchBlt(hSelDC, rectSel_dest[2] - 1, rectSel_dest[3] - 1, -rectSel_dest[2], -rectSel_dest[3], hSelDC,
924 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
925 SelectObject(hSelDC, hSelBm);
926 StretchBlt(hSelDC, rectSel_dest[2] - 1, rectSel_dest[3] - 1, -rectSel_dest[2], -rectSel_dest[3], hSelDC,
927 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
928 SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0);
929 SendMessage(hSelection, WM_MOUSEMOVE, 0, 0);
930 SendMessage(hSelection, WM_LBUTTONUP, 0, 0);
931 }
932 else
933 {
934 newReversible();
935 StretchBlt(hDrawingDC, imgXRes - 1, imgYRes - 1, -imgXRes, -imgYRes, hDrawingDC,
936 0, 0, imgXRes, imgYRes, SRCCOPY);
937 SendMessage(hImageArea, WM_PAINT, 0, 0);
938 }
939 break;
940 case 5: /* rotate 270 degrees */
941 break;
942 }
943 break;
944 case IDM_IMAGEATTRIBUTES:
945 {
946 int retVal = attributesDlg();
947 if ((LOWORD(retVal) != 0) && (HIWORD(retVal) != 0))
948 {
949 cropReversible(LOWORD(retVal), HIWORD(retVal), 0, 0);
950 updateCanvasAndScrollbars();
951 }
952 break;
953 }
954 case IDM_IMAGECHANGESIZE:
955 {
956 int retVal = changeSizeDlg();
957 if ((LOWORD(retVal) != 0) && (HIWORD(retVal) != 0))
958 {
959 insertReversible(CopyImage(hBms[currInd], IMAGE_BITMAP,
960 imgXRes * LOWORD(retVal) / 100,
961 imgYRes * HIWORD(retVal) / 100, 0));
962 updateCanvasAndScrollbars();
963 }
964 break;
965 }
966 case IDM_IMAGEDRAWOPAQUE:
967 transpBg = 1 - transpBg;
968 SendMessage(hToolSettings, WM_PAINT, 0, 0);
969 break;
970 case IDM_IMAGECROP:
971 insertReversible(CopyImage(hSelBm, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
972 updateCanvasAndScrollbars();
973 break;
974
975 case IDM_VIEWTOOLBOX:
976 ShowWindow(hToolBoxContainer, IsWindowVisible(hToolBoxContainer) ? SW_HIDE : SW_SHOW);
977 alignChildrenToMainWindow();
978 break;
979 case IDM_VIEWCOLORPALETTE:
980 ShowWindow(hPalWin, IsWindowVisible(hPalWin) ? SW_HIDE : SW_SHOW);
981 alignChildrenToMainWindow();
982 break;
983 case IDM_VIEWSTATUSBAR:
984 ShowWindow(hStatusBar, IsWindowVisible(hStatusBar) ? SW_HIDE : SW_SHOW);
985 alignChildrenToMainWindow();
986 break;
987
988 case IDM_VIEWSHOWGRID:
989 showGrid = !showGrid;
990 SendMessage(hImageArea, WM_PAINT, 0, 0);
991 break;
992 case IDM_VIEWSHOWMINIATURE:
993 showMiniature = !showMiniature;
994 ShowWindow(hwndMiniature, showMiniature ? SW_SHOW : SW_HIDE);
995 break;
996
997 case IDM_VIEWZOOM125:
998 zoomTo(125, 0, 0);
999 break;
1000 case IDM_VIEWZOOM25:
1001 zoomTo(250, 0, 0);
1002 break;
1003 case IDM_VIEWZOOM50:
1004 zoomTo(500, 0, 0);
1005 break;
1006 case IDM_VIEWZOOM100:
1007 zoomTo(1000, 0, 0);
1008 break;
1009 case IDM_VIEWZOOM200:
1010 zoomTo(2000, 0, 0);
1011 break;
1012 case IDM_VIEWZOOM400:
1013 zoomTo(4000, 0, 0);
1014 break;
1015 case IDM_VIEWZOOM800:
1016 zoomTo(8000, 0, 0);
1017 break;
1018 case ID_FREESEL:
1019 selectTool(1);
1020 break;
1021 case ID_RECTSEL:
1022 selectTool(2);
1023 break;
1024 case ID_RUBBER:
1025 selectTool(3);
1026 break;
1027 case ID_FILL:
1028 selectTool(4);
1029 break;
1030 case ID_COLOR:
1031 selectTool(5);
1032 break;
1033 case ID_ZOOM:
1034 selectTool(6);
1035 break;
1036 case ID_PEN:
1037 selectTool(7);
1038 break;
1039 case ID_BRUSH:
1040 selectTool(8);
1041 break;
1042 case ID_AIRBRUSH:
1043 selectTool(9);
1044 break;
1045 case ID_TEXT:
1046 selectTool(10);
1047 break;
1048 case ID_LINE:
1049 selectTool(11);
1050 break;
1051 case ID_BEZIER:
1052 selectTool(12);
1053 break;
1054 case ID_RECT:
1055 selectTool(13);
1056 break;
1057 case ID_SHAPE:
1058 selectTool(14);
1059 break;
1060 case ID_ELLIPSE:
1061 selectTool(15);
1062 break;
1063 case ID_RRECT:
1064 selectTool(16);
1065 break;
1066 }
1067 break;
1068 default:
1069 return DefWindowProc(hwnd, message, wParam, lParam);
1070 }
1071
1072 return 0;
1073 }