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 "ClipboardHelper.h"
24 #include "SmartHandle.h"
26 CMessageBox::CMessageBox(void)
33 , m_bDestroyIcon(FALSE
)
38 SecureZeroMemory(&m_LogFont
, sizeof(LOGFONT
));
41 CMessageBox::~CMessageBox(void)
44 ::DestroyIcon(m_hIcon
);
47 UINT
CMessageBox::ShowCheck(HWND hWnd
, UINT nMessage
, UINT nCaption
, int nDef
, LPCTSTR icon
, UINT nButton1
, UINT nButton2
, UINT nButton3
, LPCTSTR lpRegistry
, UINT nCheckMessage
/* = NULL*/, BOOL
*bChecked
)
55 sButton1
.LoadString(nButton1
);
56 sButton2
.LoadString(nButton2
);
57 sButton3
.LoadString(nButton3
);
58 sMessage
.LoadString(nMessage
);
59 sCaption
.LoadString(nCaption
);
60 nCheckMsg
.LoadString(nCheckMessage
);
61 return CMessageBox::ShowCheck(hWnd
, sMessage
, sCaption
, nDef
, icon
, sButton1
, sButton2
, sButton3
, lpRegistry
, nCheckMsg
, bChecked
);
64 UINT
CMessageBox::ShowCheck(HWND hWnd
, LPCTSTR lpMessage
, LPCTSTR lpCaption
, int nDef
, LPCTSTR icon
, LPCTSTR lpButton1
, LPCTSTR lpButton2
, LPCTSTR lpButton3
, LPCTSTR lpRegistry
, LPCTSTR lpCheckMessage
/* = NULL*/, BOOL
*bChecked
)
66 //check the registry if we have to show the box or just return with the last used return value
67 //this would be the case if the user pressed "do not show again".
71 #ifdef XMESSAGEBOX_APPREGPATH
72 path
= XMESSAGEBOX_APPREGPATH
;
74 path
= "Software\\TortoiseGit\\";
75 path
+= AfxGetApp()->m_pszProfileName
;
77 if (lpRegistry
&& *lpRegistry
&& RegOpenKeyEx(HKEY_CURRENT_USER
, path
, 0, KEY_EXECUTE
, &hKey
)==ERROR_SUCCESS
)
79 int size
= sizeof(dwRetVal
);
81 if (RegQueryValueEx(hKey
, lpRegistry
, NULL
, &type
, (BYTE
*) &dwRetVal
,(LPDWORD
) &size
)==ERROR_SUCCESS
)
83 ASSERT(type
==REG_DWORD
);
85 return (UINT
)dwRetVal
; //return with the last saved value
94 box
.m_bShowCheck
= TRUE
;
95 box
.m_sRegistryValue
= lpRegistry
;
96 if (lpCheckMessage
== NULL
)
98 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
99 box
.m_sCheckbox
= _T("do not show again");
102 m_i18l
.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN
);
103 box
.m_sCheckbox
= m_i18l
;
107 box
.m_sCheckbox
= lpCheckMessage
;
108 box
.m_bChecked
= bChecked
? *bChecked
: FALSE
;
109 box
.m_sButton1
= lpButton1
;
110 box
.m_sButton2
= lpButton2
;
111 box
.m_sButton3
= lpButton3
;
112 box
.m_hIcon
= (HICON
)::LoadImage(AfxGetResourceHandle(), icon
, IMAGE_ICON
, 0, 0, LR_DEFAULTSIZE
);
113 if (box
.m_hIcon
== NULL
)
114 box
.m_hIcon
= (HICON
)::LoadImage(NULL
, icon
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
116 box
.m_bDestroyIcon
= TRUE
;
119 int result
= box
.GoModal(CWnd::FromHandle(hWnd
), lpCaption
, lpMessage
, nDef
);
121 *bChecked
= box
.m_bChecked
;
125 UINT
CMessageBox::Show(HWND hWnd
, LPCTSTR lpMessage
, LPCTSTR lpCaption
, int nDef
, LPCTSTR icon
, LPCTSTR lpButton1
, LPCTSTR lpButton2
/* = NULL*/, LPCTSTR lpButton3
/* = NULL*/)
128 box
.m_sButton1
= lpButton1
;
129 box
.m_sButton2
= lpButton2
;
130 box
.m_sButton3
= lpButton3
;
131 box
.m_hIcon
= (HICON
)::LoadImage(AfxGetResourceHandle(), icon
, IMAGE_ICON
, 0, 0, LR_DEFAULTSIZE
);
132 if (box
.m_hIcon
== NULL
)
133 box
.m_hIcon
= (HICON
)::LoadImage(NULL
, icon
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
135 box
.m_bDestroyIcon
= TRUE
;
138 return box
.GoModal(CWnd::FromHandle(hWnd
), lpCaption
, lpMessage
, nDef
);
141 UINT
CMessageBox::Show(HWND hWnd
, UINT nMessage
, UINT nCaption
, int nDef
, LPCTSTR icon
, UINT nButton1
, UINT nButton2
, UINT nButton3
)
148 sButton1
.LoadString(nButton1
);
149 sButton2
.LoadString(nButton2
);
150 sButton3
.LoadString(nButton3
);
151 sMessage
.LoadString(nMessage
);
152 sCaption
.LoadString(nCaption
);
153 return CMessageBox::Show(hWnd
, sMessage
, sCaption
, nDef
, icon
, sButton1
, sButton2
, sButton3
);
157 UINT
CMessageBox::ShowCheck(HWND hWnd
, UINT nMessage
, UINT nCaption
, UINT uType
, LPCTSTR lpRegistry
, UINT nCheckMessage
, BOOL
*bChecked
)
162 sMessage
.LoadString(nMessage
);
163 sCaption
.LoadString(nCaption
);
164 sCheckMsg
.LoadString(nCheckMessage
);
165 return CMessageBox::ShowCheck(hWnd
, sMessage
, sCaption
, uType
, lpRegistry
, sCheckMsg
, bChecked
);
168 UINT
CMessageBox::ShowCheck(HWND hWnd
, LPCTSTR lpMessage
, LPCTSTR lpCaption
, UINT uType
, LPCTSTR lpRegistry
, LPCTSTR lpCheckMessage
, BOOL
*bChecked
)
170 //check the registry if we have to show the box or just return with the last used return value
171 //this would be the case if the user pressed "do not show again".
175 #ifdef XMESSAGEBOX_APPREGPATH
176 path
= XMESSAGEBOX_APPREGPATH
;
178 path
= "Software\\TortoiseGit\\";
179 path
+= AfxGetApp()->m_pszProfileName
;
181 if (lpRegistry
&& *lpRegistry
&& RegOpenKeyEx(HKEY_CURRENT_USER
, path
, 0, KEY_EXECUTE
, &hKey
)==ERROR_SUCCESS
)
183 int size
= sizeof(dwRetVal
);
185 if (RegQueryValueEx(hKey
, lpRegistry
, NULL
, &type
, (BYTE
*) &dwRetVal
,(LPDWORD
) &size
)==ERROR_SUCCESS
)
187 ASSERT(type
==REG_DWORD
);
189 return (UINT
)dwRetVal
; //return with the last saved value
198 box
.m_bShowCheck
= TRUE
;
199 box
.m_sRegistryValue
= lpRegistry
;
200 if (lpCheckMessage
== NULL
)
202 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
203 box
.m_sCheckbox
= _T("do not show again");
206 m_i18l
.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN
);
207 box
.m_sCheckbox
= m_i18l
;
211 box
.m_sCheckbox
= lpCheckMessage
;
212 box
.m_bChecked
= bChecked
? *bChecked
: FALSE
;
215 int result
= box
.GoModal(CWnd::FromHandle(hWnd
), lpCaption
, lpMessage
, box
.FillBoxStandard(uType
));
217 *bChecked
= box
.m_bChecked
;
221 UINT
CMessageBox::Show(HWND hWnd
, UINT nMessage
, UINT nCaption
, UINT uType
, LPCTSTR sHelpPath
)
225 sMessage
.LoadString(nMessage
);
226 sCaption
.LoadString(nCaption
);
227 return CMessageBox::Show(hWnd
, sMessage
, sCaption
, uType
, sHelpPath
);
230 UINT
CMessageBox::Show(HWND hWnd
, LPCTSTR lpMessage
, LPCTSTR lpCaption
, UINT uType
, LPCTSTR sHelpPath
)
237 box
.SetHelpPath(sHelpPath
);
238 return box
.GoModal(CWnd::FromHandle(hWnd
), lpCaption
, lpMessage
, box
.FillBoxStandard(uType
));
241 UINT
CMessageBox::Show(HWND hWnd
, UINT nMessage
, UINT nCaption
, UINT uType
, UINT nHelpID
)
246 sMessage
.LoadString(nMessage
);
247 sCaption
.LoadString(nCaption
);
251 box
.SetHelpID(nHelpID
);
253 return box
.GoModal(CWnd::FromHandle(hWnd
), sCaption
, sMessage
, box
.FillBoxStandard(uType
));
256 bool CMessageBox::RemoveRegistryKey(LPCTSTR lpRegistry
)
260 #ifdef XMESSAGEBOX_APPREGPATH
261 path
= XMESSAGEBOX_APPREGPATH
;
263 path
= "Software\\TortoiseGit\\";
264 path
+= AfxGetApp()->m_pszProfileName
;
266 if (RegOpenKeyEx(HKEY_CURRENT_USER
, path
, 0, KEY_WRITE
, &hKey
) == ERROR_SUCCESS
)
268 bool ret
= !!RegDeleteValue(hKey
, lpRegistry
);
275 int CMessageBox::FillBoxStandard(UINT uType
)
279 m_uCancelRet
= IDCANCEL
;
280 //load the icons according to uType
281 switch (uType
& 0xf0)
283 case MB_ICONEXCLAMATION
:
284 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_EXCLAMATION
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
285 ::MessageBeep(MB_ICONEXCLAMATION
);
287 case MB_ICONASTERISK
:
288 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_ASTERISK
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
289 ::MessageBeep(MB_ICONASTERISK
);
291 case MB_ICONQUESTION
:
292 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_QUESTION
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
293 ::MessageBeep(MB_ICONQUESTION
);
296 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_HAND
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
297 ::MessageBeep(MB_ICONHAND
);
300 //set up the button texts
303 case MB_ABORTRETRYIGNORE
:
304 #ifndef IDS_MSGBOX_ABORT
305 m_sButton1
= "Abort";
307 m_i18l
.LoadString(IDS_MSGBOX_ABORT
);
310 m_uButton1Ret
= IDABORT
;
311 #ifndef IDS_MSGBOX_RETRY
312 m_sButton2
= "Retry";
314 m_i18l
.LoadString(IDS_MSGBOX_RETRY
);
317 m_uButton2Ret
= IDRETRY
;
318 #ifndef IDS_MSGBOX_IGNORE
319 m_sButton3
= "Ignore";
321 m_i18l
.LoadString(IDS_MSGBOX_IGNORE
);
324 m_uButton3Ret
= IDIGNORE
;
326 case MB_CANCELTRYCONTINUE
:
327 #ifndef IDS_MSGBOX_CANCEL
328 m_sButton1
= "Cancel";
330 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
333 m_uButton1Ret
= IDCANCEL
;
334 #ifndef IDS_MSGBOX_TRYAGAIN
335 m_sButton2
= "Try Again";
337 m_i18l
.LoadString(IDS_MSGBOX_TRYAGAIN
);
340 m_uButton2Ret
= IDTRYAGAIN
;
341 #ifndef IDS_MSGBOX_CONTINUE
342 m_sButton3
= "Continue";
344 m_i18l
.LoadString(IDS_MSGBOX_CONTINUE
);
347 m_uButton3Ret
= IDCONTINUE
;
350 #ifndef IDS_MSGBOX_OK
353 m_i18l
.LoadString(IDS_MSGBOX_OK
);
356 m_uButton1Ret
= IDOK
;
357 #ifndef IDS_MSGBOX_CANCEL
358 m_sButton2
= "Cancel";
360 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
363 m_uButton2Ret
= IDCANCEL
;
366 #ifndef IDS_MSGBOX_RETRY
367 m_sButton1
= "Retry";
369 m_i18l
.LoadString(IDS_MSGBOX_RETRY
);
372 m_uButton1Ret
= IDRETRY
;
373 #ifndef IDS_MSGBOX_CANCEL
374 m_sButton2
= "Cancel";
376 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
379 m_uButton2Ret
= IDCANCEL
;
382 #ifndef IDS_MSGBOX_YES
385 m_i18l
.LoadString(IDS_MSGBOX_YES
);
388 m_uButton1Ret
= IDYES
;
389 #ifndef IDS_MSGBOX_NO
392 m_i18l
.LoadString(IDS_MSGBOX_NO
);
395 m_uButton2Ret
= IDNO
;
398 #ifndef IDS_MSGBOX_YES
401 m_i18l
.LoadString(IDS_MSGBOX_YES
);
404 m_uButton1Ret
= IDYES
;
405 #ifndef IDS_MSGBOX_NO
408 m_i18l
.LoadString(IDS_MSGBOX_NO
);
411 m_uButton2Ret
= IDNO
;
412 #ifndef IDS_MSGBOX_CANCEL
413 m_sButton3
= "Cancel";
415 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
418 m_uButton3Ret
= IDCANCEL
;
422 #ifndef IDS_MSGBOX_OK
425 m_i18l
.LoadString(IDS_MSGBOX_OK
);
429 //now set the default button
430 switch (uType
& 0xf00)
439 // do we need to add a help button?
443 #ifndef IDS_MSGBOX_HELP
444 sHelpText
= _T("Help");
446 m_i18l
.LoadString(IDS_MSGBOX_HELP
);
449 if (m_sButton2
.IsEmpty())
451 m_sButton2
= sHelpText
;
452 m_uButton2Ret
= IDHELP
;
454 else if (m_sButton3
.IsEmpty())
456 m_sButton3
= sHelpText
;
457 m_uButton3Ret
= IDHELP
;
463 UINT
CMessageBox::GoModal(CWnd
* pWnd
, const CString
& title
, const CString
& msg
, int nDefaultButton
)
465 // pre Vista struct, needed for Windows XP
466 struct OLD_NONCLIENTMETRICS
474 LOGFONT lfCaptionFont
;
476 int iSmCaptionHeight
;
477 LOGFONT lfSmCaptionFont
;
481 LOGFONT lfStatusFont
;
482 LOGFONT lfMessageFont
;
484 const UINT cbProperSize
= sizeof(OLD_NONCLIENTMETRICS
);
486 NONCLIENTMETRICS ncm
;
487 memset(&ncm
,0,sizeof(NONCLIENTMETRICS
));
488 ncm
.cbSize
= cbProperSize
;
489 SystemParametersInfo(SPI_GETNONCLIENTMETRICS
, sizeof(NONCLIENTMETRICS
), &ncm
, 0);
491 memcpy(&m_LogFont
, &(ncm
.lfMessageFont
), sizeof(LOGFONT
));
493 //the problem with the LOGFONT lfHeight is that it is not in pixels,
494 //but the dialog template needs the height in pixels.
495 //We need to convert those values first:
500 pDC
= GetDesktopWindow()->GetDC();
508 HWND hw
= pWnd
? pWnd
->m_hWnd
: nullptr;
509 int defButton
= nDefaultButton
== 1 ? MB_DEFBUTTON1
: nDefaultButton
== 2 ? MB_DEFBUTTON2
: nDefaultButton
== 3 ? MB_DEFBUTTON3
: 0;
510 return ::MessageBox(hw
, msg
, title
, m_uType
| defButton
);
513 int pix
= -MulDiv(m_LogFont
.lfHeight
, 72, GetDeviceCaps(hdc
, LOGPIXELSY
));
514 CDlgTemplate dialogTemplate
= CDlgTemplate(title
, WS_CAPTION
| DS_CENTER
,
515 0, 0, 0, 0, m_LogFont
.lfFaceName
, pix
);
516 dialogTemplate
.AddButton(_T("Button1"), WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
| ((nDefaultButton
== 1) ? BS_DEFPUSHBUTTON
: 0), 0,
517 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON1
);
518 dialogTemplate
.AddButton(_T("Button2"), WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
| ((nDefaultButton
== 2) ? BS_DEFPUSHBUTTON
: 0), 0,
519 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON2
);
520 dialogTemplate
.AddButton(_T("Button3"), WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
| ((nDefaultButton
== 3) ? BS_DEFPUSHBUTTON
: 0), 0,
521 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON3
);
522 dialogTemplate
.AddButton(_T("Checkbox"), WS_CHILD
| WS_TABSTOP
| BS_AUTOCHECKBOX
, 0,
523 0, 0, 0, 0, IDC_MESSAGEBOX_CHECKBOX
);
525 m_nDefButton
= nDefaultButton
;
527 InitModalIndirect(dialogTemplate
, pWnd
);
529 return (UINT
)DoModal();
532 void CMessageBox::SetRegistryValue(const CString
& sValue
, DWORD value
)
534 if (sValue
.IsEmpty())
538 #ifdef XMESSAGEBOX_APPREGPATH
539 path
= XMESSAGEBOX_APPREGPATH
;
541 path
= "Software\\TortoiseGit\\";
542 path
+= AfxGetApp()->m_pszProfileName
;
546 if (RegCreateKeyEx(HKEY_CURRENT_USER
, path
, 0, _T(""), REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, &disp
)!=ERROR_SUCCESS
)
550 RegSetValueEx(hKey
, sValue
, 0, REG_DWORD
,(const BYTE
*) &value
, sizeof(value
));
554 CSize
CMessageBox::GetTextSize(const CString
& str
)
557 GetWindowRect(&rect
);
563 memDC
.CreateCompatibleDC(pDC
);
564 bitmap
.CreateCompatibleBitmap(pDC
, rect
.Width(), rect
.Height());
565 CBitmap
* pOldBitmap
= memDC
.SelectObject(&bitmap
);
567 //get the minimum size of the rectangle of the tooltip
568 CSize sz
= DrawHTML(&memDC
, rect
, str
, m_LogFont
, TRUE
);
570 memDC
.SelectObject(pOldBitmap
);
572 bitmap
.DeleteObject();
579 CSize
CMessageBox::GetIconSize(HICON hIcon
)
586 //get icon dimensions
587 ::SecureZeroMemory(&ii
, sizeof(ICONINFO
));
588 if (::GetIconInfo(hIcon
, &ii
))
590 sz
.cx
= (DWORD
)(ii
.xHotspot
* 2);
591 sz
.cy
= (DWORD
)(ii
.yHotspot
* 2);
592 //release icon mask bitmaps
594 ::DeleteObject(ii
.hbmMask
);
596 ::DeleteObject(ii
.hbmColor
);
603 CSize
CMessageBox::GetButtonSize()
606 int nButtons
= 0; //number of buttons - 1
608 SetDlgItemText(IDC_MESSAGEBOX_BUTTON1
, m_sButton1
);
609 SetDlgItemText(IDC_MESSAGEBOX_BUTTON2
, m_sButton2
);
610 //GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, 1);
611 SetDlgItemText(IDC_MESSAGEBOX_BUTTON3
, m_sButton3
);
612 SetDlgItemText(IDC_MESSAGEBOX_CHECKBOX
, m_sCheckbox
);
614 CSize sz1
= GetTextSize(m_sButton1
);
615 CSize sz2
= GetTextSize(m_sButton2
);
616 CSize sz3
= GetTextSize(m_sButton3
);
618 sz1
.cx
+= 2*MESSAGEBOX_BUTTONX
;
619 sz1
.cy
+= 2*MESSAGEBOX_BUTTONY
;
623 sz2
.cx
+= 2*MESSAGEBOX_BUTTONX
;
624 sz2
.cy
+= 2*MESSAGEBOX_BUTTONY
;
629 sz3
.cx
+= 2*MESSAGEBOX_BUTTONX
;
630 sz3
.cy
+= 2*MESSAGEBOX_BUTTONY
;
634 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->MoveWindow(0, 0, sz1
.cx
, sz1
.cy
);
635 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->MoveWindow(0, 0, sz2
.cx
, sz2
.cy
);
636 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->MoveWindow(0, 0, sz3
.cx
, sz3
.cy
);
639 sz
.cx
= sz1
.cx
+ sz2
.cx
+ sz3
.cx
+ (nButtons
* MESSAGEBOX_BUTTONMARGIN
);
640 sz
.cy
= max(sz1
.cy
, sz2
.cy
);
641 sz
.cy
= max(sz
.cy
, sz3
.cy
);
645 CSize szCheck
= GetTextSize(m_sCheckbox
);
646 szCheck
.cx
+= 2*GetSystemMetrics(SM_CXMENUCHECK
);
647 szCheck
.cy
+= 2*MESSAGEBOX_BUTTONY
;
648 sz
.cx
= max(sz
.cx
, szCheck
.cx
);
649 sz
.cy
+= szCheck
.cy
+ MESSAGEBOX_BUTTONCHECKMARGIN
;
650 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->MoveWindow(0, 0, szCheck
.cx
, szCheck
.cy
);
656 BEGIN_MESSAGE_MAP(CMessageBox
, CDialog
)
660 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1
, OnButton1
)
661 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2
, OnButton2
)
662 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3
, OnButton3
)
665 void CMessageBox::OnPaint()
667 CPaintDC
dc(this); // device context for painting
672 GetClientRect(&rect
);
673 GetClientRect(&drawrect
);
675 //create a memory device-context. This is done to help reduce
676 //screen flicker, since we will paint the entire control to the
677 //off screen device context first.
680 memDC
.CreateCompatibleDC(&dc
);
681 bitmap
.CreateCompatibleBitmap(&dc
, rect
.Width(), rect
.Height());
682 CBitmap
* pOldBitmap
= memDC
.SelectObject(&bitmap
);
684 memDC
.BitBlt(rect
.left
, rect
.top
, rect
.Width(), rect
.Height(), &dc
, 0,0, SRCCOPY
);
686 memDC
.SetBkMode(TRANSPARENT
);
687 memDC
.SetBkColor(GetSysColor(COLOR_WINDOW
));
688 memDC
.SetTextColor(GetSysColor(COLOR_WINDOWTEXT
));
690 //OnDrawBackground();
691 drawrect
.DeflateRect(MESSAGEBOX_BORDERMARGINX
, MESSAGEBOX_BORDERMARGINY
);
694 DrawIconEx(memDC
.m_hDC
, drawrect
.left
, drawrect
.top
+
695 ((drawrect
.Height() - m_szAllButtons
.cy
- MESSAGEBOX_TEXTBUTTONMARGIN
- m_szIcon
.cy
) / 2),
696 m_hIcon
, m_szIcon
.cx
, m_szIcon
.cy
, 0, NULL
, DI_NORMAL
);
698 drawrect
.left
+= m_szIcon
.cx
+ MESSAGEBOX_ICONMARGIN
;
702 DrawHTML(&memDC
, drawrect
, m_sMessage
, m_LogFont
);
705 //Copy the memory device context back into the original DC.
706 dc
.BitBlt(rect
.left
, rect
.top
, rect
.Width(), rect
.Height(), &memDC
, 0,0, SRCCOPY
);
709 memDC
.SelectObject(pOldBitmap
);
711 bitmap
.DeleteObject();
716 void CMessageBox::OnMouseMove(UINT nFlags
, CPoint point
)
718 if (IsPointOverALink(point
))
720 m_Cursor
.SetCursor(IDC_HAND
);
727 __super::OnMouseMove(nFlags
, point
);
730 void CMessageBox::OnLButtonUp(UINT nFlags
, CPoint point
)
732 if (IsPointOverALink(point
))
734 CString url
= GetLinkForPoint(point
);
735 ShellExecute(NULL
, _T("open"), url
, NULL
,NULL
, 0);
738 __super::OnLButtonUp(nFlags
, point
);
741 void CMessageBox::OnButton1()
743 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->SendMessage(BM_GETCHECK
, 0, 0)==BST_CHECKED
)
746 SetRegistryValue(m_sRegistryValue
, m_uButton1Ret
);
752 EndDialog(m_uButton1Ret
);
755 void CMessageBox::OnButton2()
757 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->SendMessage(BM_GETCHECK
, 0, 0)==BST_CHECKED
)
760 SetRegistryValue(m_sRegistryValue
, m_uButton2Ret
);
766 if ((m_uButton2Ret
== IDHELP
)&&(!m_sHelpPath
.IsEmpty()))
768 typedef HWND (WINAPI
* FPHH
)(HWND
, LPCWSTR
, UINT
, DWORD
);
769 FPHH pHtmlHelp
=NULL
; // Function pointer
770 CAutoLibrary hInstHtmlHelp
= AtlLoadSystemLibraryUsingFullPath(_T("HHCtrl.ocx"));
772 if (hInstHtmlHelp
!= NULL
)
774 (FARPROC
&)pHtmlHelp
= GetProcAddress(hInstHtmlHelp
, "HtmlHelpW");
776 hHelp
= pHtmlHelp(m_hWnd
, (LPCTSTR
)m_sHelpPath
, HH_DISPLAY_TOPIC
, NULL
);
779 ::MessageBox(m_hWnd
, _T("could not show help file"), _T("Help"), MB_ICONERROR
);
781 else if (m_uButton2Ret
== IDHELP
)
786 EndDialog(m_uButton2Ret
);
789 void CMessageBox::OnButton3()
791 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->SendMessage(BM_GETCHECK
, 0, 0)==BST_CHECKED
)
794 SetRegistryValue(m_sRegistryValue
, m_uButton3Ret
);
800 if ((m_uButton3Ret
== IDHELP
)&&(!m_sHelpPath
.IsEmpty()))
802 typedef HWND (WINAPI
* FPHH
)(HWND
, LPCWSTR
, UINT
, DWORD
);
803 FPHH pHtmlHelp
=NULL
; // Function pointer
804 CAutoLibrary hInstHtmlHelp
= AtlLoadSystemLibraryUsingFullPath(_T("HHCtrl.ocx"));
806 if (hInstHtmlHelp
!= NULL
)
808 (FARPROC
&)pHtmlHelp
= GetProcAddress(hInstHtmlHelp
, "HtmlHelpW");
810 hHelp
= pHtmlHelp(m_hWnd
, (LPCTSTR
)m_sHelpPath
, HH_DISPLAY_TOPIC
, NULL
);
813 ::MessageBox(m_hWnd
, _T("could not show help file"), _T("Help"), MB_ICONERROR
);
815 else if (m_uButton3Ret
== IDHELP
)
820 EndDialog(m_uButton3Ret
);
823 void CMessageBox::OnCancel()
825 if (m_uCancelRet
== IDCANCEL
)
826 EndDialog(m_uCancelRet
);
827 //__super::OnCancel();
830 BOOL
CMessageBox::OnInitDialog()
832 __super::OnInitDialog();
834 CRect
rect(0, 0, 0, 0);
836 //determine the required size of the message box
837 CSize szText
= GetTextSize(m_sMessage
);
838 CSize szIcon
= GetIconSize(m_hIcon
);
839 CSize szButtons
= GetButtonSize();
842 szIconText
.cx
= szText
.cx
+ szIcon
.cx
+ ((szIcon
.cx
== 0) ? MESSAGEBOX_ICONMARGIN
: (2*MESSAGEBOX_ICONMARGIN
));
843 szIconText
.cy
= max(szIcon
.cy
, szText
.cy
);
845 rect
.right
= max(szButtons
.cx
, szIconText
.cx
);
846 rect
.right
+= 2*GetSystemMetrics(SM_CXBORDER
);
847 rect
.right
+= 2*MESSAGEBOX_BORDERMARGINX
;
848 rect
.bottom
= szIconText
.cy
;
849 rect
.bottom
+= szButtons
.cy
;
850 rect
.bottom
+= 2*MESSAGEBOX_BORDERMARGINY
+ MESSAGEBOX_TEXTBUTTONMARGIN
;
851 rect
.bottom
+= GetSystemMetrics(SM_CYCAPTION
);
852 rect
.bottom
+= 2*GetSystemMetrics(SM_CYBORDER
);
859 //now size and position the buttons as we need them
860 ASSERT(!m_sButton1
.IsEmpty()); //at least the first button must be there!
861 if (m_sButton2
.IsEmpty())
865 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(rt
);
867 rt
.MoveToX(rect
.left
+ ((rect
.Width() - m_szButtons
.cx
)/2));
868 rt
.MoveToY(rect
.bottom
- MESSAGEBOX_BORDERMARGINY
- m_szButtons
.cy
);
869 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->MoveWindow(rt
);
870 //hide the other two buttons
871 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->ShowWindow(SW_HIDE
);
872 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->ShowWindow(SW_HIDE
);
874 else if (m_sButton3
.IsEmpty())
879 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(rt1
);
881 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->GetWindowRect(rt2
);
883 rt1
.MoveToX(rect
.left
+ ((rect
.Width() - m_szButtons
.cx
)/2));
884 rt1
.MoveToY(rect
.bottom
- MESSAGEBOX_BORDERMARGINY
- m_szButtons
.cy
);
885 rt2
.MoveToX(rt1
.right
+ MESSAGEBOX_BUTTONMARGIN
);
886 rt2
.MoveToY(rect
.bottom
- MESSAGEBOX_BORDERMARGINY
- m_szButtons
.cy
);
887 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->MoveWindow(rt1
);
888 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->MoveWindow(rt2
);
889 //hide the third button
890 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->ShowWindow(SW_HIDE
);
896 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(buttonrect
);
900 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(rt1
);
902 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->GetWindowRect(rt2
);
904 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->GetWindowRect(rt3
);
906 rt1
.MoveToX(rect
.left
+ ((rect
.Width() - m_szButtons
.cx
)/2));
907 rt1
.MoveToY(rect
.bottom
- MESSAGEBOX_BORDERMARGINY
- m_szButtons
.cy
);
908 rt2
.MoveToX(rt1
.right
+ MESSAGEBOX_BUTTONMARGIN
);
909 rt2
.MoveToY(rect
.bottom
- MESSAGEBOX_BORDERMARGINY
- m_szButtons
.cy
);
910 rt3
.MoveToX(rt2
.right
+ MESSAGEBOX_BUTTONMARGIN
);
911 rt3
.MoveToY(rect
.bottom
- MESSAGEBOX_BORDERMARGINY
- m_szButtons
.cy
);
912 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->MoveWindow(rt1
);
913 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->MoveWindow(rt2
);
914 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->MoveWindow(rt3
);
919 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->GetWindowRect(rt
);
921 rt
.MoveToX(rect
.left
+ MESSAGEBOX_BORDERMARGINX
/*+ ((rect.Width() - szButtons.cx)/2)*/);
922 rt
.MoveToY(rect
.bottom
- MESSAGEBOX_BORDERMARGINY
- szButtons
.cy
);
923 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->MoveWindow(rt
);
924 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->ShowWindow(SW_SHOW
);
927 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->ShowWindow(SW_HIDE
);
929 SetWindowPos(&CWnd::wndTopMost
,0,0,0,0,SWP_NOMOVE
|SWP_NOSIZE
);
930 SetForegroundWindow();
931 SetFocus(); //Just playing safe
933 if (m_nDefButton
== 1)
934 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->SetFocus();
935 if (m_nDefButton
== 2)
936 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->SetFocus();
937 if (m_nDefButton
== 3)
938 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->SetFocus();
940 return FALSE
; // return TRUE unless you set the focus to a control
941 // EXCEPTION: OCX Property Pages should return FALSE
944 BOOL
CMessageBox::PreTranslateMessage(MSG
* pMsg
)
946 if (pMsg
->message
== WM_KEYDOWN
)
948 switch (pMsg
->wParam
)
953 if (GetAsyncKeyState(VK_CONTROL
)&0x8000)
955 CClipboardHelper clipboardHelper
;
956 if(clipboardHelper
.Open(GetSafeHwnd()))
959 CStringA sClipboard
= CStringA(m_sMessage
);
960 HGLOBAL hClipboardData
= CClipboardHelper::GlobalAlloc(sClipboard
.GetLength()+1);
961 char * pchData
= (char*)GlobalLock(hClipboardData
);
963 strcpy_s(pchData
, sClipboard
.GetLength()+1, (LPCSTR
)sClipboard
);
964 GlobalUnlock(hClipboardData
);
965 SetClipboardData(CF_TEXT
,hClipboardData
);
973 switch (m_uType
& 0xf)
975 case MB_ABORTRETRYIGNORE
:
976 EndDialog(m_uButton1Ret
);
978 case MB_CANCELTRYCONTINUE
:
979 EndDialog(m_uButton1Ret
);
982 EndDialog(m_uButton2Ret
);
985 EndDialog(m_uButton2Ret
);
988 EndDialog(m_uButton2Ret
);
991 EndDialog(m_uButton3Ret
);
999 return __super::PreTranslateMessage(pMsg
);