Sync TortoiseIDiff and TortoiseUDiff from TortoiseSVN
[TortoiseGit.git] / src / Utils / MiscUI / MessageBox.cpp
blobe9cc5893547cdb70f2e6dcee7fc646d4f97bfeb0
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012 - 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 int CMessageBox::FillBoxStandard(UINT uType)
248 int ret = 1;
249 m_uType = uType;
250 m_uCancelRet = IDCANCEL;
251 //load the icons according to uType
252 switch (uType & 0xf0)
254 case MB_ICONEXCLAMATION:
255 m_hIcon = (HICON)::LoadImage(NULL, IDI_EXCLAMATION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
256 ::MessageBeep(MB_ICONEXCLAMATION);
257 break;
258 case MB_ICONASTERISK:
259 m_hIcon = (HICON)::LoadImage(NULL, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
260 ::MessageBeep(MB_ICONASTERISK);
261 break;
262 case MB_ICONQUESTION:
263 m_hIcon = (HICON)::LoadImage(NULL, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
264 ::MessageBeep(MB_ICONQUESTION);
265 break;
266 case MB_ICONHAND:
267 m_hIcon = (HICON)::LoadImage(NULL, IDI_HAND, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
268 ::MessageBeep(MB_ICONHAND);
269 break;
271 //set up the button texts
272 switch (uType & 0xf)
274 case MB_ABORTRETRYIGNORE:
275 #ifndef IDS_MSGBOX_ABORT
276 m_sButton1 = "Abort";
277 #else
278 m_i18l.LoadString(IDS_MSGBOX_ABORT);
279 m_sButton1 = m_i18l;
280 #endif
281 m_uButton1Ret = IDABORT;
282 #ifndef IDS_MSGBOX_RETRY
283 m_sButton2 = "Retry";
284 #else
285 m_i18l.LoadString(IDS_MSGBOX_RETRY);
286 m_sButton2 = m_i18l;
287 #endif
288 m_uButton2Ret = IDRETRY;
289 #ifndef IDS_MSGBOX_IGNORE
290 m_sButton3 = "Ignore";
291 #else
292 m_i18l.LoadString(IDS_MSGBOX_IGNORE);
293 m_sButton3 = m_i18l;
294 #endif
295 m_uButton3Ret = IDIGNORE;
296 break;
297 case MB_CANCELTRYCONTINUE:
298 #ifndef IDS_MSGBOX_CANCEL
299 m_sButton1 = "Cancel";
300 #else
301 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
302 m_sButton1 = m_i18l;
303 #endif
304 m_uButton1Ret = IDCANCEL;
305 #ifndef IDS_MSGBOX_TRYAGAIN
306 m_sButton2 = "Try Again";
307 #else
308 m_i18l.LoadString(IDS_MSGBOX_TRYAGAIN);
309 m_sButton2 = m_i18l;
310 #endif
311 m_uButton2Ret = IDTRYAGAIN;
312 #ifndef IDS_MSGBOX_CONTINUE
313 m_sButton3 = "Continue";
314 #else
315 m_i18l.LoadString(IDS_MSGBOX_CONTINUE);
316 m_sButton3 = m_i18l;
317 #endif
318 m_uButton3Ret = IDCONTINUE;
319 break;
320 case MB_OKCANCEL:
321 #ifndef IDS_MSGBOX_OK
322 m_sButton1 = "Ok";
323 #else
324 m_i18l.LoadString(IDS_MSGBOX_OK);
325 m_sButton1 = m_i18l;
326 #endif
327 m_uButton1Ret = IDOK;
328 #ifndef IDS_MSGBOX_CANCEL
329 m_sButton2 = "Cancel";
330 #else
331 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
332 m_sButton2 = m_i18l;
333 #endif
334 m_uButton2Ret = IDCANCEL;
335 break;
336 case MB_RETRYCANCEL:
337 #ifndef IDS_MSGBOX_RETRY
338 m_sButton1 = "Retry";
339 #else
340 m_i18l.LoadString(IDS_MSGBOX_RETRY);
341 m_sButton1 = m_i18l;
342 #endif
343 m_uButton1Ret = IDRETRY;
344 #ifndef IDS_MSGBOX_CANCEL
345 m_sButton2 = "Cancel";
346 #else
347 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
348 m_sButton2 = m_i18l;
349 #endif
350 m_uButton2Ret = IDCANCEL;
351 break;
352 case MB_YESNO:
353 #ifndef IDS_MSGBOX_YES
354 m_sButton1 = "Yes";
355 #else
356 m_i18l.LoadString(IDS_MSGBOX_YES);
357 m_sButton1 = m_i18l;
358 #endif
359 m_uButton1Ret = IDYES;
360 #ifndef IDS_MSGBOX_NO
361 m_sButton2 = "No";
362 #else
363 m_i18l.LoadString(IDS_MSGBOX_NO);
364 m_sButton2 = m_i18l;
365 #endif
366 m_uButton2Ret = IDNO;
367 break;
368 case MB_YESNOCANCEL:
369 #ifndef IDS_MSGBOX_YES
370 m_sButton1 = "Yes";
371 #else
372 m_i18l.LoadString(IDS_MSGBOX_YES);
373 m_sButton1 = m_i18l;
374 #endif
375 m_uButton1Ret = IDYES;
376 #ifndef IDS_MSGBOX_NO
377 m_sButton2 = "No";
378 #else
379 m_i18l.LoadString(IDS_MSGBOX_NO);
380 m_sButton2 = m_i18l;
381 #endif
382 m_uButton2Ret = IDNO;
383 #ifndef IDS_MSGBOX_CANCEL
384 m_sButton3 = "Cancel";
385 #else
386 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
387 m_sButton3 = m_i18l;
388 #endif
389 m_uButton3Ret = IDCANCEL;
390 break;
391 case MB_OK:
392 default:
393 #ifndef IDS_MSGBOX_OK
394 m_sButton1 = "Ok";
395 #else
396 m_i18l.LoadString(IDS_MSGBOX_OK);
397 m_sButton1 = m_i18l;
398 #endif
400 //now set the default button
401 switch (uType & 0xf00)
403 case MB_DEFBUTTON2:
404 ret = 2;
405 break;
406 case MB_DEFBUTTON3:
407 ret = 3;
408 break;
410 // do we need to add a help button?
411 if (uType & MB_HELP)
413 CString sHelpText;
414 #ifndef IDS_MSGBOX_HELP
415 sHelpText = _T("Help");
416 #else
417 m_i18l.LoadString(IDS_MSGBOX_HELP);
418 sHelpText = m_i18l;
419 #endif
420 if (m_sButton2.IsEmpty())
422 m_sButton2 = sHelpText;
423 m_uButton2Ret = IDHELP;
425 else if (m_sButton3.IsEmpty())
427 m_sButton3 = sHelpText;
428 m_uButton3Ret = IDHELP;
431 return ret;
434 UINT CMessageBox::GoModal(CWnd * pWnd, const CString& title, const CString& msg, int nDefaultButton)
436 // pre Vista struct, needed for Windows XP
437 struct OLD_NONCLIENTMETRICS
439 UINT cbSize;
440 int iBorderWidth;
441 int iScrollWidth;
442 int iScrollHeight;
443 int iCaptionWidth;
444 int iCaptionHeight;
445 LOGFONT lfCaptionFont;
446 int iSmCaptionWidth;
447 int iSmCaptionHeight;
448 LOGFONT lfSmCaptionFont;
449 int iMenuWidth;
450 int iMenuHeight;
451 LOGFONT lfMenuFont;
452 LOGFONT lfStatusFont;
453 LOGFONT lfMessageFont;
455 const UINT cbProperSize = sizeof(OLD_NONCLIENTMETRICS);
457 NONCLIENTMETRICS ncm;
458 memset(&ncm,0,sizeof(NONCLIENTMETRICS));
459 ncm.cbSize = cbProperSize;
460 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
462 memcpy(&m_LogFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
464 //the problem with the LOGFONT lfHeight is that it is not in pixels,
465 //but the dialog template needs the height in pixels.
466 //We need to convert those values first:
467 CDC * pDC;
468 if (pWnd)
469 pDC = pWnd->GetDC();
470 else
471 pDC = GetDesktopWindow()->GetDC();
472 int pix = -MulDiv(m_LogFont.lfHeight, 72, GetDeviceCaps(pDC->m_hDC, LOGPIXELSY));
473 CDlgTemplate dialogTemplate = CDlgTemplate(title, WS_CAPTION | DS_CENTER,
474 0, 0, 0, 0, m_LogFont.lfFaceName, pix);
475 dialogTemplate.AddButton(_T("Button1"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 1) ? BS_DEFPUSHBUTTON : 0), 0,
476 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON1);
477 dialogTemplate.AddButton(_T("Button2"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 2) ? BS_DEFPUSHBUTTON : 0), 0,
478 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON2);
479 dialogTemplate.AddButton(_T("Button3"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 3) ? BS_DEFPUSHBUTTON : 0), 0,
480 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON3);
481 dialogTemplate.AddButton(_T("Checkbox"), WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX, 0,
482 0, 0, 0, 0, IDC_MESSAGEBOX_CHECKBOX);
484 m_nDefButton = nDefaultButton;
485 m_sMessage = msg;
486 InitModalIndirect(dialogTemplate, pWnd);
488 return (UINT)DoModal();
491 void CMessageBox::SetRegistryValue(const CString& sValue, DWORD value)
493 CString path;
494 #ifdef XMESSAGEBOX_APPREGPATH
495 path = XMESSAGEBOX_APPREGPATH;
496 #else
497 path = "Software\\TortoiseGit\\";
498 path += AfxGetAppName();
499 #endif
500 DWORD disp;
501 HKEY hKey;
502 if (RegCreateKeyEx(HKEY_CURRENT_USER, path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &disp)!=ERROR_SUCCESS)
504 return;
506 RegSetValueEx(hKey, sValue, 0, REG_DWORD,(const BYTE*) &value, sizeof(value));
507 RegCloseKey(hKey);
510 CSize CMessageBox::GetTextSize(const CString& str)
512 CRect rect;
513 GetWindowRect(&rect);
515 CDC * pDC = GetDC();
517 CDC memDC;
518 CBitmap bitmap;
519 memDC.CreateCompatibleDC(pDC);
520 bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
521 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
523 //get the minimum size of the rectangle of the tooltip
524 CSize sz = DrawHTML(&memDC, rect, str, m_LogFont, TRUE);
526 memDC.SelectObject(pOldBitmap);
527 memDC.DeleteDC();
528 bitmap.DeleteObject();
530 ReleaseDC(pDC);
532 return sz;
535 CSize CMessageBox::GetIconSize(HICON hIcon)
537 ICONINFO ii;
538 CSize sz (0, 0);
540 if (hIcon != NULL)
542 //get icon dimensions
543 ::SecureZeroMemory(&ii, sizeof(ICONINFO));
544 if (::GetIconInfo(hIcon, &ii))
546 sz.cx = (DWORD)(ii.xHotspot * 2);
547 sz.cy = (DWORD)(ii.yHotspot * 2);
548 //release icon mask bitmaps
549 if(ii.hbmMask)
550 ::DeleteObject(ii.hbmMask);
551 if(ii.hbmColor)
552 ::DeleteObject(ii.hbmColor);
555 m_szIcon = sz;
556 return sz;
559 CSize CMessageBox::GetButtonSize()
561 CSize sz;
562 int nButtons = 0; //number of buttons - 1
564 SetDlgItemText(IDC_MESSAGEBOX_BUTTON1, m_sButton1);
565 SetDlgItemText(IDC_MESSAGEBOX_BUTTON2, m_sButton2);
566 //GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, 1);
567 SetDlgItemText(IDC_MESSAGEBOX_BUTTON3, m_sButton3);
568 SetDlgItemText(IDC_MESSAGEBOX_CHECKBOX, m_sCheckbox);
570 CSize sz1 = GetTextSize(m_sButton1);
571 CSize sz2 = GetTextSize(m_sButton2);
572 CSize sz3 = GetTextSize(m_sButton3);
574 sz1.cx += 2*MESSAGEBOX_BUTTONX;
575 sz1.cy += 2*MESSAGEBOX_BUTTONY;
577 if (sz2.cx)
579 sz2.cx += 2*MESSAGEBOX_BUTTONX;
580 sz2.cy += 2*MESSAGEBOX_BUTTONY;
581 nButtons++;
583 if (sz3.cx)
585 sz3.cx += 2*MESSAGEBOX_BUTTONX;
586 sz3.cy += 2*MESSAGEBOX_BUTTONY;
587 nButtons++;
590 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(0, 0, sz1.cx, sz1.cy);
591 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(0, 0, sz2.cx, sz2.cy);
592 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(0, 0, sz3.cx, sz3.cy);
595 sz.cx = sz1.cx + sz2.cx + sz3.cx + (nButtons * MESSAGEBOX_BUTTONMARGIN);
596 sz.cy = max(sz1.cy, sz2.cy);
597 sz.cy = max(sz.cy, sz3.cy);
598 m_szButtons = sz;
599 if (m_bShowCheck)
601 CSize szCheck = GetTextSize(m_sCheckbox);
602 szCheck.cx += 2*GetSystemMetrics(SM_CXMENUCHECK);
603 szCheck.cy += 2*MESSAGEBOX_BUTTONY;
604 sz.cx = max(sz.cx, szCheck.cx);
605 sz.cy += szCheck.cy + MESSAGEBOX_BUTTONCHECKMARGIN;
606 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(0, 0, szCheck.cx, szCheck.cy);
608 m_szAllButtons = sz;
609 return sz;
612 BEGIN_MESSAGE_MAP(CMessageBox, CDialog)
613 ON_WM_PAINT()
614 ON_WM_MOUSEMOVE()
615 ON_WM_LBUTTONUP()
616 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1, OnButton1)
617 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2, OnButton2)
618 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3, OnButton3)
619 END_MESSAGE_MAP()
621 void CMessageBox::OnPaint()
623 CPaintDC dc(this); // device context for painting
626 CRect rect;
627 CRect drawrect;
628 GetClientRect(&rect);
629 GetClientRect(&drawrect);
631 //create a memory device-context. This is done to help reduce
632 //screen flicker, since we will paint the entire control to the
633 //off screen device context first.
634 CDC memDC;
635 CBitmap bitmap;
636 memDC.CreateCompatibleDC(&dc);
637 bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
638 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
640 memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, 0,0, SRCCOPY);
642 memDC.SetBkMode(TRANSPARENT);
643 memDC.SetBkColor(GetSysColor(COLOR_WINDOW));
644 memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
646 //OnDrawBackground();
647 drawrect.DeflateRect(MESSAGEBOX_BORDERMARGINX, MESSAGEBOX_BORDERMARGINY);
648 if (m_hIcon != NULL)
650 DrawIconEx(memDC.m_hDC, drawrect.left, drawrect.top +
651 ((drawrect.Height() - m_szAllButtons.cy - MESSAGEBOX_TEXTBUTTONMARGIN - m_szIcon.cy) / 2),
652 m_hIcon, m_szIcon.cx, m_szIcon.cy, 0, NULL, DI_NORMAL);
654 drawrect.left += m_szIcon.cx + MESSAGEBOX_ICONMARGIN;
658 DrawHTML(&memDC, drawrect, m_sMessage, m_LogFont);
661 //Copy the memory device context back into the original DC.
662 dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0,0, SRCCOPY);
664 //Cleanup resources.
665 memDC.SelectObject(pOldBitmap);
666 memDC.DeleteDC();
667 bitmap.DeleteObject();
672 void CMessageBox::OnMouseMove(UINT nFlags, CPoint point)
674 if (IsPointOverALink(point))
676 m_Cursor.SetCursor(IDC_HAND);
678 else
680 m_Cursor.Restore();
683 __super::OnMouseMove(nFlags, point);
686 void CMessageBox::OnLButtonUp(UINT nFlags, CPoint point)
688 if (IsPointOverALink(point))
690 CString url = GetLinkForPoint(point);
691 ShellExecute(NULL, _T("open"), url, NULL,NULL, 0);
694 __super::OnLButtonUp(nFlags, point);
697 void CMessageBox::OnButton1()
699 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
700 SetRegistryValue(m_sRegistryValue, m_uButton1Ret);
701 EndDialog(m_uButton1Ret);
704 void CMessageBox::OnButton2()
706 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
707 SetRegistryValue(m_sRegistryValue, m_uButton2Ret);
708 if ((m_uButton2Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
710 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
711 FPHH pHtmlHelp=NULL; // Function pointer
712 HINSTANCE hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(_T("HHCtrl.ocx"));
713 HWND hHelp = NULL;
714 if (hInstHtmlHelp != NULL)
716 (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
717 if (pHtmlHelp)
718 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);
720 if (hHelp == NULL)
721 ::MessageBox(m_hWnd, _T("could not show help file"), _T("Help"), MB_ICONERROR);
723 else if (m_uButton2Ret == IDHELP)
725 OnHelp();
727 else
728 EndDialog(m_uButton2Ret);
731 void CMessageBox::OnButton3()
733 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
734 SetRegistryValue(m_sRegistryValue, m_uButton3Ret);
735 if ((m_uButton3Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
737 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
738 FPHH pHtmlHelp=NULL; // Function pointer
739 HINSTANCE hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(_T("HHCtrl.ocx"));
740 HWND hHelp = NULL;
741 if (hInstHtmlHelp != NULL)
743 (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
744 if (pHtmlHelp)
745 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);
747 if (hHelp == NULL)
748 ::MessageBox(m_hWnd, _T("could not show help file"), _T("Help"), MB_ICONERROR);
750 else if (m_uButton3Ret == IDHELP)
752 OnHelp();
754 else
755 EndDialog(m_uButton3Ret);
758 void CMessageBox::OnCancel()
760 if (m_uCancelRet == IDCANCEL)
761 EndDialog(m_uCancelRet);
762 //__super::OnCancel();
765 BOOL CMessageBox::OnInitDialog()
767 __super::OnInitDialog();
769 CRect rect(0, 0, 0, 0);
771 //determine the required size of the message box
772 CSize szText = GetTextSize(m_sMessage);
773 CSize szIcon = GetIconSize(m_hIcon);
774 CSize szButtons = GetButtonSize();
776 CSize szIconText;
777 szIconText.cx = szText.cx + szIcon.cx + ((szIcon.cx == 0) ? MESSAGEBOX_ICONMARGIN : (2*MESSAGEBOX_ICONMARGIN));
778 szIconText.cy = max(szIcon.cy, szText.cy);
780 rect.right = max(szButtons.cx, szIconText.cx);
781 rect.right += 2*GetSystemMetrics(SM_CXBORDER);
782 rect.right += 2*MESSAGEBOX_BORDERMARGINX;
783 rect.bottom = szIconText.cy;
784 rect.bottom += szButtons.cy;
785 rect.bottom += 2*MESSAGEBOX_BORDERMARGINY + MESSAGEBOX_TEXTBUTTONMARGIN;
786 rect.bottom += GetSystemMetrics(SM_CYCAPTION);
787 rect.bottom += 2*GetSystemMetrics(SM_CYBORDER);
789 MoveWindow(rect);
790 CenterWindow();
792 GetClientRect(rect);
794 //now size and position the buttons as we need them
795 ASSERT(!m_sButton1.IsEmpty()); //at least the first button must be there!
796 if (m_sButton2.IsEmpty())
798 //only one button
799 CRect rt;
800 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt);
801 ScreenToClient(rt);
802 rt.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
803 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
804 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt);
805 //hide the other two buttons
806 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->ShowWindow(SW_HIDE);
807 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
809 else if (m_sButton3.IsEmpty())
811 //two buttons
812 CRect rt1;
813 CRect rt2;
814 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
815 ScreenToClient(rt1);
816 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
817 ScreenToClient(rt2);
818 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
819 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
820 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);
821 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
822 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
823 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
824 //hide the third button
825 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
827 else
829 //three buttons
830 CRect buttonrect;
831 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(buttonrect);
832 CRect rt1;
833 CRect rt2;
834 CRect rt3;
835 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
836 ScreenToClient(rt1);
837 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
838 ScreenToClient(rt2);
839 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->GetWindowRect(rt3);
840 ScreenToClient(rt3);
841 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
842 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
843 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);
844 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
845 rt3.MoveToX(rt2.right + MESSAGEBOX_BUTTONMARGIN);
846 rt3.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
847 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
848 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
849 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(rt3);
851 if (m_bShowCheck)
853 CRect rt;
854 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->GetWindowRect(rt);
855 ScreenToClient(rt);
856 rt.MoveToX(rect.left + MESSAGEBOX_BORDERMARGINX/*+ ((rect.Width() - szButtons.cx)/2)*/);
857 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - szButtons.cy);
858 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(rt);
859 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_SHOW);
861 else
862 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_HIDE);
864 SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
865 SetForegroundWindow();
866 SetFocus(); //Just playing safe
868 if (m_nDefButton == 1)
869 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->SetFocus();
870 if (m_nDefButton == 2)
871 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SetFocus();
872 if (m_nDefButton == 3)
873 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->SetFocus();
875 return FALSE; // return TRUE unless you set the focus to a control
876 // EXCEPTION: OCX Property Pages should return FALSE
879 BOOL CMessageBox::PreTranslateMessage(MSG* pMsg)
881 if (pMsg->message == WM_KEYDOWN)
883 switch (pMsg->wParam)
885 case 'C':
886 case VK_INSERT:
888 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
890 CClipboardHelper clipboardHelper;
891 if(clipboardHelper.Open(GetSafeHwnd()))
893 EmptyClipboard();
894 CStringA sClipboard = CStringA(m_sMessage);
895 HGLOBAL hClipboardData = CClipboardHelper::GlobalAlloc(sClipboard.GetLength()+1);
896 char * pchData = (char*)GlobalLock(hClipboardData);
897 if (pchData)
898 strcpy_s(pchData, sClipboard.GetLength()+1, (LPCSTR)sClipboard);
899 GlobalUnlock(hClipboardData);
900 SetClipboardData(CF_TEXT,hClipboardData);
902 return TRUE;
905 break;
906 case VK_ESCAPE:
908 switch (m_uType & 0xf)
910 case MB_ABORTRETRYIGNORE:
911 EndDialog(m_uButton1Ret);
912 break;
913 case MB_CANCELTRYCONTINUE:
914 EndDialog(m_uButton1Ret);
915 break;
916 case MB_OKCANCEL:
917 EndDialog(m_uButton2Ret);
918 break;
919 case MB_RETRYCANCEL:
920 EndDialog(m_uButton2Ret);
921 break;
922 case MB_YESNO:
923 EndDialog(m_uButton2Ret);
924 break;
925 case MB_YESNOCANCEL:
926 EndDialog(m_uButton3Ret);
927 break;
930 break;
934 return __super::PreTranslateMessage(pMsg);