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