OSDN Git Service

Add Stash Save Command Handle.
[tortoisegit/TortoiseGitJp.git] / src / 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         memset(&ncm,0,sizeof(NONCLIENTMETRICS));\r
435         ncm.cbSize = sizeof(NONCLIENTMETRICS);\r
436         SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);\r
437         \r
438     memcpy(&m_LogFont, &(ncm.lfMessageFont), sizeof(LOGFONT));\r
439 \r
440         //the problem with the LOGFONT lfHeight is that it is not in pixels,\r
441         //but the dialog template needs the height in pixels.\r
442         //We need to convert those values first:\r
443         CDC * pDC;\r
444         if (pWnd)\r
445                 pDC = pWnd->GetDC();\r
446         else\r
447                 pDC = GetDesktopWindow()->GetDC();\r
448         int pix = -MulDiv(m_LogFont.lfHeight, 72, GetDeviceCaps(pDC->m_hDC, LOGPIXELSY));\r
449         CDlgTemplate dialogTemplate = CDlgTemplate(title, WS_CAPTION | DS_CENTER,\r
450                 0, 0, 0, 0, m_LogFont.lfFaceName, pix);\r
451         dialogTemplate.AddButton(_T("Button1"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 1) ? BS_DEFPUSHBUTTON : 0), 0,\r
452                 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON1);\r
453         dialogTemplate.AddButton(_T("Button2"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 2) ? BS_DEFPUSHBUTTON : 0), 0,\r
454                 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON2);\r
455         dialogTemplate.AddButton(_T("Button3"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 3) ? BS_DEFPUSHBUTTON : 0), 0,\r
456                 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON3);\r
457         dialogTemplate.AddButton(_T("Checkbox"), WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX, 0,\r
458                 0, 0, 0, 0, IDC_MESSAGEBOX_CHECKBOX);\r
459         \r
460         m_nDefButton = nDefaultButton;\r
461         m_sMessage = msg;\r
462         InitModalIndirect(dialogTemplate, pWnd);\r
463 \r
464         return (UINT)DoModal();\r
465 }\r
466 \r
467 void CMessageBox::SetRegistryValue(const CString& sValue, DWORD value)\r
468 {\r
469         CString path;\r
470 #ifdef XMESSAGEBOX_APPREGPATH\r
471         path = XMESSAGEBOX_APPREGPATH;\r
472 #else\r
473         path = "Software\\";\r
474         path += AfxGetAppName();\r
475 #endif\r
476         DWORD disp;\r
477         HKEY hKey;\r
478         if (RegCreateKeyEx(HKEY_CURRENT_USER, path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &disp)!=ERROR_SUCCESS)\r
479         {\r
480                 return;\r
481         }\r
482         RegSetValueEx(hKey, sValue, 0, REG_DWORD,(const BYTE*) &value, sizeof(value));\r
483         RegCloseKey(hKey);\r
484 }\r
485 \r
486 CSize CMessageBox::GetTextSize(const CString& str)\r
487 {\r
488         CRect rect;\r
489         GetWindowRect(&rect);\r
490 \r
491         CDC * pDC = GetDC();\r
492 \r
493         CDC memDC;\r
494         CBitmap bitmap;\r
495         memDC.CreateCompatibleDC(pDC);\r
496         bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());\r
497         CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);\r
498 \r
499         //get the minimum size of the rectangle of the tooltip\r
500         CSize sz = DrawHTML(&memDC, rect, str, m_LogFont, TRUE);\r
501 \r
502         memDC.SelectObject(pOldBitmap);\r
503         memDC.DeleteDC();\r
504         bitmap.DeleteObject();\r
505 \r
506         ReleaseDC(pDC);\r
507 \r
508         return sz;\r
509 }\r
510 \r
511 CSize CMessageBox::GetIconSize(HICON hIcon)\r
512 {\r
513         ICONINFO ii;\r
514         CSize sz (0, 0);\r
515 \r
516         if (hIcon != NULL)\r
517         {\r
518                 //get icon dimensions\r
519                 ::SecureZeroMemory(&ii, sizeof(ICONINFO));\r
520                 if (::GetIconInfo(hIcon, &ii))\r
521                 {\r
522                         sz.cx = (DWORD)(ii.xHotspot * 2);\r
523                         sz.cy = (DWORD)(ii.yHotspot * 2);\r
524                         //release icon mask bitmaps\r
525                         if(ii.hbmMask)\r
526                                 ::DeleteObject(ii.hbmMask);\r
527                         if(ii.hbmColor)\r
528                                 ::DeleteObject(ii.hbmColor);\r
529                 }\r
530         }\r
531         m_szIcon = sz;\r
532         return sz;\r
533 }\r
534 \r
535 CSize CMessageBox::GetButtonSize()\r
536 {\r
537         CSize sz;\r
538         int nButtons = 0;               //number of buttons - 1\r
539 \r
540         SetDlgItemText(IDC_MESSAGEBOX_BUTTON1, m_sButton1);\r
541         SetDlgItemText(IDC_MESSAGEBOX_BUTTON2, m_sButton2);\r
542         //GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, 1);\r
543         SetDlgItemText(IDC_MESSAGEBOX_BUTTON3, m_sButton3);\r
544         SetDlgItemText(IDC_MESSAGEBOX_CHECKBOX, m_sCheckbox);\r
545         \r
546         CSize sz1 = GetTextSize(m_sButton1);\r
547         CSize sz2 = GetTextSize(m_sButton2);\r
548         CSize sz3 = GetTextSize(m_sButton3);\r
549 \r
550         sz1.cx += 2*MESSAGEBOX_BUTTONX;\r
551         sz1.cy += 2*MESSAGEBOX_BUTTONY;\r
552 \r
553         if (sz2.cx)\r
554         {\r
555                 sz2.cx += 2*MESSAGEBOX_BUTTONX;\r
556                 sz2.cy += 2*MESSAGEBOX_BUTTONY;\r
557                 nButtons++;\r
558         }\r
559         if (sz3.cx)\r
560         {\r
561                 sz3.cx += 2*MESSAGEBOX_BUTTONX;\r
562                 sz3.cy += 2*MESSAGEBOX_BUTTONY;\r
563                 nButtons++;\r
564         }\r
565         \r
566         GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(0, 0, sz1.cx, sz1.cy);\r
567         GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(0, 0, sz2.cx, sz2.cy);\r
568         GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(0, 0, sz3.cx, sz3.cy);\r
569 \r
570 \r
571         sz.cx = sz1.cx + sz2.cx + sz3.cx + (nButtons * MESSAGEBOX_BUTTONMARGIN);\r
572         sz.cy = max(sz1.cy, sz2.cy);\r
573         sz.cy = max(sz.cy, sz3.cy);\r
574         m_szButtons = sz;\r
575         if (m_bShowCheck)\r
576         {\r
577                 CSize szCheck = GetTextSize(m_sCheckbox);\r
578                 szCheck.cx += 2*GetSystemMetrics(SM_CXMENUCHECK);\r
579                 szCheck.cy += 2*MESSAGEBOX_BUTTONY;\r
580                 sz.cx = max(sz.cx, szCheck.cx);\r
581                 sz.cy += szCheck.cy + MESSAGEBOX_BUTTONCHECKMARGIN;\r
582                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(0, 0, szCheck.cx, szCheck.cy);\r
583         }\r
584         m_szAllButtons = sz;\r
585         return sz;\r
586 }\r
587 \r
588 BEGIN_MESSAGE_MAP(CMessageBox, CDialog)\r
589         ON_WM_PAINT()\r
590         ON_WM_MOUSEMOVE()\r
591         ON_WM_LBUTTONUP()\r
592         ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1, OnButton1)\r
593         ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2, OnButton2)\r
594         ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3, OnButton3)\r
595 END_MESSAGE_MAP()\r
596 \r
597 void CMessageBox::OnPaint()\r
598 {\r
599         CPaintDC dc(this); // device context for painting\r
600 \r
601 \r
602         CRect rect;\r
603         CRect drawrect;\r
604         GetClientRect(&rect);\r
605         GetClientRect(&drawrect);\r
606 \r
607         //create a memory device-context. This is done to help reduce\r
608         //screen flicker, since we will paint the entire control to the\r
609         //off screen device context first.\r
610         CDC memDC;\r
611         CBitmap bitmap;\r
612         memDC.CreateCompatibleDC(&dc);\r
613         bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());\r
614         CBitmap* pOldBitmap = memDC.SelectObject(&bitmap); \r
615         \r
616         memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, 0,0, SRCCOPY);\r
617 \r
618         memDC.SetBkMode(TRANSPARENT);\r
619         memDC.SetBkColor(GetSysColor(COLOR_WINDOW));\r
620         memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); \r
621 \r
622         //OnDrawBackground();\r
623         drawrect.DeflateRect(MESSAGEBOX_BORDERMARGINX, MESSAGEBOX_BORDERMARGINY);\r
624         if (m_hIcon != NULL)\r
625         {\r
626                 DrawIconEx(memDC.m_hDC, drawrect.left, drawrect.top + \r
627                         ((drawrect.Height() - m_szAllButtons.cy - MESSAGEBOX_TEXTBUTTONMARGIN - m_szIcon.cy) / 2), \r
628                         m_hIcon, m_szIcon.cx, m_szIcon.cy, 0, NULL, DI_NORMAL);\r
629 \r
630                 drawrect.left += m_szIcon.cx + MESSAGEBOX_ICONMARGIN; \r
631         }\r
632 \r
633 \r
634         DrawHTML(&memDC, drawrect, m_sMessage, m_LogFont);\r
635         \r
636 \r
637         //Copy the memory device context back into the original DC.\r
638         dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0,0, SRCCOPY);\r
639         \r
640         //Cleanup resources.\r
641         memDC.SelectObject(pOldBitmap);\r
642         memDC.DeleteDC();\r
643         bitmap.DeleteObject(); \r
644 \r
645 \r
646 }\r
647 \r
648 void CMessageBox::OnMouseMove(UINT nFlags, CPoint point)\r
649 {\r
650         if (IsPointOverALink(point))\r
651         {\r
652                 m_Cursor.SetCursor(IDC_HAND);\r
653         }\r
654         else\r
655         {\r
656                 m_Cursor.Restore();     \r
657         }\r
658 \r
659         __super::OnMouseMove(nFlags, point);\r
660 }\r
661 \r
662 void CMessageBox::OnLButtonUp(UINT nFlags, CPoint point)\r
663 {\r
664         if (IsPointOverALink(point))\r
665         {\r
666                 CString url = GetLinkForPoint(point);\r
667                 ShellExecute(NULL, _T("open"), url, NULL,NULL, 0);\r
668         }\r
669 \r
670         __super::OnLButtonUp(nFlags, point);\r
671 }\r
672 \r
673 void CMessageBox::OnButton1()\r
674 {\r
675         if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)\r
676                 SetRegistryValue(m_sRegistryValue, m_uButton1Ret);\r
677         EndDialog(m_uButton1Ret);\r
678 }\r
679 \r
680 void CMessageBox::OnButton2()\r
681 {\r
682         if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)\r
683                 SetRegistryValue(m_sRegistryValue, m_uButton2Ret);\r
684         if ((m_uButton2Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))\r
685         {\r
686                 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);\r
687                 FPHH pHtmlHelp=NULL; // Function pointer\r
688                 HINSTANCE hInstHtmlHelp = LoadLibrary(_T("HHCtrl.ocx"));\r
689                 HWND hHelp = NULL;\r
690                 if (hInstHtmlHelp != NULL)\r
691                 {\r
692                         (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");\r
693                         if (pHtmlHelp)\r
694                                 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);\r
695                 }\r
696                 if (hHelp == NULL)\r
697                         ::MessageBox(m_hWnd, _T("could not show help file"), _T("Help"), MB_ICONERROR);\r
698         }\r
699         else if (m_uButton2Ret == IDHELP)\r
700         {\r
701                 OnHelp();\r
702         }\r
703         else\r
704                 EndDialog(m_uButton2Ret);\r
705 }\r
706 \r
707 void CMessageBox::OnButton3()\r
708 {\r
709         if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)\r
710                 SetRegistryValue(m_sRegistryValue, m_uButton3Ret);\r
711         if ((m_uButton3Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))\r
712         {\r
713                 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);\r
714                 FPHH pHtmlHelp=NULL; // Function pointer\r
715                 HINSTANCE hInstHtmlHelp = LoadLibrary(_T("HHCtrl.ocx"));\r
716                 HWND hHelp = NULL;\r
717                 if (hInstHtmlHelp != NULL)\r
718                 {\r
719                         (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");\r
720                         if (pHtmlHelp)\r
721                                 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);\r
722                 }\r
723                 if (hHelp == NULL)\r
724                         ::MessageBox(m_hWnd, _T("could not show help file"), _T("Help"), MB_ICONERROR);\r
725         }\r
726         else if (m_uButton3Ret == IDHELP)\r
727         {\r
728                 OnHelp();\r
729         }\r
730         else\r
731                 EndDialog(m_uButton3Ret);\r
732 }\r
733 \r
734 void CMessageBox::OnCancel()\r
735 {\r
736         if (m_uCancelRet == IDCANCEL)\r
737                 EndDialog(m_uCancelRet);\r
738         //__super::OnCancel();\r
739 }\r
740 \r
741 BOOL CMessageBox::OnInitDialog()\r
742 {\r
743         __super::OnInitDialog();\r
744 \r
745         CRect rect(0, 0, 0, 0);\r
746 \r
747         //determine the required size of the message box\r
748         CSize szText = GetTextSize(m_sMessage);\r
749         CSize szIcon = GetIconSize(m_hIcon);\r
750         CSize szButtons = GetButtonSize();\r
751 \r
752         CSize szIconText;\r
753         szIconText.cx = szText.cx + szIcon.cx + ((szIcon.cx == 0) ? MESSAGEBOX_ICONMARGIN : (2*MESSAGEBOX_ICONMARGIN));\r
754         szIconText.cy = max(szIcon.cy, szText.cy);\r
755 \r
756         rect.right = max(szButtons.cx, szIconText.cx);\r
757         rect.right += 2*GetSystemMetrics(SM_CXBORDER);\r
758         rect.right += 2*MESSAGEBOX_BORDERMARGINX;\r
759         rect.bottom = szIconText.cy;\r
760         rect.bottom += szButtons.cy;\r
761         rect.bottom += 2*MESSAGEBOX_BORDERMARGINY + MESSAGEBOX_TEXTBUTTONMARGIN;\r
762         rect.bottom += GetSystemMetrics(SM_CYCAPTION);\r
763         rect.bottom += 2*GetSystemMetrics(SM_CYBORDER);\r
764 \r
765         MoveWindow(rect);\r
766         CenterWindow();\r
767         \r
768         GetClientRect(rect);\r
769         \r
770         //now size and position the buttons as we need them\r
771         ASSERT(!m_sButton1.IsEmpty());          //at least the first button must be there!\r
772         if (m_sButton2.IsEmpty())\r
773         {\r
774                 //only one button\r
775                 CRect rt;\r
776                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt);\r
777                 ScreenToClient(rt);\r
778                 rt.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));\r
779                 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
780                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt);\r
781                 //hide the other two buttons\r
782                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->ShowWindow(SW_HIDE);\r
783                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);\r
784         }\r
785         else if (m_sButton3.IsEmpty())\r
786         {\r
787                 //two buttons\r
788                 CRect rt1;\r
789                 CRect rt2;\r
790                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);\r
791                 ScreenToClient(rt1);\r
792                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);\r
793                 ScreenToClient(rt2);\r
794                 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));\r
795                 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
796                 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);\r
797                 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
798                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);\r
799                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);\r
800                 //hide the third button\r
801                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);\r
802         }\r
803         else\r
804         {\r
805                 //three buttons\r
806                 CRect buttonrect;\r
807                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(buttonrect);\r
808                 CRect rt1;\r
809                 CRect rt2;\r
810                 CRect rt3;\r
811                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);\r
812                 ScreenToClient(rt1);\r
813                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);\r
814                 ScreenToClient(rt2);\r
815                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->GetWindowRect(rt3);\r
816                 ScreenToClient(rt3);\r
817                 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));\r
818                 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
819                 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);\r
820                 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
821                 rt3.MoveToX(rt2.right + MESSAGEBOX_BUTTONMARGIN);\r
822                 rt3.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);\r
823                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);\r
824                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);\r
825                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(rt3);\r
826         }\r
827         if (m_bShowCheck)\r
828         {\r
829                 CRect rt;\r
830                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->GetWindowRect(rt);\r
831                 ScreenToClient(rt);\r
832                 rt.MoveToX(rect.left + MESSAGEBOX_BORDERMARGINX/*+ ((rect.Width() - szButtons.cx)/2)*/);\r
833                 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - szButtons.cy);\r
834                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(rt);\r
835                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_SHOW);\r
836         }\r
837         else\r
838                 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_HIDE);\r
839 \r
840         if (m_nDefButton == 1)\r
841                 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->SetFocus();\r
842         if (m_nDefButton == 2)\r
843                 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SetFocus();\r
844         if (m_nDefButton == 3)\r
845                 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->SetFocus();\r
846 \r
847         SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);\r
848         SetForegroundWindow();\r
849         SetFocus(); //Just playing safe\r
850 \r
851         return FALSE;  // return TRUE unless you set the focus to a control\r
852         // EXCEPTION: OCX Property Pages should return FALSE\r
853 }\r
854 \r
855 BOOL CMessageBox::PreTranslateMessage(MSG* pMsg)\r
856 {\r
857         if (pMsg->message == WM_KEYDOWN)\r
858         {\r
859                 switch (pMsg->wParam)\r
860                 {\r
861                 case 'C':\r
862                 case VK_INSERT:\r
863                         {\r
864                                 if (GetAsyncKeyState(VK_CONTROL)&0x8000)\r
865                                 {\r
866                                         CStringA sClipboard = CStringA(m_sMessage);\r
867                                         if (OpenClipboard())\r
868                                         {\r
869                                                 EmptyClipboard();\r
870                                                 HGLOBAL hClipboardData;\r
871                                                 hClipboardData = GlobalAlloc(GMEM_DDESHARE, sClipboard.GetLength()+1);\r
872                                                 char * pchData;\r
873                                                 pchData = (char*)GlobalLock(hClipboardData);\r
874                                                 strcpy_s(pchData, sClipboard.GetLength()+1, (LPCSTR)sClipboard);\r
875                                                 GlobalUnlock(hClipboardData);\r
876                                                 SetClipboardData(CF_TEXT,hClipboardData);\r
877                                                 CloseClipboard();\r
878                                         }\r
879                                         return TRUE;\r
880                                 }\r
881                         }\r
882                         break;\r
883                 case VK_ESCAPE:\r
884                         {\r
885                                 switch (m_uType & 0xf)\r
886                                 {\r
887                                 case MB_ABORTRETRYIGNORE:\r
888                                         EndDialog(m_uButton1Ret);\r
889                                         break;\r
890                                 case MB_CANCELTRYCONTINUE:\r
891                                         EndDialog(m_uButton1Ret);\r
892                                         break;\r
893                                 case MB_OKCANCEL:\r
894                                         EndDialog(m_uButton2Ret);\r
895                                         break;\r
896                                 case MB_RETRYCANCEL:\r
897                                         EndDialog(m_uButton2Ret);\r
898                                         break;\r
899                                 case MB_YESNO:\r
900                                         EndDialog(m_uButton2Ret);\r
901                                         break;\r
902                                 case MB_YESNOCANCEL:\r
903                                         EndDialog(m_uButton3Ret);\r
904                                         break;\r
905                                 }\r
906                         }\r
907                         break;\r
908                 }\r
909         }\r
910 \r
911         return __super::PreTranslateMessage(pMsg);\r
912 }\r
913 \r
914 \r
915 \r
916 \r
917 \r
918 \r
919 \r