Don't pass wrong type
[TortoiseGit.git] / src / Utils / MiscUI / MessageBox.cpp
blobf40671710d0f485dcc0369f2a9a19e008d871c75
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2012-2016, 2018-2021 - 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"
27 #include "LoadIconEx.h"
29 #define BTN_OFFSET 100 // use an offset in order to not interfere with IDYES and so on...
31 CMessageBox::CMessageBox()
32 : m_hIcon(nullptr)
33 , m_uButton1Ret(1)
34 , m_uButton2Ret(2)
35 , m_uButton3Ret(3)
36 , m_uCancelRet(0)
37 , m_bShowCheck(FALSE)
38 , m_bDestroyIcon(FALSE)
39 , m_nDefButton(0)
40 , m_uType(0)
41 , m_bChecked(FALSE)
43 SecureZeroMemory(&m_LogFont, sizeof(LOGFONT));
46 CMessageBox::~CMessageBox()
48 if (m_bDestroyIcon)
49 ::DestroyIcon(m_hIcon);
52 static HWND GetMainHWND(HWND hWnd)
54 if (!hWnd || !IsWindow(hWnd))
55 return CWnd::GetSafeOwner_(nullptr, nullptr);
56 return hWnd;
59 UINT CMessageBox::ShowCheck(HWND hWnd, UINT nMessage, UINT nCaption, int nDef, LPCWSTR icon, UINT nButton1, UINT nButton2, UINT nButton3, LPCWSTR lpRegistry, UINT nCheckMessage/* = nullptr*/, BOOL* bChecked)
61 CString sButton1;
62 CString sButton2;
63 CString sButton3;
64 CString sMessage;
65 CString sCaption;
66 CString nCheckMsg;
67 sButton1.LoadString(nButton1);
68 sButton2.LoadString(nButton2);
69 sButton3.LoadString(nButton3);
70 sMessage.LoadString(nMessage);
71 sCaption.LoadString(nCaption);
72 nCheckMsg.LoadString(nCheckMessage);
73 return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3, lpRegistry, nCheckMsg, bChecked);
76 UINT CMessageBox::ShowCheck(HWND hWnd, LPCWSTR lpMessage, LPCWSTR lpCaption, int nDef, LPCWSTR icon, LPCWSTR lpButton1, LPCWSTR lpButton2, LPCWSTR lpButton3, LPCWSTR lpRegistry, LPCWSTR lpCheckMessage/* = nullptr*/, BOOL* bChecked)
78 //check the registry if we have to show the box or just return with the last used return value
79 //this would be the case if the user pressed "do not show again".
80 DWORD dwRetVal;
81 HKEY hKey;
82 CString path;
83 #ifdef XMESSAGEBOX_APPREGPATH
84 path = XMESSAGEBOX_APPREGPATH;
85 #else
86 path = "Software\\TortoiseGit\\";
87 path += AfxGetApp()->m_pszProfileName;
88 #endif
89 if (lpRegistry && *lpRegistry && RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)
91 DWORD size = sizeof(dwRetVal);
92 DWORD type;
93 if (RegQueryValueEx(hKey, lpRegistry, nullptr, &type, reinterpret_cast<BYTE*>(&dwRetVal), &size) == ERROR_SUCCESS)
95 ASSERT(type==REG_DWORD);
96 RegCloseKey(hKey);
97 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Using stored value %ld for \"%s\"\n", dwRetVal, lpMessage);
98 return static_cast<UINT>(dwRetVal); //return with the last saved value
100 else
102 RegCloseKey(hKey);
106 if (CTaskDialog::IsSupported())
108 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_USE_COMMAND_LINKS | TDF_POSITION_RELATIVE_TO_WINDOW);
109 taskdlg.AddCommandControl(BTN_OFFSET + 1, lpButton1);
110 if (lpButton2 && *lpButton2)
111 taskdlg.AddCommandControl(BTN_OFFSET + 2, lpButton2);
112 if (lpButton3 && *lpButton3)
113 taskdlg.AddCommandControl(BTN_OFFSET + 3, lpButton3);
114 taskdlg.SetDefaultCommandControl(BTN_OFFSET + nDef);
115 taskdlg.SetMainIcon(icon);
116 if (!lpCheckMessage)
118 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
119 taskdlg.SetVerificationCheckboxText(L"do not show again");
120 #else
121 CString m_i18l;
122 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
123 taskdlg.SetVerificationCheckboxText(m_i18l);
124 #endif
126 else
127 taskdlg.SetVerificationCheckboxText(lpCheckMessage);
128 int result = static_cast<int>(taskdlg.DoModal(GetMainHWND(hWnd))) - BTN_OFFSET;
129 if (bChecked)
130 *bChecked = taskdlg.GetVerificationCheckboxState();
131 if (lpRegistry && *lpRegistry && taskdlg.GetVerificationCheckboxState())
132 SetRegistryValue(lpRegistry, result);
134 return result;
137 CMessageBox box;
138 box.m_bShowCheck = TRUE;
139 box.m_sRegistryValue = lpRegistry;
140 if (!lpCheckMessage)
142 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
143 box.m_sCheckbox = L"do not show again";
144 #else
145 CString m_i18l;
146 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
147 box.m_sCheckbox = m_i18l;
148 #endif
150 else
151 box.m_sCheckbox = lpCheckMessage;
152 box.m_bChecked = bChecked ? *bChecked : FALSE;
153 box.m_sButton1 = lpButton1;
154 box.m_sButton2 = lpButton2;
155 box.m_sButton3 = lpButton3;
156 box.m_hIcon = LoadIconEx(AfxGetResourceHandle(), icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
157 if (!box.m_hIcon)
158 box.m_hIcon = LoadIconEx(nullptr, icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
159 else
160 box.m_bDestroyIcon = TRUE;
161 if (!IsWindow(hWnd))
162 hWnd = nullptr;
163 int result = box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef);
164 if (bChecked)
165 *bChecked = box.m_bChecked;
166 return result;
169 UINT CMessageBox::Show(HWND hWnd, LPCWSTR lpMessage, LPCWSTR lpCaption, int nDef, LPCWSTR icon, LPCWSTR lpButton1, LPCWSTR lpButton2/* = nullptr*/, LPCWSTR lpButton3/* = nullptr*/)
171 if (CTaskDialog::IsSupported())
173 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_USE_COMMAND_LINKS | TDF_POSITION_RELATIVE_TO_WINDOW);
174 taskdlg.AddCommandControl(BTN_OFFSET + 1, lpButton1);
175 if (lpButton2 && *lpButton2)
176 taskdlg.AddCommandControl(BTN_OFFSET + 2, lpButton2);
177 if (lpButton3 && *lpButton3)
178 taskdlg.AddCommandControl(BTN_OFFSET + 3, lpButton3);
179 taskdlg.SetDefaultCommandControl(BTN_OFFSET + nDef);
180 taskdlg.SetMainIcon(icon);
181 return static_cast<UINT>(taskdlg.DoModal(GetMainHWND(hWnd))) - BTN_OFFSET;
183 CMessageBox box;
184 box.m_sButton1 = lpButton1;
185 box.m_sButton2 = lpButton2;
186 box.m_sButton3 = lpButton3;
187 box.m_hIcon = LoadIconEx(AfxGetResourceHandle(), icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
188 if (!box.m_hIcon)
189 box.m_hIcon = LoadIconEx(nullptr, icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
190 else
191 box.m_bDestroyIcon = TRUE;
192 if (!IsWindow(hWnd))
193 hWnd = nullptr;
194 return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, nDef);
197 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, int nDef, LPCWSTR icon, UINT nButton1, UINT nButton2, UINT nButton3)
199 CString sButton1;
200 CString sButton2;
201 CString sButton3;
202 CString sMessage;
203 CString sCaption;
204 sButton1.LoadString(nButton1);
205 sButton2.LoadString(nButton2);
206 sButton3.LoadString(nButton3);
207 sMessage.LoadString(nMessage);
208 sCaption.LoadString(nCaption);
209 return CMessageBox::Show(hWnd, sMessage, sCaption, nDef, icon, sButton1, sButton2, sButton3);
212 UINT CMessageBox::ShowCheck(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCWSTR lpRegistry, UINT nCheckMessage, BOOL* bChecked)
214 CString sMessage;
215 CString sCaption;
216 CString sCheckMsg;
217 sMessage.LoadString(nMessage);
218 sCaption.LoadString(nCaption);
219 sCheckMsg.LoadString(nCheckMessage);
220 return CMessageBox::ShowCheck(hWnd, sMessage, sCaption, uType, lpRegistry, sCheckMsg, bChecked);
223 UINT CMessageBox::ShowCheck(HWND hWnd, LPCWSTR lpMessage, LPCWSTR lpCaption, UINT uType, LPCWSTR lpRegistry, LPCWSTR lpCheckMessage, BOOL* bChecked)
225 //check the registry if we have to show the box or just return with the last used return value
226 //this would be the case if the user pressed "do not show again".
227 DWORD dwRetVal;
228 HKEY hKey;
229 CString path;
230 #ifdef XMESSAGEBOX_APPREGPATH
231 path = XMESSAGEBOX_APPREGPATH;
232 #else
233 path = "Software\\TortoiseGit\\";
234 path += AfxGetApp()->m_pszProfileName;
235 #endif
236 if (lpRegistry && *lpRegistry && RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_EXECUTE, &hKey)==ERROR_SUCCESS)
238 DWORD size = sizeof(dwRetVal);
239 DWORD type;
240 if (RegQueryValueEx(hKey, lpRegistry, nullptr, &type, reinterpret_cast<BYTE*>(&dwRetVal), &size) == ERROR_SUCCESS)
242 ASSERT(type==REG_DWORD);
243 RegCloseKey(hKey);
244 CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": Using stored value %ld for \"%s\"\n", dwRetVal, lpMessage);
245 return static_cast<UINT>(dwRetVal); // return with the last saved value
247 else
249 RegCloseKey(hKey);
252 if (CTaskDialog::IsSupported() && !(uType & MB_HELP) && !((uType & 0xf) == MB_ABORTRETRYIGNORE) && !((uType & 0xf) == MB_CANCELTRYCONTINUE))
254 CTaskDialog taskdlg(lpMessage, L"", lpCaption, 0, TDF_POSITION_RELATIVE_TO_WINDOW);
255 // set up icon
256 switch (uType & 0xf0)
258 case MB_ICONEXCLAMATION:
259 taskdlg.SetMainIcon(IDI_EXCLAMATION);
260 break;
261 case MB_ICONASTERISK:
262 taskdlg.SetMainIcon(IDI_ASTERISK);
263 break;
264 case MB_ICONQUESTION:
265 taskdlg.SetMainIcon(IDI_QUESTION);
266 break;
267 case MB_ICONHAND:
268 taskdlg.SetMainIcon(IDI_HAND);
269 break;
271 // set up the buttons
272 switch (uType & 0xf)
274 case MB_ABORTRETRYIGNORE:
275 ASSERT(FALSE);
276 break;
277 case MB_CANCELTRYCONTINUE:
278 ASSERT(FALSE);
279 break;
280 case MB_OKCANCEL:
281 taskdlg.SetCommonButtons(TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON);
282 switch (uType & 0xf00)
284 case MB_DEFBUTTON2:
285 taskdlg.SetDefaultCommandControl(IDCANCEL);
286 break;
288 break;
289 case MB_RETRYCANCEL:
290 taskdlg.SetCommonButtons(TDCBF_RETRY_BUTTON | TDCBF_CANCEL_BUTTON);
291 switch (uType & 0xf00)
293 case MB_DEFBUTTON2:
294 taskdlg.SetDefaultCommandControl(IDCANCEL);
295 break;
297 break;
298 case MB_YESNO:
299 taskdlg.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON);
300 switch (uType & 0xf00)
302 case MB_DEFBUTTON2:
303 taskdlg.SetDefaultCommandControl(IDNO);
304 break;
306 break;
307 case MB_YESNOCANCEL:
308 taskdlg.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
309 switch (uType & 0xf00)
311 case MB_DEFBUTTON2:
312 taskdlg.SetDefaultCommandControl(IDNO);
313 break;
314 case MB_DEFBUTTON3:
315 taskdlg.SetDefaultCommandControl(IDCANCEL);
316 break;
318 break;
319 case MB_OK:
320 default:
321 taskdlg.SetCommonButtons(TDCBF_OK_BUTTON);
324 if (!lpCheckMessage)
326 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
327 taskdlg.SetVerificationCheckboxText(L"do not show again");
328 #else
329 CString m_i18l;
330 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
331 taskdlg.SetVerificationCheckboxText(m_i18l);
332 #endif
334 else
335 taskdlg.SetVerificationCheckboxText(lpCheckMessage);
336 int result = static_cast<int>(taskdlg.DoModal(GetMainHWND(hWnd)));
337 if (bChecked)
338 *bChecked = taskdlg.GetVerificationCheckboxState();
339 if (lpRegistry && *lpRegistry && taskdlg.GetVerificationCheckboxState())
340 SetRegistryValue(lpRegistry, result);
342 return result;
345 CMessageBox box;
346 box.m_bShowCheck = TRUE;
347 box.m_sRegistryValue = lpRegistry;
348 if (!lpCheckMessage)
350 #ifndef IDS_MSGBOX_DONOTSHOWAGAIN
351 box.m_sCheckbox = L"do not show again";
352 #else
353 CString m_i18l;
354 m_i18l.LoadString(IDS_MSGBOX_DONOTSHOWAGAIN);
355 box.m_sCheckbox = m_i18l;
356 #endif
358 else
359 box.m_sCheckbox = lpCheckMessage;
360 box.m_bChecked = bChecked ? *bChecked : FALSE;
361 if (!IsWindow(hWnd))
362 hWnd = nullptr;
363 int result = box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));
364 if (bChecked)
365 *bChecked = box.m_bChecked;
366 return result;
369 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, LPCWSTR sHelpPath)
371 CString sMessage;
372 CString sCaption;
373 sMessage.LoadString(nMessage);
374 sCaption.LoadString(nCaption);
375 return CMessageBox::Show(hWnd, sMessage, sCaption, uType, sHelpPath);
378 UINT CMessageBox::Show(HWND hWnd, LPCWSTR lpMessage, LPCWSTR lpCaption, UINT uType, LPCWSTR sHelpPath)
380 if (!IsWindow(hWnd))
381 hWnd = nullptr;
382 if (sHelpPath)
384 CMessageBox box;
385 box.SetHelpPath(sHelpPath);
386 return box.GoModal(CWnd::FromHandle(hWnd), lpCaption, lpMessage, box.FillBoxStandard(uType));
389 return ::MessageBox(GetMainHWND(hWnd), lpMessage, lpCaption, uType);
392 UINT CMessageBox::Show(HWND hWnd, UINT nMessage, UINT nCaption, UINT uType, UINT nHelpID)
394 CString sMessage;
395 CString sCaption;
396 sMessage.LoadString(nMessage);
397 sCaption.LoadString(nCaption);
399 if (!IsWindow(hWnd))
400 hWnd = nullptr;
401 if (nHelpID)
403 CMessageBox box;
404 box.SetHelpID(nHelpID);
405 return box.GoModal(CWnd::FromHandle(hWnd), sCaption, sMessage, box.FillBoxStandard(uType));
408 return ::MessageBox(GetMainHWND(hWnd), sMessage, sCaption, uType);
411 bool CMessageBox::RemoveRegistryKey(LPCWSTR lpRegistry)
413 HKEY hKey;
414 CString path;
415 #ifdef XMESSAGEBOX_APPREGPATH
416 path = XMESSAGEBOX_APPREGPATH;
417 #else
418 path = "Software\\TortoiseGit\\";
419 path += AfxGetApp()->m_pszProfileName;
420 #endif
421 if (RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
423 bool ret = !!RegDeleteValue(hKey, lpRegistry);
424 RegCloseKey(hKey);
425 return ret;
427 return false;
430 int CMessageBox::FillBoxStandard(UINT uType)
432 int ret = 1;
433 m_uType = uType;
434 m_uCancelRet = IDCANCEL;
435 //load the icons according to uType
436 switch (uType & 0xf0)
438 case MB_ICONEXCLAMATION:
439 m_hIcon = LoadIconEx(nullptr, IDI_EXCLAMATION, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
440 ::MessageBeep(MB_ICONEXCLAMATION);
441 break;
442 case MB_ICONASTERISK:
443 m_hIcon = LoadIconEx(nullptr, IDI_ASTERISK, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
444 ::MessageBeep(MB_ICONASTERISK);
445 break;
446 case MB_ICONQUESTION:
447 m_hIcon = LoadIconEx(nullptr, IDI_QUESTION, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
448 ::MessageBeep(MB_ICONQUESTION);
449 break;
450 case MB_ICONHAND:
451 m_hIcon = LoadIconEx(nullptr, IDI_HAND, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
452 ::MessageBeep(MB_ICONHAND);
453 break;
455 //set up the button texts
456 switch (uType & 0xf)
458 case MB_ABORTRETRYIGNORE:
459 #ifndef IDS_MSGBOX_ABORT
460 m_sButton1 = "&Abort";
461 #else
462 m_i18l.LoadString(IDS_MSGBOX_ABORT);
463 m_sButton1 = m_i18l;
464 #endif
465 m_uButton1Ret = IDABORT;
466 #ifndef IDS_MSGBOX_RETRY
467 m_sButton2 = "&Retry";
468 #else
469 m_i18l.LoadString(IDS_MSGBOX_RETRY);
470 m_sButton2 = m_i18l;
471 #endif
472 m_uButton2Ret = IDRETRY;
473 #ifndef IDS_MSGBOX_IGNORE
474 m_sButton3 = "&Ignore";
475 #else
476 m_i18l.LoadString(IDS_MSGBOX_IGNORE);
477 m_sButton3 = m_i18l;
478 #endif
479 m_uButton3Ret = IDIGNORE;
480 break;
481 case MB_CANCELTRYCONTINUE:
482 #ifndef IDS_MSGBOX_CANCEL
483 m_sButton1 = "Cancel";
484 #else
485 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
486 m_sButton1 = m_i18l;
487 #endif
488 m_uButton1Ret = IDCANCEL;
489 #ifndef IDS_MSGBOX_TRYAGAIN
490 m_sButton2 = "&Try Again";
491 #else
492 m_i18l.LoadString(IDS_MSGBOX_TRYAGAIN);
493 m_sButton2 = m_i18l;
494 #endif
495 m_uButton2Ret = IDTRYAGAIN;
496 #ifndef IDS_MSGBOX_CONTINUE
497 m_sButton3 = "&Continue";
498 #else
499 m_i18l.LoadString(IDS_MSGBOX_CONTINUE);
500 m_sButton3 = m_i18l;
501 #endif
502 m_uButton3Ret = IDCONTINUE;
503 break;
504 case MB_OKCANCEL:
505 #ifndef IDS_MSGBOX_OK
506 m_sButton1 = "OK";
507 #else
508 m_i18l.LoadString(IDS_MSGBOX_OK);
509 m_sButton1 = m_i18l;
510 #endif
511 m_uButton1Ret = IDOK;
512 #ifndef IDS_MSGBOX_CANCEL
513 m_sButton2 = "Cancel";
514 #else
515 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
516 m_sButton2 = m_i18l;
517 #endif
518 m_uButton2Ret = IDCANCEL;
519 break;
520 case MB_RETRYCANCEL:
521 #ifndef IDS_MSGBOX_RETRY
522 m_sButton1 = "&Retry";
523 #else
524 m_i18l.LoadString(IDS_MSGBOX_RETRY);
525 m_sButton1 = m_i18l;
526 #endif
527 m_uButton1Ret = IDRETRY;
528 #ifndef IDS_MSGBOX_CANCEL
529 m_sButton2 = "Cancel";
530 #else
531 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
532 m_sButton2 = m_i18l;
533 #endif
534 m_uButton2Ret = IDCANCEL;
535 break;
536 case MB_YESNO:
537 #ifndef IDS_MSGBOX_YES
538 m_sButton1 = "&Yes";
539 #else
540 m_i18l.LoadString(IDS_MSGBOX_YES);
541 m_sButton1 = m_i18l;
542 #endif
543 m_uButton1Ret = IDYES;
544 #ifndef IDS_MSGBOX_NO
545 m_sButton2 = "&No";
546 #else
547 m_i18l.LoadString(IDS_MSGBOX_NO);
548 m_sButton2 = m_i18l;
549 #endif
550 m_uButton2Ret = IDNO;
551 break;
552 case MB_YESNOCANCEL:
553 #ifndef IDS_MSGBOX_YES
554 m_sButton1 = "&Yes";
555 #else
556 m_i18l.LoadString(IDS_MSGBOX_YES);
557 m_sButton1 = m_i18l;
558 #endif
559 m_uButton1Ret = IDYES;
560 #ifndef IDS_MSGBOX_NO
561 m_sButton2 = "&No";
562 #else
563 m_i18l.LoadString(IDS_MSGBOX_NO);
564 m_sButton2 = m_i18l;
565 #endif
566 m_uButton2Ret = IDNO;
567 #ifndef IDS_MSGBOX_CANCEL
568 m_sButton3 = "Cancel";
569 #else
570 m_i18l.LoadString(IDS_MSGBOX_CANCEL);
571 m_sButton3 = m_i18l;
572 #endif
573 m_uButton3Ret = IDCANCEL;
574 break;
575 case MB_OK:
576 default:
577 #ifndef IDS_MSGBOX_OK
578 m_sButton1 = "OK";
579 #else
580 m_i18l.LoadString(IDS_MSGBOX_OK);
581 m_sButton1 = m_i18l;
582 #endif
584 //now set the default button
585 switch (uType & 0xf00)
587 case MB_DEFBUTTON2:
588 ret = 2;
589 break;
590 case MB_DEFBUTTON3:
591 ret = 3;
592 break;
594 // do we need to add a help button?
595 if (uType & MB_HELP)
597 CString sHelpText;
598 #ifndef IDS_MSGBOX_HELP
599 sHelpText = L"Help";
600 #else
601 m_i18l.LoadString(IDS_MSGBOX_HELP);
602 sHelpText = m_i18l;
603 #endif
604 if (m_sButton2.IsEmpty())
606 m_sButton2 = sHelpText;
607 m_uButton2Ret = IDHELP;
609 else if (m_sButton3.IsEmpty())
611 m_sButton3 = sHelpText;
612 m_uButton3Ret = IDHELP;
615 return ret;
618 UINT CMessageBox::GoModal(CWnd * pWnd, const CString& title, const CString& msg, int nDefaultButton)
620 NONCLIENTMETRICS ncm = { 0 };
621 ncm.cbSize = sizeof(NONCLIENTMETRICS);
622 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
624 memcpy(&m_LogFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
626 //the problem with the LOGFONT lfHeight is that it is not in pixels,
627 //but the dialog template needs the height in pixels.
628 //We need to convert those values first:
629 CDC * pDC;
630 if (pWnd)
631 pDC = pWnd->GetDC();
632 else
633 pDC = GetDesktopWindow()->GetDC();
634 HDC hdc;
635 if (pDC)
636 hdc = pDC->m_hDC;
637 else
638 hdc = ::GetDC(nullptr);
639 if (!hdc)
641 HWND hw = pWnd ? pWnd->m_hWnd : nullptr;
642 int defButton = nDefaultButton == 1 ? MB_DEFBUTTON1 : nDefaultButton == 2 ? MB_DEFBUTTON2 : nDefaultButton == 3 ? MB_DEFBUTTON3 : 0;
643 return ::MessageBox(hw, msg, title, m_uType | defButton);
646 int pix = -CDPIAware::Instance().PixelsToPointsY(m_LogFont.lfHeight);
647 CDlgTemplate dialogTemplate = CDlgTemplate(title, WS_CAPTION | DS_CENTER,
648 0, 0, 0, 0, m_LogFont.lfFaceName, pix);
649 dialogTemplate.AddButton(L"Button1", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 1) ? BS_DEFPUSHBUTTON : 0), 0,
650 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON1);
651 dialogTemplate.AddButton(L"Button2", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 2) ? BS_DEFPUSHBUTTON : 0), 0,
652 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON2);
653 dialogTemplate.AddButton(L"Button3", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | ((nDefaultButton == 3) ? BS_DEFPUSHBUTTON : 0), 0,
654 2 + 3, 62, 56, 13, IDC_MESSAGEBOX_BUTTON3);
655 dialogTemplate.AddButton(L"Checkbox", WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX, 0,
656 0, 0, 0, 0, IDC_MESSAGEBOX_CHECKBOX);
658 m_nDefButton = nDefaultButton;
659 m_sMessage = msg;
660 InitModalIndirect(dialogTemplate, pWnd);
662 return static_cast<UINT>(DoModal());
665 void CMessageBox::SetRegistryValue(const CString& sValue, DWORD value)
667 if (sValue.IsEmpty())
668 return;
670 CString path;
671 #ifdef XMESSAGEBOX_APPREGPATH
672 path = XMESSAGEBOX_APPREGPATH;
673 #else
674 path = "Software\\TortoiseGit\\";
675 path += AfxGetApp()->m_pszProfileName;
676 #endif
677 DWORD disp;
678 HKEY hKey;
679 if (RegCreateKeyEx(HKEY_CURRENT_USER, path, 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, &disp) != ERROR_SUCCESS)
681 return;
683 RegSetValueEx(hKey, sValue, 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
684 RegCloseKey(hKey);
687 typedef enum {
688 NONE = 0,
689 NEW_LINE,
690 TABULATION,
691 } COMMAND;
693 CSize DrawText(CDC* pDC, CRect rect, const CString& str, LOGFONT font, BOOL bCalculate = FALSE)
695 CSize sz(0, 0);
697 if (str.IsEmpty())
698 return sz;
700 CPoint pt = rect.TopLeft();
701 CPoint ptCur = pt;
703 LOGFONT lf;
704 memcpy(&lf, &font, sizeof(LOGFONT));
706 CFont tempFont;
707 tempFont.CreateFontIndirect(&lf);
709 CFont* pOldFont = pDC->SelectObject(&tempFont);
711 TEXTMETRIC textMetric;
712 pDC->GetTextMetrics(&textMetric);
713 int nHeight = textMetric.tmHeight;
714 int nWidth = textMetric.tmAveCharWidth;
716 CString strText;
718 //iterate through all characters of the string
719 for (int i = 0; i <= str.GetLength(); ++i)
721 COMMAND nCmd = NONE;
722 if (i < str.GetLength())
724 switch (str.GetAt(i))
726 case L'\n':
727 nCmd = NEW_LINE;
728 break;
729 case L'\t':
730 nCmd = TABULATION;
731 break;
732 case L'\r':
733 break;
734 default:
735 strText += str.GetAt(i);
736 break;
739 else // Immitates new line at the end of the string
740 nCmd = NEW_LINE;
742 if (nCmd != NONE)
744 if (!strText.IsEmpty())
746 if (!bCalculate)
747 pDC->TextOut(ptCur.x, ptCur.y, strText);
748 CSize s = pDC->GetTextExtent(strText);
749 ptCur.x += s.cx;
750 strText.Empty();
753 // Executes command
754 switch (nCmd)
756 case NEW_LINE:
757 // New line
758 sz.cx = max(sz.cx, ptCur.x - pt.x);
759 ptCur.y += nHeight;
760 ptCur.x = pt.x;
761 break;
762 case TABULATION:
763 // Tabulation
764 int nTemp = (ptCur.x - pt.x) % (nWidth * 4);
765 if (nTemp)
767 //aligns with tab
768 ptCur.x += (nWidth * 4) - nTemp;
770 ptCur.x += nWidth * 4;
771 break;
776 //Gets real height of the tooltip
777 sz.cy = ptCur.y - pt.y;
779 pDC->SelectObject(pOldFont);
780 tempFont.DeleteObject();
782 return sz;
785 CSize CMessageBox::GetTextSize(const CString& str)
787 CRect rect;
788 GetWindowRect(&rect);
790 CDC * pDC = GetDC();
792 CDC memDC;
793 CBitmap bitmap;
794 memDC.CreateCompatibleDC(pDC);
795 bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
796 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
798 //get the minimum size of the rectangle of the tooltip
799 CSize sz = DrawText(&memDC, rect, str, m_LogFont, TRUE);
801 memDC.SelectObject(pOldBitmap);
802 memDC.DeleteDC();
803 bitmap.DeleteObject();
805 ReleaseDC(pDC);
807 return sz;
810 CSize CMessageBox::GetIconSize(HICON hIcon)
812 CSize sz (0, 0);
814 if (hIcon)
816 ICONINFO ii = { 0 };
817 //get icon dimensions
818 if (::GetIconInfo(hIcon, &ii))
820 sz.cx = static_cast<DWORD>(ii.xHotspot * 2);
821 sz.cy = static_cast<DWORD>(ii.yHotspot * 2);
822 //release icon mask bitmaps
823 if(ii.hbmMask)
824 ::DeleteObject(ii.hbmMask);
825 if(ii.hbmColor)
826 ::DeleteObject(ii.hbmColor);
829 m_szIcon = sz;
830 return sz;
833 CSize CMessageBox::GetButtonSize()
835 CSize sz;
836 int nButtons = 0; //number of buttons - 1
838 SetDlgItemText(IDC_MESSAGEBOX_BUTTON1, m_sButton1);
839 SetDlgItemText(IDC_MESSAGEBOX_BUTTON2, m_sButton2);
840 //GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, 1);
841 SetDlgItemText(IDC_MESSAGEBOX_BUTTON3, m_sButton3);
842 SetDlgItemText(IDC_MESSAGEBOX_CHECKBOX, m_sCheckbox);
844 CSize sz1 = GetTextSize(m_sButton1);
845 CSize sz2 = GetTextSize(m_sButton2);
846 CSize sz3 = GetTextSize(m_sButton3);
848 sz1.cx += CDPIAware::Instance().ScaleX(2 * MESSAGEBOX_BUTTONX);
849 sz1.cy += CDPIAware::Instance().ScaleY(2 * MESSAGEBOX_BUTTONY);
851 if (sz2.cx)
853 sz2.cx += CDPIAware::Instance().ScaleX(2 * MESSAGEBOX_BUTTONX);
854 sz2.cy += CDPIAware::Instance().ScaleY(2 * MESSAGEBOX_BUTTONY);
855 nButtons++;
857 if (sz3.cx)
859 sz3.cx += CDPIAware::Instance().ScaleX(2 * MESSAGEBOX_BUTTONX);
860 sz3.cy += CDPIAware::Instance().ScaleY(2 * MESSAGEBOX_BUTTONY);
861 nButtons++;
864 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(0, 0, sz1.cx, sz1.cy);
865 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(0, 0, sz2.cx, sz2.cy);
866 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(0, 0, sz3.cx, sz3.cy);
868 sz.cx = sz1.cx + sz2.cx + sz3.cx + (nButtons * CDPIAware::Instance().ScaleX(MESSAGEBOX_BUTTONMARGIN));
869 sz.cy = max(sz1.cy, sz2.cy);
870 sz.cy = max(sz.cy, sz3.cy);
871 m_szButtons = sz;
872 if (m_bShowCheck)
874 CSize szCheck = GetTextSize(m_sCheckbox);
875 szCheck.cx += 2*GetSystemMetrics(SM_CXMENUCHECK);
876 szCheck.cy += 2*MESSAGEBOX_BUTTONY;
877 sz.cx = max(sz.cx, szCheck.cx);
878 sz.cy += szCheck.cy + CDPIAware::Instance().ScaleY(MESSAGEBOX_BUTTONCHECKMARGIN);
879 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(0, 0, szCheck.cx, szCheck.cy);
881 m_szAllButtons = sz;
882 return sz;
885 BEGIN_MESSAGE_MAP(CMessageBox, CDialog)
886 ON_WM_PAINT()
887 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON1, OnButton1)
888 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON2, OnButton2)
889 ON_BN_CLICKED(IDC_MESSAGEBOX_BUTTON3, OnButton3)
890 END_MESSAGE_MAP()
892 void CMessageBox::OnPaint()
894 CPaintDC dc(this); // device context for painting
896 CRect rect;
897 CRect drawrect;
898 GetClientRect(&rect);
899 GetClientRect(&drawrect);
901 //create a memory device-context. This is done to help reduce
902 //screen flicker, since we will paint the entire control to the
903 //off screen device context first.
904 CDC memDC;
905 CBitmap bitmap;
906 memDC.CreateCompatibleDC(&dc);
907 bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
908 CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
910 memDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, 0,0, SRCCOPY);
912 memDC.SetBkMode(TRANSPARENT);
913 memDC.SetBkColor(GetSysColor(COLOR_WINDOW));
914 memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
916 //OnDrawBackground();
917 drawrect.DeflateRect(CDPIAware::Instance().ScaleX(MESSAGEBOX_BORDERMARGINX), CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY));
918 if (m_hIcon)
920 DrawIconEx(memDC.m_hDC, drawrect.left, max(drawrect.top, drawrect.top +
921 ((drawrect.Height() - m_szAllButtons.cy - CDPIAware::Instance().ScaleY(MESSAGEBOX_TEXTBUTTONMARGIN) - m_szIcon.cy) / 2)),
922 m_hIcon, m_szIcon.cx, m_szIcon.cy, 0, nullptr, DI_NORMAL);
924 drawrect.left += m_szIcon.cx + CDPIAware::Instance().ScaleX(MESSAGEBOX_ICONMARGIN);
925 if (m_szIcon.cy > m_szText.cy)
926 drawrect.top += (m_szIcon.cy - m_szText.cy) / 2;
929 DrawText(&memDC, drawrect, m_sMessage, m_LogFont);
931 //Copy the memory device context back into the original DC.
932 dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0,0, SRCCOPY);
934 //Cleanup resources.
935 memDC.SelectObject(pOldBitmap);
936 memDC.DeleteDC();
937 bitmap.DeleteObject();
940 void CMessageBox::OnButton1()
942 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
944 m_bChecked = TRUE;
945 SetRegistryValue(m_sRegistryValue, m_uButton1Ret);
947 else
948 m_bChecked = FALSE;
949 EndDialog(m_uButton1Ret);
952 void CMessageBox::OnButton2()
954 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
956 m_bChecked = TRUE;
957 SetRegistryValue(m_sRegistryValue, m_uButton2Ret);
959 else
960 m_bChecked = FALSE;
961 if ((m_uButton2Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
963 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
964 FPHH pHtmlHelp = nullptr; // Function pointer
965 CAutoLibrary hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(L"HHCtrl.ocx");
966 HWND hHelp = nullptr;
967 if (hInstHtmlHelp)
969 reinterpret_cast<FARPROC&>(pHtmlHelp) = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
970 if (pHtmlHelp)
971 hHelp = pHtmlHelp(m_hWnd, static_cast<LPCWSTR>(m_sHelpPath), HH_DISPLAY_TOPIC, NULL);
973 if (!hHelp)
974 ::MessageBox(m_hWnd, L"could not show help file", L"Help", MB_ICONERROR);
976 else if (m_uButton2Ret == IDHELP)
977 OnHelp();
978 else
979 EndDialog(m_uButton2Ret);
982 void CMessageBox::OnButton3()
984 if (GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->SendMessage(BM_GETCHECK, 0, 0)==BST_CHECKED)
986 m_bChecked = TRUE;
987 SetRegistryValue(m_sRegistryValue, m_uButton3Ret);
989 else
990 m_bChecked = FALSE;
991 if ((m_uButton3Ret == IDHELP)&&(!m_sHelpPath.IsEmpty()))
993 typedef HWND (WINAPI* FPHH)(HWND, LPCWSTR, UINT, DWORD);
994 FPHH pHtmlHelp = nullptr; // Function pointer
995 CAutoLibrary hInstHtmlHelp = AtlLoadSystemLibraryUsingFullPath(L"HHCtrl.ocx");
996 HWND hHelp = nullptr;
997 if (hInstHtmlHelp)
999 reinterpret_cast<FARPROC&>(pHtmlHelp) = GetProcAddress(hInstHtmlHelp, "HtmlHelpW");
1000 if (pHtmlHelp)
1001 hHelp = pHtmlHelp(m_hWnd, static_cast<LPCWSTR>(m_sHelpPath), HH_DISPLAY_TOPIC, NULL);
1003 if (!hHelp)
1004 ::MessageBox(m_hWnd, L"could not show help file", L"Help", MB_ICONERROR);
1006 else if (m_uButton3Ret == IDHELP)
1007 OnHelp();
1008 else
1009 EndDialog(m_uButton3Ret);
1012 void CMessageBox::OnCancel()
1014 if (m_uCancelRet == IDCANCEL)
1015 EndDialog(m_uCancelRet);
1016 //__super::OnCancel();
1019 BOOL CMessageBox::OnInitDialog()
1021 __super::OnInitDialog();
1023 CRect rect(0, 0, 0, 0);
1025 //determine the required size of the message box
1026 m_szText = GetTextSize(m_sMessage);
1027 CSize szIcon = GetIconSize(m_hIcon);
1028 CSize szButtons = GetButtonSize();
1030 CSize szIconText;
1031 szIconText.cx = m_szText.cx + szIcon.cx + CDPIAware::Instance().ScaleX((szIcon.cx == 0) ? MESSAGEBOX_ICONMARGIN : (2 * MESSAGEBOX_ICONMARGIN));
1032 szIconText.cy = max(szIcon.cy, m_szText.cy);
1034 rect.right = max(szButtons.cx, szIconText.cx);
1035 rect.right += 2*GetSystemMetrics(SM_CXBORDER);
1036 rect.right += CDPIAware::Instance().ScaleX(2 * MESSAGEBOX_BORDERMARGINX);
1037 rect.bottom = szIconText.cy;
1038 rect.bottom += szButtons.cy;
1039 rect.bottom += CDPIAware::Instance().ScaleY(2 * MESSAGEBOX_BORDERMARGINY + MESSAGEBOX_TEXTBUTTONMARGIN);
1040 rect.bottom += GetSystemMetrics(SM_CYCAPTION);
1041 rect.bottom += 2 * GetSystemMetrics(SM_CYFIXEDFRAME);
1042 rect.bottom += 2*GetSystemMetrics(SM_CYBORDER);
1044 MoveWindow(rect);
1045 CenterWindow();
1047 GetClientRect(rect);
1049 //now size and position the buttons as we need them
1050 ASSERT(!m_sButton1.IsEmpty()); //at least the first button must be there!
1051 if (m_sButton2.IsEmpty())
1053 //only one button
1054 CRect rt;
1055 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt);
1056 ScreenToClient(rt);
1057 rt.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1058 rt.MoveToY(rect.bottom - CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY) - m_szButtons.cy);
1059 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt);
1060 //hide the other two buttons
1061 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->ShowWindow(SW_HIDE);
1062 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
1064 else if (m_sButton3.IsEmpty())
1066 //two buttons
1067 CRect rt1;
1068 CRect rt2;
1069 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
1070 ScreenToClient(rt1);
1071 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
1072 ScreenToClient(rt2);
1073 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1074 rt1.MoveToY(rect.bottom - CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY) - m_szButtons.cy);
1075 rt2.MoveToX(rt1.right + CDPIAware::Instance().ScaleX(MESSAGEBOX_BUTTONMARGIN));
1076 rt2.MoveToY(rect.bottom -CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY) - m_szButtons.cy);
1077 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
1078 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
1079 //hide the third button
1080 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->ShowWindow(SW_HIDE);
1082 else
1084 //three buttons
1085 CRect buttonrect;
1086 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(buttonrect);
1087 CRect rt1;
1088 CRect rt2;
1089 CRect rt3;
1090 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->GetWindowRect(rt1);
1091 ScreenToClient(rt1);
1092 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->GetWindowRect(rt2);
1093 ScreenToClient(rt2);
1094 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->GetWindowRect(rt3);
1095 ScreenToClient(rt3);
1096 rt1.MoveToX(rect.left + ((rect.Width() - m_szButtons.cx)/2));
1097 rt1.MoveToY(rect.bottom - CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY) - m_szButtons.cy);
1098 rt2.MoveToX(rt1.right + CDPIAware::Instance().ScaleX(MESSAGEBOX_BUTTONMARGIN));
1099 rt2.MoveToY(rect.bottom - CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY) - m_szButtons.cy);
1100 rt3.MoveToX(rt2.right + CDPIAware::Instance().ScaleX(MESSAGEBOX_BUTTONMARGIN));
1101 rt3.MoveToY(rect.bottom - CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY) - m_szButtons.cy);
1102 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->MoveWindow(rt1);
1103 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->MoveWindow(rt2);
1104 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->MoveWindow(rt3);
1106 if (m_bShowCheck)
1108 CRect rt;
1109 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->GetWindowRect(rt);
1110 ScreenToClient(rt);
1111 rt.MoveToX(rect.left + CDPIAware::Instance().ScaleX(MESSAGEBOX_BORDERMARGINX) /*+ ((rect.Width() - szButtons.cx)/2)*/);
1112 rt.MoveToY(rect.bottom - CDPIAware::Instance().ScaleY(MESSAGEBOX_BORDERMARGINY) - szButtons.cy);
1113 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->MoveWindow(rt);
1114 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_SHOW);
1116 else
1117 GetDlgItem(IDC_MESSAGEBOX_CHECKBOX)->ShowWindow(SW_HIDE);
1119 SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
1120 SetForegroundWindow();
1121 SetFocus(); //Just playing safe
1123 if (m_nDefButton == 1)
1124 GetDlgItem(IDC_MESSAGEBOX_BUTTON1)->SetFocus();
1125 if (m_nDefButton == 2)
1126 GetDlgItem(IDC_MESSAGEBOX_BUTTON2)->SetFocus();
1127 if (m_nDefButton == 3)
1128 GetDlgItem(IDC_MESSAGEBOX_BUTTON3)->SetFocus();
1130 return FALSE; // return TRUE unless you set the focus to a control
1131 // EXCEPTION: OCX Property Pages should return FALSE
1134 BOOL CMessageBox::PreTranslateMessage(MSG* pMsg)
1136 if (pMsg->message == WM_KEYDOWN)
1138 switch (pMsg->wParam)
1140 case 'C':
1141 case VK_INSERT:
1143 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
1145 CClipboardHelper clipboardHelper;
1146 if(clipboardHelper.Open(GetSafeHwnd()))
1148 EmptyClipboard();
1149 CStringA sClipboard = CStringA(m_sMessage);
1150 HGLOBAL hClipboardData = CClipboardHelper::GlobalAlloc(sClipboard.GetLength()+1);
1151 auto pchData = static_cast<char*>(GlobalLock(hClipboardData));
1152 if (pchData)
1153 strcpy_s(pchData, sClipboard.GetLength() + 1, static_cast<LPCSTR>(sClipboard));
1154 GlobalUnlock(hClipboardData);
1155 SetClipboardData(CF_TEXT,hClipboardData);
1157 return TRUE;
1160 break;
1161 case VK_ESCAPE:
1163 switch (m_uType & 0xf)
1165 case MB_ABORTRETRYIGNORE:
1166 EndDialog(m_uButton1Ret);
1167 break;
1168 case MB_CANCELTRYCONTINUE:
1169 EndDialog(m_uButton1Ret);
1170 break;
1171 case MB_OKCANCEL:
1172 EndDialog(m_uButton2Ret);
1173 break;
1174 case MB_RETRYCANCEL:
1175 EndDialog(m_uButton2Ret);
1176 break;
1177 case MB_YESNO:
1178 EndDialog(m_uButton2Ret);
1179 break;
1180 case MB_YESNOCANCEL:
1181 EndDialog(m_uButton3Ret);
1182 break;
1185 break;
1189 return __super::PreTranslateMessage(pMsg);