Integrate the DPIAware.h changes from TortoiseSVN
[TortoiseGit.git] / src / Utils / MiscUI / MessageBox.cpp
blob41f5d906c0c65f961f16f7e5500153f4c6ca2146
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2016, 2018 - 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 "ClipboardHelper.h"
24 #include "SmartHandle.h"
25 #include <afxtaskdialog.h>
26 #include "DPIAware.h"
28 #define BTN_OFFSET 100 // use an offset in order to not interfere with IDYES and so on...
30 CMessageBox::CMessageBox(void)
31 : m_hIcon(nullptr)
32 , m_uButton1Ret(1)
33 , m_uButton2Ret(2)
34 , m_uButton3Ret(3)
35 , m_uCancelRet(0)
36 , m_bShowCheck(FALSE)
37 , m_bDestroyIcon(FALSE)
38 , m_nDefButton(0)
39 , m_uType(0)
40 , m_bChecked(FALSE)
42 SecureZeroMemory(&m_LogFont, sizeof(LOGFONT));
45 CMessageBox::~CMessageBox(void)
47 if (m_bDestroyIcon)
48 ::DestroyIcon(m_hIcon);
51 static HWND GetMainHWND(HWND hWnd)
53 if (!hWnd || !IsWindow(hWnd))
54 return CWnd::GetSafeOwner_(nullptr, nullptr);
55 return hWnd;
58 UINT CMessageBox::ShowCheck(HWND hWnd, UINT nMessage, UINT nCaption, int nDef, LPCTSTR icon, UINT nButton1, UINT nButton2, UINT nButton3, LPCTSTR lpRegistry, UINT nCheckMessage/* = nullptr*/, BOOL* bChecked)
60 CString sButton1;
61 CString sButton2;
62 CString sButton3;
63 CString sMessage;
64 CString sCaption;
65 CString nCheckMsg;
66 sButton1.LoadString(nButton1);
67 sButton2.LoadString(nButton2);
68 sButton3.LoadString(nButton3);
69 sMessage.LoadString(nMessage);
70 sCaption.LoadString(nCaption);
71 nCheckMsg.LoadString(nCheckMessage);
72 return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3, lpRegistry, nCheckMsg, bChecked);
75 UINT CMessageBox::ShowCheck(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, int nDef, LPCTSTR icon, LPCTSTR lpButton1, LPCTSTR lpButton2, LPCTSTR lpButton3, LPCTSTR lpRegistry, LPCTSTR lpCheckMessage/* = nullptr*/, BOOL* bChecked)
77 //check the registry if we have to show the box or just return with the last used return value
78 //this would be the case if the user pressed "do not show again".
79 DWORD dwRetVal;
80 HKEY hKey;
81 CString path;
82 #ifdef XMESSAGEBOX_APPREGPATH
83 path = XMESSAGEBOX_APPREGPATH;
84 #else
85 path = "Software\\TortoiseGit\\";
86 path += AfxGetApp()->m_pszProfileName;
87 #endif
88 if (lpRegistry && *lpRegistry && RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)
90 int size = sizeof(dwRetVal);
91 DWORD type;
92 if (RegQueryValueEx(hKey, lpRegistry, nullptr, &type, (BYTE*)&dwRetVal,(LPDWORD)&size) == ERROR_SUCCESS)
94 ASSERT(type==REG_DWORD);
95 RegCloseKey(hKey);
96 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Using stored value %ld for \"%s\"\n", dwRetVal, lpMessage);
97 return (UINT)dwRetVal; //return with the last saved value
99 else
101 RegCloseKey(hKey);
105 if (CTaskDialog::IsSupported())
107 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_USE_COMMAND_LINKS | TDF_POSITION_RELATIVE_TO_WINDOW);
108 taskdlg.AddCommandControl(BTN_OFFSET + 1, lpButton1);
109 if (lpButton2 && *lpButton2)
110 taskdlg.AddCommandControl(BTN_OFFSET + 2, lpButton2);
111 if (lpButton3 && *lpButton3)
112 taskdlg.AddCommandControl(BTN_OFFSET + 3, lpButton3);
113 taskdlg.SetDefaultCommandControl(BTN_OFFSET + nDef);
114 taskdlg.SetMainIcon(icon);
115 if (!lpCheckMessage)
117 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
118 taskdlg.SetVerificationCheckboxText(L"do not show again");
119 #else
120 CString m_i18l;
121 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
122 taskdlg.SetVerificationCheckboxText(m_i18l);
123 #endif
125 else
126 taskdlg.SetVerificationCheckboxText(lpCheckMessage);
127 int result = (int)taskdlg.DoModal(GetMainHWND(hWnd)) - BTN_OFFSET;
128 if (bChecked)
129 *bChecked = taskdlg.GetVerificationCheckboxState();
130 if (lpRegistry && *lpRegistry && taskdlg.GetVerificationCheckboxState())
131 SetRegistryValue(lpRegistry, result);
133 return result;
136 CMessageBox box;
137 box.m_bShowCheck = TRUE;
138 box.m_sRegistryValue = lpRegistry;
139 if (!lpCheckMessage)
141 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
142 box.m_sCheckbox = L"do not show again";
143 #else
144 CString m_i18l;
145 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
146 box.m_sCheckbox = m_i18l;
147 #endif
149 else
150 box.m_sCheckbox = lpCheckMessage;
151 box.m_bChecked = bChecked ? *bChecked : FALSE;
152 box.m_sButton1 = lpButton1;
153 box.m_sButton2 = lpButton2;
154 box.m_sButton3 = lpButton3;
155 box.m_hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), icon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
156 if (!box.m_hIcon)
157 box.m_hIcon = (HICON)::LoadImage(nullptr, icon, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
158 else
159 box.m_bDestroyIcon = TRUE;
160 if (!IsWindow(hWnd))
161 hWnd = nullptr;
162 int result = box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef);
163 if (bChecked)
164 *bChecked = box.m_bChecked;
165 return result;
168 UINT CMessageBox::Show(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, int nDef, LPCTSTR icon, LPCTSTR lpButton1, LPCTSTR lpButton2/* = nullptr*/, LPCTSTR lpButton3/* = nullptr*/)
170 if (CTaskDialog::IsSupported())
172 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_USE_COMMAND_LINKS | TDF_POSITION_RELATIVE_TO_WINDOW);
173 taskdlg.AddCommandControl(BTN_OFFSET + 1, lpButton1);
174 if (lpButton2 && *lpButton2)
175 taskdlg.AddCommandControl(BTN_OFFSET + 2, lpButton2);
176 if (lpButton3 && *lpButton3)
177 taskdlg.AddCommandControl(BTN_OFFSET + 3, lpButton3);
178 taskdlg.SetDefaultCommandControl(BTN_OFFSET + nDef);
179 taskdlg.SetMainIcon(icon);
180 return (UINT)taskdlg.DoModal(GetMainHWND(hWnd)) - BTN_OFFSET;
182 CMessageBox box;
183 box.m_sButton1 = lpButton1;
184 box.m_sButton2 = lpButton2;
185 box.m_sButton3 = lpButton3;
186 box.m_hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), icon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
187 if (!box.m_hIcon)
188 box.m_hIcon = (HICON)::LoadImage(nullptr, icon, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
189 else
190 box.m_bDestroyIcon = TRUE;
191 if (!IsWindow(hWnd))
192 hWnd = nullptr;
193 return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef);
196 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, int nDef, LPCTSTR icon, UINT nButton1, UINT nButton2, UINT nButton3)
198 CString sButton1;
199 CString sButton2;
200 CString sButton3;
201 CString sMessage;
202 CString sCaption;
203 sButton1.LoadString(nButton1);
204 sButton2.LoadString(nButton2);
205 sButton3.LoadString(nButton3);
206 sMessage.LoadString(nMessage);
207 sCaption.LoadString(nCaption);
208 return CMessageBox::Show(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3);
211 UINT CMessageBox::ShowCheck(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCTSTR lpRegistry, UINT nCheckMessage, BOOL *bChecked)
213 CString sMessage;
214 CString sCaption;
215 CString sCheckMsg;
216 sMessage.LoadString(nMessage);
217 sCaption.LoadString(nCaption);
218 sCheckMsg.LoadString(nCheckMessage);
219 return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, uType, lpRegistry, sCheckMsg, bChecked);
222 UINT CMessageBox::ShowCheck(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, UINT uType, LPCTSTR lpRegistry, LPCTSTR lpCheckMessage, BOOL *bChecked)
224 //check the registry if we have to show the box or just return with the last used return value
225 //this would be the case if the user pressed "do not show again".
226 DWORD dwRetVal;
227 HKEY hKey;
228 CString path;
229 #ifdef XMESSAGEBOX_APPREGPATH
230 path = XMESSAGEBOX_APPREGPATH;
231 #else
232 path = "Software\\TortoiseGit\\";
233 path += AfxGetApp()->m_pszProfileName;
234 #endif
235 if (lpRegistry && *lpRegistry && RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)
237 int size = sizeof(dwRetVal);
238 DWORD type;
239 if (RegQueryValueEx(hKey, lpRegistry, nullptr, &type, (BYTE*)&dwRetVal,(LPDWORD)&size) == ERROR_SUCCESS)
241 ASSERT(type==REG_DWORD);
242 RegCloseKey(hKey);
243 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Using stored value %ld for \"%s\"\n", dwRetVal, lpMessage);
244 return (UINT)dwRetVal; //return with the last saved value
246 else
248 RegCloseKey(hKey);
251 if (CTaskDialog::IsSupported() && !(uType & MB_HELP) && !((uType & 0xf) == MB_ABORTRETRYIGNORE) && !((uType & 0xf) == MB_CANCELTRYCONTINUE))
253 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_POSITION_RELATIVE_TO_WINDOW);
254 // set up icon
255 switch (uType & 0xf0)
257 case MB_ICONEXCLAMATION:
258 taskdlg.SetMainIcon(IDI_EXCLAMATION);
259 break;
260 case MB_ICONASTERISK:
261 taskdlg.SetMainIcon(IDI_ASTERISK);
262 break;
263 case MB_ICONQUESTION:
264 taskdlg.SetMainIcon(IDI_QUESTION);
265 break;
266 case MB_ICONHAND:
267 taskdlg.SetMainIcon(IDI_HAND);
268 break;
270 // set up the buttons
271 switch (uType & 0xf)
273 case MB_ABORTRETRYIGNORE:
274 ASSERT(FALSE);
275 break;
276 case MB_CANCELTRYCONTINUE:
277 ASSERT(FALSE);
278 break;
279 case MB_OKCANCEL:
280 taskdlg.SetCommonButtons(TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON);
281 switch (uType & 0xf00)
283 case MB_DEFBUTTON2:
284 taskdlg.SetDefaultCommandControl(IDCANCEL);
285 break;
287 break;
288 case MB_RETRYCANCEL:
289 taskdlg.SetCommonButtons(TDCBF_RETRY_BUTTON | TDCBF_CANCEL_BUTTON);
290 switch (uType & 0xf00)
292 case MB_DEFBUTTON2:
293 taskdlg.SetDefaultCommandControl(IDCANCEL);
294 break;
296 break;
297 case MB_YESNO:
298 taskdlg.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON);
299 switch (uType & 0xf00)
301 case MB_DEFBUTTON2:
302 taskdlg.SetDefaultCommandControl(IDNO);
303 break;
305 break;
306 case MB_YESNOCANCEL:
307 taskdlg.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
308 switch (uType & 0xf00)
310 case MB_DEFBUTTON2:
311 taskdlg.SetDefaultCommandControl(IDNO);
312 break;
313 case MB_DEFBUTTON3:
314 taskdlg.SetDefaultCommandControl(IDCANCEL);
315 break;
317 break;
318 case MB_OK:
319 default:
320 taskdlg.SetCommonButtons(TDCBF_OK_BUTTON);
323 if (!lpCheckMessage)
325 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
326 taskdlg.SetVerificationCheckboxText(L"do not show again");
327 #else
328 CString m_i18l;
329 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
330 taskdlg.SetVerificationCheckboxText(m_i18l);
331 #endif
333 else
334 taskdlg.SetVerificationCheckboxText(lpCheckMessage);
335 int result = (int)taskdlg.DoModal(GetMainHWND(hWnd));
336 if (bChecked)
337 *bChecked = taskdlg.GetVerificationCheckboxState();
338 if (lpRegistry && *lpRegistry && taskdlg.GetVerificationCheckboxState())
339 SetRegistryValue(lpRegistry, result);
341 return result;
344 CMessageBox box;
345 box.m_bShowCheck = TRUE;
346 box.m_sRegistryValue = lpRegistry;
347 if (!lpCheckMessage)
349 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
350 box.m_sCheckbox = L"do not show again";
351 #else
352 CString m_i18l;
353 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
354 box.m_sCheckbox = m_i18l;
355 #endif
357 else
358 box.m_sCheckbox = lpCheckMessage;
359 box.m_bChecked = bChecked ? *bChecked : FALSE;
360 if (!IsWindow(hWnd))
361 hWnd = nullptr;
362 int result = box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));
363 if (bChecked)
364 *bChecked = box.m_bChecked;
365 return result;
368 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCTSTR sHelpPath)
370 CString sMessage;
371 CString sCaption;
372 sMessage.LoadString(nMessage);
373 sCaption.LoadString(nCaption);
374 return CMessageBox::Show(hWnd, sMessage, sCaption, uType, sHelpPath);
377 UINT CMessageBox::Show(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, UINT uType, LPCTSTR sHelpPath)
379 if (!IsWindow(hWnd))
380 hWnd = nullptr;
381 if (sHelpPath)
383 CMessageBox box;
384 box.SetHelpPath(sHelpPath);
385 return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));
388 return ::MessageBox(GetMainHWND(hWnd), lpMessage, lpCaption, uType);
391 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, UINT nHelpID)
393 CString sMessage;
394 CString sCaption;
395 sMessage.LoadString(nMessage);
396 sCaption.LoadString(nCaption);
398 if (!IsWindow(hWnd))
399 hWnd = nullptr;
400 if (nHelpID)
402 CMessageBox box;
403 box.SetHelpID(nHelpID);
404 return box.GoModal(CWnd::FromHandle(hWnd), sCaption, sMessage, box.FillBoxStandard(uType));
407 return ::MessageBox(GetMainHWND(hWnd), sMessage, sCaption, uType);
410 bool CMessageBox::RemoveRegistryKey(LPCTSTR lpRegistry)
412 HKEY hKey;
413 CString path;
414 #ifdef XMESSAGEBOX_APPREGPATH
415 path = XMESSAGEBOX_APPREGPATH;
416 #else
417 path = "Software\\TortoiseGit\\";
418 path += AfxGetApp()->m_pszProfileName;
419 #endif
420 if (RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
422 bool ret = !!RegDeleteValue(hKey, lpRegistry);
423 RegCloseKey(hKey);
424 return ret;
426 return false;
429 int CMessageBox::FillBoxStandard(UINT uType)
431 int ret = 1;
432 m_uType = uType;
433 m_uCancelRet = IDCANCEL;
434 //load the icons according to uType
435 switch (uType & 0xf0)
437 case MB_ICONEXCLAMATION:
438 m_hIcon = (HICON)::LoadImage(nullptr, IDI_EXCLAMATION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
439 ::MessageBeep(MB_ICONEXCLAMATION);
440 break;
441 case MB_ICONASTERISK:
442 m_hIcon = (HICON)::LoadImage(nullptr, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
443 ::MessageBeep(MB_ICONASTERISK);
444 break;
445 case MB_ICONQUESTION:
446 m_hIcon = (HICON)::LoadImage(nullptr, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
447 ::MessageBeep(MB_ICONQUESTION);
448 break;
449 case MB_ICONHAND:
450 m_hIcon = (HICON)::LoadImage(nullptr, IDI_HAND, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
451 ::MessageBeep(MB_ICONHAND);
452 break;
454 //set up the button texts
455 switch (uType & 0xf)
457 case MB_ABORTRETRYIGNORE:
458 #ifndef IDS_MSGBOX_ABORT
459 m_sButton1 = "&Abort";
460 #else
461 m_i18l.LoadString(IDS_MSGBOX_ABORT);
462 m_sButton1 = m_i18l;
463 #endif
464 m_uButton1Ret = IDABORT;
465 #ifndef IDS_MSGBOX_RETRY
466 m_sButton2 = "&Retry";
467 #else
468 m_i18l.LoadString(IDS_MSGBOX_RETRY);
469 m_sButton2 = m_i18l;
470 #endif
471 m_uButton2Ret = IDRETRY;
472 #ifndef IDS_MSGBOX_IGNORE
473 m_sButton3 = "&Ignore";
474 #else
475 m_i18l.LoadString(IDS_MSGBOX_IGNORE);
476 m_sButton3 = m_i18l;
477 #endif
478 m_uButton3Ret = IDIGNORE;
479 break;
480 case MB_CANCELTRYCONTINUE:
481 #ifndef IDS_MSGBOX_CANCEL
482 m_sButton1 = "Cancel";
483 #else
484 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
485 m_sButton1 = m_i18l;
486 #endif
487 m_uButton1Ret = IDCANCEL;
488 #ifndef IDS_MSGBOX_TRYAGAIN
489 m_sButton2 = "&Try Again";
490 #else
491 m_i18l.LoadString(IDS_MSGBOX_TRYAGAIN);
492 m_sButton2 = m_i18l;
493 #endif
494 m_uButton2Ret = IDTRYAGAIN;
495 #ifndef IDS_MSGBOX_CONTINUE
496 m_sButton3 = "&Continue";
497 #else
498 m_i18l.LoadString(IDS_MSGBOX_CONTINUE);
499 m_sButton3 = m_i18l;
500 #endif
501 m_uButton3Ret = IDCONTINUE;
502 break;
503 case MB_OKCANCEL:
504 #ifndef IDS_MSGBOX_OK
505 m_sButton1 = "OK";
506 #else
507 m_i18l.LoadString(IDS_MSGBOX_OK);
508 m_sButton1 = m_i18l;
509 #endif
510 m_uButton1Ret = IDOK;
511 #ifndef IDS_MSGBOX_CANCEL
512 m_sButton2 = "Cancel";
513 #else
514 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
515 m_sButton2 = m_i18l;
516 #endif
517 m_uButton2Ret = IDCANCEL;
518 break;
519 case MB_RETRYCANCEL:
520 #ifndef IDS_MSGBOX_RETRY
521 m_sButton1 = "&Retry";
522 #else
523 m_i18l.LoadString(IDS_MSGBOX_RETRY);
524 m_sButton1 = m_i18l;
525 #endif
526 m_uButton1Ret = IDRETRY;
527 #ifndef IDS_MSGBOX_CANCEL
528 m_sButton2 = "Cancel";
529 #else
530 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
531 m_sButton2 = m_i18l;
532 #endif
533 m_uButton2Ret = IDCANCEL;
534 break;
535 case MB_YESNO:
536 #ifndef IDS_MSGBOX_YES
537 m_sButton1 = "&Yes";
538 #else
539 m_i18l.LoadString(IDS_MSGBOX_YES);
540 m_sButton1 = m_i18l;
541 #endif
542 m_uButton1Ret = IDYES;
543 #ifndef IDS_MSGBOX_NO
544 m_sButton2 = "&No";
545 #else
546 m_i18l.LoadString(IDS_MSGBOX_NO);
547 m_sButton2 = m_i18l;
548 #endif
549 m_uButton2Ret = IDNO;
550 break;
551 case MB_YESNOCANCEL:
552 #ifndef IDS_MSGBOX_YES
553 m_sButton1 = "&Yes";
554 #else
555 m_i18l.LoadString(IDS_MSGBOX_YES);
556 m_sButton1 = m_i18l;
557 #endif
558 m_uButton1Ret = IDYES;
559 #ifndef IDS_MSGBOX_NO
560 m_sButton2 = "&No";
561 #else
562 m_i18l.LoadString(IDS_MSGBOX_NO);
563 m_sButton2 = m_i18l;
564 #endif
565 m_uButton2Ret = IDNO;
566 #ifndef IDS_MSGBOX_CANCEL
567 m_sButton3 = "Cancel";
568 #else
569 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
570 m_sButton3 = m_i18l;
571 #endif
572 m_uButton3Ret = IDCANCEL;
573 break;
574 case MB_OK:
575 default:
576 #ifndef IDS_MSGBOX_OK
577 m_sButton1 = "OK";
578 #else
579 m_i18l.LoadString(IDS_MSGBOX_OK);
580 m_sButton1 = m_i18l;
581 #endif
583 //now set the default button
584 switch (uType & 0xf00)
586 case MB_DEFBUTTON2:
587 ret = 2;
588 break;
589 case MB_DEFBUTTON3:
590 ret = 3;
591 break;
593 // do we need to add a help button?
594 if (uType & MB_HELP)
596 CString sHelpText;
597 #ifndef IDS_MSGBOX_HELP
598 sHelpText = L"Help";
599 #else
600 m_i18l.LoadString(IDS_MSGBOX_HELP);
601 sHelpText = m_i18l;
602 #endif
603 if (m_sButton2.IsEmpty())
605 m_sButton2 = sHelpText;
606 m_uButton2Ret = IDHELP;
608 else if (m_sButton3.IsEmpty())
610 m_sButton3 = sHelpText;
611 m_uButton3Ret = IDHELP;
614 return ret;
617 UINT CMessageBox::GoModal(CWnd * pWnd, const CString& title, const CString& msg, int nDefaultButton)
619 NONCLIENTMETRICS ncm = { 0 };
620 ncm.cbSize = sizeof(NONCLIENTMETRICS);
621 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
623 memcpy(&m_LogFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
625 //the problem with the LOGFONT lfHeight is that it is not in pixels,
626 //but the dialog template needs the height in pixels.
627 //We need to convert those values first:
628 CDC * pDC;
629 if (pWnd)
630 pDC = pWnd->GetDC();
631 else
632 pDC = GetDesktopWindow()->GetDC();
633 HDC hdc;
634 if (pDC)
635 hdc = pDC->m_hDC;
636 else
637 hdc = ::GetDC(nullptr);
638 if (!hdc)
640 HWND hw = pWnd ? pWnd->m_hWnd : nullptr;
641 int defButton = nDefaultButton == 1 ? MB_DEFBUTTON1 : nDefaultButton == 2 ? MB_DEFBUTTON2 : nDefaultButton == 3 ? MB_DEFBUTTON3 : 0;
642 return ::MessageBox(hw, msg, title, m_uType | defButton);
645 int pix = -CDPIAware::Instance().PointsToPixelsY(m_LogFont.lfHeight);
646 CDlgTemplate dialogTemplate = CDlgTemplate(title, WS_CAPTION | DS_CENTER,
647 0, 0, 0, 0, m_LogFont.lfFaceName, pix);
648 dialogTemplate.AddButton(L"Button1", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 1) ? BS_DEFPUSHBUTTON : 0), 0,
649 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON1);
650 dialogTemplate.AddButton(L"Button2", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 2) ? BS_DEFPUSHBUTTON : 0), 0,
651 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON2);
652 dialogTemplate.AddButton(L"Button3", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 3) ? BS_DEFPUSHBUTTON : 0), 0,
653 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON3);
654 dialogTemplate.AddButton(L"Checkbox", WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX, 0,
655 0, 0, 0, 0, IDC_MESSAGEBOX_CHECKBOX);
657 m_nDefButton = nDefaultButton;
658 m_sMessage = msg;
659 InitModalIndirect(dialogTemplate, pWnd);
661 return (UINT)DoModal();
664 void CMessageBox::SetRegistryValue(const CString& sValue, DWORD value)
666 if (sValue.IsEmpty())
667 return;
669 CString path;
670 #ifdef XMESSAGEBOX_APPREGPATH
671 path = XMESSAGEBOX_APPREGPATH;
672 #else
673 path = "Software\\TortoiseGit\\";
674 path += AfxGetApp()->m_pszProfileName;
675 #endif
676 DWORD disp;
677 HKEY hKey;
678 if (RegCreateKeyEx(HKEY_CURRENT_USER, path, 0, L"", REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, &disp) != ERROR_SUCCESS)
680 return;
682 RegSetValueEx(hKey, sValue, 0, REG_DWORD,(const BYTE*) &value, sizeof(value));
683 RegCloseKey(hKey);
686 typedef enum {
687 NONE = 0,
688 NEW_LINE,
689 TABULATION,
690 } COMMAND;
692 CSize DrawText(CDC* pDC, CRect rect, const CString& str, LOGFONT font, BOOL bCalculate = FALSE)
694 CSize sz(0, 0);
696 if (str.IsEmpty())
697 return sz;
699 CPoint pt = rect.TopLeft();
700 CPoint ptCur = pt;
702 LOGFONT lf;
703 memcpy(&lf, &font, sizeof(LOGFONT));
705 CFont tempFont;
706 tempFont.CreateFontIndirect(&lf);
708 CFont* pOldFont = pDC->SelectObject(&tempFont);
710 TEXTMETRIC textMetric;
711 pDC->GetTextMetrics(&textMetric);
712 int nHeight = textMetric.tmHeight;
713 int nWidth = textMetric.tmAveCharWidth;
715 CString strText;
717 //iterate through all characters of the string
718 for (int i = 0; i <= str.GetLength(); ++i)
720 COMMAND nCmd = NONE;
721 if (i < str.GetLength())
723 switch (str.GetAt(i))
725 case L'\n':
726 nCmd = NEW_LINE;
727 break;
728 case L'\t':
729 nCmd = TABULATION;
730 break;
731 case L'\r':
732 break;
733 default:
734 strText += str.GetAt(i);
735 break;
738 else // Immitates new line at the end of the string
739 nCmd = NEW_LINE;
741 if (nCmd != NONE)
743 if (!strText.IsEmpty())
745 if (!bCalculate)
746 pDC->TextOut(ptCur.x, ptCur.y, strText);
747 CSize s = pDC->GetTextExtent(strText);
748 ptCur.x += s.cx;
749 strText.Empty();
752 // Executes command
753 switch (nCmd)
755 case NEW_LINE:
756 // New line
757 sz.cx = max(sz.cx, ptCur.x - pt.x);
758 ptCur.y += nHeight;
759 ptCur.x = pt.x;
760 break;
761 case TABULATION:
762 // Tabulation
763 int nTemp = (ptCur.x - pt.x) % (nWidth * 4);
764 if (nTemp)
766 //aligns with tab
767 ptCur.x += (nWidth * 4) - nTemp;
769 ptCur.x += nWidth * 4;
770 break;
775 //Gets real height of the tooltip
776 sz.cy = ptCur.y - pt.y;
778 pDC->SelectObject(pOldFont);
779 tempFont.DeleteObject();
781 return sz;
784 CSize CMessageBox::GetTextSize(const CString& str)
786 CRect rect;
787 GetWindowRect(&rect);
789 CDC * pDC = GetDC();
791 CDC memDC;
792 CBitmap bitmap;
793 memDC.CreateCompatibleDC(pDC);
794 bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
795 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
797 //get the minimum size of the rectangle of the tooltip
798 CSize sz = DrawText(&memDC, rect, str, m_LogFont, TRUE);
800 memDC.SelectObject(pOldBitmap);
801 memDC.DeleteDC();
802 bitmap.DeleteObject();
804 ReleaseDC(pDC);
806 return sz;
809 CSize CMessageBox::GetIconSize(HICON hIcon)
811 CSize sz (0, 0);
813 if (hIcon)
815 ICONINFO ii = { 0 };
816 //get icon dimensions
817 if (::GetIconInfo(hIcon, &ii))
819 sz.cx = (DWORD)(ii.xHotspot * 2);
820 sz.cy = (DWORD)(ii.yHotspot * 2);
821 //release icon mask bitmaps
822 if(ii.hbmMask)
823 ::DeleteObject(ii.hbmMask);
824 if(ii.hbmColor)
825 ::DeleteObject(ii.hbmColor);
828 m_szIcon = sz;
829 return sz;
832 CSize CMessageBox::GetButtonSize()
834 CSize sz;
835 int nButtons = 0; //number of buttons - 1
837 SetDlgItemText(IDC_MESSAGEBOX_BUTTON1, m_sButton1);
838 SetDlgItemText(IDC_MESSAGEBOX_BUTTON2, m_sButton2);
839 //GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, 1);
840 SetDlgItemText(IDC_MESSAGEBOX_BUTTON3, m_sButton3);
841 SetDlgItemText(IDC_MESSAGEBOX_CHECKBOX, m_sCheckbox);
843 CSize sz1 = GetTextSize(m_sButton1);
844 CSize sz2 = GetTextSize(m_sButton2);
845 CSize sz3 = GetTextSize(m_sButton3);
847 sz1.cx += 2*MESSAGEBOX_BUTTONX;
848 sz1.cy += 2*MESSAGEBOX_BUTTONY;
850 if (sz2.cx)
852 sz2.cx += 2*MESSAGEBOX_BUTTONX;
853 sz2.cy += 2*MESSAGEBOX_BUTTONY;
854 nButtons++;
856 if (sz3.cx)
858 sz3.cx += 2*MESSAGEBOX_BUTTONX;
859 sz3.cy += 2*MESSAGEBOX_BUTTONY;
860 nButtons++;
863 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(0, 0, sz1.cx, sz1.cy);
864 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(0, 0, sz2.cx, sz2.cy);
865 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(0, 0, sz3.cx, sz3.cy);
867 sz.cx = sz1.cx + sz2.cx + sz3.cx + (nButtons * MESSAGEBOX_BUTTONMARGIN);
868 sz.cy = max(sz1.cy, sz2.cy);
869 sz.cy = max(sz.cy, sz3.cy);
870 m_szButtons = sz;
871 if (m_bShowCheck)
873 CSize szCheck = GetTextSize(m_sCheckbox);
874 szCheck.cx += 2*GetSystemMetrics(SM_CXMENUCHECK);
875 szCheck.cy += 2*MESSAGEBOX_BUTTONY;
876 sz.cx = max(sz.cx, szCheck.cx);
877 sz.cy += szCheck.cy + MESSAGEBOX_BUTTONCHECKMARGIN;
878 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(0, 0, szCheck.cx, szCheck.cy);
880 m_szAllButtons = sz;
881 return sz;
884 BEGIN_MESSAGE_MAP(CMessageBox, CDialog)
885 ON_WM_PAINT()
886 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1, OnButton1)
887 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2, OnButton2)
888 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3, OnButton3)
889 END_MESSAGE_MAP()
891 void CMessageBox::OnPaint()
893 CPaintDC dc(this); // device context for painting
895 CRect rect;
896 CRect drawrect;
897 GetClientRect(&rect);
898 GetClientRect(&drawrect);
900 //create a memory device-context. This is done to help reduce
901 //screen flicker, since we will paint the entire control to the
902 //off screen device context first.
903 CDC memDC;
904 CBitmap bitmap;
905 memDC.CreateCompatibleDC(&dc);
906 bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
907 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
909 memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, 0,0, SRCCOPY);
911 memDC.SetBkMode(TRANSPARENT);
912 memDC.SetBkColor(GetSysColor(COLOR_WINDOW));
913 memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
915 //OnDrawBackground();
916 drawrect.DeflateRect(MESSAGEBOX_BORDERMARGINX, MESSAGEBOX_BORDERMARGINY);
917 if (m_hIcon)
919 DrawIconEx(memDC.m_hDC, drawrect.left, max(drawrect.top, drawrect.top +
920 ((drawrect.Height() - m_szAllButtons.cy - MESSAGEBOX_TEXTBUTTONMARGIN - m_szIcon.cy) / 2)),
921 m_hIcon, m_szIcon.cx, m_szIcon.cy, 0, nullptr, DI_NORMAL);
923 drawrect.left += m_szIcon.cx + MESSAGEBOX_ICONMARGIN;
924 if (m_szIcon.cy > m_szText.cy)
925 drawrect.top += (m_szIcon.cy - m_szText.cy) / 2;
928 DrawText(&memDC, drawrect, m_sMessage, m_LogFont);
930 //Copy the memory device context back into the original DC.
931 dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0,0, SRCCOPY);
933 //Cleanup resources.
934 memDC.SelectObject(pOldBitmap);
935 memDC.DeleteDC();
936 bitmap.DeleteObject();
939 void CMessageBox::OnButton1()
941 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
943 m_bChecked = TRUE;
944 SetRegistryValue(m_sRegistryValue, m_uButton1Ret);
946 else
947 m_bChecked = FALSE;
948 EndDialog(m_uButton1Ret);
951 void CMessageBox::OnButton2()
953 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
955 m_bChecked = TRUE;
956 SetRegistryValue(m_sRegistryValue, m_uButton2Ret);
958 else
959 m_bChecked = FALSE;
960 if ((m_uButton2Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
962 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
963 FPHH pHtmlHelp = nullptr; // Function pointer
964 CAutoLibrary hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(L"HHCtrl.ocx");
965 HWND hHelp = nullptr;
966 if (hInstHtmlHelp)
968 (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
969 if (pHtmlHelp)
970 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);
972 if (!hHelp)
973 ::MessageBox(m_hWnd, L"could not show help file", L"Help", MB_ICONERROR);
975 else if (m_uButton2Ret == IDHELP)
976 OnHelp();
977 else
978 EndDialog(m_uButton2Ret);
981 void CMessageBox::OnButton3()
983 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
985 m_bChecked = TRUE;
986 SetRegistryValue(m_sRegistryValue, m_uButton3Ret);
988 else
989 m_bChecked = FALSE;
990 if ((m_uButton3Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
992 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
993 FPHH pHtmlHelp = nullptr; // Function pointer
994 CAutoLibrary hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(L"HHCtrl.ocx");
995 HWND hHelp = nullptr;
996 if (hInstHtmlHelp)
998 (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
999 if (pHtmlHelp)
1000 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);
1002 if (!hHelp)
1003 ::MessageBox(m_hWnd, L"could not show help file", L"Help", MB_ICONERROR);
1005 else if (m_uButton3Ret == IDHELP)
1006 OnHelp();
1007 else
1008 EndDialog(m_uButton3Ret);
1011 void CMessageBox::OnCancel()
1013 if (m_uCancelRet == IDCANCEL)
1014 EndDialog(m_uCancelRet);
1015 //__super::OnCancel();
1018 BOOL CMessageBox::OnInitDialog()
1020 __super::OnInitDialog();
1022 CRect rect(0, 0, 0, 0);
1024 //determine the required size of the message box
1025 m_szText = GetTextSize(m_sMessage);
1026 CSize szIcon = GetIconSize(m_hIcon);
1027 CSize szButtons = GetButtonSize();
1029 CSize szIconText;
1030 szIconText.cx = m_szText.cx + szIcon.cx + ((szIcon.cx == 0) ? MESSAGEBOX_ICONMARGIN : (2 * MESSAGEBOX_ICONMARGIN));
1031 szIconText.cy = max(szIcon.cy, m_szText.cy);
1033 rect.right = max(szButtons.cx, szIconText.cx);
1034 rect.right += 2*GetSystemMetrics(SM_CXBORDER);
1035 rect.right += 2*MESSAGEBOX_BORDERMARGINX;
1036 rect.bottom = szIconText.cy;
1037 rect.bottom += szButtons.cy;
1038 rect.bottom += 2*MESSAGEBOX_BORDERMARGINY + MESSAGEBOX_TEXTBUTTONMARGIN;
1039 rect.bottom += GetSystemMetrics(SM_CYCAPTION);
1040 rect.bottom += 2 * GetSystemMetrics(SM_CYFIXEDFRAME);
1041 rect.bottom += 2*GetSystemMetrics(SM_CYBORDER);
1043 MoveWindow(rect);
1044 CenterWindow();
1046 GetClientRect(rect);
1048 //now size and position the buttons as we need them
1049 ASSERT(!m_sButton1.IsEmpty()); //at least the first button must be there!
1050 if (m_sButton2.IsEmpty())
1052 //only one button
1053 CRect rt;
1054 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt);
1055 ScreenToClient(rt);
1056 rt.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1057 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1058 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt);
1059 //hide the other two buttons
1060 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->ShowWindow(SW_HIDE);
1061 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
1063 else if (m_sButton3.IsEmpty())
1065 //two buttons
1066 CRect rt1;
1067 CRect rt2;
1068 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
1069 ScreenToClient(rt1);
1070 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
1071 ScreenToClient(rt2);
1072 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1073 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1074 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);
1075 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1076 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
1077 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
1078 //hide the third button
1079 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
1081 else
1083 //three buttons
1084 CRect buttonrect;
1085 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(buttonrect);
1086 CRect rt1;
1087 CRect rt2;
1088 CRect rt3;
1089 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
1090 ScreenToClient(rt1);
1091 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
1092 ScreenToClient(rt2);
1093 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->GetWindowRect(rt3);
1094 ScreenToClient(rt3);
1095 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1096 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1097 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);
1098 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1099 rt3.MoveToX(rt2.right + MESSAGEBOX_BUTTONMARGIN);
1100 rt3.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1101 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
1102 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
1103 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(rt3);
1105 if (m_bShowCheck)
1107 CRect rt;
1108 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->GetWindowRect(rt);
1109 ScreenToClient(rt);
1110 rt.MoveToX(rect.left + MESSAGEBOX_BORDERMARGINX/*+ ((rect.Width() - szButtons.cx)/2)*/);
1111 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - szButtons.cy);
1112 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(rt);
1113 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_SHOW);
1115 else
1116 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_HIDE);
1118 SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
1119 SetForegroundWindow();
1120 SetFocus(); //Just playing safe
1122 if (m_nDefButton == 1)
1123 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->SetFocus();
1124 if (m_nDefButton == 2)
1125 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SetFocus();
1126 if (m_nDefButton == 3)
1127 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->SetFocus();
1129 return FALSE; // return TRUE unless you set the focus to a control
1130 // EXCEPTION: OCX Property Pages should return FALSE
1133 BOOL CMessageBox::PreTranslateMessage(MSG* pMsg)
1135 if (pMsg->message == WM_KEYDOWN)
1137 switch (pMsg->wParam)
1139 case 'C':
1140 case VK_INSERT:
1142 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
1144 CClipboardHelper clipboardHelper;
1145 if(clipboardHelper.Open(GetSafeHwnd()))
1147 EmptyClipboard();
1148 CStringA sClipboard = CStringA(m_sMessage);
1149 HGLOBAL hClipboardData = CClipboardHelper::GlobalAlloc(sClipboard.GetLength()+1);
1150 char * pchData = (char*)GlobalLock(hClipboardData);
1151 if (pchData)
1152 strcpy_s(pchData, sClipboard.GetLength()+1, (LPCSTR)sClipboard);
1153 GlobalUnlock(hClipboardData);
1154 SetClipboardData(CF_TEXT,hClipboardData);
1156 return TRUE;
1159 break;
1160 case VK_ESCAPE:
1162 switch (m_uType & 0xf)
1164 case MB_ABORTRETRYIGNORE:
1165 EndDialog(m_uButton1Ret);
1166 break;
1167 case MB_CANCELTRYCONTINUE:
1168 EndDialog(m_uButton1Ret);
1169 break;
1170 case MB_OKCANCEL:
1171 EndDialog(m_uButton2Ret);
1172 break;
1173 case MB_RETRYCANCEL:
1174 EndDialog(m_uButton2Ret);
1175 break;
1176 case MB_YESNO:
1177 EndDialog(m_uButton2Ret);
1178 break;
1179 case MB_YESNOCANCEL:
1180 EndDialog(m_uButton3Ret);
1181 break;
1184 break;
1188 return __super::PreTranslateMessage(pMsg);