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     CheckDlgButton(IDD_ATTRIBUTESRB5, BST_CHECKED);
107     SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE);
108     SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE);
109 
110     if (g_isAFile)
111     {
112         TCHAR date[100];
113         TCHAR temp[100];
114         GetDateFormat(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, date, _countof(date));
115         GetTimeFormat(LOCALE_USER_DEFAULT, 0, &g_fileTime, NULL, temp, _countof(temp));
116         _tcscat(date, _T(" "));
117         _tcscat(date, temp);
118         CString strSize;
119         strSize.Format(IDS_FILESIZE, g_fileSize);
120         SetDlgItemText(IDD_ATTRIBUTESTEXT6, date);
121         SetDlgItemText(IDD_ATTRIBUTESTEXT7, strSize);
122     }
123 
124     CString strUnit;
125     GetDlgItemText(IDD_ATTRIBUTESTEXT8, strUnit);
126 
127     CString strRes;
128     if (strUnit == L"dpi")
129         strRes.Format(IDS_PRINTRES, ROUND(g_xDpi), ROUND(g_yDpi));
130     else
131         strRes.Format(IDS_PRINTRES, ROUND(PpcmFromDpi(g_xDpi)), ROUND(PpcmFromDpi(g_yDpi)));
132 
133     SetDlgItemText(IDD_ATTRIBUTESTEXT8, strRes);
134     return TRUE;
135 }
136 
137 LRESULT CAttributesDialog::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
138 {
139     EndDialog(0);
140     return 0;
141 }
142 
143 LRESULT CAttributesDialog::OnOk(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
144 {
145     EndDialog(1);
146     return 0;
147 }
148 
149 LRESULT CAttributesDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
150 {
151     EndDialog(0);
152     return 0;
153 }
154 
155 LRESULT CAttributesDialog::OnDefault(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
156 {
157     newWidth = imageModel.GetWidth();
158     newHeight = imageModel.GetHeight();
159     CheckDlgButton(IDD_ATTRIBUTESRB3, BST_CHECKED);
160     CheckDlgButton(IDD_ATTRIBUTESRB5, BST_CHECKED);
161     SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE);
162     SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE);
163     return 0;
164 }
165 
166 LRESULT CAttributesDialog::OnRadioButton1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
167 {
168     if (IsDlgButtonChecked(IDD_ATTRIBUTESRB1) != BST_CHECKED)
169         return 0;
170 
171     CString strNum;
172     strNum.Format(_T("%.3lf"), newWidth / g_xDpi);
173     SetDlgItemText(IDD_ATTRIBUTESEDIT1, strNum);
174     strNum.Format(_T("%.3lf"), newHeight / g_yDpi);
175     SetDlgItemText(IDD_ATTRIBUTESEDIT2, strNum);
176     return 0;
177 }
178 
179 LRESULT CAttributesDialog::OnRadioButton2(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
180 {
181     if (IsDlgButtonChecked(IDD_ATTRIBUTESRB2) != BST_CHECKED)
182         return 0;
183 
184     CString strNum;
185     strNum.Format(_T("%.3lf"), newWidth / PpcmFromDpi(g_xDpi));
186     SetDlgItemText(IDD_ATTRIBUTESEDIT1, strNum);
187     strNum.Format(_T("%.3lf"), newHeight / PpcmFromDpi(g_yDpi));
188     SetDlgItemText(IDD_ATTRIBUTESEDIT2, strNum);
189     return 0;
190 }
191 
192 LRESULT CAttributesDialog::OnRadioButton3(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
193 {
194     if (IsDlgButtonChecked(IDD_ATTRIBUTESRB3) != BST_CHECKED)
195         return 0;
196 
197     SetDlgItemInt(IDD_ATTRIBUTESEDIT1, newWidth, FALSE);
198     SetDlgItemInt(IDD_ATTRIBUTESEDIT2, newHeight, FALSE);
199     return 0;
200 }
201 
202 LRESULT CAttributesDialog::OnEdit1(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
203 {
204     if (Edit_GetModify(hWndCtl))
205     {
206         TCHAR tempS[100];
207         if (IsDlgButtonChecked(IDD_ATTRIBUTESRB1))
208         {
209             GetDlgItemText(IDD_ATTRIBUTESEDIT1, tempS, _countof(tempS));
210             newWidth = max(1, (int) (_tcstod(tempS, NULL) * g_xDpi));
211         }
212         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB2))
213         {
214             GetDlgItemText(IDD_ATTRIBUTESEDIT1, tempS, _countof(tempS));
215             newWidth = max(1, (int) (_tcstod(tempS, NULL) * PpcmFromDpi(g_xDpi)));
216         }
217         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB3))
218         {
219             GetDlgItemText(IDD_ATTRIBUTESEDIT1, tempS, _countof(tempS));
220             newWidth = max(1, _tstoi(tempS));
221         }
222         Edit_SetModify(hWndCtl, FALSE);
223     }
224     return 0;
225 }
226 
227 LRESULT CAttributesDialog::OnEdit2(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
228 {
229     if (Edit_GetModify(hWndCtl))
230     {
231         TCHAR tempS[100];
232         if (IsDlgButtonChecked(IDD_ATTRIBUTESRB1))
233         {
234             GetDlgItemText(IDD_ATTRIBUTESEDIT2, tempS, _countof(tempS));
235             newHeight = max(1, (int) (_tcstod(tempS, NULL) * g_yDpi));
236         }
237         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB2))
238         {
239             GetDlgItemText(IDD_ATTRIBUTESEDIT2, tempS, _countof(tempS));
240             newHeight = max(1, (int) (_tcstod(tempS, NULL) * PpcmFromDpi(g_yDpi)));
241         }
242         else if (IsDlgButtonChecked(IDD_ATTRIBUTESRB3))
243         {
244             GetDlgItemText(IDD_ATTRIBUTESEDIT2, tempS, _countof(tempS));
245             newHeight = max(1, _tstoi(tempS));
246         }
247         Edit_SetModify(hWndCtl, FALSE);
248     }
249     return 0;
250 }
251 
252 
253 
254 LRESULT CStretchSkewDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
255 {
256     SetDlgItemInt(IDD_STRETCHSKEWEDITHSTRETCH, 100, FALSE);
257     SetDlgItemInt(IDD_STRETCHSKEWEDITVSTRETCH, 100, FALSE);
258     SetDlgItemInt(IDD_STRETCHSKEWEDITHSKEW, 0, FALSE);
259     SetDlgItemInt(IDD_STRETCHSKEWEDITVSKEW, 0, FALSE);
260     return TRUE;
261 }
262 
263 LRESULT CStretchSkewDialog::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
264 {
265     EndDialog(0);
266     return 0;
267 }
268 
269 LRESULT CStretchSkewDialog::OnOk(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
270 {
271     CString strrcIntNumbers;
272     CString strrcPercentage;
273     CString strrcAngle;
274     BOOL tr1, tr2, tr3, tr4;
275 
276     strrcIntNumbers.LoadString(g_hinstExe, IDS_INTNUMBERS);
277     strrcPercentage.LoadString(g_hinstExe, IDS_PERCENTAGE);
278     strrcAngle.LoadString(g_hinstExe, IDS_ANGLE);
279 
280     percentage.x = GetDlgItemInt(IDD_STRETCHSKEWEDITHSTRETCH, &tr1, FALSE);
281     percentage.y = GetDlgItemInt(IDD_STRETCHSKEWEDITVSTRETCH, &tr2, FALSE);
282     angle.x = GetDlgItemInt(IDD_STRETCHSKEWEDITHSKEW, &tr3, TRUE);
283     angle.y = GetDlgItemInt(IDD_STRETCHSKEWEDITVSKEW, &tr4, TRUE);
284 
285     if (!(tr1 && tr2 && tr3 && tr4))
286         MessageBox(strrcIntNumbers, NULL, MB_ICONEXCLAMATION);
287     else if (percentage.x < 1 || percentage.x > 500 || percentage.y < 1 || percentage.y > 500)
288         MessageBox(strrcPercentage, NULL, MB_ICONEXCLAMATION);
289     else if (angle.x < -89 || angle.x > 89 || angle.y < -89 || angle.y > 89)
290         MessageBox(strrcAngle, NULL, MB_ICONEXCLAMATION);
291     else
292         EndDialog(1);
293     return 0;
294 }
295 
296 LRESULT CStretchSkewDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
297 {
298     EndDialog(0);
299     return 0;
300 }
301 
302 static INT CALLBACK
303 EnumFontFamProc(ENUMLOGFONT *lpelf, NEWTEXTMETRIC *lpntm, INT FontType, LPARAM lParam)
304 {
305     CSimpleArray<CString>& arrFontNames = *reinterpret_cast<CSimpleArray<CString>*>(lParam);
306     LPTSTR name = lpelf->elfLogFont.lfFaceName;
307     if (name[0] == TEXT('@')) // Vertical fonts
308         return TRUE;
309 
310     for (INT i = 0; i < arrFontNames.GetSize(); ++i)
311     {
312         if (arrFontNames[i] == name) // Already exists
313             return TRUE;
314     }
315 
316     arrFontNames.Add(name);
317     return TRUE;
318 }
319 
320 // TODO: AutoComplete font names
321 // TODO: Vertical text
322 CFontsDialog::CFontsDialog()
323 {
324 }
325 
326 void CFontsDialog::InitFontNames()
327 {
328     // List the fonts
329     CSimpleArray<CString> arrFontNames;
330     HDC hDC = CreateCompatibleDC(NULL);
331     if (hDC)
332     {
333         EnumFontFamilies(hDC, NULL, (FONTENUMPROC)EnumFontFamProc,
334                          reinterpret_cast<LPARAM>(&arrFontNames));
335         DeleteDC(hDC);
336     }
337 
338     // Actually add them to the combobox
339     HWND hwndNames = GetDlgItem(IDD_FONTSNAMES);
340     SendMessage(hwndNames, CB_RESETCONTENT, 0, 0);
341     for (INT i = 0; i < arrFontNames.GetSize(); ++i)
342     {
343         ComboBox_AddString(hwndNames, arrFontNames[i]);
344     }
345 
346     ::SetWindowText(hwndNames, registrySettings.strFontName);
347 }
348 
349 void CFontsDialog::InitFontSizes()
350 {
351     static const INT s_sizes[] =
352     {
353         8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72
354     };
355 
356     HWND hwndSizes = GetDlgItem(IDD_FONTSSIZES);
357     ComboBox_ResetContent(hwndSizes);
358 
359     TCHAR szText[16];
360     for (UINT i = 0; i < _countof(s_sizes); ++i)
361     {
362         wsprintf(szText, TEXT("%d"), s_sizes[i]);
363         INT iItem = ComboBox_AddString(hwndSizes, szText);
364         if (s_sizes[i] == (INT)registrySettings.PointSize)
365             ComboBox_SetCurSel(hwndSizes, iItem);
366     }
367 
368     if (ComboBox_GetCurSel(hwndSizes) == CB_ERR)
369     {
370         wsprintf(szText, TEXT("%d"), (INT)registrySettings.PointSize);
371         ::SetWindowText(hwndSizes, szText);
372     }
373 }
374 
375 void CFontsDialog::InitToolbar()
376 {
377     HWND hwndToolbar = GetDlgItem(IDD_FONTSTOOLBAR);
378     SendMessage(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
379     SendMessage(hwndToolbar, TB_SETBITMAPSIZE, 0, MAKELPARAM(16, 16));
380     SendMessage(hwndToolbar, TB_SETBUTTONWIDTH, 0, MAKELPARAM(20, 20));
381 
382     TBADDBITMAP AddBitmap;
383     AddBitmap.hInst = g_hinstExe;
384     AddBitmap.nID = IDB_FONTSTOOLBAR;
385     SendMessage(hwndToolbar, TB_ADDBITMAP, 4, (LPARAM)&AddBitmap);
386 
387     HIMAGELIST himl = ImageList_LoadImage(g_hinstExe, MAKEINTRESOURCE(IDB_FONTSTOOLBAR),
388                                           16, 8, RGB(255, 0, 255), IMAGE_BITMAP,
389                                           LR_CREATEDIBSECTION);
390     SendMessage(hwndToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl);
391 
392     TBBUTTON buttons[] =
393     {
394         { 0, IDM_BOLD, TBSTATE_ENABLED, TBSTYLE_CHECK },
395         { 1, IDM_ITALIC, TBSTATE_ENABLED, TBSTYLE_CHECK },
396         { 2, IDM_UNDERLINE, TBSTATE_ENABLED, TBSTYLE_CHECK },
397         { 3, IDM_VERTICAL, 0, TBSTYLE_CHECK }, // TODO:
398     };
399     SendMessage(hwndToolbar, TB_ADDBUTTONS, _countof(buttons), (LPARAM)&buttons);
400 
401     SendMessage(hwndToolbar, TB_CHECKBUTTON, IDM_BOLD, registrySettings.Bold);
402     SendMessage(hwndToolbar, TB_CHECKBUTTON, IDM_ITALIC, registrySettings.Italic);
403     SendMessage(hwndToolbar, TB_CHECKBUTTON, IDM_UNDERLINE, registrySettings.Underline);
404 }
405 
406 LRESULT CFontsDialog::OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
407 {
408     // TODO: Tooltips
409     InitFontNames();
410     InitFontSizes();
411     InitToolbar();
412 
413     if (registrySettings.FontsPositionX != 0 || registrySettings.FontsPositionY != 0)
414     {
415         SetWindowPos(NULL,
416                      registrySettings.FontsPositionX, registrySettings.FontsPositionY,
417                      0, 0,
418                      SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
419         SendMessage(DM_REPOSITION, 0, 0);
420     }
421 
422     if (!registrySettings.ShowTextTool)
423         ShowWindow(SW_HIDE);
424 
425     return TRUE;
426 }
427 
428 LRESULT CFontsDialog::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
429 {
430     ShowWindow(SW_HIDE); // Just hide. Recycle for optimization
431     return 0;
432 }
433 
434 void CFontsDialog::OnFontName(UINT codeNotify)
435 {
436     HWND hwndNames = GetDlgItem(IDD_FONTSNAMES);
437     INT iItem = CB_ERR;
438     UINT cch;
439     TCHAR szText[LF_FACESIZE];
440 
441     switch (codeNotify)
442     {
443         case CBN_SELCHANGE:
444             iItem = ComboBox_GetCurSel(hwndNames);
445             cch = ComboBox_GetLBTextLen(hwndNames, iItem);
446             if (iItem != CB_ERR && 0 < cch && cch < _countof(szText))
447             {
448                 ComboBox_GetLBText(hwndNames, iItem, szText);
449             }
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 = _ttoi(szText);
481             }
482             break;
483 
484         case CBN_EDITCHANGE:
485             ::GetWindowText(hwndSizes, szText, _countof(szText));
486             PointSize = _ttoi(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 = ::SendMessage(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         LPTOOLTIPTEXT pToolTip = reinterpret_cast<LPTOOLTIPTEXT>(lParam);
547         pToolTip->hinst = g_hinstExe;
548         switch (pnmhdr->idFrom)
549         {
550             case IDM_BOLD:      pToolTip->lpszText = MAKEINTRESOURCE(IDS_BOLD); break;
551             case IDM_ITALIC:    pToolTip->lpszText = MAKEINTRESOURCE(IDS_ITALIC); break;
552             case IDM_UNDERLINE: pToolTip->lpszText = MAKEINTRESOURCE(IDS_UNDERLINE); break;
553             case IDM_VERTICAL:  pToolTip->lpszText = MAKEINTRESOURCE(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         TCHAR 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             DrawText(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