Index: mptrack/dlg_misc.cpp
===================================================================
--- mptrack/dlg_misc.cpp	(revision 24083)
+++ mptrack/dlg_misc.cpp	(working copy)
@@ -1573,27 +1573,29 @@
 	if((TrackerSettings::Instance().gnMsgBoxVisiblityFlags & msg.mask) == 0)
 		return;
 
-#if MPT_WINNT_AT_LEAST(MPT_WIN_VISTA) && defined(UNICODE)
-	if(CTaskDialog::IsSupported()
-	   && !(mpt::OS::Windows::IsWine() && theApp.GetWineVersion()->Version().IsBefore(mpt::OS::Wine::Version(3, 13, 0))))
+	TaskDlg dlg = TaskDlg{}
+		.WindowTitle(msg.mainTitle)
+		.Icon(MB_ICONINFORMATION);
+
+	bool dontShowAgain;
+	if(TaskDlg::ModernTaskDialogSupported())
 	{
-		CTaskDialog taskDialog(msg.message, msg.mainTitle ? CString{msg.mainTitle} : CString{}, AfxGetAppName(), TDCBF_OK_BUTTON);
-		taskDialog.SetVerificationCheckboxText(_T("Do not show this message again"));
-		taskDialog.SetVerificationCheckbox(msg.defaultDontShowAgainStatus);
-		taskDialog.DoModal();
-
-		if(taskDialog.GetVerificationCheckboxState())
-			TrackerSettings::Instance().gnMsgBoxVisiblityFlags &= ~msg.mask;
-		else
-			TrackerSettings::Instance().gnMsgBoxVisiblityFlags |= msg.mask;
+		dlg.Description(msg.message)
+			.VerificationText(_T("Do not show this message again"))
+			.VerificationChecked(msg.defaultDontShowAgainStatus);
+		dontShowAgain = dlg.DoModal().verificationChecked;
 	} else
-#endif
 	{
-		if(Reporting::Confirm(msg.message + CString(_T("\n\nShow this message again?")), msg.mainTitle ? CString{msg.mainTitle} : CString{}, msg.defaultDontShowAgainStatus) == cnfNo)
-			TrackerSettings::Instance().gnMsgBoxVisiblityFlags &= ~msg.mask;
-		else
-			TrackerSettings::Instance().gnMsgBoxVisiblityFlags |= msg.mask;
+		dlg.Description(CString{msg.message} + _T("\n\nShow this message again?"))
+			.Buttons({{_T("Yes"), IDYES}, {_T("No"), IDNO} })
+			.DefaultButton(msg.defaultDontShowAgainStatus ? IDNO : IDYES);
+		dontShowAgain = dlg.DoModal().buttonId == IDNO;
 	}
+
+	if(dontShowAgain)
+		TrackerSettings::Instance().gnMsgBoxVisiblityFlags &= ~msg.mask;
+	else
+		TrackerSettings::Instance().gnMsgBoxVisiblityFlags |= msg.mask;
 }
 
 
Index: mptrack/Reporting.cpp
===================================================================
--- mptrack/Reporting.cpp	(revision 24083)
+++ mptrack/Reporting.cpp	(working copy)
@@ -10,23 +10,27 @@
 
 #include "stdafx.h"
 #include "Reporting.h"
-#include "../mptrack/Mainfrm.h"
+#include "Mainfrm.h"
 
+#if MPT_WINNT_AT_LEAST(MPT_WIN_VISTA) && defined(UNICODE)
+#include "Mptrack.h"
+#include <afxtaskdialog.h>
+#endif
 
 OPENMPT_NAMESPACE_BEGIN
 
 
-static inline UINT LogLevelToFlags(LogLevel level)
+static inline UINT LogLevelToIcon(LogLevel level)
 {
 	switch(level)
 	{
-	case LogDebug: return MB_OK; break;
-	case LogNotification: return MB_OK; break;
-	case LogInformation: return MB_OK | MB_ICONINFORMATION; break;
-	case LogWarning: return MB_OK | MB_ICONWARNING; break;
-	case LogError: return MB_OK | MB_ICONERROR; break;
+	case LogDebug: return 0;
+	case LogNotification: return 0;
+	case LogInformation: return MB_ICONINFORMATION;
+	case LogWarning: return MB_ICONWARNING;
+	case LogError: return MB_ICONERROR;
 	}
-	return MB_OK;
+	return 0;
 }
 
 
@@ -80,70 +84,264 @@
 		text.SetAt(uint16_max - 2, _T('.'));
 		text.SetAt(uint16_max - 3, _T('.'));
 	}
-	UINT result = ::MessageBox(parent->GetSafeHwnd(), text, caption.IsEmpty() ? CString(MAINFRAME_TITLE) : caption, flags);
+	UINT result = ::MessageBox(parent->GetSafeHwnd(), text, caption.IsEmpty() ? CString{MAINFRAME_TITLE} : caption, flags);
 	return result;
 }
 
 
+static const TCHAR *GetButtonString(UINT id)
+{
+	mpt::Library user32{mpt::LibraryPath::System(P_("user32"))};
+	using PMB_GETSTRING = LPCWSTR(WINAPI *)(UINT);
+	PMB_GETSTRING MB_GetString = nullptr;
+	user32.Bind(MB_GetString, "MB_GetString");
+	if(MB_GetString)
+		return MB_GetString(id - 1);
+
+	switch(id)
+	{
+	case IDOK: return _T("&OK");
+	case IDCANCEL: return _T("&Cancel");
+	case IDABORT: return _T("&Abort");
+	case IDRETRY: return _T("&Retry");
+	case IDIGNORE: return _T("&Ignore");
+	case IDYES: return _T("&Yes");
+	case IDNO: return _T("&No");
+	case IDCLOSE: return _T("&Close");
+	case IDHELP: return _T("Help");
+	case IDTRYAGAIN: return _T("&Try Again");
+	case IDCONTINUE: return _T("&Continue");
+	default: return _T("");
+	}
+}
+
+
+bool TaskDlg::ModernTaskDialogSupported()
+{
+#if MPT_WINNT_AT_LEAST(MPT_WIN_VISTA) && defined(UNICODE)
+	return CTaskDialog::IsSupported()
+		&& !(mpt::OS::Windows::IsWine() && theApp.GetWineVersion()->Version().IsBefore(mpt::OS::Wine::Version(3, 13, 0)));
+#else
+	return false;
+#endif
+}
+
+
+TaskDlg::Result TaskDlg::DoModal(const CWnd *parent) const
+{
+	if(!parent)
+		parent = CMainFrame::GetActiveWindow();
+
+#if MPT_WINNT_AT_LEAST(MPT_WIN_VISTA) && defined(UNICODE)
+	if(ModernTaskDialogSupported())
+	{
+		CTaskDialog taskDialog{
+			description,
+			headline,
+			windowTitle.IsEmpty() ? GetTitle() : windowTitle,
+			buttons.empty() ? TDCBF_OK_BUTTON : 0,
+			bigButtons ? TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS : 0};
+
+		if(icon == MB_ICONINFORMATION)
+			taskDialog.SetMainIcon(TD_INFORMATION_ICON);
+		else if(icon == MB_ICONWARNING)
+			taskDialog.SetMainIcon(TD_WARNING_ICON);
+		else if(icon == MB_ICONERROR)
+			taskDialog.SetMainIcon(TD_ERROR_ICON);
+		else if(icon == MB_ICONQUESTION)
+			taskDialog.SetMainIcon(TD_INFORMATION_ICON);  // theApp.LoadStandardIcon(IDI_QUESTION) - this icon hasn't been updated since Vista, and shouldn't be used according to guidelines anyway...
+
+		for(const auto &button : buttons)
+		{
+			taskDialog.AddCommandControl(button.commandId, button.text);
+		}
+
+		if(!verificationText.IsEmpty())
+		{
+			taskDialog.SetVerificationCheckboxText(verificationText);
+			taskDialog.SetVerificationCheckbox(verificationChecked);
+		}
+
+		if(defaultButton)
+			taskDialog.SetDefaultCommandControl(defaultButton);
+
+		UINT result = static_cast<UINT>(taskDialog.DoModal(parent->GetSafeHwnd()));
+		return {result, !verificationText.IsEmpty() ? !!taskDialog.GetVerificationCheckboxState() : false};
+	}
+#endif
+
+	// Fallback using regular MessageBox
+	UINT flags = MB_OK;
+	if(buttons.size() <= 1)
+	{
+		flags = MB_OK;
+	} else if(buttons.size() == 2)
+	{
+		uint32 hasButton = 0;
+		for(const auto &button : buttons)
+		{
+			hasButton |= (1 << button.commandId);
+		}
+		if(hasButton == ((1 << IDOK) | (1 << IDCANCEL)))
+			flags = MB_OKCANCEL;
+		else if(hasButton == ((1 << IDYES) | (1 << IDNO)))
+			flags = MB_YESNO;
+		else if(hasButton == ((1 << IDRETRY) | (1 << IDCANCEL)))
+			flags = MB_RETRYCANCEL;
+		else
+			flags = MB_OKCANCEL;
+	} else if(buttons.size() == 3)
+	{
+		flags = MB_YESNOCANCEL;
+	}
+
+	if(defaultButton != IDOK)
+	{
+		if(defaultButton == IDCANCEL)
+			flags |= MB_DEFBUTTON3;
+		else if(defaultButton == IDNO)
+			flags |= MB_DEFBUTTON2;
+	}
+
+	CString messageText = description;
+	if(!headline.IsEmpty())
+		messageText = headline + _T("\n\n") + messageText;
+
+	// Workaround MessageBox text length limitation: Better show a truncated string than no message at all.
+	if(messageText.GetLength() > uint16_max)
+	{
+		messageText.Truncate(uint16_max);
+		messageText.SetAt(uint16_max - 1, _T('.'));
+		messageText.SetAt(uint16_max - 2, _T('.'));
+		messageText.SetAt(uint16_max - 3, _T('.'));
+	}
+	UINT result = ::MessageBox(parent->GetSafeHwnd(), messageText, windowTitle.IsEmpty() ? GetTitle() : windowTitle, flags | icon);
+	return {result, false};
+}
+
+
 void Reporting::Notification(const AnyStringLocale &text, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(CString(), LogNotification), LogLevelToFlags(LogNotification), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption({}, LogNotification))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.DoModal(parent);
 }
 void Reporting::Notification(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(mpt::ToCString(caption), LogNotification), LogLevelToFlags(LogNotification), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption(mpt::ToCString(caption), LogNotification))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.DoModal(parent);
 }
 
 
 void Reporting::Information(const AnyStringLocale &text, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(CString(), LogInformation), LogLevelToFlags(LogInformation), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption({}, LogInformation))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(MB_ICONINFORMATION)
+		.DoModal(parent);
 }
 void Reporting::Information(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(mpt::ToCString(caption), LogInformation), LogLevelToFlags(LogInformation), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption(mpt::ToCString(caption), LogInformation))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(MB_ICONINFORMATION)
+		.DoModal(parent);
 }
 
 
 void Reporting::Warning(const AnyStringLocale &text, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(CString(), LogWarning), LogLevelToFlags(LogWarning), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption({}, LogWarning))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(MB_ICONWARNING)
+		.DoModal(parent);
 }
 void Reporting::Warning(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(mpt::ToCString(caption), LogWarning), LogLevelToFlags(LogWarning), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption(mpt::ToCString(caption), LogWarning))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(MB_ICONWARNING)
+		.DoModal(parent);
 }
 
 
 void Reporting::Error(const AnyStringLocale &text, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(CString(), LogError), LogLevelToFlags(LogError), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption({}, LogError))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(MB_ICONERROR)
+		.DoModal(parent);
 }
 void Reporting::Error(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(mpt::ToCString(caption), LogError), LogLevelToFlags(LogError), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption(mpt::ToCString(caption), LogError))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(MB_ICONERROR)
+		.DoModal(parent);
 }
 
 
 void Reporting::Message(LogLevel level, const AnyStringLocale &text, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(CString(), level), LogLevelToFlags(level), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption({}, level))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(LogLevelToIcon(level))
+		.DoModal(parent);
 }
 void Reporting::Message(LogLevel level, const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent)
 {
-	ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(mpt::ToCString(caption), level), LogLevelToFlags(level), parent);
+	TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption(mpt::ToCString(caption), level))
+		.AddButton(GetButtonString(IDOK), IDOK)
+		.Icon(LogLevelToIcon(level))
+		.DoModal(parent);
 }
 
 
 ConfirmAnswer Reporting::Confirm(const AnyStringLocale &text, bool showCancel, bool defaultNo, const CWnd *parent)
 {
-	return Confirm(mpt::ToCString(text), GetTitle() + _T(" - Confirmation"), showCancel, defaultNo, parent);
+	return Confirm(text, GetTitle() + _T(" - Confirmation"), showCancel, defaultNo, parent);
 }
+ConfirmAnswer Reporting::Confirm(const AnyStringLocale &text, const AnyStringLocale &caption, bool showCancel, bool defaultNo, const CWnd *parent)
+{
+	std::vector<TaskDlg::Button> buttonList =
+	{
+		{GetButtonString(IDYES), IDYES},
+		{GetButtonString(IDNO), IDNO}
+	};
+	if(showCancel)
+		buttonList.push_back({GetButtonString(IDCANCEL), IDCANCEL});
 
+	TaskDlg params = TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption(mpt::ToCString(caption)))
+		.Buttons(buttonList)
+		.Icon(MB_ICONQUESTION);
 
-ConfirmAnswer Reporting::Confirm(const AnyStringLocale &text, const AnyStringLocale &caption, bool showCancel, bool defaultNo, const CWnd *parent)
-{
-	UINT result = ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(mpt::ToCString(caption)), (showCancel ? MB_YESNOCANCEL : MB_YESNO) | MB_ICONQUESTION | (defaultNo ? MB_DEFBUTTON2 : 0), parent);
+	if(defaultNo)
+		params.DefaultButton(IDNO);
+
+	auto result = params.DoModal(parent).buttonId;
 	switch(result)
 	{
 	case IDYES:
@@ -155,25 +353,18 @@
 		return cnfCancel;
 	}
 }
-
-
 RetryAnswer Reporting::RetryCancel(const AnyStringLocale &text, const CWnd *parent)
 {
-	return RetryCancel(mpt::ToCString(text), GetTitle(), parent);
+	return RetryCancel(text, GetTitle(), parent);
 }
-
-
 RetryAnswer Reporting::RetryCancel(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent)
 {
-	UINT result = ShowNotificationImpl(mpt::ToCString(text), FillEmptyCaption(mpt::ToCString(caption)), MB_RETRYCANCEL, parent);
-	switch(result)
-	{
-	case IDRETRY:
-		return rtyRetry;
-	default:
-	case IDCANCEL:
-		return rtyCancel;
-	}
+	auto result = TaskDlg{}
+		.Description(mpt::ToCString(text))
+		.WindowTitle(FillEmptyCaption(mpt::ToCString(caption)))
+		.Buttons({{GetButtonString(IDRETRY), IDRETRY}, {GetButtonString(IDCANCEL), IDCANCEL}})
+		.DoModal(parent).buttonId;
+	return (result == IDRETRY) ? rtyRetry : rtyCancel;
 }
 
 
Index: mptrack/Reporting.h
===================================================================
--- mptrack/Reporting.h	(revision 24083)
+++ mptrack/Reporting.h	(working copy)
@@ -12,10 +12,55 @@
 
 #include "openmpt/all/BuildSettings.hpp"
 
+#include <vector>
 
 OPENMPT_NAMESPACE_BEGIN
 
 
+struct TaskDlg
+{
+	// When assigning a custom command ID instead of IDOK/IDCANCEL/..., use this base offset
+	static constexpr int CUSTOM_ID_BASE = 200;
+
+	struct Button
+	{
+		CString text;
+		UINT commandId;
+	};
+
+	struct Result
+	{
+		UINT buttonId;
+		bool verificationChecked;
+	};
+
+	Result DoModal(const CWnd *parent = nullptr) const;
+
+	static bool ModernTaskDialogSupported();
+
+	TaskDlg &WindowTitle(CString title) { windowTitle = std::move(title); return *this; }
+	TaskDlg &Headline(CString text) { headline = std::move(text); return *this; }
+	TaskDlg &Description(CString text) { description = std::move(text); return *this; }
+	TaskDlg &AddButton(CString text, UINT commandID) { buttons.push_back({std::move(text), commandID}); return *this; }
+	TaskDlg &Buttons(std::vector<Button> buttonList) { buttons = std::move(buttonList); return *this; }
+	TaskDlg &DefaultButton(int commandID) { defaultButton = commandID; return *this; }
+	TaskDlg &Icon(UINT iconType) { icon = iconType; return *this; }
+	TaskDlg &VerificationText(CString text) { verificationText = std::move(text); return *this; }
+	TaskDlg &VerificationChecked(bool checked) { verificationChecked = checked; return *this; }
+	TaskDlg &UseBigButtons(bool useBigButtons) { bigButtons = useBigButtons; return *this; }
+
+protected:
+	CString windowTitle;
+	CString headline;
+	CString description;
+	CString verificationText;
+	std::vector<Button> buttons;
+	int defaultButton = 0;
+	UINT icon = 0;
+	bool verificationChecked = false;
+	bool bigButtons = false;
+};
+
 enum ConfirmAnswer
 {
 	cnfYes,
@@ -31,42 +76,39 @@
 };
 
 
-class Reporting
+namespace Reporting
 {
-
-public:
 	// Show a simple notification
-	static void Notification(const AnyStringLocale &text, const CWnd *parent = nullptr);
-	static void Notification(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
+	void Notification(const AnyStringLocale &text, const CWnd *parent = nullptr);
+	void Notification(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
 
 	// Show a simple information
-	static void Information(const AnyStringLocale &text, const CWnd *parent = nullptr);
-	static void Information(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
+	void Information(const AnyStringLocale &text, const CWnd *parent = nullptr);
+	void Information(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
 
 	// Show a simple warning
-	static void Warning(const AnyStringLocale &text, const CWnd *parent = nullptr);
-	static void Warning(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
+	void Warning(const AnyStringLocale &text, const CWnd *parent = nullptr);
+	void Warning(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
 
 	// Show an error box.
-	static void Error(const AnyStringLocale &text, const CWnd *parent = nullptr);
-	static void Error(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
+	void Error(const AnyStringLocale &text, const CWnd *parent = nullptr);
+	void Error(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
 
 	// Simplified version of the above
-	static void Message(LogLevel level, const AnyStringLocale &text, const CWnd *parent = nullptr);
-	static void Message(LogLevel level, const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
+	void Message(LogLevel level, const AnyStringLocale &text, const CWnd *parent = nullptr);
+	void Message(LogLevel level, const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
 
 	// Show a confirmation dialog.
-	static ConfirmAnswer Confirm(const AnyStringLocale &text, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr);
-	static ConfirmAnswer Confirm(const AnyStringLocale &text, const AnyStringLocale &caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr);
+	ConfirmAnswer Confirm(const AnyStringLocale &text, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr);
+	ConfirmAnswer Confirm(const AnyStringLocale &text, const AnyStringLocale &caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr);
 	// work-around string literals for caption decaying to bool and catching the wrong overload instead of converting to a string.
-	static ConfirmAnswer Confirm(const AnyStringLocale &text, const char *caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr) { return Confirm(text, AnyStringLocale(caption), showCancel, defaultNo, parent); }
-	static ConfirmAnswer Confirm(const AnyStringLocale &text, const wchar_t *caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr) { return Confirm(text, AnyStringLocale(caption), showCancel, defaultNo, parent); }
-	static ConfirmAnswer Confirm(const AnyStringLocale &text, const CString &caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr) { return Confirm(text, AnyStringLocale(caption), showCancel, defaultNo, parent); }
+	inline ConfirmAnswer Confirm(const AnyStringLocale &text, const char *caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr) { return Confirm(text, AnyStringLocale(caption), showCancel, defaultNo, parent); }
+	inline ConfirmAnswer Confirm(const AnyStringLocale &text, const wchar_t *caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr) { return Confirm(text, AnyStringLocale(caption), showCancel, defaultNo, parent); }
+	inline ConfirmAnswer Confirm(const AnyStringLocale &text, const CString &caption, bool showCancel = false, bool defaultNo = false, const CWnd *parent = nullptr) { return Confirm(text, AnyStringLocale(caption), showCancel, defaultNo, parent); }
 
 	// Show a confirmation dialog.
-	static RetryAnswer RetryCancel(const AnyStringLocale &text, const CWnd *parent = nullptr);
-	static RetryAnswer RetryCancel(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
-
+	RetryAnswer RetryCancel(const AnyStringLocale &text, const CWnd *parent = nullptr);
+	RetryAnswer RetryCancel(const AnyStringLocale &text, const AnyStringLocale &caption, const CWnd *parent = nullptr);
 };
 
 
