OSDN Git Service

6a086cc718dfa8389782563eb73872849a1e73ff
[tortoisegit/TortoiseGitJp.git] / Utils / MiscUI / MessageBox.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "StdAfx.h"\r
20 //#include "resource.h"                 //if you defined some IDS_MSGBOX_xxxx this include is needed!\r
21 #include "messagebox.h"\r
22 #include ".\messagebox.h"\r
23 \r
24 \r
25 CMessageBox::CMessageBox(void)\r
26 {\r
27         m_hIcon = NULL;\r
28         m_uButton1Ret = 1;\r
29         m_uButton2Ret = 2;\r
30         m_uButton3Ret = 3;\r
31         m_uCancelRet = 0;\r
32         m_bShowCheck = FALSE;\r
33         m_bDestroyIcon = FALSE;\r
34 }\r
35 \r
36 CMessageBox::~CMessageBox(void)\r
37 {\r
38         if (m_bDestroyIcon)\r
39                 ::DestroyIcon(m_hIcon);\r
40 }\r
41 \r
42 UINT CMessageBox::ShowCheck(HWND hWnd, UINT nMessage, UINT nCaption, int nDef, LPCTSTR icon, UINT nButton1, UINT nButton2, UINT nButton3, LPCTSTR lpRegistry, UINT nCheckMessage/* = NULL*/)\r
43 {\r
44         CString sButton1;\r
45         CString sButton2;\r
46         CString sButton3;\r
47         CString sMessage;\r
48         CString sCaption;\r
49         CString nCheckMsg;\r
50         sButton1.LoadString(nButton1);\r
51         sButton2.LoadString(nButton2);\r
52         sButton3.LoadString(nButton3);\r
53         sMessage.LoadString(nMessage);\r
54         sCaption.LoadString(nCaption);\r
55         nCheckMsg.LoadString(nCheckMessage);\r
56         return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3, lpRegistry, nCheckMsg);\r
57 }\r
58 \r
59 UINT CMessageBox::ShowCheck(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, int nDef, LPCTSTR icon, LPCTSTR lpButton1, LPCTSTR lpButton2, LPCTSTR lpButton3, LPCTSTR lpRegistry, LPCTSTR lpCheckMessage/* = NULL*/)\r
60 {\r
61         //check the registry if we have to show the box or just return with the last used return value\r
62         //this would be the case if the user pressed "do not show again".\r
63         DWORD dwRetVal;\r
64         HKEY hKey;\r
65         CString path;\r
66 #ifdef XMESSAGEBOX_APPREGPATH\r
67         path = XMESSAGEBOX_APPREGPATH;\r
68 #else\r
69         path = "Software\\";\r
70         path += AfxGetAppName();\r
71 #endif\r
72         if (RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)\r
73         {\r
74                 int size = sizeof(dwRetVal);\r
75                 DWORD type;\r
76                 if (RegQueryValueEx(hKey, lpRegistry, NULL, &type, (BYTE*) &dwRetVal,(LPDWORD) &size)==ERROR_SUCCESS)\r
77                 {\r
78                         ASSERT(type==REG_DWORD);\r
79                         RegCloseKey(hKey);\r
80                         return (UINT)dwRetVal;                  //return with the last saved value\r
81                 }\r
82                 else\r
83                 {\r
84                         RegCloseKey(hKey);\r
85                 }\r
86         }\r
87 \r
88         CMessageBox box;\r
89         box.m_bShowCheck = TRUE;\r
90         box.m_sRegistryValue = lpRegistry;\r
91         if (lpCheckMessage == NULL)\r
92         {\r
93 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN\r
94                 box.m_sCheckbox = _T("do not show again");\r
95 #else\r
96                 CString m_i18l;\r
97                 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);\r
98                 box.m_sCheckbox = m_i18l;\r
99 #endif\r
100         }\r
101         else\r
102                 box.m_sCheckbox = lpCheckMessage;\r
103         box.m_sButton1 = lpButton1;\r
104         box.m_sButton2 = lpButton2;\r
105         box.m_sButton3 = lpButton3;\r
106         box.m_hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), icon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);\r
107         if (box.m_hIcon == NULL)\r
108                 box.m_hIcon = (HICON)::LoadImage(NULL, icon, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);\r
109         else\r
110                 box.m_bDestroyIcon = TRUE;\r
111         if (!IsWindow(hWnd))\r
112                 hWnd = NULL;\r
113         return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef); \r
114 }\r
115 \r
116 UINT CMessageBox::Show(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, int nDef, LPCTSTR icon, LPCTSTR lpButton1, LPCTSTR lpButton2/* = NULL*/, LPCTSTR lpButton3/* = NULL*/)\r
117 {\r
118         CMessageBox box;\r
119         box.m_sButton1 = lpButton1;\r
120         box.m_sButton2 = lpButton2;\r
121         box.m_sButton3 = lpButton3;\r
122         box.m_hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), icon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);\r
123         if (box.m_hIcon == NULL)\r
124                 box.m_hIcon = (HICON)::LoadImage(NULL, icon, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);\r
125         else\r
126                 box.m_bDestroyIcon = TRUE;\r
127         if (!IsWindow(hWnd))\r
128                 hWnd = NULL;\r
129         return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef);\r
130 }\r
131 \r
132 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, int nDef, LPCTSTR icon, UINT nButton1, UINT nButton2, UINT nButton3)\r
133 {\r
134         CString sButton1;\r
135         CString sButton2;\r
136         CString sButton3;\r
137         CString sMessage;\r
138         CString sCaption;\r
139         sButton1.LoadString(nButton1);\r
140         sButton2.LoadString(nButton2);\r
141         sButton3.LoadString(nButton3);\r
142         sMessage.LoadString(nMessage);\r
143         sCaption.LoadString(nCaption);\r
144         return CMessageBox::Show(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3);\r
145 }\r
146 \r
147 \r
148 UINT CMessageBox::ShowCheck(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCTSTR lpRegistry, UINT nCheckMessage)\r
149 {\r
150         CString sMessage;\r
151         CString sCaption;\r
152         CString sCheckMsg;\r
153         sMessage.LoadString(nMessage);\r
154         sCaption.LoadString(nCaption);\r
155         sCheckMsg.LoadString(nCheckMessage);\r
156         return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, uType, lpRegistry, sCheckMsg);\r
157 }\r
158 \r
159 UINT CMessageBox::ShowCheck(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, UINT uType, LPCTSTR lpRegistry, LPCTSTR lpCheckMessage)\r
160 {\r
161         //check the registry if we have to show the box or just return with the last used return value\r
162         //this would be the case if the user pressed "do not show again".\r
163         DWORD dwRetVal;\r
164         HKEY hKey;\r
165         CString path;\r
166 #ifdef XMESSAGEBOX_APPREGPATH\r
167         path = XMESSAGEBOX_APPREGPATH;\r
168 #else\r
169         path = "Software\\";\r
170         path += AfxGetAppName();\r
171 #endif\r
172         if (RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)\r
173         {\r
174                 int size = sizeof(dwRetVal);\r
175                 DWORD type;\r
176                 if (RegQueryValueEx(hKey, lpRegistry, NULL, &type, (BYTE*) &dwRetVal,(LPDWORD) &size)==ERROR_SUCCESS)\r
177                 {\r
178                         ASSERT(type==REG_DWORD);\r
179                         RegCloseKey(hKey);\r
180                         return (UINT)dwRetVal;                  //return with the last saved value\r
181                 }\r
182                 else\r
183                 {\r
184                         RegCloseKey(hKey);\r
185                 }\r
186         }\r
187 \r
188         CMessageBox box;\r
189         box.m_bShowCheck = TRUE;\r
190         box.m_sRegistryValue = lpRegistry;\r
191         if (lpCheckMessage == NULL)\r
192         {\r
193 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN\r
194                 box.m_sCheckbox = _T("do not show again");\r
195 #else\r
196                 CString m_i18l;\r
197                 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);\r
198                 box.m_sCheckbox = m_i18l;\r
199 #endif\r
200         }\r
201         else\r
202                 box.m_sCheckbox = lpCheckMessage;\r
203         if (!IsWindow(hWnd))\r
204                 hWnd = NULL;\r
205         return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));\r
206 }\r
207 \r
208 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCTSTR sHelpPath)\r
209 {\r
210         CString sMessage;\r
211         CString sCaption;\r
212         sMessage.LoadString(nMessage);\r
213         sCaption.LoadString(nCaption);\r
214         return CMessageBox::Show(hWnd, sMessage, sCaption, uType, sHelpPath);\r
215 }\r
216 \r
217 UINT CMessageBox::Show(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, UINT uType, LPCTSTR sHelpPath)\r
218 {\r
219         CMessageBox box;\r
220         \r
221         if (!IsWindow(hWnd))\r
222                 hWnd = NULL;\r
223         if (sHelpPath)\r
224                 box.SetHelpPath(sHelpPath);\r
225         return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));\r
226 }\r
227 \r
228 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, UINT nHelpID)\r
229 {\r
230         CMessageBox box;\r
231         CString sMessage;\r
232         CString sCaption;\r
233         sMessage.LoadString(nMessage);\r
234         sCaption.LoadString(nCaption);\r
235 \r
236         if (!IsWindow(hWnd))\r
237                 hWnd = NULL;\r
238         box.SetHelpID(nHelpID);\r
239 \r
240         return box.GoModal(CWnd::FromHandle(hWnd), sCaption, sMessage, box.FillBoxStandard(uType));\r
241 }\r
242 \r
243 int CMessageBox::FillBoxStandard(UINT uType)\r
244 {\r
245         int ret = 1;\r
246         m_uType = uType;\r
247         m_uCancelRet = IDCANCEL;\r
248         //load the icons according to uType\r
249         switch (uType & 0xf0)\r
250         {\r
251         case MB_ICONEXCLAMATION:\r
252                 m_hIcon = (HICON)::LoadImage(NULL, IDI_EXCLAMATION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);\r
253                 ::MessageBeep(MB_ICONEXCLAMATION);\r
254                 break;\r
255         case MB_ICONASTERISK:\r
256                 m_hIcon = (HICON)::LoadImage(NULL, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);\r
257                 ::MessageBeep(MB_ICONASTERISK);\r
258                 break;\r
259         case MB_ICONQUESTION:\r
260                 m_hIcon = (HICON)::LoadImage(NULL, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);\r
261                 ::MessageBeep(MB_ICONQUESTION);\r
262                 break;\r
263         case MB_ICONHAND:\r
264                 m_hIcon = (HICON)::LoadImage(NULL, IDI_HAND, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);\r
265                 ::MessageBeep(MB_ICONHAND);\r
266                 break;\r
267         }\r
268         //set up the button texts\r
269         switch (uType & 0xf)\r
270         {\r
271         case MB_ABORTRETRYIGNORE:\r
272 #ifndef IDS_MSGBOX_ABORT\r
273                 m_sButton1 = "Abort";\r
274 #else\r
275                 m_i18l.LoadString(IDS_MSGBOX_ABORT);\r
276                 m_sButton1 = m_i18l;\r
277 #endif\r
278                 m_uButton1Ret = IDABORT;\r
279 #ifndef IDS_MSGBOX_RETRY\r
280                 m_sButton2 = "Retry";\r
281 #else\r
282                 m_i18l.LoadString(IDS_MSGBOX_RETRY);\r
283                 m_sButton2 = m_i18l;\r
284 #endif\r
285                 m_uButton2Ret = IDRETRY;\r
286 #ifndef IDS_MSGBOX_IGNORE\r
287                 m_sButton3 = "Ignore";\r
288 #else\r
289                 m_i18l.LoadString(IDS_MSGBOX_IGNORE);\r
290                 m_sButton3 = m_i18l;\r
291 #endif\r
292                 m_uButton3Ret = IDIGNORE;\r
293                 break;\r
294         case MB_CANCELTRYCONTINUE:\r
295 #ifndef IDS_MSGBOX_CANCEL\r
296                 m_sButton1 = "Cancel";\r
297 #else\r
298                 m_i18l.LoadString(IDS_MSGBOX_CANCEL);\r
299                 m_sButton1 = m_i18l;\r
300 #endif\r
301                 m_uButton1Ret = IDCANCEL;\r
302 #ifndef IDS_MSGBOX_TRYAGAIN\r
303                 m_sButton2 = "Try Again";\r
304 #else\r
305                 m_i18l.LoadString(IDS_MSGBOX_TRYAGAIN);\r
306                 m_sButton2 = m_i18l;\r
307 #endif\r
308                 m_uButton2Ret = IDTRYAGAIN;\r
309 #ifndef IDS_MSGBOX_CONTINUE\r
310                 m_sButton3 = "Continue";\r
311 #else\r
312                 m_i18l.LoadString(IDS_MSGBOX_CONTINUE);\r
313                 m_sButton3 = m_i18l;\r
314 #endif\r
315                 m_uButton3Ret = IDCONTINUE;\r
316                 break;\r
317         case MB_OKCANCEL:\r
318 #ifndef IDS_MSGBOX_OK\r
319                 m_sButton1 = "Ok";\r
320 #else\r
321                 m_i18l.LoadString(IDS_MSGBOX_OK);\r
322                 m_sButton1 = m_i18l;\r
323 #endif\r
324                 m_uButton1Ret = IDOK;\r
325 #ifndef IDS_MSGBOX_CANCEL\r
326                 m_sButton2 = "Cancel";\r
327 #else\r
328                 m_i18l.LoadString(IDS_MSGBOX_CANCEL);\r
329                 m_sButton2 = m_i18l;\r
330 #endif\r
331                 m_uButton2Ret = IDCANCEL;\r
332                 break;\r
333         case MB_RETRYCANCEL:\r
334 #ifndef IDS_MSGBOX_RETRY\r
335                 m_sButton1 = "Retry";\r
336 #else\r
337                 m_i18l.LoadString(IDS_MSGBOX_RETRY);\r
338                 m_sButton1 = m_i18l;\r
339 #endif\r
340                 m_uButton1Ret = IDRETRY;\r
341 #ifndef IDS_MSGBOX_CANCEL\r
342                 m_sButton2 = "Cancel";\r
343 #else\r
344                 m_i18l.LoadString(IDS_MSGBOX_CANCEL);\r
345                 m_sButton2 = m_i18l;\r
346 #endif\r
347                 m_uButton2Ret = IDCANCEL;\r
348                 break;\r
349         case MB_YESNO:\r
350 #ifndef IDS_MSGBOX_YES\r
351                 m_sButton1 = "Yes";\r
352 #else\r
353                 m_i18l.LoadString(IDS_MSGBOX_YES);\r
354                 m_sButton1 = m_i18l;\r
355 #endif\r
356                 m_uButton1Ret = IDYES;\r
357 #ifndef IDS_MSGBOX_NO\r
358                 m_sButton2 = "No";\r
359 #else\r
360                 m_i18l.LoadString(IDS_MSGBOX_NO);\r
361                 m_sButton2 = m_i18l;\r
362 #endif\r
363                 m_uButton2Ret = IDNO;\r
364                 break;\r
365         case MB_YESNOCANCEL:\r
366 #ifndef IDS_MSGBOX_YES\r
367                 m_sButton1 = "Yes";\r
368 #else\r
369                 m_i18l.LoadString(IDS_MSGBOX_YES);\r
370                 m_sButton1 = m_i18l;\r
371 #endif\r
372                 m_uButton1Ret = IDYES;\r
373 #ifndef IDS_MSGBOX_NO\r
374                 m_sButton2 = "No";\r
375 #else\r
376                 m_i18l.LoadString(IDS_MSGBOX_NO);\r
377                 m_sButton2 = m_i18l;\r
378 #endif\r
379                 m_uButton2Ret = IDNO;\r
380 #ifndef IDS_MSGBOX_CANCEL\r
381                 m_sButton3 = "Cancel";\r
382 #else\r
383                 m_i18l.LoadString(IDS_MSGBOX_CANCEL);\r
384                 m_sButton3 = m_i18l;\r
385 #endif\r
386                 m_uButton3Ret = IDCANCEL;\r
387                 break;\r
388         case MB_OK:\r
389         default:\r
390 #ifndef IDS_MSGBOX_OK\r
391                 m_sButton1 = "Ok";\r
392 #else\r
393                 m_i18l.LoadString(IDS_MSGBOX_OK);\r
394                 m_sButton1 = m_i18l;\r
395 #endif\r
396         }\r
397         //now set the default button\r
398         switch (uType & 0xf00)\r
399         {\r
400         case MB_DEFBUTTON2:\r
401                 ret = 2;\r
402                 break;\r
403         case MB_DEFBUTTON3:\r
404                 ret = 3;\r
405                 break;\r
406         }\r
407         // do we need to add a help button?\r
408         if (uType & MB_HELP)\r
409         {\r
410                 CString sHelpText;\r
411 #ifndef IDS_MSGBOX_HELP\r
412                 sHelpText = _T("Help");\r
413 #else\r
414                 m_i18l.LoadString(IDS_MSGBOX_HELP);\r
415                 sHelpText = m_i18l;\r
416 #endif\r
417                 if (m_sButton2.IsEmpty())\r
418                 {\r
419                         m_sButton2 = sHelpText;\r
420                         m_uButton2Ret = IDHELP;\r
421                 }\r
422                 else if (m_sButton3.IsEmpty())\r
423                 {\r
424                         m_sButton3 = sHelpText;\r
425                         m_uButton3Ret = IDHELP;\r
426                 }\r
427         }\r
428         return ret;\r
429 }\r
430 \r
431 UINT CMessageBox::GoModal(CWnd * pWnd, const CString& title, const CString& msg, int nDefaultButton)\r
432 {\r
433         NONCLIENTMETRICS ncm;\r
434         ncm.cbSize = sizeof(NONCLIENTMETRICS);\r
435         VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));\r
436     memcpy(&m_LogFont, &(ncm.lfMessageFont), sizeof(LOGFONT));\r
437 \r
438         //the problem with the LOGFONT lfHeight is that it is not in pixels,\r
439         //but the dialog template needs the height in pixels.\r
440         //We need to convert those values first:\r
441         CDC * pDC;\r
442         if (pWnd)\r
443                 pDC = pWnd->GetDC();\r
444         else\r
445                 pDC = GetDesktopWindow()->GetDC();\r
446         int pix = -MulDiv(m_LogFont.lfHeight, 72, GetDeviceCaps(pDC->m_hDC, LOGPIXELSY));\r
447         CDlgTemplate dialogTemplate = CDlgTemplate(title, WS_CAPTION | DS_CENTER,\r
448                 0, 0, 0, 0, m_LogFont.lfFaceName, pix);\r
449         dialogTemplate.AddButton(_T("Button1"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 1) ? BS_DEFPUSHBUTTON : 0), 0,\r
450                 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON1);\r
451         dialogTemplate.AddButton(_T("Button2"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 2) ? BS_DEFPUSHBUTTON : 0), 0,\r
452                 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON2);\r
453         dialogTemplate.AddButton(_T("Button3"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 3) ? BS_DEFPUSHBUTTON : 0), 0,\r
454                 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON3);\r
455         dialogTemplate.AddButton(_T("Checkbox"), WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX, 0,\r
456                 0, 0, 0, 0, IDC_MESSAGEBOX_CHECKBOX);\r
457         \r
458         m_nDefButton = nDefaultButton;\r
459         m_sMessage = msg;\r
460         InitModalIndirect(dialogTemplate, pWnd);\r
461 \r
462         return (UINT)DoModal();\r
463 }\r
464 \r
465 void CMessageBox::SetRegistryValue(const CString& sValue, DWORD value)\r
466 {\r
467         CString path;\r
468 #ifdef XMESSAGEBOX_APPREGPATH\r
469         path = XMESSAGEBOX_APPREGPATH;\r
470 #else\r
471         path = "Software\\";\r
472         path += AfxGetAppName();\r
473 #endif\r
474         DWORD disp;\r
475         HKEY hKey;\r
476         if (RegCreateKeyEx(HKEY_CURRENT_USER, path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &disp)!=ERROR_SUCCESS)\r
477         {\r
478                 return;\r
479         }\r
480         RegSetValueEx(hKey, sValue, 0, REG_DWORD,(const BYTE*) &value, sizeof(value));\r
481         RegCloseKey(hKey);\r
482 }\r
483 \r
484 CSize CMessageBox::GetTextSize(const CString& str)\r
485 {\r
486         CRect rect;\r
487         GetWindowRect(&rect);\r
488 \r
489         CDC * pDC = GetDC();\r
490 \r
491         CDC memDC;\r
492         CBitmap bitmap;\r
493         memDC.CreateCompatibleDC(pDC);\r
494         bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());\r
495         CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);\r
496 \r
497         //get the minimum size of the rectangle of the tooltip\r
498         CSize sz = DrawHTML(&memDC, rect, str, m_LogFont, TRUE);\r
499 \r
500         memDC.SelectObject(pOldBitmap);\r
501         memDC.DeleteDC();\r
502         bitmap.DeleteObject();\r
503 \r
504         ReleaseDC(pDC);\r
505 \r
506         return sz;\r
507 }\r
508 \r
509 CSize CMessageBox::GetIconSize(HICON hIcon)\r
510 {\r
511         ICONINFO ii;\r
512         CSize sz (0, 0);\r
513 \r
514         if (hIcon != NULL)\r
515         {\r
516                 //get icon dimensions\r
517                 ::SecureZeroMemory(&ii, sizeof(ICONINFO));\r
518                 if (::GetIconInfo(hIcon, &ii))\r
519                 {\r
520                         sz.cx = (DWORD)(ii.xHotspot * 2);\r
521                         sz.cy = (DWORD)(ii.yHotspot * 2);\r
522                         //release icon mask bitmaps\r
523                         if(ii.hbmMask)\r
524                                 ::DeleteObject(ii.hbmMask);\r
525                         if(ii.hbmColor)\r
526                                 ::DeleteObject(ii.hbmColor);\r
527                 }\r
528         }\r
529         m_szIcon = sz;\r
530         return sz;\r
531 }\r
532 \r
533 CSize CMessageBox::GetButtonSize()\r
534 {\r
535         CSize sz;\r
536         int nButtons = 0;               //number of buttons - 1\r
537 \r
538         SetDlgItemText(IDC_MESSAGEBOX_BUTTON1, m_sButton1);\r
539         SetDlgItemText(IDC_MESSAGEBOX_BUTTON2, m_sButton2);\r
540         //GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, 1);\r
541         SetDlgItemText(IDC_MESSAGEBOX_BUTTON3, m_sButton3);\r
542         SetDlgItemText(IDC_MESSAGEBOX_CHECKBOX, m_sCheckbox);\r
543         \r
544         CSize sz1 = GetTextSize(m_sButton1);\r
545         CSize sz2 = GetTextSize(m_sButton2);\r
546         CSize sz3 = GetTextSize(m_sButton3);\r
547 \r
548         sz1.cx += 2*MESSAGEBOX_BUTTONX;\r
549         sz1.cy += 2*MESSAGEBOX_BUTTONY;\r
550 \r
551         if (sz2.cx)\r
552         {\r
553                 sz2.cx += 2*MESSAGEBOX_BUTTONX;\r
554                 sz2.cy += 2*MESSAGEBOX_BUTTONY;\r
555                 nButtons++;\r
556         }\r
557         if (sz3.cx)\r
558         {\r
559                 sz3.cx += 2*MESSAGEBOX_BUTTONX;\r
560                 sz3.cy += 2*MESSAGEBOX_BUTTONY;\r
561                 nButtons++;\r
562         }\r
563         \r
564         GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(0, 0, sz1.cx, sz1.cy);\r
565         GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(0, 0, sz2.cx, sz2.cy);\r
566         GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(0, 0, sz3.cx, sz3.cy);\r
567 \r
568 \r
569         sz.cx = sz1.cx + sz2.cx + sz3.cx + (nButtons * MESSAGEBOX_BUTTONMARGIN);\r
570         sz.cy = max(sz1.cy, sz2.cy);\r
571         sz.cy = max(sz.cy, sz3.cy);\r
572         m_szButtons = sz;\r
573         if (m_bShowCheck)\r
574         {\r
575                 CSize szCheck = GetTextSize(m_sCheckbox);\r
576                 szCheck.cx += 2*GetSystemMetrics(SM_CXMENUCHECK);\r
577                 szCheck.cy += 2*MESSAGEBOX_BUTTONY;\r
578                 sz.cx = max(sz.cx, szCheck.cx);\r
579                 sz.cy += szCheck.cy + MESSAGEBOX_BUTTONCHECKMARGIN;\r
580                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(0, 0, szCheck.cx, szCheck.cy);\r
581         }\r
582         m_szAllButtons = sz;\r
583         return sz;\r
584 }\r
585 \r
586 BEGIN_MESSAGE_MAP(CMessageBox, CDialog)\r
587         ON_WM_PAINT()\r
588         ON_WM_MOUSEMOVE()\r
589         ON_WM_LBUTTONUP()\r
590         ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1, OnButton1)\r
591         ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2, OnButton2)\r
592         ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3, OnButton3)\r
593 END_MESSAGE_MAP()\r
594 \r
595 void CMessageBox::OnPaint()\r
596 {\r
597         CPaintDC dc(this); // device context for painting\r
598 \r
599 \r
600         CRect rect;\r
601         CRect drawrect;\r
602         GetClientRect(&rect);\r
603         GetClientRect(&drawrect);\r
604 \r
605         //create a memory device-context. This is done to help reduce\r
606         //screen flicker, since we will paint the entire control to the\r
607         //off screen device context first.\r
608         CDC memDC;\r
609         CBitmap bitmap;\r
610         memDC.CreateCompatibleDC(&dc);\r
611         bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());\r
612         CBitmap* pOldBitmap = memDC.SelectObject(&bitmap); \r
613         \r
614         memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, 0,0, SRCCOPY);\r
615 \r
616         memDC.SetBkMode(TRANSPARENT);\r
617         memDC.SetBkColor(GetSysColor(COLOR_WINDOW));\r
618         memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); \r
619 \r
620         //OnDrawBackground();\r
621         drawrect.DeflateRect(MESSAGEBOX_BORDERMARGINX, MESSAGEBOX_BORDERMARGINY);\r
622         if (m_hIcon != NULL)\r
623         {\r
624                 DrawIconEx(memDC.m_hDC, drawrect.left, drawrect.top + \r
625                         ((drawrect.Height() - m_szAllButtons.cy - MESSAGEBOX_TEXTBUTTONMARGIN - m_szIcon.cy) / 2), \r
626                         m_hIcon, m_szIcon.cx, m_szIcon.cy, 0, NULL, DI_NORMAL);\r
627 \r
628                 drawrect.left += m_szIcon.cx + MESSAGEBOX_ICONMARGIN; \r
629         }\r
630 \r
631 \r
632         DrawHTML(&memDC, drawrect, m_sMessage, m_LogFont);\r
633         \r
634 \r
635         //Copy the memory device context back into the original DC.\r
636         dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0,0, SRCCOPY);\r
637         \r
638         //Cleanup resources.\r
639         memDC.SelectObject(pOldBitmap);\r
640         memDC.DeleteDC();\r
641         bitmap.DeleteObject(); \r
642 \r
643 \r
644 }\r
645 \r
646 void CMessageBox::OnMouseMove(UINT nFlags, CPoint point)\r
647 {\r
648         if (IsPointOverALink(point))\r
649         {\r
650                 m_Cursor.SetCursor(IDC_HAND);\r
651         }\r
652         else\r
653         {\r
654                 m_Cursor.Restore();     \r
655         }\r
656 \r
657         __super::OnMouseMove(nFlags, point);\r
658 }\r
659 \r
660 void CMessageBox::OnLButtonUp(UINT nFlags, CPoint point)\r
661 {\r
662         if (IsPointOverALink(point))\r
663         {\r
664                 CString url = GetLinkForPoint(point);\r
665                 ShellExecute(NULL, _T("open"), url, NULL,NULL, 0);\r
666         }\r
667 \r
668         __super::OnLButtonUp(nFlags, point);\r
669 }\r
670 \r
671 void CMessageBox::OnButton1()\r
672 {\r
673         if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)\r
674                 SetRegistryValue(m_sRegistryValue, m_uButton1Ret);\r
675         EndDialog(m_uButton1Ret);\r
676 }\r
677 \r
678 void CMessageBox::OnButton2()\r
679 {\r
680         if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)\r
681                 SetRegistryValue(m_sRegistryValue, m_uButton2Ret);\r
682         if ((m_uButton2Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))\r
683         {\r
684                 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);\r
685                 FPHH pHtmlHelp=NULL; // Function pointer\r
686                 HINSTANCE hInstHtmlHelp = LoadLibrary(_T("HHCtrl.ocx"));\r
687                 HWND hHelp = NULL;\r
688                 if (hInstHtmlHelp != NULL)\r
689                 {\r
690                         (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");\r
691                         if (pHtmlHelp)\r
692                                 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);\r
693                 }\r
694                 if (hHelp == NULL)\r
695                         ::MessageBox(m_hWnd, _T("could not show help file"), _T("Help"), MB_ICONERROR);\r
696         }\r
697         else if (m_uButton2Ret == IDHELP)\r
698         {\r
699                 OnHelp();\r
700         }\r
701         else\r
702                 EndDialog(m_uButton2Ret);\r
703 }\r
704 \r
705 void CMessageBox::OnButton3()\r
706 {\r
707         if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)\r
708                 SetRegistryValue(m_sRegistryValue, m_uButton3Ret);\r
709         if ((m_uButton3Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))\r
710         {\r
711                 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);\r
712                 FPHH pHtmlHelp=NULL; // Function pointer\r
713                 HINSTANCE hInstHtmlHelp = LoadLibrary(_T("HHCtrl.ocx"));\r
714                 HWND hHelp = NULL;\r
715                 if (hInstHtmlHelp != NULL)\r
716                 {\r
717                         (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");\r
718                         if (pHtmlHelp)\r
719                                 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);\r
720                 }\r
721                 if (hHelp == NULL)\r
722                         ::MessageBox(m_hWnd, _T("could not show help file"), _T("Help"), MB_ICONERROR);\r
723         }\r
724         else if (m_uButton3Ret == IDHELP)\r
725         {\r
726                 OnHelp();\r
727         }\r
728         else\r
729                 EndDialog(m_uButton3Ret);\r
730 }\r
731 \r
732 void CMessageBox::OnCancel()\r
733 {\r
734         if (m_uCancelRet == IDCANCEL)\r
735                 EndDialog(m_uCancelRet);\r
736         //__super::OnCancel();\r
737 }\r
738 \r
739 BOOL CMessageBox::OnInitDialog()\r
740 {\r
741         __super::OnInitDialog();\r
742 \r
743         CRect rect(0, 0, 0, 0);\r
744 \r
745         //determine the required size of the message box\r
746         CSize szText = GetTextSize(m_sMessage);\r
747         CSize szIcon = GetIconSize(m_hIcon);\r
748         CSize szButtons = GetButtonSize();\r
749 \r
750         CSize szIconText;\r
751         szIconText.cx = szText.cx + szIcon.cx + ((szIcon.cx == 0) ? MESSAGEBOX_ICONMARGIN : (2*MESSAGEBOX_ICONMARGIN));\r
752         szIconText.cy = max(szIcon.cy, szText.cy);\r
753 \r
754         rect.right = max(szButtons.cx, szIconText.cx);\r
755         rect.right += 2*GetSystemMetrics(SM_CXBORDER);\r
756         rect.right += 2*MESSAGEBOX_BORDERMARGINX;\r
757         rect.bottom = szIconText.cy;\r
758         rect.bottom += szButtons.cy;\r
759         rect.bottom += 2*MESSAGEBOX_BORDERMARGINY + MESSAGEBOX_TEXTBUTTONMARGIN;\r
760         rect.bottom += GetSystemMetrics(SM_CYCAPTION);\r
761         rect.bottom += 2*GetSystemMetrics(SM_CYBORDER);\r
762 \r
763         MoveWindow(rect);\r
764         CenterWindow();\r
765         \r
766         GetClientRect(rect);\r
767         \r
768         //now size and position the buttons as we need them\r
769         ASSERT(!m_sButton1.IsEmpty());          //at least the first button must be there!\r
770         if (m_sButton2.IsEmpty())\r
771         {\r
772                 //only one button\r
773                 CRect rt;\r
774                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt);\r
775                 ScreenToClient(rt);\r
776                 rt.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));\r
777                 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
778                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt);\r
779                 //hide the other two buttons\r
780                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->ShowWindow(SW_HIDE);\r
781                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);\r
782         }\r
783         else if (m_sButton3.IsEmpty())\r
784         {\r
785                 //two buttons\r
786                 CRect rt1;\r
787                 CRect rt2;\r
788                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);\r
789                 ScreenToClient(rt1);\r
790                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);\r
791                 ScreenToClient(rt2);\r
792                 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));\r
793                 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
794                 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);\r
795                 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
796                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);\r
797                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);\r
798                 //hide the third button\r
799                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);\r
800         }\r
801         else\r
802         {\r
803                 //three buttons\r
804                 CRect buttonrect;\r
805                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(buttonrect);\r
806                 CRect rt1;\r
807                 CRect rt2;\r
808                 CRect rt3;\r
809                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);\r
810                 ScreenToClient(rt1);\r
811                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);\r
812                 ScreenToClient(rt2);\r
813                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->GetWindowRect(rt3);\r
814                 ScreenToClient(rt3);\r
815                 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));\r
816                 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
817                 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);\r
818                 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
819                 rt3.MoveToX(rt2.right + MESSAGEBOX_BUTTONMARGIN);\r
820                 rt3.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
821                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);\r
822                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);\r
823                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(rt3);\r
824         }\r
825         if (m_bShowCheck)\r
826         {\r
827                 CRect rt;\r
828                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->GetWindowRect(rt);\r
829                 ScreenToClient(rt);\r
830                 rt.MoveToX(rect.left + MESSAGEBOX_BORDERMARGINX/*+ ((rect.Width() - szButtons.cx)/2)*/);\r
831                 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - szButtons.cy);\r
832                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(rt);\r
833                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_SHOW);\r
834         }\r
835         else\r
836                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_HIDE);\r
837 \r
838         if (m_nDefButton == 1)\r
839                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->SetFocus();\r
840         if (m_nDefButton == 2)\r
841                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SetFocus();\r
842         if (m_nDefButton == 3)\r
843                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->SetFocus();\r
844 \r
845         SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);\r
846         SetForegroundWindow();\r
847         SetFocus(); //Just playing safe\r
848 \r
849         return FALSE;  // return TRUE unless you set the focus to a control\r
850         // EXCEPTION: OCX Property Pages should return FALSE\r
851 }\r
852 \r
853 BOOL CMessageBox::PreTranslateMessage(MSG* pMsg)\r
854 {\r
855         if (pMsg->message == WM_KEYDOWN)\r
856         {\r
857                 switch (pMsg->wParam)\r
858                 {\r
859                 case 'C':\r
860                 case VK_INSERT:\r
861                         {\r
862                                 if (GetAsyncKeyState(VK_CONTROL)&0x8000)\r
863                                 {\r
864                                         CStringA sClipboard = CStringA(m_sMessage);\r
865                                         if (OpenClipboard())\r
866                                         {\r
867                                                 EmptyClipboard();\r
868                                                 HGLOBAL hClipboardData;\r
869                                                 hClipboardData = GlobalAlloc(GMEM_DDESHARE, sClipboard.GetLength()+1);\r
870                                                 char * pchData;\r
871                                                 pchData = (char*)GlobalLock(hClipboardData);\r
872                                                 strcpy_s(pchData, sClipboard.GetLength()+1, (LPCSTR)sClipboard);\r
873                                                 GlobalUnlock(hClipboardData);\r
874                                                 SetClipboardData(CF_TEXT,hClipboardData);\r
875                                                 CloseClipboard();\r
876                                         }\r
877                                         return TRUE;\r
878                                 }\r
879                         }\r
880                         break;\r
881                 case VK_ESCAPE:\r
882                         {\r
883                                 switch (m_uType & 0xf)\r
884                                 {\r
885                                 case MB_ABORTRETRYIGNORE:\r
886                                         EndDialog(m_uButton1Ret);\r
887                                         break;\r
888                                 case MB_CANCELTRYCONTINUE:\r
889                                         EndDialog(m_uButton1Ret);\r
890                                         break;\r
891                                 case MB_OKCANCEL:\r
892                                         EndDialog(m_uButton2Ret);\r
893                                         break;\r
894                                 case MB_RETRYCANCEL:\r
895                                         EndDialog(m_uButton2Ret);\r
896                                         break;\r
897                                 case MB_YESNO:\r
898                                         EndDialog(m_uButton2Ret);\r
899                                         break;\r
900                                 case MB_YESNOCANCEL:\r
901                                         EndDialog(m_uButton3Ret);\r
902                                         break;\r
903                                 }\r
904                         }\r
905                         break;\r
906                 }\r
907         }\r
908 \r
909         return __super::PreTranslateMessage(pMsg);\r
910 }\r
911 \r
912 \r
913 \r
914 \r
915 \r
916 \r
917 \r