ee09d6fba996421cf10534d8350b279e0ad8bef0
[reactos.git] / base / applications / mspaint / winproc.cpp
1 /*
2 * PROJECT: PAINT for ReactOS
3 * LICENSE: LGPL
4 * FILE: base/applications/mspaint/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 * Katayama Hirofumi MZ
9 * Stanislav Motylkov
10 */
11
12 #include "precomp.h"
13 #include <assert.h>
14
15 typedef HWND (WINAPI *FN_HtmlHelpW)(HWND, LPCWSTR, UINT, DWORD_PTR);
16
17 static HINSTANCE s_hHHCTRL_OCX = NULL; // HtmlHelpW needs "hhctrl.ocx"
18 static FN_HtmlHelpW s_pHtmlHelpW = NULL;
19
20 HWND hStatusBar = NULL;
21
22 /* FUNCTIONS ********************************************************/
23
24 // A wrapper function for HtmlHelpW
25 static HWND DoHtmlHelpW(HWND hwndCaller, LPCWSTR pszFile, UINT uCommand, DWORD_PTR dwData)
26 {
27 WCHAR szPath[MAX_PATH];
28
29 if (!s_hHHCTRL_OCX && (uCommand != HH_CLOSE_ALL))
30 {
31 // The function loads the system library, not local
32 GetSystemDirectoryW(szPath, _countof(szPath));
33 wcscat(szPath, L"\\hhctrl.ocx");
34 s_hHHCTRL_OCX = LoadLibraryW(szPath);
35 if (s_hHHCTRL_OCX)
36 s_pHtmlHelpW = (FN_HtmlHelpW)GetProcAddress(s_hHHCTRL_OCX, "HtmlHelpW");
37 }
38
39 if (!s_pHtmlHelpW)
40 return NULL;
41
42 return s_pHtmlHelpW(hwndCaller, pszFile, uCommand, dwData);
43 }
44
45 BOOL
46 zoomTo(int newZoom, int mouseX, int mouseY)
47 {
48 RECT clientRectScrollbox;
49 RECT clientRectImageArea;
50 int x, y, w, h;
51 canvasWindow.GetClientRect(&clientRectScrollbox);
52 imageArea.GetClientRect(&clientRectImageArea);
53 w = clientRectImageArea.right * newZoom / toolsModel.GetZoom();
54 h = clientRectImageArea.bottom * newZoom / toolsModel.GetZoom();
55 if (!w || !h)
56 {
57 return FALSE;
58 }
59 w = clientRectImageArea.right * clientRectScrollbox.right / w;
60 h = clientRectImageArea.bottom * clientRectScrollbox.bottom / h;
61 x = max(0, min(clientRectImageArea.right - w, mouseX - w / 2)) * newZoom / toolsModel.GetZoom();
62 y = max(0, min(clientRectImageArea.bottom - h, mouseY - h / 2)) * newZoom / toolsModel.GetZoom();
63
64 toolsModel.SetZoom(newZoom);
65
66 imageArea.MoveWindow(GRIP_SIZE, GRIP_SIZE, Zoomed(imageModel.GetWidth()), Zoomed(imageModel.GetHeight()), FALSE);
67 canvasWindow.Invalidate(TRUE);
68 imageArea.Invalidate(FALSE);
69
70 canvasWindow.SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, x), 0);
71 canvasWindow.SendMessage(WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, y), 0);
72 return TRUE;
73 }
74
75 void CMainWindow::alignChildrenToMainWindow()
76 {
77 RECT clientRect, rc;
78 GetClientRect(&clientRect);
79 RECT rcSpace = clientRect;
80
81 if (::IsWindowVisible(hStatusBar))
82 {
83 ::GetWindowRect(hStatusBar, &rc);
84 rcSpace.bottom -= rc.bottom - rc.top;
85 }
86
87 HDWP hDWP = ::BeginDeferWindowPos(3);
88
89 if (::IsWindowVisible(toolBoxContainer))
90 {
91 hDWP = ::DeferWindowPos(hDWP, toolBoxContainer, NULL,
92 rcSpace.left, rcSpace.top,
93 CX_TOOLBAR, rcSpace.bottom - rcSpace.top,
94 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
95 rcSpace.left += CX_TOOLBAR;
96 }
97
98 if (::IsWindowVisible(paletteWindow))
99 {
100 hDWP = ::DeferWindowPos(hDWP, paletteWindow, NULL,
101 rcSpace.left, rcSpace.top,
102 rcSpace.right - rcSpace.left, CY_PALETTE,
103 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
104 rcSpace.top += CY_PALETTE;
105 }
106
107 if (canvasWindow.IsWindow())
108 {
109 hDWP = ::DeferWindowPos(hDWP, canvasWindow, NULL,
110 rcSpace.left, rcSpace.top,
111 rcSpace.right - rcSpace.left, rcSpace.bottom - rcSpace.top,
112 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION);
113 }
114
115 ::EndDeferWindowPos(hDWP);
116 }
117
118 void CMainWindow::saveImage(BOOL overwrite)
119 {
120 imageArea.finishDrawing();
121
122 if (isAFile && overwrite)
123 {
124 imageModel.SaveImage(filepathname);
125 }
126 else if (GetSaveFileName(filepathname, _countof(filepathname)))
127 {
128 imageModel.SaveImage(filepathname);
129
130 CString strTitle;
131 strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname));
132 SetWindowText(strTitle);
133 isAFile = TRUE;
134 }
135 }
136
137 void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window)
138 {
139 int width = GetDIBWidth(bitmap);
140 int height = GetDIBHeight(bitmap);
141 int curWidth = imageModel.GetWidth();
142 int curHeight = imageModel.GetHeight();
143
144 if (width > curWidth || height > curHeight)
145 {
146 BOOL shouldEnlarge = TRUE;
147
148 if (askBeforeEnlarging)
149 {
150 TCHAR programname[20];
151 TCHAR shouldEnlargePromptText[100];
152
153 LoadString(hProgInstance, IDS_PROGRAMNAME, programname, _countof(programname));
154 LoadString(hProgInstance, IDS_ENLARGEPROMPTTEXT, shouldEnlargePromptText, _countof(shouldEnlargePromptText));
155
156 switch (MessageBox(shouldEnlargePromptText, programname, MB_YESNOCANCEL | MB_ICONQUESTION))
157 {
158 case IDYES:
159 break;
160 case IDNO:
161 shouldEnlarge = FALSE;
162 break;
163 case IDCANCEL:
164 return;
165 }
166 }
167
168 if (shouldEnlarge)
169 {
170 if (width > curWidth)
171 curWidth = width;
172
173 if (height > curHeight)
174 curHeight = height;
175
176 imageModel.Crop(curWidth, curHeight, 0, 0);
177 }
178 }
179
180 HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, TOOLBARCLASSNAME, NULL);
181 SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELPARAM(TRUE, 0));
182 toolBoxContainer.SendMessage(WM_COMMAND, ID_RECTSEL);
183
184 imageModel.CopyPrevious();
185 selectionModel.InsertFromHBITMAP(bitmap);
186
187 placeSelWin();
188 selectionWindow.ShowWindow(SW_SHOW);
189 selectionWindow.ForceRefreshSelectionContents();
190 }
191
192 LRESULT CMainWindow::OnMouseWheel(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
193 {
194 INT zDelta = (SHORT)HIWORD(wParam);
195
196 if (::GetAsyncKeyState(VK_CONTROL) < 0)
197 {
198 if (zDelta < 0)
199 {
200 if (toolsModel.GetZoom() > MIN_ZOOM)
201 zoomTo(toolsModel.GetZoom() / 2, 0, 0);
202 }
203 else if (zDelta > 0)
204 {
205 if (toolsModel.GetZoom() < MAX_ZOOM)
206 zoomTo(toolsModel.GetZoom() * 2, 0, 0);
207 }
208 }
209 else
210 {
211 UINT nCount = 3;
212 if (::GetAsyncKeyState(VK_SHIFT) < 0)
213 {
214 #ifndef SPI_GETWHEELSCROLLCHARS
215 #define SPI_GETWHEELSCROLLCHARS 0x006C // Needed for pre-NT6 PSDK
216 #endif
217 SystemParametersInfoW(SPI_GETWHEELSCROLLCHARS, 0, &nCount, 0);
218 for (UINT i = 0; i < nCount; ++i)
219 {
220 if (zDelta < 0)
221 ::PostMessageW(canvasWindow, WM_HSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
222 else if (zDelta > 0)
223 ::PostMessageW(canvasWindow, WM_HSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
224 }
225 }
226 else
227 {
228 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &nCount, 0);
229 for (UINT i = 0; i < nCount; ++i)
230 {
231 if (zDelta < 0)
232 ::PostMessageW(canvasWindow, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0);
233 else if (zDelta > 0)
234 ::PostMessageW(canvasWindow, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0);
235 }
236 }
237 }
238
239 return 0;
240 }
241
242 LRESULT CMainWindow::OnDropFiles(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
243 {
244 TCHAR droppedfile[MAX_PATH];
245
246 HDROP hDrop = (HDROP)wParam;
247 DragQueryFile(hDrop, 0, droppedfile, _countof(droppedfile));
248 DragFinish(hDrop);
249
250 ConfirmSave() && DoLoadImageFile(m_hWnd, droppedfile, TRUE);
251
252 return 0;
253 }
254
255 LRESULT CMainWindow::OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
256 {
257 // Loading and setting the window menu from resource
258 m_hMenu = ::LoadMenu(hProgInstance, MAKEINTRESOURCE(ID_MENU));
259 SetMenu(m_hMenu);
260
261 // Create the status bar
262 DWORD style = SBARS_SIZEGRIP | WS_CHILD | (registrySettings.ShowStatusBar ? WS_VISIBLE : 0);
263 hStatusBar = ::CreateWindowEx(0, STATUSCLASSNAME, NULL, style, 0, 0, 0, 0, m_hWnd,
264 NULL, hProgInstance, NULL);
265 ::SendMessage(hStatusBar, SB_SETMINHEIGHT, 21, 0);
266
267 // Create the tool box
268 toolBoxContainer.DoCreate(m_hWnd);
269
270 // Create the palette window
271 RECT rcEmpty = { 0, 0, 0, 0 }; // Rely on WM_SIZE
272 style = WS_CHILD | (registrySettings.ShowPalette ? WS_VISIBLE : 0);
273 paletteWindow.Create(m_hWnd, rcEmpty, NULL, style, WS_EX_STATICEDGE);
274
275 // Create the canvas
276 style = WS_CHILD | WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE;
277 canvasWindow.Create(m_hWnd, rcEmpty, NULL, style, WS_EX_CLIENTEDGE);
278
279 // Creating the window inside the canvas
280 imageArea.Create(canvasWindow, rcEmpty, NULL, WS_CHILD | WS_VISIBLE);
281
282 // Create selection window (initially hidden)
283 selectionWindow.Create(imageArea, rcEmpty, NULL, WS_CHILD | BS_OWNERDRAW);
284
285 // Create and show the miniature if necessary
286 if (registrySettings.ShowThumbnail)
287 {
288 miniature.DoCreate(m_hWnd);
289 miniature.ShowWindow(SW_SHOWNOACTIVATE);
290 }
291
292 // Set icon
293 SendMessage(WM_SETICON, ICON_BIG, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
294 SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON)));
295
296 return 0;
297 }
298
299 LRESULT CMainWindow::OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
300 {
301 registrySettings.WindowPlacement.length = sizeof(WINDOWPLACEMENT);
302 GetWindowPlacement(&(registrySettings.WindowPlacement));
303
304 DoHtmlHelpW(NULL, NULL, HH_CLOSE_ALL, 0);
305
306 if (s_hHHCTRL_OCX)
307 {
308 FreeLibrary(s_hHHCTRL_OCX);
309 s_hHHCTRL_OCX = NULL;
310 s_pHtmlHelpW = NULL;
311 }
312
313 SetMenu(NULL);
314 if (m_hMenu)
315 {
316 ::DestroyMenu(m_hMenu);
317 m_hMenu = NULL;
318 }
319
320 PostQuitMessage(0); /* send a WM_QUIT to the message queue */
321 return 0;
322 }
323
324 BOOL CMainWindow::ConfirmSave()
325 {
326 imageArea.finishDrawing();
327
328 if (imageModel.IsImageSaved())
329 return TRUE;
330
331 CString strProgramName;
332 strProgramName.LoadString(IDS_PROGRAMNAME);
333
334 CString strSavePromptText;
335 strSavePromptText.Format(IDS_SAVEPROMPTTEXT, PathFindFileName(filepathname));
336
337 switch (MessageBox(strSavePromptText, strProgramName, MB_YESNOCANCEL | MB_ICONQUESTION))
338 {
339 case IDYES:
340 saveImage(TRUE);
341 return imageModel.IsImageSaved();
342 case IDNO:
343 return TRUE;
344 case IDCANCEL:
345 return FALSE;
346 }
347
348 return TRUE;
349 }
350
351 LRESULT CMainWindow::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
352 {
353 if (ConfirmSave())
354 {
355 DestroyWindow();
356 }
357 return 0;
358 }
359
360 void CMainWindow::ProcessFileMenu(HMENU hPopupMenu)
361 {
362 LPCTSTR dotext = PathFindExtensionW(filepathname);
363 BOOL isBMP = FALSE;
364 if (_tcsicmp(dotext, _T(".bmp")) == 0 ||
365 _tcsicmp(dotext, _T(".dib")) == 0 ||
366 _tcsicmp(dotext, _T(".rle")) == 0)
367 {
368 isBMP = TRUE;
369 }
370
371 EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERPLANE, ENABLED_IF(isAFile && isBMP));
372 EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERCENTERED, ENABLED_IF(isAFile && isBMP));
373 EnableMenuItem(hPopupMenu, IDM_FILEASWALLPAPERSTRETCHED, ENABLED_IF(isAFile && isBMP));
374
375 for (INT iItem = 0; iItem < MAX_RECENT_FILES; ++iItem)
376 RemoveMenu(hPopupMenu, IDM_FILE1 + iItem, MF_BYCOMMAND);
377
378 if (registrySettings.strFiles[0].IsEmpty())
379 return;
380
381 RemoveMenu(hPopupMenu, IDM_FILEMOSTRECENTLYUSEDFILE, MF_BYCOMMAND);
382
383 INT cMenuItems = GetMenuItemCount(hPopupMenu);
384
385 for (INT iItem = 0; iItem < MAX_RECENT_FILES; ++iItem)
386 {
387 CString& strFile = registrySettings.strFiles[iItem];
388 if (strFile.IsEmpty())
389 break;
390
391 // Condense the lengthy pathname by using '...'
392 #define MAX_RECENT_PATHNAME_DISPLAY 30
393 CPath pathFile(strFile);
394 pathFile.CompactPathEx(MAX_RECENT_PATHNAME_DISPLAY);
395 assert(_tcslen((LPCTSTR)pathFile) <= MAX_RECENT_PATHNAME_DISPLAY);
396
397 // Add an accelerator (by '&') to the item number for quick access
398 TCHAR szText[4 + MAX_RECENT_PATHNAME_DISPLAY + 1];
399 wsprintf(szText, _T("&%u %s"), iItem + 1, (LPCTSTR)pathFile);
400
401 INT iMenuItem = (cMenuItems - 2) + iItem;
402 InsertMenu(hPopupMenu, iMenuItem, MF_BYPOSITION | MF_STRING, IDM_FILE1 + iItem, szText);
403 }
404 }
405
406 LRESULT CMainWindow::OnInitMenuPopup(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
407 {
408 HMENU menu = (HMENU)wParam;
409 BOOL trueSelection =
410 (::IsWindowVisible(selectionWindow) &&
411 ((toolsModel.GetActiveTool() == TOOL_FREESEL) || (toolsModel.GetActiveTool() == TOOL_RECTSEL)));
412
413 switch (lParam)
414 {
415 case 0: /* File menu */
416 ProcessFileMenu((HMENU)wParam);
417 break;
418 case 1: /* Edit menu */
419 EnableMenuItem(menu, IDM_EDITUNDO, ENABLED_IF(imageModel.HasUndoSteps()));
420 EnableMenuItem(menu, IDM_EDITREDO, ENABLED_IF(imageModel.HasRedoSteps()));
421 EnableMenuItem(menu, IDM_EDITCUT, ENABLED_IF(trueSelection));
422 EnableMenuItem(menu, IDM_EDITCOPY, ENABLED_IF(trueSelection));
423 EnableMenuItem(menu, IDM_EDITDELETESELECTION, ENABLED_IF(trueSelection));
424 EnableMenuItem(menu, IDM_EDITINVERTSELECTION, ENABLED_IF(trueSelection));
425 EnableMenuItem(menu, IDM_EDITCOPYTO, ENABLED_IF(trueSelection));
426 OpenClipboard();
427 EnableMenuItem(menu, IDM_EDITPASTE, ENABLED_IF(GetClipboardData(CF_BITMAP) != NULL));
428 CloseClipboard();
429 break;
430 case 2: /* View menu */
431 CheckMenuItem(menu, IDM_VIEWTOOLBOX, CHECKED_IF(::IsWindowVisible(toolBoxContainer)));
432 CheckMenuItem(menu, IDM_VIEWCOLORPALETTE, CHECKED_IF(::IsWindowVisible(paletteWindow)));
433 CheckMenuItem(menu, IDM_VIEWSTATUSBAR, CHECKED_IF(::IsWindowVisible(hStatusBar)));
434 CheckMenuItem(menu, IDM_FORMATICONBAR, CHECKED_IF(::IsWindowVisible(fontsDialog)));
435 EnableMenuItem(menu, IDM_FORMATICONBAR, ENABLED_IF(toolsModel.GetActiveTool() == TOOL_TEXT));
436
437 CheckMenuItem(menu, IDM_VIEWSHOWGRID, CHECKED_IF(showGrid));
438 CheckMenuItem(menu, IDM_VIEWSHOWMINIATURE, CHECKED_IF(registrySettings.ShowThumbnail));
439 break;
440 case 3: /* Image menu */
441 EnableMenuItem(menu, IDM_IMAGECROP, ENABLED_IF(::IsWindowVisible(selectionWindow)));
442 CheckMenuItem(menu, IDM_IMAGEDRAWOPAQUE, CHECKED_IF(!toolsModel.IsBackgroundTransparent()));
443 break;
444 }
445
446 CheckMenuItem(menu, IDM_VIEWZOOM125, CHECKED_IF(toolsModel.GetZoom() == 125));
447 CheckMenuItem(menu, IDM_VIEWZOOM25, CHECKED_IF(toolsModel.GetZoom() == 250));
448 CheckMenuItem(menu, IDM_VIEWZOOM50, CHECKED_IF(toolsModel.GetZoom() == 500));
449 CheckMenuItem(menu, IDM_VIEWZOOM100, CHECKED_IF(toolsModel.GetZoom() == 1000));
450 CheckMenuItem(menu, IDM_VIEWZOOM200, CHECKED_IF(toolsModel.GetZoom() == 2000));
451 CheckMenuItem(menu, IDM_VIEWZOOM400, CHECKED_IF(toolsModel.GetZoom() == 4000));
452 CheckMenuItem(menu, IDM_VIEWZOOM800, CHECKED_IF(toolsModel.GetZoom() == 8000));
453
454 CheckMenuItem(menu, IDM_COLORSMODERNPALETTE, CHECKED_IF(paletteModel.SelectedPalette() == PAL_MODERN));
455 CheckMenuItem(menu, IDM_COLORSOLDPALETTE, CHECKED_IF(paletteModel.SelectedPalette() == PAL_OLDTYPE));
456 return 0;
457 }
458
459 LRESULT CMainWindow::OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
460 {
461 int test[] = { LOWORD(lParam) - 260, LOWORD(lParam) - 140, LOWORD(lParam) - 20 };
462 if (::IsWindow(hStatusBar))
463 {
464 ::SendMessage(hStatusBar, WM_SIZE, 0, 0);
465 ::SendMessage(hStatusBar, SB_SETPARTS, 3, (LPARAM)&test);
466 }
467 alignChildrenToMainWindow();
468 return 0;
469 }
470
471 LRESULT CMainWindow::OnGetMinMaxInfo(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
472 {
473 MINMAXINFO *mm = (LPMINMAXINFO) lParam;
474 mm->ptMinTrackSize.x = 330;
475 mm->ptMinTrackSize.y = 360;
476 return 0;
477 }
478
479 LRESULT CMainWindow::OnKeyDown(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
480 {
481 if (wParam == VK_ESCAPE)
482 {
483 HWND hwndCapture = GetCapture();
484 if (hwndCapture)
485 {
486 if (canvasWindow.m_hWnd == hwndCapture ||
487 selectionWindow.m_hWnd == hwndCapture ||
488 imageArea.m_hWnd == hwndCapture ||
489 fullscreenWindow.m_hWnd == hwndCapture)
490 {
491 SendMessage(hwndCapture, nMsg, wParam, lParam);
492 }
493 }
494 else
495 {
496 imageArea.SendMessage(nMsg, wParam, lParam);
497 }
498 }
499 return 0;
500 }
501
502 LRESULT CMainWindow::OnSysColorChange(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
503 {
504 /* Redirect message to common controls */
505 HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, TOOLBARCLASSNAME, NULL);
506 SendMessage(hToolbar, WM_SYSCOLORCHANGE, 0, 0);
507 return 0;
508 }
509
510 LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
511 {
512 // Disable commands while dragging mouse
513 if (imageArea.drawing && ::GetCapture())
514 {
515 ATLTRACE("locking!\n");
516 return 0;
517 }
518
519 switch (LOWORD(wParam))
520 {
521 case IDM_HELPINFO:
522 {
523 HICON paintIcon = LoadIcon(hProgInstance, MAKEINTRESOURCE(IDI_APPICON));
524 TCHAR infotitle[100];
525 TCHAR infotext[200];
526 LoadString(hProgInstance, IDS_INFOTITLE, infotitle, _countof(infotitle));
527 LoadString(hProgInstance, IDS_INFOTEXT, infotext, _countof(infotext));
528 ShellAbout(m_hWnd, infotitle, infotext, paintIcon);
529 DeleteObject(paintIcon);
530 break;
531 }
532 case IDM_HELPHELPTOPICS:
533 DoHtmlHelpW(m_hWnd, L"%SystemRoot%\\Help\\mspaint.chm", HH_DISPLAY_TOPIC, 0);
534 break;
535 case IDM_FILEEXIT:
536 SendMessage(WM_CLOSE, wParam, lParam);
537 break;
538 case IDM_FILENEW:
539 if (ConfirmSave())
540 {
541 SetBitmapAndInfo(NULL, NULL, 0, FALSE);
542 }
543 break;
544 case IDM_FILEOPEN:
545 {
546 TCHAR szFileName[MAX_LONG_PATH] = _T("");
547 if (ConfirmSave() && GetOpenFileName(szFileName, _countof(szFileName)))
548 {
549 DoLoadImageFile(m_hWnd, szFileName, TRUE);
550 }
551 break;
552 }
553 case IDM_FILESAVE:
554 saveImage(TRUE);
555 break;
556 case IDM_FILESAVEAS:
557 saveImage(FALSE);
558 break;
559 case IDM_FILEPAGESETUP:
560 // DUMMY: Shows the dialog only, no functionality
561 PAGESETUPDLG psd;
562 ZeroMemory(&psd, sizeof(psd));
563 psd.lStructSize = sizeof(psd);
564 psd.hwndOwner = m_hWnd;
565 PageSetupDlg(&psd);
566 break;
567 case IDM_FILEPRINT:
568 // TODO: Test whether it actually works
569 PRINTDLG pd;
570 ZeroMemory(&pd, sizeof(pd));
571 pd.lStructSize = sizeof(pd);
572 pd.hwndOwner = m_hWnd;
573 pd.hDevMode = NULL; // freed by user
574 pd.hDevNames = NULL; // freed by user
575 pd.Flags = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC;
576 pd.nCopies = 1;
577 pd.nFromPage = 0xffff;
578 pd.nToPage = 0xffff;
579 pd.nMinPage = 1;
580 pd.nMaxPage = 0xffff;
581 if (PrintDlg(&pd) == TRUE)
582 {
583 BitBlt(pd.hDC, 0, 0, imageModel.GetWidth(), imageModel.GetHeight(), imageModel.GetDC(), 0, 0, SRCCOPY);
584 DeleteDC(pd.hDC);
585 }
586 if (pd.hDevMode)
587 GlobalFree(pd.hDevMode);
588 if (pd.hDevNames)
589 GlobalFree(pd.hDevNames);
590 break;
591 case IDM_FILEASWALLPAPERPLANE:
592 RegistrySettings::SetWallpaper(filepathname, RegistrySettings::TILED);
593 break;
594 case IDM_FILEASWALLPAPERCENTERED:
595 RegistrySettings::SetWallpaper(filepathname, RegistrySettings::CENTERED);
596 break;
597 case IDM_FILEASWALLPAPERSTRETCHED:
598 RegistrySettings::SetWallpaper(filepathname, RegistrySettings::STRETCHED);
599 break;
600 case IDM_FILE1:
601 case IDM_FILE2:
602 case IDM_FILE3:
603 case IDM_FILE4:
604 {
605 INT iFile = LOWORD(wParam) - IDM_FILE1;
606 if (ConfirmSave())
607 DoLoadImageFile(m_hWnd, registrySettings.strFiles[iFile], TRUE);
608 break;
609 }
610 case IDM_EDITUNDO:
611 if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
612 break;
613 if (selectionWindow.IsWindowVisible())
614 {
615 if (toolsModel.GetActiveTool() == TOOL_RECTSEL ||
616 toolsModel.GetActiveTool() == TOOL_FREESEL)
617 {
618 imageArea.cancelDrawing();
619 break;
620 }
621 }
622 if (ToolBase::pointSP != 0) // drawing something?
623 {
624 imageArea.cancelDrawing();
625 break;
626 }
627 imageModel.Undo();
628 imageArea.Invalidate(FALSE);
629 break;
630 case IDM_EDITREDO:
631 if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
632 break;
633 if (ToolBase::pointSP != 0) // drawing something?
634 {
635 imageArea.finishDrawing();
636 break;
637 }
638 imageModel.Redo();
639 imageArea.Invalidate(FALSE);
640 break;
641 case IDM_EDITCOPY:
642 OpenClipboard();
643 EmptyClipboard();
644 SetClipboardData(CF_BITMAP, CopyDIBImage(selectionModel.GetBitmap()));
645 CloseClipboard();
646 break;
647 case IDM_EDITCUT:
648 /* Copy */
649 SendMessage(WM_COMMAND, IDM_EDITCOPY, 0);
650 /* Delete selection */
651 SendMessage(WM_COMMAND, IDM_EDITDELETESELECTION, 0);
652 break;
653 case IDM_EDITPASTE:
654 OpenClipboard();
655 if (GetClipboardData(CF_BITMAP) != NULL)
656 {
657 InsertSelectionFromHBITMAP((HBITMAP) GetClipboardData(CF_BITMAP), m_hWnd);
658 }
659 CloseClipboard();
660 break;
661 case IDM_EDITDELETESELECTION:
662 {
663 switch (toolsModel.GetActiveTool())
664 {
665 case TOOL_FREESEL:
666 case TOOL_RECTSEL:
667 imageModel.DeleteSelection();
668 break;
669
670 case TOOL_TEXT:
671 imageArea.cancelDrawing();
672 break;
673 default:
674 break;
675 }
676 break;
677 }
678 case IDM_EDITSELECTALL:
679 {
680 if (toolsModel.GetActiveTool() == TOOL_TEXT && ::IsWindowVisible(textEditWindow))
681 {
682 textEditWindow.SendMessage(EM_SETSEL, 0, -1);
683 break;
684 }
685 HWND hToolbar = FindWindowEx(toolBoxContainer.m_hWnd, NULL, TOOLBARCLASSNAME, NULL);
686 SendMessage(hToolbar, TB_CHECKBUTTON, ID_RECTSEL, MAKELPARAM(TRUE, 0));
687 toolsModel.selectAll();
688 imageArea.Invalidate(TRUE);
689 break;
690 }
691 case IDM_EDITCOPYTO:
692 {
693 TCHAR szFileName[MAX_LONG_PATH] = _T("");
694 if (GetSaveFileName(szFileName, _countof(szFileName)))
695 SaveDIBToFile(selectionModel.GetBitmap(), szFileName, imageModel.GetDC());
696 break;
697 }
698 case IDM_EDITPASTEFROM:
699 {
700 TCHAR szFileName[MAX_LONG_PATH] = _T("");
701 if (GetOpenFileName(szFileName, _countof(szFileName)))
702 {
703 HBITMAP hbmNew = DoLoadImageFile(m_hWnd, szFileName, FALSE);
704 if (hbmNew)
705 {
706 InsertSelectionFromHBITMAP(hbmNew, m_hWnd);
707 DeleteObject(hbmNew);
708 }
709 }
710 break;
711 }
712 case IDM_COLORSEDITPALETTE:
713 {
714 COLORREF rgbColor = paletteModel.GetFgColor();
715 if (ChooseColor(&rgbColor))
716 paletteModel.SetFgColor(rgbColor);
717 break;
718 }
719 case IDM_COLORSMODERNPALETTE:
720 paletteModel.SelectPalette(PAL_MODERN);
721 break;
722 case IDM_COLORSOLDPALETTE:
723 paletteModel.SelectPalette(PAL_OLDTYPE);
724 break;
725 case IDM_IMAGEINVERTCOLORS:
726 {
727 imageModel.InvertColors();
728 break;
729 }
730 case IDM_IMAGEDELETEIMAGE:
731 imageModel.CopyPrevious();
732 Rect(imageModel.GetDC(), 0, 0, imageModel.GetWidth(), imageModel.GetHeight(), paletteModel.GetBgColor(), paletteModel.GetBgColor(), 0, TRUE);
733 imageArea.Invalidate(FALSE);
734 break;
735 case IDM_IMAGEROTATEMIRROR:
736 switch (mirrorRotateDialog.DoModal(mainWindow.m_hWnd))
737 {
738 case 1: /* flip horizontally */
739 if (::IsWindowVisible(selectionWindow))
740 selectionModel.FlipHorizontally();
741 else
742 imageModel.FlipHorizontally();
743 break;
744 case 2: /* flip vertically */
745 if (::IsWindowVisible(selectionWindow))
746 selectionModel.FlipVertically();
747 else
748 imageModel.FlipVertically();
749 break;
750 case 3: /* rotate 90 degrees */
751 if (::IsWindowVisible(selectionWindow))
752 selectionModel.RotateNTimes90Degrees(1);
753 else
754 imageModel.RotateNTimes90Degrees(1);
755 break;
756 case 4: /* rotate 180 degrees */
757 if (::IsWindowVisible(selectionWindow))
758 selectionModel.RotateNTimes90Degrees(2);
759 else
760 imageModel.RotateNTimes90Degrees(2);
761 break;
762 case 5: /* rotate 270 degrees */
763 if (::IsWindowVisible(selectionWindow))
764 selectionModel.RotateNTimes90Degrees(3);
765 else
766 imageModel.RotateNTimes90Degrees(3);
767 break;
768 }
769 break;
770 case IDM_IMAGEATTRIBUTES:
771 {
772 if (attributesDialog.DoModal(mainWindow.m_hWnd))
773 {
774 imageModel.Crop(attributesDialog.newWidth, attributesDialog.newHeight, 0, 0);
775 }
776 break;
777 }
778 case IDM_IMAGESTRETCHSKEW:
779 {
780 if (stretchSkewDialog.DoModal(mainWindow.m_hWnd))
781 {
782 if (::IsWindowVisible(selectionWindow))
783 {
784 selectionModel.StretchSkew(stretchSkewDialog.percentage.x, stretchSkewDialog.percentage.y,
785 stretchSkewDialog.angle.x, stretchSkewDialog.angle.y);
786 }
787 else
788 {
789 imageModel.StretchSkew(stretchSkewDialog.percentage.x, stretchSkewDialog.percentage.y,
790 stretchSkewDialog.angle.x, stretchSkewDialog.angle.y);
791 }
792 }
793 break;
794 }
795 case IDM_IMAGEDRAWOPAQUE:
796 toolsModel.SetBackgroundTransparent(!toolsModel.IsBackgroundTransparent());
797 break;
798 case IDM_IMAGECROP:
799 imageModel.Insert(CopyDIBImage(selectionModel.GetBitmap()));
800 break;
801
802 case IDM_VIEWTOOLBOX:
803 registrySettings.ShowToolBox = !toolBoxContainer.IsWindowVisible();
804 toolBoxContainer.ShowWindow(registrySettings.ShowToolBox ? SW_SHOWNOACTIVATE : SW_HIDE);
805 alignChildrenToMainWindow();
806 break;
807 case IDM_VIEWCOLORPALETTE:
808 registrySettings.ShowPalette = !paletteWindow.IsWindowVisible();
809 paletteWindow.ShowWindow(registrySettings.ShowPalette ? SW_SHOWNOACTIVATE : SW_HIDE);
810 alignChildrenToMainWindow();
811 break;
812 case IDM_VIEWSTATUSBAR:
813 registrySettings.ShowStatusBar = !::IsWindowVisible(hStatusBar);
814 ::ShowWindow(hStatusBar, (registrySettings.ShowStatusBar ? SW_SHOWNOACTIVATE : SW_HIDE));
815 alignChildrenToMainWindow();
816 break;
817 case IDM_FORMATICONBAR:
818 if (toolsModel.GetActiveTool() == TOOL_TEXT)
819 {
820 if (!fontsDialog.IsWindow())
821 {
822 fontsDialog.Create(mainWindow);
823 }
824 registrySettings.ShowTextTool = !::IsWindowVisible(fontsDialog);
825 fontsDialog.ShowWindow(registrySettings.ShowTextTool ? SW_SHOW : SW_HIDE);
826 fontsDialog.SendMessage(DM_REPOSITION, 0, 0);
827 }
828 break;
829 case IDM_VIEWSHOWGRID:
830 showGrid = !showGrid;
831 imageArea.Invalidate(FALSE);
832 break;
833 case IDM_VIEWSHOWMINIATURE:
834 registrySettings.ShowThumbnail = !::IsWindowVisible(miniature);
835 miniature.DoCreate(m_hWnd);
836 miniature.ShowWindow(registrySettings.ShowThumbnail ? SW_SHOWNOACTIVATE : SW_HIDE);
837 break;
838
839 case IDM_VIEWZOOM125:
840 zoomTo(125, 0, 0);
841 break;
842 case IDM_VIEWZOOM25:
843 zoomTo(250, 0, 0);
844 break;
845 case IDM_VIEWZOOM50:
846 zoomTo(500, 0, 0);
847 break;
848 case IDM_VIEWZOOM100:
849 zoomTo(1000, 0, 0);
850 break;
851 case IDM_VIEWZOOM200:
852 zoomTo(2000, 0, 0);
853 break;
854 case IDM_VIEWZOOM400:
855 zoomTo(4000, 0, 0);
856 break;
857 case IDM_VIEWZOOM800:
858 zoomTo(8000, 0, 0);
859 break;
860
861 case IDM_VIEWFULLSCREEN:
862 // Create and show the fullscreen window
863 fullscreenWindow.DoCreate();
864 fullscreenWindow.ShowWindow(SW_SHOWMAXIMIZED);
865 ShowWindow(SW_HIDE);
866 break;
867 }
868 return 0;
869 }