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.
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)
33 , m_bDestroyIcon(FALSE
)
39 CMessageBox::~CMessageBox(void)
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*/)
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".
69 #ifdef XMESSAGEBOX_APPREGPATH
70 path
= XMESSAGEBOX_APPREGPATH
;
72 path
= "Software\\TortoiseGit\\";
73 path
+= AfxGetAppName();
75 if (RegOpenKeyEx(HKEY_CURRENT_USER
, path
, 0, KEY_EXECUTE
, &hKey
)==ERROR_SUCCESS
)
77 int size
= sizeof(dwRetVal
);
79 if (RegQueryValueEx(hKey
, lpRegistry
, NULL
, &type
, (BYTE
*) &dwRetVal
,(LPDWORD
) &size
)==ERROR_SUCCESS
)
81 ASSERT(type
==REG_DWORD
);
83 return (UINT
)dwRetVal
; //return with the last saved value
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");
100 m_i18l
.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN
);
101 box
.m_sCheckbox
= m_i18l
;
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
);
113 box
.m_bDestroyIcon
= TRUE
;
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*/)
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
);
129 box
.m_bDestroyIcon
= TRUE
;
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
)
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
)
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".
169 #ifdef XMESSAGEBOX_APPREGPATH
170 path
= XMESSAGEBOX_APPREGPATH
;
172 path
= "Software\\TortoiseGit\\";
173 path
+= AfxGetAppName();
175 if (RegOpenKeyEx(HKEY_CURRENT_USER
, path
, 0, KEY_EXECUTE
, &hKey
)==ERROR_SUCCESS
)
177 int size
= sizeof(dwRetVal
);
179 if (RegQueryValueEx(hKey
, lpRegistry
, NULL
, &type
, (BYTE
*) &dwRetVal
,(LPDWORD
) &size
)==ERROR_SUCCESS
)
181 ASSERT(type
==REG_DWORD
);
183 return (UINT
)dwRetVal
; //return with the last saved value
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");
200 m_i18l
.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN
);
201 box
.m_sCheckbox
= m_i18l
;
205 box
.m_sCheckbox
= lpCheckMessage
;
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
)
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
)
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
)
236 sMessage
.LoadString(nMessage
);
237 sCaption
.LoadString(nCaption
);
241 box
.SetHelpID(nHelpID
);
243 return box
.GoModal(CWnd::FromHandle(hWnd
), sCaption
, sMessage
, box
.FillBoxStandard(uType
));
246 bool CMessageBox::RemoveRegistryKey(LPCTSTR lpRegistry
)
250 #ifdef XMESSAGEBOX_APPREGPATH
251 path
= XMESSAGEBOX_APPREGPATH
;
253 path
= "Software\\TortoiseGit\\";
254 path
+= AfxGetAppName();
256 if (RegOpenKeyEx(HKEY_CURRENT_USER
, path
, 0, KEY_WRITE
, &hKey
) == ERROR_SUCCESS
)
258 bool ret
= !!RegDeleteValue(hKey
, lpRegistry
);
265 int CMessageBox::FillBoxStandard(UINT 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
);
277 case MB_ICONASTERISK
:
278 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_ASTERISK
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
279 ::MessageBeep(MB_ICONASTERISK
);
281 case MB_ICONQUESTION
:
282 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_QUESTION
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
283 ::MessageBeep(MB_ICONQUESTION
);
286 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_HAND
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
287 ::MessageBeep(MB_ICONHAND
);
290 //set up the button texts
293 case MB_ABORTRETRYIGNORE
:
294 #ifndef IDS_MSGBOX_ABORT
295 m_sButton1
= "Abort";
297 m_i18l
.LoadString(IDS_MSGBOX_ABORT
);
300 m_uButton1Ret
= IDABORT
;
301 #ifndef IDS_MSGBOX_RETRY
302 m_sButton2
= "Retry";
304 m_i18l
.LoadString(IDS_MSGBOX_RETRY
);
307 m_uButton2Ret
= IDRETRY
;
308 #ifndef IDS_MSGBOX_IGNORE
309 m_sButton3
= "Ignore";
311 m_i18l
.LoadString(IDS_MSGBOX_IGNORE
);
314 m_uButton3Ret
= IDIGNORE
;
316 case MB_CANCELTRYCONTINUE
:
317 #ifndef IDS_MSGBOX_CANCEL
318 m_sButton1
= "Cancel";
320 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
323 m_uButton1Ret
= IDCANCEL
;
324 #ifndef IDS_MSGBOX_TRYAGAIN
325 m_sButton2
= "Try Again";
327 m_i18l
.LoadString(IDS_MSGBOX_TRYAGAIN
);
330 m_uButton2Ret
= IDTRYAGAIN
;
331 #ifndef IDS_MSGBOX_CONTINUE
332 m_sButton3
= "Continue";
334 m_i18l
.LoadString(IDS_MSGBOX_CONTINUE
);
337 m_uButton3Ret
= IDCONTINUE
;
340 #ifndef IDS_MSGBOX_OK
343 m_i18l
.LoadString(IDS_MSGBOX_OK
);
346 m_uButton1Ret
= IDOK
;
347 #ifndef IDS_MSGBOX_CANCEL
348 m_sButton2
= "Cancel";
350 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
353 m_uButton2Ret
= IDCANCEL
;
356 #ifndef IDS_MSGBOX_RETRY
357 m_sButton1
= "Retry";
359 m_i18l
.LoadString(IDS_MSGBOX_RETRY
);
362 m_uButton1Ret
= IDRETRY
;
363 #ifndef IDS_MSGBOX_CANCEL
364 m_sButton2
= "Cancel";
366 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
369 m_uButton2Ret
= IDCANCEL
;
372 #ifndef IDS_MSGBOX_YES
375 m_i18l
.LoadString(IDS_MSGBOX_YES
);
378 m_uButton1Ret
= IDYES
;
379 #ifndef IDS_MSGBOX_NO
382 m_i18l
.LoadString(IDS_MSGBOX_NO
);
385 m_uButton2Ret
= IDNO
;
388 #ifndef IDS_MSGBOX_YES
391 m_i18l
.LoadString(IDS_MSGBOX_YES
);
394 m_uButton1Ret
= IDYES
;
395 #ifndef IDS_MSGBOX_NO
398 m_i18l
.LoadString(IDS_MSGBOX_NO
);
401 m_uButton2Ret
= IDNO
;
402 #ifndef IDS_MSGBOX_CANCEL
403 m_sButton3
= "Cancel";
405 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
408 m_uButton3Ret
= IDCANCEL
;
412 #ifndef IDS_MSGBOX_OK
415 m_i18l
.LoadString(IDS_MSGBOX_OK
);
419 //now set the default button
420 switch (uType
& 0xf00)
429 // do we need to add a help button?
433 #ifndef IDS_MSGBOX_HELP
434 sHelpText
= _T("Help");
436 m_i18l
.LoadString(IDS_MSGBOX_HELP
);
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
;
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
464 LOGFONT lfCaptionFont
;
466 int iSmCaptionHeight
;
467 LOGFONT lfSmCaptionFont
;
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:
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
;
505 InitModalIndirect(dialogTemplate
, pWnd
);
507 return (UINT
)DoModal();
510 void CMessageBox::SetRegistryValue(const CString
& sValue
, DWORD value
)
513 #ifdef XMESSAGEBOX_APPREGPATH
514 path
= XMESSAGEBOX_APPREGPATH
;
516 path
= "Software\\TortoiseGit\\";
517 path
+= AfxGetAppName();
521 if (RegCreateKeyEx(HKEY_CURRENT_USER
, path
, 0, _T(""), REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, &disp
)!=ERROR_SUCCESS
)
525 RegSetValueEx(hKey
, sValue
, 0, REG_DWORD
,(const BYTE
*) &value
, sizeof(value
));
529 CSize
CMessageBox::GetTextSize(const CString
& str
)
532 GetWindowRect(&rect
);
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
);
547 bitmap
.DeleteObject();
554 CSize
CMessageBox::GetIconSize(HICON hIcon
)
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
569 ::DeleteObject(ii
.hbmMask
);
571 ::DeleteObject(ii
.hbmColor
);
578 CSize
CMessageBox::GetButtonSize()
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
;
598 sz2
.cx
+= 2*MESSAGEBOX_BUTTONX
;
599 sz2
.cy
+= 2*MESSAGEBOX_BUTTONY
;
604 sz3
.cx
+= 2*MESSAGEBOX_BUTTONX
;
605 sz3
.cy
+= 2*MESSAGEBOX_BUTTONY
;
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
);
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
);
631 BEGIN_MESSAGE_MAP(CMessageBox
, CDialog
)
635 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1
, OnButton1
)
636 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2
, OnButton2
)
637 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3
, OnButton3
)
640 void CMessageBox::OnPaint()
642 CPaintDC
dc(this); // device context for painting
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.
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
);
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
);
684 memDC
.SelectObject(pOldBitmap
);
686 bitmap
.DeleteObject();
691 void CMessageBox::OnMouseMove(UINT nFlags
, CPoint point
)
693 if (IsPointOverALink(point
))
695 m_Cursor
.SetCursor(IDC_HAND
);
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"));
733 if (hInstHtmlHelp
!= NULL
)
735 (FARPROC
&)pHtmlHelp
= GetProcAddress(hInstHtmlHelp
, "HtmlHelpW");
737 hHelp
= pHtmlHelp(m_hWnd
, (LPCTSTR
)m_sHelpPath
, HH_DISPLAY_TOPIC
, NULL
);
740 ::MessageBox(m_hWnd
, _T("could not show help file"), _T("Help"), MB_ICONERROR
);
742 else if (m_uButton2Ret
== IDHELP
)
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"));
760 if (hInstHtmlHelp
!= NULL
)
762 (FARPROC
&)pHtmlHelp
= GetProcAddress(hInstHtmlHelp
, "HtmlHelpW");
764 hHelp
= pHtmlHelp(m_hWnd
, (LPCTSTR
)m_sHelpPath
, HH_DISPLAY_TOPIC
, NULL
);
767 ::MessageBox(m_hWnd
, _T("could not show help file"), _T("Help"), MB_ICONERROR
);
769 else if (m_uButton3Ret
== IDHELP
)
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();
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
);
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())
819 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(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())
833 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(rt1
);
835 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->GetWindowRect(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
);
850 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(buttonrect
);
854 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(rt1
);
856 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->GetWindowRect(rt2
);
858 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->GetWindowRect(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
);
873 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->GetWindowRect(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
);
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
)
907 if (GetAsyncKeyState(VK_CONTROL
)&0x8000)
909 CClipboardHelper clipboardHelper
;
910 if(clipboardHelper
.Open(GetSafeHwnd()))
913 CStringA sClipboard
= CStringA(m_sMessage
);
914 HGLOBAL hClipboardData
= CClipboardHelper::GlobalAlloc(sClipboard
.GetLength()+1);
915 char * pchData
= (char*)GlobalLock(hClipboardData
);
917 strcpy_s(pchData
, sClipboard
.GetLength()+1, (LPCSTR
)sClipboard
);
918 GlobalUnlock(hClipboardData
);
919 SetClipboardData(CF_TEXT
,hClipboardData
);
927 switch (m_uType
& 0xf)
929 case MB_ABORTRETRYIGNORE
:
930 EndDialog(m_uButton1Ret
);
932 case MB_CANCELTRYCONTINUE
:
933 EndDialog(m_uButton1Ret
);
936 EndDialog(m_uButton2Ret
);
939 EndDialog(m_uButton2Ret
);
942 EndDialog(m_uButton2Ret
);
945 EndDialog(m_uButton3Ret
);
953 return __super::PreTranslateMessage(pMsg
);