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