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.
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 int CMessageBox::FillBoxStandard(UINT 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
);
258 case MB_ICONASTERISK
:
259 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_ASTERISK
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
260 ::MessageBeep(MB_ICONASTERISK
);
262 case MB_ICONQUESTION
:
263 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_QUESTION
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
264 ::MessageBeep(MB_ICONQUESTION
);
267 m_hIcon
= (HICON
)::LoadImage(NULL
, IDI_HAND
, IMAGE_ICON
, 0, 0, LR_SHARED
| LR_DEFAULTSIZE
);
268 ::MessageBeep(MB_ICONHAND
);
271 //set up the button texts
274 case MB_ABORTRETRYIGNORE
:
275 #ifndef IDS_MSGBOX_ABORT
276 m_sButton1
= "Abort";
278 m_i18l
.LoadString(IDS_MSGBOX_ABORT
);
281 m_uButton1Ret
= IDABORT
;
282 #ifndef IDS_MSGBOX_RETRY
283 m_sButton2
= "Retry";
285 m_i18l
.LoadString(IDS_MSGBOX_RETRY
);
288 m_uButton2Ret
= IDRETRY
;
289 #ifndef IDS_MSGBOX_IGNORE
290 m_sButton3
= "Ignore";
292 m_i18l
.LoadString(IDS_MSGBOX_IGNORE
);
295 m_uButton3Ret
= IDIGNORE
;
297 case MB_CANCELTRYCONTINUE
:
298 #ifndef IDS_MSGBOX_CANCEL
299 m_sButton1
= "Cancel";
301 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
304 m_uButton1Ret
= IDCANCEL
;
305 #ifndef IDS_MSGBOX_TRYAGAIN
306 m_sButton2
= "Try Again";
308 m_i18l
.LoadString(IDS_MSGBOX_TRYAGAIN
);
311 m_uButton2Ret
= IDTRYAGAIN
;
312 #ifndef IDS_MSGBOX_CONTINUE
313 m_sButton3
= "Continue";
315 m_i18l
.LoadString(IDS_MSGBOX_CONTINUE
);
318 m_uButton3Ret
= IDCONTINUE
;
321 #ifndef IDS_MSGBOX_OK
324 m_i18l
.LoadString(IDS_MSGBOX_OK
);
327 m_uButton1Ret
= IDOK
;
328 #ifndef IDS_MSGBOX_CANCEL
329 m_sButton2
= "Cancel";
331 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
334 m_uButton2Ret
= IDCANCEL
;
337 #ifndef IDS_MSGBOX_RETRY
338 m_sButton1
= "Retry";
340 m_i18l
.LoadString(IDS_MSGBOX_RETRY
);
343 m_uButton1Ret
= IDRETRY
;
344 #ifndef IDS_MSGBOX_CANCEL
345 m_sButton2
= "Cancel";
347 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
350 m_uButton2Ret
= IDCANCEL
;
353 #ifndef IDS_MSGBOX_YES
356 m_i18l
.LoadString(IDS_MSGBOX_YES
);
359 m_uButton1Ret
= IDYES
;
360 #ifndef IDS_MSGBOX_NO
363 m_i18l
.LoadString(IDS_MSGBOX_NO
);
366 m_uButton2Ret
= IDNO
;
369 #ifndef IDS_MSGBOX_YES
372 m_i18l
.LoadString(IDS_MSGBOX_YES
);
375 m_uButton1Ret
= IDYES
;
376 #ifndef IDS_MSGBOX_NO
379 m_i18l
.LoadString(IDS_MSGBOX_NO
);
382 m_uButton2Ret
= IDNO
;
383 #ifndef IDS_MSGBOX_CANCEL
384 m_sButton3
= "Cancel";
386 m_i18l
.LoadString(IDS_MSGBOX_CANCEL
);
389 m_uButton3Ret
= IDCANCEL
;
393 #ifndef IDS_MSGBOX_OK
396 m_i18l
.LoadString(IDS_MSGBOX_OK
);
400 //now set the default button
401 switch (uType
& 0xf00)
410 // do we need to add a help button?
414 #ifndef IDS_MSGBOX_HELP
415 sHelpText
= _T("Help");
417 m_i18l
.LoadString(IDS_MSGBOX_HELP
);
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
;
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
445 LOGFONT lfCaptionFont
;
447 int iSmCaptionHeight
;
448 LOGFONT lfSmCaptionFont
;
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:
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
;
486 InitModalIndirect(dialogTemplate
, pWnd
);
488 return (UINT
)DoModal();
491 void CMessageBox::SetRegistryValue(const CString
& sValue
, DWORD value
)
494 #ifdef XMESSAGEBOX_APPREGPATH
495 path
= XMESSAGEBOX_APPREGPATH
;
497 path
= "Software\\TortoiseGit\\";
498 path
+= AfxGetAppName();
502 if (RegCreateKeyEx(HKEY_CURRENT_USER
, path
, 0, _T(""), REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &hKey
, &disp
)!=ERROR_SUCCESS
)
506 RegSetValueEx(hKey
, sValue
, 0, REG_DWORD
,(const BYTE
*) &value
, sizeof(value
));
510 CSize
CMessageBox::GetTextSize(const CString
& str
)
513 GetWindowRect(&rect
);
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
);
528 bitmap
.DeleteObject();
535 CSize
CMessageBox::GetIconSize(HICON hIcon
)
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
550 ::DeleteObject(ii
.hbmMask
);
552 ::DeleteObject(ii
.hbmColor
);
559 CSize
CMessageBox::GetButtonSize()
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
;
579 sz2
.cx
+= 2*MESSAGEBOX_BUTTONX
;
580 sz2
.cy
+= 2*MESSAGEBOX_BUTTONY
;
585 sz3
.cx
+= 2*MESSAGEBOX_BUTTONX
;
586 sz3
.cy
+= 2*MESSAGEBOX_BUTTONY
;
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
);
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
);
612 BEGIN_MESSAGE_MAP(CMessageBox
, CDialog
)
616 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1
, OnButton1
)
617 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2
, OnButton2
)
618 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3
, OnButton3
)
621 void CMessageBox::OnPaint()
623 CPaintDC
dc(this); // device context for painting
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.
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
);
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
);
665 memDC
.SelectObject(pOldBitmap
);
667 bitmap
.DeleteObject();
672 void CMessageBox::OnMouseMove(UINT nFlags
, CPoint point
)
674 if (IsPointOverALink(point
))
676 m_Cursor
.SetCursor(IDC_HAND
);
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"));
714 if (hInstHtmlHelp
!= NULL
)
716 (FARPROC
&)pHtmlHelp
= GetProcAddress(hInstHtmlHelp
, "HtmlHelpW");
718 hHelp
= pHtmlHelp(m_hWnd
, (LPCTSTR
)m_sHelpPath
, HH_DISPLAY_TOPIC
, NULL
);
721 ::MessageBox(m_hWnd
, _T("could not show help file"), _T("Help"), MB_ICONERROR
);
723 else if (m_uButton2Ret
== IDHELP
)
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"));
741 if (hInstHtmlHelp
!= NULL
)
743 (FARPROC
&)pHtmlHelp
= GetProcAddress(hInstHtmlHelp
, "HtmlHelpW");
745 hHelp
= pHtmlHelp(m_hWnd
, (LPCTSTR
)m_sHelpPath
, HH_DISPLAY_TOPIC
, NULL
);
748 ::MessageBox(m_hWnd
, _T("could not show help file"), _T("Help"), MB_ICONERROR
);
750 else if (m_uButton3Ret
== IDHELP
)
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();
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
);
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())
800 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(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())
814 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(rt1
);
816 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->GetWindowRect(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
);
831 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(buttonrect
);
835 GetDlgItem(IDC_MESSAGEBOX_BUTTON1
)->GetWindowRect(rt1
);
837 GetDlgItem(IDC_MESSAGEBOX_BUTTON2
)->GetWindowRect(rt2
);
839 GetDlgItem(IDC_MESSAGEBOX_BUTTON3
)->GetWindowRect(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
);
854 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX
)->GetWindowRect(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
);
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
)
888 if (GetAsyncKeyState(VK_CONTROL
)&0x8000)
890 CClipboardHelper clipboardHelper
;
891 if(clipboardHelper
.Open(GetSafeHwnd()))
894 CStringA sClipboard
= CStringA(m_sMessage
);
895 HGLOBAL hClipboardData
= CClipboardHelper::GlobalAlloc(sClipboard
.GetLength()+1);
896 char * pchData
= (char*)GlobalLock(hClipboardData
);
898 strcpy_s(pchData
, sClipboard
.GetLength()+1, (LPCSTR
)sClipboard
);
899 GlobalUnlock(hClipboardData
);
900 SetClipboardData(CF_TEXT
,hClipboardData
);
908 switch (m_uType
& 0xf)
910 case MB_ABORTRETRYIGNORE
:
911 EndDialog(m_uButton1Ret
);
913 case MB_CANCELTRYCONTINUE
:
914 EndDialog(m_uButton1Ret
);
917 EndDialog(m_uButton2Ret
);
920 EndDialog(m_uButton2Ret
);
923 EndDialog(m_uButton2Ret
);
926 EndDialog(m_uButton3Ret
);
934 return __super::PreTranslateMessage(pMsg
);