[USB-BRINGUP]
[reactos.git] / base / applications / paint / 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_COMMAND:
696 switch (LOWORD(wParam))
697 {
698 case IDM_HELPINFO:
699 {
700 HICON paintIcon = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON));
701 TCHAR infotitle[100];
702 TCHAR infotext[200];
703 LoadString(hProgInstance, IDS_INFOTITLE, infotitle, SIZEOF(infotitle));
704 LoadString(hProgInstance, IDS_INFOTEXT, infotext, SIZEOF(infotext));
705 ShellAbout(hMainWnd, infotitle, infotext, paintIcon);
706 DeleteObject(paintIcon);
707 break;
708 }
709 case IDM_HELPHELPTOPICS:
710 //HtmlHelp(hMainWnd, "help\\Paint.chm", 0, 0);
711 break;
712 case IDM_FILEEXIT:
713 SendMessage(hwnd, WM_CLOSE, wParam, lParam);
714 break;
715 case IDM_FILENEW:
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_EDITPASTE:
790 OpenClipboard(hMainWnd);
791 if (GetClipboardData(CF_BITMAP) != NULL)
792 {
793 DeleteObject(SelectObject(hSelDC, hSelBm = CopyImage(GetClipboardData(CF_BITMAP),
794 IMAGE_BITMAP, 0, 0,
795 LR_COPYRETURNORG)));
796 newReversible();
797 rectSel_src[0] = rectSel_src[1] = rectSel_src[2] = rectSel_src[3] = 0;
798 rectSel_dest[0] = rectSel_dest[1] = 0;
799 rectSel_dest[2] = GetDIBWidth(hSelBm);
800 rectSel_dest[3] = GetDIBHeight(hSelBm);
801 BitBlt(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2], rectSel_dest[3],
802 hSelDC, 0, 0, SRCCOPY);
803 placeSelWin();
804 ShowWindow(hSelection, SW_SHOW);
805 }
806 CloseClipboard();
807 break;
808 case IDM_EDITDELETESELECTION:
809 {
810 /* remove selection window and already painted content using undo(),
811 paint Rect for rectangular selections and Poly for freeform selections */
812 undo();
813 if (activeTool == TOOL_RECTSEL)
814 {
815 newReversible();
816 Rect(hDrawingDC, rectSel_dest[0], rectSel_dest[1], rectSel_dest[2] + rectSel_dest[0],
817 rectSel_dest[3] + rectSel_dest[1], bgColor, bgColor, 0, TRUE);
818 }
819 if (activeTool == TOOL_FREESEL)
820 {
821 newReversible();
822 Poly(hDrawingDC, ptStack, ptSP + 1, 0, 0, 2, 0, FALSE);
823 }
824 break;
825 }
826 case IDM_EDITSELECTALL:
827 {
828 HWND hToolbar = FindWindowEx(hToolBoxContainer, NULL, TOOLBARCLASSNAME, NULL);
829 SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELONG(TRUE, 0));
830 SendMessage(hwnd, WM_COMMAND, ID_RECTSEL, 0);
831 startPaintingL(hDrawingDC, 0, 0, fgColor, bgColor);
832 whilePaintingL(hDrawingDC, imgXRes, imgYRes, fgColor, bgColor);
833 endPaintingL(hDrawingDC, imgXRes, imgYRes, fgColor, bgColor);
834 break;
835 }
836 case IDM_EDITCOPYTO:
837 if (GetSaveFileName(&ofn) != 0)
838 SaveDIBToFile(hSelBm, ofn.lpstrFile, hDrawingDC, NULL, NULL, fileHPPM, fileVPPM);
839 break;
840 case IDM_COLORSEDITPALETTE:
841 if (ChooseColor(&choosecolor))
842 {
843 fgColor = choosecolor.rgbResult;
844 SendMessage(hPalWin, WM_PAINT, 0, 0);
845 }
846 break;
847 case IDM_IMAGEINVERTCOLORS:
848 {
849 RECT tempRect;
850 newReversible();
851 SetRect(&tempRect, 0, 0, imgXRes, imgYRes);
852 InvertRect(hDrawingDC, &tempRect);
853 SendMessage(hImageArea, WM_PAINT, 0, 0);
854 break;
855 }
856 case IDM_IMAGEDELETEIMAGE:
857 newReversible();
858 Rect(hDrawingDC, 0, 0, imgXRes, imgYRes, bgColor, bgColor, 0, TRUE);
859 SendMessage(hImageArea, WM_PAINT, 0, 0);
860 break;
861 case IDM_IMAGEROTATEMIRROR:
862 switch (mirrorRotateDlg())
863 {
864 case 1: /* flip horizontally */
865 if (IsWindowVisible(hSelection))
866 {
867 SelectObject(hSelDC, hSelMask);
868 StretchBlt(hSelDC, rectSel_dest[2] - 1, 0, -rectSel_dest[2], rectSel_dest[3], hSelDC,
869 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
870 SelectObject(hSelDC, hSelBm);
871 StretchBlt(hSelDC, rectSel_dest[2] - 1, 0, -rectSel_dest[2], rectSel_dest[3], hSelDC,
872 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
873 /* force refresh of selection contents, used also in case 2 and case 4 */
874 SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0);
875 SendMessage(hSelection, WM_MOUSEMOVE, 0, 0);
876 SendMessage(hSelection, WM_LBUTTONUP, 0, 0);
877 }
878 else
879 {
880 newReversible();
881 StretchBlt(hDrawingDC, imgXRes - 1, 0, -imgXRes, imgYRes, hDrawingDC, 0, 0,
882 imgXRes, imgYRes, SRCCOPY);
883 SendMessage(hImageArea, WM_PAINT, 0, 0);
884 }
885 break;
886 case 2: /* flip vertically */
887 if (IsWindowVisible(hSelection))
888 {
889 SelectObject(hSelDC, hSelMask);
890 StretchBlt(hSelDC, 0, rectSel_dest[3] - 1, rectSel_dest[2], -rectSel_dest[3], hSelDC,
891 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
892 SelectObject(hSelDC, hSelBm);
893 StretchBlt(hSelDC, 0, rectSel_dest[3] - 1, rectSel_dest[2], -rectSel_dest[3], hSelDC,
894 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
895 SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0);
896 SendMessage(hSelection, WM_MOUSEMOVE, 0, 0);
897 SendMessage(hSelection, WM_LBUTTONUP, 0, 0);
898 }
899 else
900 {
901 newReversible();
902 StretchBlt(hDrawingDC, 0, imgYRes - 1, imgXRes, -imgYRes, hDrawingDC, 0, 0,
903 imgXRes, imgYRes, SRCCOPY);
904 SendMessage(hImageArea, WM_PAINT, 0, 0);
905 }
906 break;
907 case 3: /* rotate 90 degrees */
908 break;
909 case 4: /* rotate 180 degrees */
910 if (IsWindowVisible(hSelection))
911 {
912 SelectObject(hSelDC, hSelMask);
913 StretchBlt(hSelDC, rectSel_dest[2] - 1, rectSel_dest[3] - 1, -rectSel_dest[2], -rectSel_dest[3], hSelDC,
914 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
915 SelectObject(hSelDC, hSelBm);
916 StretchBlt(hSelDC, rectSel_dest[2] - 1, rectSel_dest[3] - 1, -rectSel_dest[2], -rectSel_dest[3], hSelDC,
917 0, 0, rectSel_dest[2], rectSel_dest[3], SRCCOPY);
918 SendMessage(hSelection, WM_LBUTTONDOWN, 0, 0);
919 SendMessage(hSelection, WM_MOUSEMOVE, 0, 0);
920 SendMessage(hSelection, WM_LBUTTONUP, 0, 0);
921 }
922 else
923 {
924 newReversible();
925 StretchBlt(hDrawingDC, imgXRes - 1, imgYRes - 1, -imgXRes, -imgYRes, hDrawingDC,
926 0, 0, imgXRes, imgYRes, SRCCOPY);
927 SendMessage(hImageArea, WM_PAINT, 0, 0);
928 }
929 break;
930 case 5: /* rotate 270 degrees */
931 break;
932 }
933 break;
934 case IDM_IMAGEATTRIBUTES:
935 {
936 int retVal = attributesDlg();
937 if ((LOWORD(retVal) != 0) && (HIWORD(retVal) != 0))
938 {
939 cropReversible(LOWORD(retVal), HIWORD(retVal), 0, 0);
940 updateCanvasAndScrollbars();
941 }
942 break;
943 }
944 case IDM_IMAGECHANGESIZE:
945 {
946 int retVal = changeSizeDlg();
947 if ((LOWORD(retVal) != 0) && (HIWORD(retVal) != 0))
948 {
949 insertReversible(CopyImage(hBms[currInd], IMAGE_BITMAP,
950 imgXRes * LOWORD(retVal) / 100,
951 imgYRes * HIWORD(retVal) / 100, 0));
952 updateCanvasAndScrollbars();
953 }
954 break;
955 }
956 case IDM_IMAGEDRAWOPAQUE:
957 transpBg = 1 - transpBg;
958 SendMessage(hToolSettings, WM_PAINT, 0, 0);
959 break;
960 case IDM_IMAGECROP:
961 insertReversible(CopyImage(hSelBm, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG));
962 updateCanvasAndScrollbars();
963 break;
964
965 case IDM_VIEWTOOLBOX:
966 ShowWindow(hToolBoxContainer, IsWindowVisible(hToolBoxContainer) ? SW_HIDE : SW_SHOW);
967 alignChildrenToMainWindow();
968 break;
969 case IDM_VIEWCOLORPALETTE:
970 ShowWindow(hPalWin, IsWindowVisible(hPalWin) ? SW_HIDE : SW_SHOW);
971 alignChildrenToMainWindow();
972 break;
973 case IDM_VIEWSTATUSBAR:
974 ShowWindow(hStatusBar, IsWindowVisible(hStatusBar) ? SW_HIDE : SW_SHOW);
975 alignChildrenToMainWindow();
976 break;
977
978 case IDM_VIEWSHOWGRID:
979 showGrid = !showGrid;
980 SendMessage(hImageArea, WM_PAINT, 0, 0);
981 break;
982 case IDM_VIEWSHOWMINIATURE:
983 showMiniature = !showMiniature;
984 ShowWindow(hwndMiniature, showMiniature ? SW_SHOW : SW_HIDE);
985 break;
986
987 case IDM_VIEWZOOM125:
988 zoomTo(125, 0, 0);
989 break;
990 case IDM_VIEWZOOM25:
991 zoomTo(250, 0, 0);
992 break;
993 case IDM_VIEWZOOM50:
994 zoomTo(500, 0, 0);
995 break;
996 case IDM_VIEWZOOM100:
997 zoomTo(1000, 0, 0);
998 break;
999 case IDM_VIEWZOOM200:
1000 zoomTo(2000, 0, 0);
1001 break;
1002 case IDM_VIEWZOOM400:
1003 zoomTo(4000, 0, 0);
1004 break;
1005 case IDM_VIEWZOOM800:
1006 zoomTo(8000, 0, 0);
1007 break;
1008 case ID_FREESEL:
1009 selectTool(1);
1010 break;
1011 case ID_RECTSEL:
1012 selectTool(2);
1013 break;
1014 case ID_RUBBER:
1015 selectTool(3);
1016 break;
1017 case ID_FILL:
1018 selectTool(4);
1019 break;
1020 case ID_COLOR:
1021 selectTool(5);
1022 break;
1023 case ID_ZOOM:
1024 selectTool(6);
1025 break;
1026 case ID_PEN:
1027 selectTool(7);
1028 break;
1029 case ID_BRUSH:
1030 selectTool(8);
1031 break;
1032 case ID_AIRBRUSH:
1033 selectTool(9);
1034 break;
1035 case ID_TEXT:
1036 selectTool(10);
1037 break;
1038 case ID_LINE:
1039 selectTool(11);
1040 break;
1041 case ID_BEZIER:
1042 selectTool(12);
1043 break;
1044 case ID_RECT:
1045 selectTool(13);
1046 break;
1047 case ID_SHAPE:
1048 selectTool(14);
1049 break;
1050 case ID_ELLIPSE:
1051 selectTool(15);
1052 break;
1053 case ID_RRECT:
1054 selectTool(16);
1055 break;
1056 }
1057 break;
1058 default:
1059 return DefWindowProc(hwnd, message, wParam, lParam);
1060 }
1061
1062 return 0;
1063 }