1 /*
2  * PROJECT:    PAINT for ReactOS
3  * LICENSE:    LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:    Window procedures of the dialog windows plus launching functions
5  * COPYRIGHT:  Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
6  */
7 
8 /* INCLUDES *********************************************************/
9 
10 #include "precomp.h"
11 
12 #include "dialogs.h"
13 
14 #include <winnls.h>
15 
16 /* GLOBALS **********************************************************/
17 
18 CMirrorRotateDialog mirrorRotateDialog;
19 CAttributesDialog attributesDialog;
20 CStretchSkewDialog stretchSkewDialog;
21 CFontsDialog fontsDialog;
22 
23 /* FUNCTIONS ********************************************************/
24 
25 void ShowError(INT stringID, ...)
26 {
27     va_list va;
28     va_start(va, stringID);
29 
30     CStringW strFormat, strText;
31     strFormat.LoadString(stringID);
32     strText.FormatV(strFormat, va);
33 
34     CStringW strProgramName;
35     strProgramName.LoadString(IDS_PROGRAMNAME);
36 
37     mainWindow.MessageBox(strText, strProgramName, MB_ICONERROR);
38     va_end(va);
39 }
40 
41 LRESULT CMirrorRotateDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
42 {
43     CheckDlgButton(IDD_MIRRORROTATERB1, BST_CHECKED);
44     CheckDlgButton(IDD_MIRRORROTATERB4, BST_CHECKED);
45     return TRUE;
46 }
47 
48 LRESULT CMirrorRotateDialog::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
49 {
50     EndDialog(0);
51     return 0;
52 }
53 
54 LRESULT CMirrorRotateDialog::OnOk(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
55 {
56     if (IsDlgButtonChecked(IDD_MIRRORROTATERB1))
57         EndDialog(1);
58     else if (IsDlgButtonChecked(IDD_MIRRORROTATERB2))
59         EndDialog(2);
60     else if (IsDlgButtonChecked(IDD_MIRRORROTATERB4))
61         EndDialog(3);
62     else if (IsDlgButtonChecked(IDD_MIRRORROTATERB5))
63         EndDialog(4);
64     else if (IsDlgButtonChecked(IDD_MIRRORROTATERB6))
65         EndDialog(5);
66     return 0;
67 }
68 
69 LRESULT CMirrorRotateDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
70 {
71     EndDialog(0);
72     return 0;
73 }
74 
75 LRESULT CMirrorRotateDialog::OnRadioButton3(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
76 {
77     if (IsDlgButtonChecked(IDD_MIRRORROTATERB3) != BST_CHECKED)
78         return 0;
79 
80     ::EnableWindow(GetDlgItem(IDD_MIRRORROTATERB4), TRUE);
81     ::EnableWindow(GetDlgItem(IDD_MIRRORROTATERB5), TRUE);
82     ::EnableWindow(GetDlgItem(IDD_MIRRORROTATERB6), TRUE);
83     return 0;
84 }
85 
86 LRESULT CMirrorRotateDialog::OnRadioButton12(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
87 {
88     if (IsDlgButtonChecked(IDD_MIRRORROTATERB1) != BST_CHECKED &&
89         IsDlgButtonChecked(IDD_MIRRORROTATERB2) != BST_CHECKED)
90     {
91         return 0;
92     }
93 
94     ::EnableWindow(GetDlgItem(IDD_MIRRORROTATERB4), FALSE);
95     ::EnableWindow(GetDlgItem(IDD_MIRRORROTATERB5), FALSE);
96     ::EnableWindow(GetDlgItem(IDD_MIRRORROTATERB6), FALSE);
97     return 0;
98 }
99 
100 LRESULT CAttributesDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
101 {
102     newWidth = imageModel.GetWidth();
103     newHeight = imageModel.GetHeight();
104 
105     CheckDlgButton(IDD_ATTRIBUTESRB3, BST_CHECKED);
106     SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE);
107     SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE);
108 
109     if (imageModel.IsBlackAndWhite())
110         CheckRadioButton(IDD_ATTRIBUTESRB4, IDD_ATTRIBUTESRB5, IDD_ATTRIBUTESRB4);
111     else
112         CheckRadioButton(IDD_ATTRIBUTESRB4, IDD_ATTRIBUTESRB5, IDD_ATTRIBUTESRB5);
113 
114     if (g_isAFile)
115     {
116         WCHAR date[100], temp[100];
117         GetDateFormatW(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, date, _countof(date));
118         GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, temp, _countof(temp));
119         StringCchCatW(date, _countof(date), L" ");
120         StringCchCatW(date, _countof(date), temp);
121         CStringW strSize;
122         strSize.Format(IDS_FILESIZE, g_fileSize);
123         SetDlgItemText(IDD_ATTRIBUTESTEXT6, date);
124         SetDlgItemText(IDD_ATTRIBUTESTEXT7, strSize);
125     }
126 
127     CStringW strUnit;
128     GetDlgItemText(IDD_ATTRIBUTESTEXT8, strUnit);
129 
130     CStringW strRes;
131     if (strUnit == L"dpi")
132         strRes.Format(IDS_PRINTRES, ROUND(g_xDpi), ROUND(g_yDpi));
133     else
134         strRes.Format(IDS_PRINTRES, ROUND(PpcmFromDpi(g_xDpi)), ROUND(PpcmFromDpi(g_yDpi)));
135 
136     SetDlgItemText(IDD_ATTRIBUTESTEXT8, strRes);
137     return TRUE;
138 }
139 
140 LRESULT CAttributesDialog::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
141 {
142     EndDialog(0);
143     return 0;
144 }
145 
146 LRESULT CAttributesDialog::OnOk(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
147 {
148     m_bBlackAndWhite = (IsDlgButtonChecked(IDD_ATTRIBUTESRB4) == BST_CHECKED);
149     EndDialog(1);
150     return 0;
151 }
152 
153 LRESULT CAttributesDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
154 {
155     EndDialog(0);
156     return 0;
157 }
158 
159 LRESULT CAttributesDialog::OnDefault(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
160 {
161     newWidth = imageModel.GetWidth();
162     newHeight = imageModel.GetHeight();
163     CheckDlgButton(IDD_ATTRIBUTESRB3, BST_CHECKED);
164     CheckDlgButton(IDD_ATTRIBUTESRB5, BST_CHECKED);
165     SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE);
166     SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE);
167     return 0;
168 }
169 
170 LRESULT CAttributesDialog::OnRadioButton1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
171 {
172     if (IsDlgButtonChecked(IDD_ATTRIBUTESRB1) != BST_CHECKED)
173         return 0;
174 
175     CStringW strNum;
176     strNum.Format(L"%.3lf", newWidth / g_xDpi);
177     SetDlgItemText(IDD_ATTRIBUTESEDIT1, strNum);
178     strNum.Format(L"%.3lf", newHeight / g_yDpi);
179     SetDlgItemText(IDD_ATTRIBUTESEDIT2, strNum);
180     return 0;
181 }
182 
183 LRESULT CAttributesDialog::OnRadioButton2(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
184 {
185     if (IsDlgButtonChecked(IDD_ATTRIBUTESRB2) != BST_CHECKED)
186         return 0;
187 
188     CStringW strNum;
189     strNum.Format(L"%.3lf", newWidth / PpcmFromDpi(g_xDpi));
190     SetDlgItemText(IDD_ATTRIBUTESEDIT1, strNum);
191     strNum.Format(L"%.3lf", newHeight / PpcmFromDpi(g_yDpi));
192     SetDlgItemText(IDD_ATTRIBUTESEDIT2, strNum);
193     return 0;
194 }
195 
196 LRESULT CAttributesDialog::OnRadioButton3(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
197 {
198     if (IsDlgButtonChecked(IDD_ATTRIBUTESRB3) != BST_CHECKED)
199         return 0;
200 
201     SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE);
202     SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE);
203     return 0;
204 }
205 
206 LRESULT CAttributesDialog::OnEdit1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
207 {
208     if (Edit_GetModify(hWndCtl))
209     {
210         WCHAR tempS[100];
211         if (IsDlgButtonChecked(IDD_ATTRIBUTESRB1))
212         {
213             GetDlgItemText(IDD_ATTRIBUTESEDIT1, tempS, _countof(tempS));
214             newWidth = max(1, (int)(wcstod(tempS, NULL) * g_xDpi));
215         }
216         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB2))
217         {
218             GetDlgItemText(IDD_ATTRIBUTESEDIT1, tempS, _countof(tempS));
219             newWidth = max(1, (int)(wcstod(tempS, NULL) * PpcmFromDpi(g_xDpi)));
220         }
221         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB3))
222         {
223             GetDlgItemText(IDD_ATTRIBUTESEDIT1, tempS, _countof(tempS));
224             newWidth = max(1, _wtoi(tempS));
225         }
226         Edit_SetModify(hWndCtl, FALSE);
227     }
228     return 0;
229 }
230 
231 LRESULT CAttributesDialog::OnEdit2(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
232 {
233     if (Edit_GetModify(hWndCtl))
234     {
235         WCHAR tempS[100];
236         if (IsDlgButtonChecked(IDD_ATTRIBUTESRB1))
237         {
238             GetDlgItemText(IDD_ATTRIBUTESEDIT2, tempS, _countof(tempS));
239             newHeight = max(1, (int)(wcstod(tempS, NULL) * g_yDpi));
240         }
241         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB2))
242         {
243             GetDlgItemText(IDD_ATTRIBUTESEDIT2, tempS, _countof(tempS));
244             newHeight = max(1, (int)(wcstod(tempS, NULL) * PpcmFromDpi(g_yDpi)));
245         }
246         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB3))
247         {
248             GetDlgItemText(IDD_ATTRIBUTESEDIT2, tempS, _countof(tempS));
249             newHeight = max(1, _wtoi(tempS));
250         }
251         Edit_SetModify(hWndCtl, FALSE);
252     }
253     return 0;
254 }
255 
256 
257 
258 LRESULT CStretchSkewDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
259 {
260     SetDlgItemInt(IDD_STRETCHSKEWEDITHSTRETCH, 100, FALSE);
261     SetDlgItemInt(IDD_STRETCHSKEWEDITVSTRETCH, 100, FALSE);
262     SetDlgItemInt(IDD_STRETCHSKEWEDITHSKEW, 0, FALSE);
263     SetDlgItemInt(IDD_STRETCHSKEWEDITVSKEW, 0, FALSE);
264     return TRUE;
265 }
266 
267 LRESULT CStretchSkewDialog::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
268 {
269     EndDialog(0);
270     return 0;
271 }
272 
273 LRESULT CStretchSkewDialog::OnOk(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
274 {
275     CStringW strrcIntNumbers, strrcPercentage, strrcAngle;
276     BOOL tr1, tr2, tr3, tr4;
277 
278     strrcIntNumbers.LoadString(g_hinstExe, IDS_INTNUMBERS);
279     strrcPercentage.LoadString(g_hinstExe, IDS_PERCENTAGE);
280     strrcAngle.LoadString(g_hinstExe, IDS_ANGLE);
281 
282     percentage.x = GetDlgItemInt(IDD_STRETCHSKEWEDITHSTRETCH, &tr1, FALSE);
283     percentage.y = GetDlgItemInt(IDD_STRETCHSKEWEDITVSTRETCH, &tr2, FALSE);
284     angle.x = GetDlgItemInt(IDD_STRETCHSKEWEDITHSKEW, &tr3, TRUE);
285     angle.y = GetDlgItemInt(IDD_STRETCHSKEWEDITVSKEW, &tr4, TRUE);
286 
287     if (!(tr1 && tr2 && tr3 && tr4))
288         MessageBox(strrcIntNumbers, NULL, MB_ICONEXCLAMATION);
289     else if (percentage.x < 1 || percentage.x > 500 || percentage.y < 1 || percentage.y > 500)
290         MessageBox(strrcPercentage, NULL, MB_ICONEXCLAMATION);
291     else if (angle.x < -89 || angle.x > 89 || angle.y < -89 || angle.y > 89)
292         MessageBox(strrcAngle, NULL, MB_ICONEXCLAMATION);
293     else
294         EndDialog(1);
295     return 0;
296 }
297 
298 LRESULT CStretchSkewDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
299 {
300     EndDialog(0);
301     return 0;
302 }
303 
304 static INT CALLBACK
305 EnumFontFamProc(ENUMLOGFONTW *lpelf, NEWTEXTMETRICW *lpntm, INT FontType, LPARAM lParam)
306 {
307     CSimpleArray<CStringW>& arrFontNames = *reinterpret_cast<CSimpleArray<CStringW>*>(lParam);
308     LPWSTR name = lpelf->elfLogFont.lfFaceName;
309     if (name[0] == L'@') // Vertical fonts
310         return TRUE;
311 
312     for (INT i = 0; i < arrFontNames.GetSize(); ++i)
313     {
314         if (arrFontNames[i] == name) // Already exists
315             return TRUE;
316     }
317 
318     arrFontNames.Add(name);
319     return TRUE;
320 }
321 
322 // TODO: AutoComplete font names
323 // TODO: Vertical text
324 CFontsDialog::CFontsDialog()
325 {
326 }
327 
328 void CFontsDialog::InitFontNames()
329 {
330     // List the fonts
331     CSimpleArray<CStringW> arrFontNames;
332     HDC hDC = CreateCompatibleDC(NULL);
333     if (hDC)
334     {
335         EnumFontFamiliesW(hDC, NULL, (FONTENUMPROCW)EnumFontFamProc,
336                           reinterpret_cast<LPARAM>(&arrFontNames));
337         ::DeleteDC(hDC);
338     }
339 
340     // Actually add them to the combobox
341     HWND hwndNames = GetDlgItem(IDD_FONTSNAMES);
342     ::SendMessageW(hwndNames, CB_RESETCONTENT, 0, 0);
343     for (INT i = 0; i < arrFontNames.GetSize(); ++i)
344     {
345         ComboBox_AddString(hwndNames, arrFontNames[i]);
346     }
347 
348     ::SetWindowTextW(hwndNames, registrySettings.strFontName);
349 }
350 
351 void CFontsDialog::InitFontSizes()
352 {
353     static const INT s_sizes[] =
354     {
355         8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72
356     };
357 
358     HWND hwndSizes = GetDlgItem(IDD_FONTSSIZES);
359     ComboBox_ResetContent(hwndSizes);
360 
361     WCHAR szText[16];
362     for (UINT i = 0; i < _countof(s_sizes); ++i)
363     {
364         StringCchPrintfW(szText, _countof(szText), L"%d", s_sizes[i]);
365         INT iItem = ComboBox_AddString(hwndSizes, szText);
366         if (s_sizes[i] == (INT)registrySettings.PointSize)
367             ComboBox_SetCurSel(hwndSizes, iItem);
368     }
369 
370     if (ComboBox_GetCurSel(hwndSizes) == CB_ERR)
371     {
372         StringCchPrintfW(szText, _countof(szText), L"%d", (INT)registrySettings.PointSize);
373         ::SetWindowTextW(hwndSizes, szText);
374     }
375 }
376 
377 void CFontsDialog::InitToolbar()
378 {
379     HWND hwndToolbar = GetDlgItem(IDD_FONTSTOOLBAR);
380     ::SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
381     ::SendMessageW(hwndToolbar, TB_SETBITMAPSIZE, 0, MAKELPARAM(16, 16));
382     ::SendMessageW(hwndToolbar, TB_SETBUTTONWIDTH, 0, MAKELPARAM(20, 20));
383 
384     TBADDBITMAP AddBitmap;
385     AddBitmap.hInst = g_hinstExe;
386     AddBitmap.nID = IDB_FONTSTOOLBAR;
387     ::SendMessageW(hwndToolbar, TB_ADDBITMAP, 4, (LPARAM)&AddBitmap);
388 
389     HIMAGELIST himl = ImageList_LoadImage(g_hinstExe, MAKEINTRESOURCEW(IDB_FONTSTOOLBAR),
390                                           16, 8, RGB(255, 0, 255), IMAGE_BITMAP,
391                                           LR_CREATEDIBSECTION);
392     ::SendMessageW(hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl);
393 
394     TBBUTTON buttons[] =
395     {
396         { 0, IDM_BOLD, TBSTATE_ENABLED, TBSTYLE_CHECK },
397         { 1, IDM_ITALIC, TBSTATE_ENABLED, TBSTYLE_CHECK },
398         { 2, IDM_UNDERLINE, TBSTATE_ENABLED, TBSTYLE_CHECK },
399         { 3, IDM_VERTICAL, 0, TBSTYLE_CHECK }, // TODO:
400     };
401     ::SendMessageW(hwndToolbar, TB_ADDBUTTONS, _countof(buttons), (LPARAM)&buttons);
402 
403     ::SendMessageW(hwndToolbar, TB_CHECKBUTTON, IDM_BOLD, registrySettings.Bold);
404     ::SendMessageW(hwndToolbar, TB_CHECKBUTTON, IDM_ITALIC, registrySettings.Italic);
405     ::SendMessageW(hwndToolbar, TB_CHECKBUTTON, IDM_UNDERLINE, registrySettings.Underline);
406 }
407 
408 LRESULT CFontsDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
409 {
410     // TODO: Tooltips
411     InitFontNames();
412     InitFontSizes();
413     InitToolbar();
414 
415     if (registrySettings.FontsPositionX != 0 || registrySettings.FontsPositionY != 0)
416     {
417         SetWindowPos(NULL,
418                      registrySettings.FontsPositionX, registrySettings.FontsPositionY,
419                      0, 0,
420                      SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
421         SendMessage(DM_REPOSITION, 0, 0);
422     }
423 
424     if (!registrySettings.ShowTextTool)
425         ShowWindow(SW_HIDE);
426 
427     return TRUE;
428 }
429 
430 LRESULT CFontsDialog::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
431 {
432     ShowWindow(SW_HIDE); // Just hide. Recycle for optimization
433     return 0;
434 }
435 
436 void CFontsDialog::OnFontName(UINT codeNotify)
437 {
438     HWND hwndNames = GetDlgItem(IDD_FONTSNAMES);
439     INT iItem = CB_ERR;
440     UINT cch;
441     WCHAR szText[LF_FACESIZE];
442 
443     switch (codeNotify)
444     {
445         case CBN_SELCHANGE:
446             iItem = ComboBox_GetCurSel(hwndNames);
447             cch = ComboBox_GetLBTextLen(hwndNames, iItem);
448             if (iItem != CB_ERR && 0 < cch && cch < _countof(szText))
449                 ComboBox_GetLBText(hwndNames, iItem, szText);
450             break;
451 
452         case CBN_EDITCHANGE:
453             GetDlgItemText(IDD_FONTSNAMES, szText, _countof(szText));
454             iItem = ComboBox_FindStringExact(hwndNames, -1, szText);
455             break;
456     }
457 
458     if (iItem != CB_ERR && registrySettings.strFontName.CompareNoCase(szText) != 0)
459     {
460         registrySettings.strFontName = szText;
461         toolsModel.NotifyToolChanged();
462     }
463 }
464 
465 void CFontsDialog::OnFontSize(UINT codeNotify)
466 {
467     HWND hwndSizes = GetDlgItem(IDD_FONTSSIZES);
468     WCHAR szText[8];
469     INT iItem, PointSize = 0;
470     UINT cch;
471 
472     switch (codeNotify)
473     {
474         case CBN_SELCHANGE:
475             iItem = ComboBox_GetCurSel(hwndSizes);
476             cch = ComboBox_GetLBTextLen(hwndSizes, iItem);
477             if (iItem != CB_ERR && 0 < cch && cch < _countof(szText))
478             {
479                 ComboBox_GetLBText(hwndSizes, iItem, szText);
480                 PointSize = _wtoi(szText);
481             }
482             break;
483 
484         case CBN_EDITCHANGE:
485             ::GetWindowTextW(hwndSizes, szText, _countof(szText));
486             PointSize = _wtoi(szText);
487             break;
488     }
489 
490     if (PointSize > 0)
491     {
492         registrySettings.PointSize = PointSize;
493         toolsModel.NotifyToolChanged();
494     }
495 }
496 
497 LRESULT CFontsDialog::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
498 {
499     UINT id = LOWORD(wParam);
500     UINT codeNotify = HIWORD(wParam);
501     HWND hwndToolbar = GetDlgItem(IDD_FONTSTOOLBAR);
502     BOOL bChecked = (BOOL)::SendMessageW(hwndToolbar, TB_ISBUTTONCHECKED, id, 0);
503 
504     switch (id)
505     {
506         case IDCANCEL:
507             ShowWindow(SW_HIDE);
508             registrySettings.ShowTextTool = FALSE;
509             break;
510 
511         case IDD_FONTSNAMES:
512             OnFontName(codeNotify);
513             break;
514 
515         case IDD_FONTSSIZES:
516             OnFontSize(codeNotify);
517             break;
518 
519         case IDM_BOLD:
520             registrySettings.Bold = bChecked;
521             toolsModel.NotifyToolChanged();
522             break;
523 
524         case IDM_ITALIC:
525             registrySettings.Italic = bChecked;
526             toolsModel.NotifyToolChanged();
527             break;
528 
529         case IDM_UNDERLINE:
530             registrySettings.Underline = bChecked;
531             toolsModel.NotifyToolChanged();
532             break;
533 
534         case IDM_VERTICAL:
535             // TODO:
536             break;
537     }
538     return 0;
539 }
540 
541 LRESULT CFontsDialog::OnNotify(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
542 {
543     NMHDR *pnmhdr = reinterpret_cast<NMHDR *>(lParam);
544     if (pnmhdr->code == TTN_NEEDTEXT)
545     {
546         LPTOOLTIPTEXTW pToolTip = reinterpret_cast<LPTOOLTIPTEXTW>(lParam);
547         pToolTip->hinst = g_hinstExe;
548         switch (pnmhdr->idFrom)
549         {
550             case IDM_BOLD:      pToolTip->lpszText = MAKEINTRESOURCEW(IDS_BOLD); break;
551             case IDM_ITALIC:    pToolTip->lpszText = MAKEINTRESOURCEW(IDS_ITALIC); break;
552             case IDM_UNDERLINE: pToolTip->lpszText = MAKEINTRESOURCEW(IDS_UNDERLINE); break;
553             case IDM_VERTICAL:  pToolTip->lpszText = MAKEINTRESOURCEW(IDS_VERTICAL); break;
554 
555             default:
556                 break;
557         }
558     }
559     return 0;
560 }
561 
562 LRESULT CFontsDialog::OnMove(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
563 {
564     RECT rc;
565     GetWindowRect(&rc);
566     registrySettings.FontsPositionX = rc.left;
567     registrySettings.FontsPositionY = rc.top;
568     return 0;
569 }
570 
571 LRESULT CFontsDialog::OnToolsModelToolChanged(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
572 {
573     if (wParam != TOOL_TEXT)
574         ShowWindow(SW_HIDE);
575 
576     return 0;
577 }
578 
579 LRESULT CFontsDialog::OnMeasureItem(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
580 {
581     if (wParam == IDD_FONTSNAMES)
582     {
583         LPMEASUREITEMSTRUCT pMeasureItem = reinterpret_cast<LPMEASUREITEMSTRUCT>(lParam);
584         RECT rc;
585         ::GetClientRect(GetDlgItem(IDD_FONTSNAMES), &rc);
586         pMeasureItem->itemWidth = rc.right - rc.left;
587         pMeasureItem->itemHeight = GetSystemMetrics(SM_CYVSCROLL);
588         return TRUE;
589     }
590     return 0;
591 }
592 
593 LRESULT CFontsDialog::OnDrawItem(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
594 {
595     // TODO: Owner-draw the font types
596     if (wParam == IDD_FONTSNAMES)
597     {
598         LPDRAWITEMSTRUCT pDrawItem = reinterpret_cast<LPDRAWITEMSTRUCT>(lParam);
599         if (pDrawItem->itemID == (UINT)-1)
600             return TRUE;
601 
602         ::SetBkMode(pDrawItem->hDC, TRANSPARENT);
603 
604         HWND hwndItem = pDrawItem->hwndItem;
605         RECT rcItem = pDrawItem->rcItem;
606         if (pDrawItem->itemState & ODS_SELECTED)
607         {
608             ::FillRect(pDrawItem->hDC, &rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
609             ::SetTextColor(pDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
610         }
611         else
612         {
613             ::FillRect(pDrawItem->hDC, &rcItem, GetSysColorBrush(COLOR_WINDOW));
614             ::SetTextColor(pDrawItem->hDC, GetSysColor(COLOR_WINDOWTEXT));
615         }
616 
617         WCHAR szText[LF_FACESIZE];
618         if ((UINT)ComboBox_GetLBTextLen(hwndItem, pDrawItem->itemID) < _countof(szText))
619         {
620             szText[0] = 0;
621             ComboBox_GetLBText(hwndItem, pDrawItem->itemID, szText);
622 
623             rcItem.left += 24;
624             ::DrawTextW(pDrawItem->hDC, szText, -1, &rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
625         }
626 
627         if (pDrawItem->itemState & ODS_FOCUS)
628             ::DrawFocusRect(pDrawItem->hDC, &pDrawItem->rcItem);
629 
630         return TRUE;
631     }
632     return 0;
633 }
634