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