Allow to move item past last item
[TortoiseGit.git] / src / Utils / MiscUI / MessageBox.cpp
blob533456a3ad5388fb4cfe0c560b3ba8b852746d12
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2016 - 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>
27 #define BTN_OFFSET 100 // use an offset in order to not interfere with IDYES and so on...
29 CMessageBox::CMessageBox(void)
30 : m_hIcon(nullptr)
31 , m_uButton1Ret(1)
32 , m_uButton2Ret(2)
33 , m_uButton3Ret(3)
34 , m_uCancelRet(0)
35 , m_bShowCheck(FALSE)
36 , m_bDestroyIcon(FALSE)
37 , m_nDefButton(0)
38 , m_uType(0)
39 , m_bChecked(FALSE)
41 SecureZeroMemory(&m_LogFont, sizeof(LOGFONT));
44 CMessageBox::~CMessageBox(void)
46 if (m_bDestroyIcon)
47 ::DestroyIcon(m_hIcon);
50 static HWND GetMainHWND(HWND hWnd)
52 if (!hWnd || !IsWindow(hWnd))
53 return CWnd::GetSafeOwner_(nullptr, nullptr);
54 return hWnd;
57 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)
59 CString sButton1;
60 CString sButton2;
61 CString sButton3;
62 CString sMessage;
63 CString sCaption;
64 CString nCheckMsg;
65 sButton1.LoadString(nButton1);
66 sButton2.LoadString(nButton2);
67 sButton3.LoadString(nButton3);
68 sMessage.LoadString(nMessage);
69 sCaption.LoadString(nCaption);
70 nCheckMsg.LoadString(nCheckMessage);
71 return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3, lpRegistry, nCheckMsg, bChecked);
74 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)
76 //check the registry if we have to show the box or just return with the last used return value
77 //this would be the case if the user pressed "do not show again".
78 DWORD dwRetVal;
79 HKEY hKey;
80 CString path;
81 #ifdef XMESSAGEBOX_APPREGPATH
82 path = XMESSAGEBOX_APPREGPATH;
83 #else
84 path = "Software\\TortoiseGit\\";
85 path += AfxGetApp()->m_pszProfileName;
86 #endif
87 if (lpRegistry && *lpRegistry && RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)
89 int size = sizeof(dwRetVal);
90 DWORD type;
91 if (RegQueryValueEx(hKey, lpRegistry, nullptr, &type, (BYTE*)&dwRetVal,(LPDWORD)&size) == ERROR_SUCCESS)
93 ASSERT(type==REG_DWORD);
94 RegCloseKey(hKey);
95 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Using stored value %ld for \"%s\"\n", dwRetVal, lpMessage);
96 return (UINT)dwRetVal; //return with the last saved value
98 else
100 RegCloseKey(hKey);
104 if (CTaskDialog::IsSupported())
106 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_USE_COMMAND_LINKS | TDF_POSITION_RELATIVE_TO_WINDOW);
107 taskdlg.AddCommandControl(BTN_OFFSET + 1, lpButton1);
108 if (lpButton2 && *lpButton2)
109 taskdlg.AddCommandControl(BTN_OFFSET + 2, lpButton2);
110 if (lpButton3 && *lpButton3)
111 taskdlg.AddCommandControl(BTN_OFFSET + 3, lpButton3);
112 taskdlg.SetDefaultCommandControl(BTN_OFFSET + nDef);
113 taskdlg.SetMainIcon(icon);
114 if (!lpCheckMessage)
116 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
117 taskdlg.SetVerificationCheckboxText(L"do not show again");
118 #else
119 CString m_i18l;
120 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
121 taskdlg.SetVerificationCheckboxText(m_i18l);
122 #endif
124 else
125 taskdlg.SetVerificationCheckboxText(lpCheckMessage);
126 int result = (int)taskdlg.DoModal(GetMainHWND(hWnd)) - BTN_OFFSET;
127 if (bChecked)
128 *bChecked = taskdlg.GetVerificationCheckboxState();
129 if (lpRegistry && *lpRegistry && taskdlg.GetVerificationCheckboxState())
130 SetRegistryValue(lpRegistry, result);
132 return result;
135 CMessageBox box;
136 box.m_bShowCheck = TRUE;
137 box.m_sRegistryValue = lpRegistry;
138 if (!lpCheckMessage)
140 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
141 box.m_sCheckbox = L"do not show again";
142 #else
143 CString m_i18l;
144 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
145 box.m_sCheckbox = m_i18l;
146 #endif
148 else
149 box.m_sCheckbox = lpCheckMessage;
150 box.m_bChecked = bChecked ? *bChecked : FALSE;
151 box.m_sButton1 = lpButton1;
152 box.m_sButton2 = lpButton2;
153 box.m_sButton3 = lpButton3;
154 box.m_hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), icon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
155 if (!box.m_hIcon)
156 box.m_hIcon = (HICON)::LoadImage(nullptr, icon, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
157 else
158 box.m_bDestroyIcon = TRUE;
159 if (!IsWindow(hWnd))
160 hWnd = nullptr;
161 int result = box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef);
162 if (bChecked)
163 *bChecked = box.m_bChecked;
164 return result;
167 UINT CMessageBox::Show(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, int nDef, LPCTSTR icon, LPCTSTR lpButton1, LPCTSTR lpButton2/* = nullptr*/, LPCTSTR lpButton3/* = nullptr*/)
169 if (CTaskDialog::IsSupported())
171 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_USE_COMMAND_LINKS | TDF_POSITION_RELATIVE_TO_WINDOW);
172 taskdlg.AddCommandControl(BTN_OFFSET + 1, lpButton1);
173 if (lpButton2 && *lpButton2)
174 taskdlg.AddCommandControl(BTN_OFFSET + 2, lpButton2);
175 if (lpButton3 && *lpButton3)
176 taskdlg.AddCommandControl(BTN_OFFSET + 3, lpButton3);
177 taskdlg.SetDefaultCommandControl(BTN_OFFSET + nDef);
178 taskdlg.SetMainIcon(icon);
179 return (UINT)taskdlg.DoModal(GetMainHWND(hWnd)) - BTN_OFFSET;
181 CMessageBox box;
182 box.m_sButton1 = lpButton1;
183 box.m_sButton2 = lpButton2;
184 box.m_sButton3 = lpButton3;
185 box.m_hIcon = (HICON)::LoadImage(AfxGetResourceHandle(), icon, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
186 if (!box.m_hIcon)
187 box.m_hIcon = (HICON)::LoadImage(nullptr, icon, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
188 else
189 box.m_bDestroyIcon = TRUE;
190 if (!IsWindow(hWnd))
191 hWnd = nullptr;
192 return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef);
195 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, int nDef, LPCTSTR icon, UINT nButton1, UINT nButton2, UINT nButton3)
197 CString sButton1;
198 CString sButton2;
199 CString sButton3;
200 CString sMessage;
201 CString sCaption;
202 sButton1.LoadString(nButton1);
203 sButton2.LoadString(nButton2);
204 sButton3.LoadString(nButton3);
205 sMessage.LoadString(nMessage);
206 sCaption.LoadString(nCaption);
207 return CMessageBox::Show(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3);
210 UINT CMessageBox::ShowCheck(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCTSTR lpRegistry, UINT nCheckMessage, BOOL *bChecked)
212 CString sMessage;
213 CString sCaption;
214 CString sCheckMsg;
215 sMessage.LoadString(nMessage);
216 sCaption.LoadString(nCaption);
217 sCheckMsg.LoadString(nCheckMessage);
218 return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, uType, lpRegistry, sCheckMsg, bChecked);
221 UINT CMessageBox::ShowCheck(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, UINT uType, LPCTSTR lpRegistry, LPCTSTR lpCheckMessage, BOOL *bChecked)
223 //check the registry if we have to show the box or just return with the last used return value
224 //this would be the case if the user pressed "do not show again".
225 DWORD dwRetVal;
226 HKEY hKey;
227 CString path;
228 #ifdef XMESSAGEBOX_APPREGPATH
229 path = XMESSAGEBOX_APPREGPATH;
230 #else
231 path = "Software\\TortoiseGit\\";
232 path += AfxGetApp()->m_pszProfileName;
233 #endif
234 if (lpRegistry && *lpRegistry && RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)
236 int size = sizeof(dwRetVal);
237 DWORD type;
238 if (RegQueryValueEx(hKey, lpRegistry, nullptr, &type, (BYTE*)&dwRetVal,(LPDWORD)&size) == ERROR_SUCCESS)
240 ASSERT(type==REG_DWORD);
241 RegCloseKey(hKey);
242 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Using stored value %ld for \"%s\"\n", dwRetVal, lpMessage);
243 return (UINT)dwRetVal; //return with the last saved value
245 else
247 RegCloseKey(hKey);
250 if (CTaskDialog::IsSupported() && !(uType & MB_HELP) && !((uType & 0xf) == MB_ABORTRETRYIGNORE) && !((uType & 0xf) == MB_CANCELTRYCONTINUE))
252 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_POSITION_RELATIVE_TO_WINDOW);
253 // set up icon
254 switch (uType & 0xf0)
256 case MB_ICONEXCLAMATION:
257 taskdlg.SetMainIcon(IDI_EXCLAMATION);
258 break;
259 case MB_ICONASTERISK:
260 taskdlg.SetMainIcon(IDI_ASTERISK);
261 break;
262 case MB_ICONQUESTION:
263 taskdlg.SetMainIcon(IDI_QUESTION);
264 break;
265 case MB_ICONHAND:
266 taskdlg.SetMainIcon(IDI_HAND);
267 break;
269 // set up the buttons
270 switch (uType & 0xf)
272 case MB_ABORTRETRYIGNORE:
273 ASSERT(FALSE);
274 break;
275 case MB_CANCELTRYCONTINUE:
276 ASSERT(FALSE);
277 break;
278 case MB_OKCANCEL:
279 taskdlg.SetCommonButtons(TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON);
280 switch (uType & 0xf00)
282 case MB_DEFBUTTON2:
283 taskdlg.SetDefaultCommandControl(IDCANCEL);
284 break;
286 break;
287 case MB_RETRYCANCEL:
288 taskdlg.SetCommonButtons(TDCBF_RETRY_BUTTON | TDCBF_CANCEL_BUTTON);
289 switch (uType & 0xf00)
291 case MB_DEFBUTTON2:
292 taskdlg.SetDefaultCommandControl(IDCANCEL);
293 break;
295 break;
296 case MB_YESNO:
297 taskdlg.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON);
298 switch (uType & 0xf00)
300 case MB_DEFBUTTON2:
301 taskdlg.SetDefaultCommandControl(IDNO);
302 break;
304 break;
305 case MB_YESNOCANCEL:
306 taskdlg.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
307 switch (uType & 0xf00)
309 case MB_DEFBUTTON2:
310 taskdlg.SetDefaultCommandControl(IDNO);
311 break;
312 case MB_DEFBUTTON3:
313 taskdlg.SetDefaultCommandControl(IDCANCEL);
314 break;
316 break;
317 case MB_OK:
318 default:
319 taskdlg.SetCommonButtons(TDCBF_OK_BUTTON);
322 if (!lpCheckMessage)
324 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
325 taskdlg.SetVerificationCheckboxText(L"do not show again");
326 #else
327 CString m_i18l;
328 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
329 taskdlg.SetVerificationCheckboxText(m_i18l);
330 #endif
332 else
333 taskdlg.SetVerificationCheckboxText(lpCheckMessage);
334 int result = (int)taskdlg.DoModal(GetMainHWND(hWnd));
335 if (bChecked)
336 *bChecked = taskdlg.GetVerificationCheckboxState();
337 if (lpRegistry && *lpRegistry && taskdlg.GetVerificationCheckboxState())
338 SetRegistryValue(lpRegistry, result);
340 return result;
343 CMessageBox box;
344 box.m_bShowCheck = TRUE;
345 box.m_sRegistryValue = lpRegistry;
346 if (!lpCheckMessage)
348 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
349 box.m_sCheckbox = L"do not show again";
350 #else
351 CString m_i18l;
352 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
353 box.m_sCheckbox = m_i18l;
354 #endif
356 else
357 box.m_sCheckbox = lpCheckMessage;
358 box.m_bChecked = bChecked ? *bChecked : FALSE;
359 if (!IsWindow(hWnd))
360 hWnd = nullptr;
361 int result = box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));
362 if (bChecked)
363 *bChecked = box.m_bChecked;
364 return result;
367 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCTSTR sHelpPath)
369 CString sMessage;
370 CString sCaption;
371 sMessage.LoadString(nMessage);
372 sCaption.LoadString(nCaption);
373 return CMessageBox::Show(hWnd, sMessage, sCaption, uType, sHelpPath);
376 UINT CMessageBox::Show(HWND hWnd, LPCTSTR lpMessage, LPCTSTR lpCaption, UINT uType, LPCTSTR sHelpPath)
378 if (!IsWindow(hWnd))
379 hWnd = nullptr;
380 if (sHelpPath)
382 CMessageBox box;
383 box.SetHelpPath(sHelpPath);
384 return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));
387 return ::MessageBox(GetMainHWND(hWnd), lpMessage, lpCaption, uType);
390 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, UINT nHelpID)
392 CString sMessage;
393 CString sCaption;
394 sMessage.LoadString(nMessage);
395 sCaption.LoadString(nCaption);
397 if (!IsWindow(hWnd))
398 hWnd = nullptr;
399 if (nHelpID)
401 CMessageBox box;
402 box.SetHelpID(nHelpID);
403 return box.GoModal(CWnd::FromHandle(hWnd), sCaption, sMessage, box.FillBoxStandard(uType));
406 return ::MessageBox(GetMainHWND(hWnd), sMessage, sCaption, uType);
409 bool CMessageBox::RemoveRegistryKey(LPCTSTR lpRegistry)
411 HKEY hKey;
412 CString path;
413 #ifdef XMESSAGEBOX_APPREGPATH
414 path = XMESSAGEBOX_APPREGPATH;
415 #else
416 path = "Software\\TortoiseGit\\";
417 path += AfxGetApp()->m_pszProfileName;
418 #endif
419 if (RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
421 bool ret = !!RegDeleteValue(hKey, lpRegistry);
422 RegCloseKey(hKey);
423 return ret;
425 return false;
428 int CMessageBox::FillBoxStandard(UINT uType)
430 int ret = 1;
431 m_uType = uType;
432 m_uCancelRet = IDCANCEL;
433 //load the icons according to uType
434 switch (uType & 0xf0)
436 case MB_ICONEXCLAMATION:
437 m_hIcon = (HICON)::LoadImage(nullptr, IDI_EXCLAMATION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
438 ::MessageBeep(MB_ICONEXCLAMATION);
439 break;
440 case MB_ICONASTERISK:
441 m_hIcon = (HICON)::LoadImage(nullptr, IDI_ASTERISK, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
442 ::MessageBeep(MB_ICONASTERISK);
443 break;
444 case MB_ICONQUESTION:
445 m_hIcon = (HICON)::LoadImage(nullptr, IDI_QUESTION, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
446 ::MessageBeep(MB_ICONQUESTION);
447 break;
448 case MB_ICONHAND:
449 m_hIcon = (HICON)::LoadImage(nullptr, IDI_HAND, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
450 ::MessageBeep(MB_ICONHAND);
451 break;
453 //set up the button texts
454 switch (uType & 0xf)
456 case MB_ABORTRETRYIGNORE:
457 #ifndef IDS_MSGBOX_ABORT
458 m_sButton1 = "&Abort";
459 #else
460 m_i18l.LoadString(IDS_MSGBOX_ABORT);
461 m_sButton1 = m_i18l;
462 #endif
463 m_uButton1Ret = IDABORT;
464 #ifndef IDS_MSGBOX_RETRY
465 m_sButton2 = "&Retry";
466 #else
467 m_i18l.LoadString(IDS_MSGBOX_RETRY);
468 m_sButton2 = m_i18l;
469 #endif
470 m_uButton2Ret = IDRETRY;
471 #ifndef IDS_MSGBOX_IGNORE
472 m_sButton3 = "&Ignore";
473 #else
474 m_i18l.LoadString(IDS_MSGBOX_IGNORE);
475 m_sButton3 = m_i18l;
476 #endif
477 m_uButton3Ret = IDIGNORE;
478 break;
479 case MB_CANCELTRYCONTINUE:
480 #ifndef IDS_MSGBOX_CANCEL
481 m_sButton1 = "Cancel";
482 #else
483 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
484 m_sButton1 = m_i18l;
485 #endif
486 m_uButton1Ret = IDCANCEL;
487 #ifndef IDS_MSGBOX_TRYAGAIN
488 m_sButton2 = "&Try Again";
489 #else
490 m_i18l.LoadString(IDS_MSGBOX_TRYAGAIN);
491 m_sButton2 = m_i18l;
492 #endif
493 m_uButton2Ret = IDTRYAGAIN;
494 #ifndef IDS_MSGBOX_CONTINUE
495 m_sButton3 = "&Continue";
496 #else
497 m_i18l.LoadString(IDS_MSGBOX_CONTINUE);
498 m_sButton3 = m_i18l;
499 #endif
500 m_uButton3Ret = IDCONTINUE;
501 break;
502 case MB_OKCANCEL:
503 #ifndef IDS_MSGBOX_OK
504 m_sButton1 = "OK";
505 #else
506 m_i18l.LoadString(IDS_MSGBOX_OK);
507 m_sButton1 = m_i18l;
508 #endif
509 m_uButton1Ret = IDOK;
510 #ifndef IDS_MSGBOX_CANCEL
511 m_sButton2 = "Cancel";
512 #else
513 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
514 m_sButton2 = m_i18l;
515 #endif
516 m_uButton2Ret = IDCANCEL;
517 break;
518 case MB_RETRYCANCEL:
519 #ifndef IDS_MSGBOX_RETRY
520 m_sButton1 = "&Retry";
521 #else
522 m_i18l.LoadString(IDS_MSGBOX_RETRY);
523 m_sButton1 = m_i18l;
524 #endif
525 m_uButton1Ret = IDRETRY;
526 #ifndef IDS_MSGBOX_CANCEL
527 m_sButton2 = "Cancel";
528 #else
529 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
530 m_sButton2 = m_i18l;
531 #endif
532 m_uButton2Ret = IDCANCEL;
533 break;
534 case MB_YESNO:
535 #ifndef IDS_MSGBOX_YES
536 m_sButton1 = "&Yes";
537 #else
538 m_i18l.LoadString(IDS_MSGBOX_YES);
539 m_sButton1 = m_i18l;
540 #endif
541 m_uButton1Ret = IDYES;
542 #ifndef IDS_MSGBOX_NO
543 m_sButton2 = "&No";
544 #else
545 m_i18l.LoadString(IDS_MSGBOX_NO);
546 m_sButton2 = m_i18l;
547 #endif
548 m_uButton2Ret = IDNO;
549 break;
550 case MB_YESNOCANCEL:
551 #ifndef IDS_MSGBOX_YES
552 m_sButton1 = "&Yes";
553 #else
554 m_i18l.LoadString(IDS_MSGBOX_YES);
555 m_sButton1 = m_i18l;
556 #endif
557 m_uButton1Ret = IDYES;
558 #ifndef IDS_MSGBOX_NO
559 m_sButton2 = "&No";
560 #else
561 m_i18l.LoadString(IDS_MSGBOX_NO);
562 m_sButton2 = m_i18l;
563 #endif
564 m_uButton2Ret = IDNO;
565 #ifndef IDS_MSGBOX_CANCEL
566 m_sButton3 = "Cancel";
567 #else
568 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
569 m_sButton3 = m_i18l;
570 #endif
571 m_uButton3Ret = IDCANCEL;
572 break;
573 case MB_OK:
574 default:
575 #ifndef IDS_MSGBOX_OK
576 m_sButton1 = "OK";
577 #else
578 m_i18l.LoadString(IDS_MSGBOX_OK);
579 m_sButton1 = m_i18l;
580 #endif
582 //now set the default button
583 switch (uType & 0xf00)
585 case MB_DEFBUTTON2:
586 ret = 2;
587 break;
588 case MB_DEFBUTTON3:
589 ret = 3;
590 break;
592 // do we need to add a help button?
593 if (uType & MB_HELP)
595 CString sHelpText;
596 #ifndef IDS_MSGBOX_HELP
597 sHelpText = L"Help";
598 #else
599 m_i18l.LoadString(IDS_MSGBOX_HELP);
600 sHelpText = m_i18l;
601 #endif
602 if (m_sButton2.IsEmpty())
604 m_sButton2 = sHelpText;
605 m_uButton2Ret = IDHELP;
607 else if (m_sButton3.IsEmpty())
609 m_sButton3 = sHelpText;
610 m_uButton3Ret = IDHELP;
613 return ret;
616 UINT CMessageBox::GoModal(CWnd * pWnd, const CString& title, const CString& msg, int nDefaultButton)
618 NONCLIENTMETRICS ncm = { 0 };
619 ncm.cbSize = sizeof(NONCLIENTMETRICS);
620 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
622 memcpy(&m_LogFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
624 //the problem with the LOGFONT lfHeight is that it is not in pixels,
625 //but the dialog template needs the height in pixels.
626 //We need to convert those values first:
627 CDC * pDC;
628 if (pWnd)
629 pDC = pWnd->GetDC();
630 else
631 pDC = GetDesktopWindow()->GetDC();
632 HDC hdc;
633 if (pDC)
634 hdc = pDC->m_hDC;
635 else
636 hdc = ::GetDC(nullptr);
637 if (!hdc)
639 HWND hw = pWnd ? pWnd->m_hWnd : nullptr;
640 int defButton = nDefaultButton == 1 ? MB_DEFBUTTON1 : nDefaultButton == 2 ? MB_DEFBUTTON2 : nDefaultButton == 3 ? MB_DEFBUTTON3 : 0;
641 return ::MessageBox(hw, msg, title, m_uType | defButton);
644 int pix = -MulDiv(m_LogFont.lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY));
645 CDlgTemplate dialogTemplate = CDlgTemplate(title, WS_CAPTION | DS_CENTER,
646 0, 0, 0, 0, m_LogFont.lfFaceName, pix);
647 dialogTemplate.AddButton(L"Button1", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 1) ? BS_DEFPUSHBUTTON : 0), 0,
648 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON1);
649 dialogTemplate.AddButton(L"Button2", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 2) ? BS_DEFPUSHBUTTON : 0), 0,
650 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON2);
651 dialogTemplate.AddButton(L"Button3", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 3) ? BS_DEFPUSHBUTTON : 0), 0,
652 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON3);
653 dialogTemplate.AddButton(L"Checkbox", WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX, 0,
654 0, 0, 0, 0, IDC_MESSAGEBOX_CHECKBOX);
656 m_nDefButton = nDefaultButton;
657 m_sMessage = msg;
658 InitModalIndirect(dialogTemplate, pWnd);
660 return (UINT)DoModal();
663 void CMessageBox::SetRegistryValue(const CString& sValue, DWORD value)
665 if (sValue.IsEmpty())
666 return;
668 CString path;
669 #ifdef XMESSAGEBOX_APPREGPATH
670 path = XMESSAGEBOX_APPREGPATH;
671 #else
672 path = "Software\\TortoiseGit\\";
673 path += AfxGetApp()->m_pszProfileName;
674 #endif
675 DWORD disp;
676 HKEY hKey;
677 if (RegCreateKeyEx(HKEY_CURRENT_USER, path, 0, L"", REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, &disp) != ERROR_SUCCESS)
679 return;
681 RegSetValueEx(hKey, sValue, 0, REG_DWORD,(const BYTE*) &value, sizeof(value));
682 RegCloseKey(hKey);
685 typedef enum {
686 NONE = 0,
687 NEW_LINE,
688 TABULATION,
689 } COMMAND;
691 CSize DrawText(CDC* pDC, CRect rect, const CString& str, LOGFONT font, BOOL bCalculate = FALSE)
693 CSize sz(0, 0);
695 if (str.IsEmpty())
696 return sz;
698 CPoint pt = rect.TopLeft();
699 CPoint ptCur = pt;
701 LOGFONT lf;
702 memcpy(&lf, &font, sizeof(LOGFONT));
704 CFont tempFont;
705 tempFont.CreateFontIndirect(&lf);
707 CFont* pOldFont = pDC->SelectObject(&tempFont);
709 TEXTMETRIC textMetric;
710 pDC->GetTextMetrics(&textMetric);
711 int nHeight = textMetric.tmHeight;
712 int nWidth = textMetric.tmAveCharWidth;
714 CString strText;
716 //iterate through all characters of the string
717 for (int i = 0; i <= str.GetLength(); ++i)
719 COMMAND nCmd = NONE;
720 if (i < str.GetLength())
722 switch (str.GetAt(i))
724 case L'\n':
725 nCmd = NEW_LINE;
726 break;
727 case L'\t':
728 nCmd = TABULATION;
729 break;
730 case L'\r':
731 break;
732 default:
733 strText += str.GetAt(i);
734 break;
737 else // Immitates new line at the end of the string
738 nCmd = NEW_LINE;
740 if (nCmd != NONE)
742 if (!strText.IsEmpty())
744 if (!bCalculate)
745 pDC->TextOut(ptCur.x, ptCur.y, strText);
746 CSize s = pDC->GetTextExtent(strText);
747 ptCur.x += s.cx;
748 strText.Empty();
751 // Executes command
752 switch (nCmd)
754 case NEW_LINE:
755 // New line
756 sz.cx = max(sz.cx, ptCur.x - pt.x);
757 ptCur.y += nHeight;
758 ptCur.x = pt.x;
759 break;
760 case TABULATION:
761 // Tabulation
762 int nTemp = (ptCur.x - pt.x) % (nWidth * 4);
763 if (nTemp)
765 //aligns with tab
766 ptCur.x += (nWidth * 4) - nTemp;
768 ptCur.x += nWidth * 4;
769 break;
774 //Gets real height of the tooltip
775 sz.cy = ptCur.y - pt.y;
777 pDC->SelectObject(pOldFont);
778 tempFont.DeleteObject();
780 return sz;
783 CSize CMessageBox::GetTextSize(const CString& str)
785 CRect rect;
786 GetWindowRect(&rect);
788 CDC * pDC = GetDC();
790 CDC memDC;
791 CBitmap bitmap;
792 memDC.CreateCompatibleDC(pDC);
793 bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
794 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
796 //get the minimum size of the rectangle of the tooltip
797 CSize sz = DrawText(&memDC, rect, str, m_LogFont, TRUE);
799 memDC.SelectObject(pOldBitmap);
800 memDC.DeleteDC();
801 bitmap.DeleteObject();
803 ReleaseDC(pDC);
805 return sz;
808 CSize CMessageBox::GetIconSize(HICON hIcon)
810 CSize sz (0, 0);
812 if (hIcon)
814 ICONINFO ii = { 0 };
815 //get icon dimensions
816 if (::GetIconInfo(hIcon, &ii))
818 sz.cx = (DWORD)(ii.xHotspot * 2);
819 sz.cy = (DWORD)(ii.yHotspot * 2);
820 //release icon mask bitmaps
821 if(ii.hbmMask)
822 ::DeleteObject(ii.hbmMask);
823 if(ii.hbmColor)
824 ::DeleteObject(ii.hbmColor);
827 m_szIcon = sz;
828 return sz;
831 CSize CMessageBox::GetButtonSize()
833 CSize sz;
834 int nButtons = 0; //number of buttons - 1
836 SetDlgItemText(IDC_MESSAGEBOX_BUTTON1, m_sButton1);
837 SetDlgItemText(IDC_MESSAGEBOX_BUTTON2, m_sButton2);
838 //GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, 1);
839 SetDlgItemText(IDC_MESSAGEBOX_BUTTON3, m_sButton3);
840 SetDlgItemText(IDC_MESSAGEBOX_CHECKBOX, m_sCheckbox);
842 CSize sz1 = GetTextSize(m_sButton1);
843 CSize sz2 = GetTextSize(m_sButton2);
844 CSize sz3 = GetTextSize(m_sButton3);
846 sz1.cx += 2*MESSAGEBOX_BUTTONX;
847 sz1.cy += 2*MESSAGEBOX_BUTTONY;
849 if (sz2.cx)
851 sz2.cx += 2*MESSAGEBOX_BUTTONX;
852 sz2.cy += 2*MESSAGEBOX_BUTTONY;
853 nButtons++;
855 if (sz3.cx)
857 sz3.cx += 2*MESSAGEBOX_BUTTONX;
858 sz3.cy += 2*MESSAGEBOX_BUTTONY;
859 nButtons++;
862 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(0, 0, sz1.cx, sz1.cy);
863 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(0, 0, sz2.cx, sz2.cy);
864 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(0, 0, sz3.cx, sz3.cy);
866 sz.cx = sz1.cx + sz2.cx + sz3.cx + (nButtons * MESSAGEBOX_BUTTONMARGIN);
867 sz.cy = max(sz1.cy, sz2.cy);
868 sz.cy = max(sz.cy, sz3.cy);
869 m_szButtons = sz;
870 if (m_bShowCheck)
872 CSize szCheck = GetTextSize(m_sCheckbox);
873 szCheck.cx += 2*GetSystemMetrics(SM_CXMENUCHECK);
874 szCheck.cy += 2*MESSAGEBOX_BUTTONY;
875 sz.cx = max(sz.cx, szCheck.cx);
876 sz.cy += szCheck.cy + MESSAGEBOX_BUTTONCHECKMARGIN;
877 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(0, 0, szCheck.cx, szCheck.cy);
879 m_szAllButtons = sz;
880 return sz;
883 BEGIN_MESSAGE_MAP(CMessageBox, CDialog)
884 ON_WM_PAINT()
885 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1, OnButton1)
886 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2, OnButton2)
887 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3, OnButton3)
888 END_MESSAGE_MAP()
890 void CMessageBox::OnPaint()
892 CPaintDC dc(this); // device context for painting
894 CRect rect;
895 CRect drawrect;
896 GetClientRect(&rect);
897 GetClientRect(&drawrect);
899 //create a memory device-context. This is done to help reduce
900 //screen flicker, since we will paint the entire control to the
901 //off screen device context first.
902 CDC memDC;
903 CBitmap bitmap;
904 memDC.CreateCompatibleDC(&dc);
905 bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
906 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
908 memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, 0,0, SRCCOPY);
910 memDC.SetBkMode(TRANSPARENT);
911 memDC.SetBkColor(GetSysColor(COLOR_WINDOW));
912 memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
914 //OnDrawBackground();
915 drawrect.DeflateRect(MESSAGEBOX_BORDERMARGINX, MESSAGEBOX_BORDERMARGINY);
916 if (m_hIcon)
918 DrawIconEx(memDC.m_hDC, drawrect.left, max(drawrect.top, drawrect.top +
919 ((drawrect.Height() - m_szAllButtons.cy - MESSAGEBOX_TEXTBUTTONMARGIN - m_szIcon.cy) / 2)),
920 m_hIcon, m_szIcon.cx, m_szIcon.cy, 0, nullptr, DI_NORMAL);
922 drawrect.left += m_szIcon.cx + MESSAGEBOX_ICONMARGIN;
923 if (m_szIcon.cy > m_szText.cy)
924 drawrect.top += (m_szIcon.cy - m_szText.cy) / 2;
927 DrawText(&memDC, drawrect, m_sMessage, m_LogFont);
929 //Copy the memory device context back into the original DC.
930 dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0,0, SRCCOPY);
932 //Cleanup resources.
933 memDC.SelectObject(pOldBitmap);
934 memDC.DeleteDC();
935 bitmap.DeleteObject();
938 void CMessageBox::OnButton1()
940 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
942 m_bChecked = TRUE;
943 SetRegistryValue(m_sRegistryValue, m_uButton1Ret);
945 else
946 m_bChecked = FALSE;
947 EndDialog(m_uButton1Ret);
950 void CMessageBox::OnButton2()
952 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
954 m_bChecked = TRUE;
955 SetRegistryValue(m_sRegistryValue, m_uButton2Ret);
957 else
958 m_bChecked = FALSE;
959 if ((m_uButton2Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
961 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
962 FPHH pHtmlHelp = nullptr; // Function pointer
963 CAutoLibrary hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(L"HHCtrl.ocx");
964 HWND hHelp = nullptr;
965 if (hInstHtmlHelp)
967 (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
968 if (pHtmlHelp)
969 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);
971 if (!hHelp)
972 ::MessageBox(m_hWnd, L"could not show help file", L"Help", MB_ICONERROR);
974 else if (m_uButton2Ret == IDHELP)
975 OnHelp();
976 else
977 EndDialog(m_uButton2Ret);
980 void CMessageBox::OnButton3()
982 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
984 m_bChecked = TRUE;
985 SetRegistryValue(m_sRegistryValue, m_uButton3Ret);
987 else
988 m_bChecked = FALSE;
989 if ((m_uButton3Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
991 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
992 FPHH pHtmlHelp = nullptr; // Function pointer
993 CAutoLibrary hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(L"HHCtrl.ocx");
994 HWND hHelp = nullptr;
995 if (hInstHtmlHelp)
997 (FARPROC&)pHtmlHelp = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
998 if (pHtmlHelp)
999 hHelp = pHtmlHelp(m_hWnd, (LPCTSTR)m_sHelpPath, HH_DISPLAY_TOPIC, NULL);
1001 if (!hHelp)
1002 ::MessageBox(m_hWnd, L"could not show help file", L"Help", MB_ICONERROR);
1004 else if (m_uButton3Ret == IDHELP)
1005 OnHelp();
1006 else
1007 EndDialog(m_uButton3Ret);
1010 void CMessageBox::OnCancel()
1012 if (m_uCancelRet == IDCANCEL)
1013 EndDialog(m_uCancelRet);
1014 //__super::OnCancel();
1017 BOOL CMessageBox::OnInitDialog()
1019 __super::OnInitDialog();
1021 CRect rect(0, 0, 0, 0);
1023 //determine the required size of the message box
1024 m_szText = GetTextSize(m_sMessage);
1025 CSize szIcon = GetIconSize(m_hIcon);
1026 CSize szButtons = GetButtonSize();
1028 CSize szIconText;
1029 szIconText.cx = m_szText.cx + szIcon.cx + ((szIcon.cx == 0) ? MESSAGEBOX_ICONMARGIN : (2 * MESSAGEBOX_ICONMARGIN));
1030 szIconText.cy = max(szIcon.cy, m_szText.cy);
1032 rect.right = max(szButtons.cx, szIconText.cx);
1033 rect.right += 2*GetSystemMetrics(SM_CXBORDER);
1034 rect.right += 2*MESSAGEBOX_BORDERMARGINX;
1035 rect.bottom = szIconText.cy;
1036 rect.bottom += szButtons.cy;
1037 rect.bottom += 2*MESSAGEBOX_BORDERMARGINY + MESSAGEBOX_TEXTBUTTONMARGIN;
1038 rect.bottom += GetSystemMetrics(SM_CYCAPTION);
1039 rect.bottom += 2 * GetSystemMetrics(SM_CYFIXEDFRAME);
1040 rect.bottom += 2*GetSystemMetrics(SM_CYBORDER);
1042 MoveWindow(rect);
1043 CenterWindow();
1045 GetClientRect(rect);
1047 //now size and position the buttons as we need them
1048 ASSERT(!m_sButton1.IsEmpty()); //at least the first button must be there!
1049 if (m_sButton2.IsEmpty())
1051 //only one button
1052 CRect rt;
1053 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt);
1054 ScreenToClient(rt);
1055 rt.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1056 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1057 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt);
1058 //hide the other two buttons
1059 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->ShowWindow(SW_HIDE);
1060 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
1062 else if (m_sButton3.IsEmpty())
1064 //two buttons
1065 CRect rt1;
1066 CRect rt2;
1067 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
1068 ScreenToClient(rt1);
1069 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
1070 ScreenToClient(rt2);
1071 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1072 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1073 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);
1074 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1075 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
1076 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
1077 //hide the third button
1078 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
1080 else
1082 //three buttons
1083 CRect buttonrect;
1084 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(buttonrect);
1085 CRect rt1;
1086 CRect rt2;
1087 CRect rt3;
1088 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
1089 ScreenToClient(rt1);
1090 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
1091 ScreenToClient(rt2);
1092 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->GetWindowRect(rt3);
1093 ScreenToClient(rt3);
1094 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1095 rt1.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1096 rt2.MoveToX(rt1.right + MESSAGEBOX_BUTTONMARGIN);
1097 rt2.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1098 rt3.MoveToX(rt2.right + MESSAGEBOX_BUTTONMARGIN);
1099 rt3.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - m_szButtons.cy);
1100 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
1101 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
1102 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(rt3);
1104 if (m_bShowCheck)
1106 CRect rt;
1107 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->GetWindowRect(rt);
1108 ScreenToClient(rt);
1109 rt.MoveToX(rect.left + MESSAGEBOX_BORDERMARGINX/*+ ((rect.Width() - szButtons.cx)/2)*/);
1110 rt.MoveToY(rect.bottom - MESSAGEBOX_BORDERMARGINY - szButtons.cy);
1111 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(rt);
1112 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_SHOW);
1114 else
1115 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_HIDE);
1117 SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
1118 SetForegroundWindow();
1119 SetFocus(); //Just playing safe
1121 if (m_nDefButton == 1)
1122 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->SetFocus();
1123 if (m_nDefButton == 2)
1124 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SetFocus();
1125 if (m_nDefButton == 3)
1126 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->SetFocus();
1128 return FALSE; // return TRUE unless you set the focus to a control
1129 // EXCEPTION: OCX Property Pages should return FALSE
1132 BOOL CMessageBox::PreTranslateMessage(MSG* pMsg)
1134 if (pMsg->message == WM_KEYDOWN)
1136 switch (pMsg->wParam)
1138 case 'C':
1139 case VK_INSERT:
1141 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
1143 CClipboardHelper clipboardHelper;
1144 if(clipboardHelper.Open(GetSafeHwnd()))
1146 EmptyClipboard();
1147 CStringA sClipboard = CStringA(m_sMessage);
1148 HGLOBAL hClipboardData = CClipboardHelper::GlobalAlloc(sClipboard.GetLength()+1);
1149 char * pchData = (char*)GlobalLock(hClipboardData);
1150 if (pchData)
1151 strcpy_s(pchData, sClipboard.GetLength()+1, (LPCSTR)sClipboard);
1152 GlobalUnlock(hClipboardData);
1153 SetClipboardData(CF_TEXT,hClipboardData);
1155 return TRUE;
1158 break;
1159 case VK_ESCAPE:
1161 switch (m_uType & 0xf)
1163 case MB_ABORTRETRYIGNORE:
1164 EndDialog(m_uButton1Ret);
1165 break;
1166 case MB_CANCELTRYCONTINUE:
1167 EndDialog(m_uButton1Ret);
1168 break;
1169 case MB_OKCANCEL:
1170 EndDialog(m_uButton2Ret);
1171 break;
1172 case MB_RETRYCANCEL:
1173 EndDialog(m_uButton2Ret);
1174 break;
1175 case MB_YESNO:
1176 EndDialog(m_uButton2Ret);
1177 break;
1178 case MB_YESNOCANCEL:
1179 EndDialog(m_uButton3Ret);
1180 break;
1183 break;
1187 return __super::PreTranslateMessage(pMsg);