+ iconId = dlg.GetEffectiveIcon();
+ style = dlg.GetMessageDialogStyle();
+ useCustomLabels = dlg.HasCustomLabels();
+ btnYesLabel = dlg.GetYesLabel();
+ btnNoLabel = dlg.GetNoLabel();
+ btnOKLabel = dlg.GetOKLabel();
+ btnCancelLabel = dlg.GetCancelLabel();
+ btnHelpLabel = dlg.GetHelpLabel();
+}
+
+void wxMSWTaskDialogConfig::MSWCommonTaskDialogInit(TASKDIALOGCONFIG &tdc)
+{
+ // Use TDF_SIZE_TO_CONTENT to try to prevent Windows from truncating or
+ // ellipsizing the message text. This doesn't always work as Windows will
+ // still do it if the message contains too long "words" (i.e. runs of the
+ // text without spaces) but at least it ensures that the message text is
+ // fully shown for reasonably-sized words whereas without it using almost
+ // any file system path in a message box would result in truncation.
+ tdc.dwFlags = TDF_EXPAND_FOOTER_AREA |
+ TDF_POSITION_RELATIVE_TO_WINDOW |
+ TDF_SIZE_TO_CONTENT;
+ tdc.hInstance = wxGetInstance();
+ tdc.pszWindowTitle = caption.t_str();
+
+ // use the top level window as parent if none specified
+ tdc.hwndParent = parent ? GetHwndOf(parent) : NULL;
+
+ if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+ tdc.dwFlags |= TDF_RTL_LAYOUT;
+
+ // If we have both the main and extended messages, just use them as
+ // intended. However if only one message is given we normally use it as the
+ // content and not as the main instruction because the latter is supposed
+ // to stand out compared to the former and doesn't look good if there is
+ // nothing for it to contrast with. Finally, notice that the extended
+ // message we use here might be automatically extracted from the main
+ // message in our ctor, see comment there.
+ if ( !extendedMessage.empty() )
+ {
+ tdc.pszMainInstruction = message.t_str();
+ tdc.pszContent = extendedMessage.t_str();
+ }
+ else
+ {
+ tdc.pszContent = message.t_str();
+ }
+
+ // set an icon to be used, if possible
+ switch ( iconId )
+ {
+ case wxICON_ERROR:
+ tdc.pszMainIcon = TD_ERROR_ICON;
+ break;
+
+ case wxICON_WARNING:
+ tdc.pszMainIcon = TD_WARNING_ICON;
+ break;
+
+ case wxICON_INFORMATION:
+ tdc.pszMainIcon = TD_INFORMATION_ICON;
+ break;
+ }
+
+ // custom label button array that can hold all buttons in use
+ tdc.pButtons = buttons.get();
+
+ if ( style & wxYES_NO )
+ {
+ AddTaskDialogButton(tdc, IDYES, TDCBF_YES_BUTTON, btnYesLabel);
+ AddTaskDialogButton(tdc, IDNO, TDCBF_NO_BUTTON, btnNoLabel);
+
+ if (style & wxCANCEL)
+ AddTaskDialogButton(tdc, IDCANCEL,
+ TDCBF_CANCEL_BUTTON, btnCancelLabel);
+
+ if ( style & wxNO_DEFAULT )
+ tdc.nDefaultButton = IDNO;
+ else if ( style & wxCANCEL_DEFAULT )
+ tdc.nDefaultButton = IDCANCEL;
+ }
+ else // without Yes/No we're going to have an OK button
+ {
+ if ( style & wxCANCEL )
+ {
+ AddTaskDialogButton(tdc, IDOK, TDCBF_OK_BUTTON, btnOKLabel);
+ AddTaskDialogButton(tdc, IDCANCEL,
+ TDCBF_CANCEL_BUTTON, btnCancelLabel);
+
+ if ( style & wxCANCEL_DEFAULT )
+ tdc.nDefaultButton = IDCANCEL;
+ }
+ else // Only "OK"
+ {
+ // We actually create a "Cancel" button instead because we want to
+ // allow closing the dialog box with Escape (and also Alt-F4 or
+ // clicking the close button in the title bar) which wouldn't work
+ // without a Cancel button.
+ if ( !useCustomLabels )
+ {
+ useCustomLabels = true;
+ btnOKLabel = _("OK");
+ }
+
+ AddTaskDialogButton(tdc, IDCANCEL, TDCBF_CANCEL_BUTTON, btnOKLabel);
+ }
+ }
+
+ if ( style & wxHELP )
+ {
+ // There is no support for "Help" button in the task dialog, it can
+ // only show "Retry" or "Close" ones.
+ useCustomLabels = true;
+
+ AddTaskDialogButton(tdc, IDHELP, 0 /* not used */, btnHelpLabel);
+ }
+}
+
+void wxMSWTaskDialogConfig::AddTaskDialogButton(TASKDIALOGCONFIG &tdc,
+ int btnCustomId,
+ int btnCommonId,
+ const wxString& customLabel)
+{
+ if ( useCustomLabels )
+ {
+ // use custom buttons to implement custom labels
+ TASKDIALOG_BUTTON &tdBtn = buttons[tdc.cButtons];
+
+ tdBtn.nButtonID = btnCustomId;
+ tdBtn.pszButtonText = customLabel.t_str();
+ tdc.cButtons++;
+
+ // We should never have more than 4 buttons currently as this is the
+ // maximal number of buttons supported by the message dialog.
+ wxASSERT_MSG( tdc.cButtons <= MAX_BUTTONS, wxT("Too many buttons") );
+ }
+ else
+ {
+ tdc.dwCommonButtons |= btnCommonId;
+ }
+}
+
+// Task dialog can be used from different threads (and wxProgressDialog always
+// uses it from another thread in fact) so protect access to the static
+// variable below with a critical section.
+wxCRIT_SECT_DECLARE(gs_csTaskDialogIndirect);
+
+TaskDialogIndirect_t wxMSWMessageDialog::GetTaskDialogIndirectFunc()
+{
+ // Initialize the function pointer to an invalid value different from NULL
+ // to avoid reloading comctl32.dll and trying to resolve it every time
+ // we're called if task dialog is not available (notice that this may
+ // happen even under Vista+ if we don't use comctl32.dll v6).
+ static const TaskDialogIndirect_t
+ INVALID_TASKDIALOG_FUNC = reinterpret_cast<TaskDialogIndirect_t>(-1);
+ static TaskDialogIndirect_t s_TaskDialogIndirect = INVALID_TASKDIALOG_FUNC;
+
+ wxCRIT_SECT_LOCKER(lock, gs_csTaskDialogIndirect);
+
+ if ( s_TaskDialogIndirect == INVALID_TASKDIALOG_FUNC )
+ {
+ wxLoadedDLL dllComCtl32("comctl32.dll");
+ wxDL_INIT_FUNC(s_, TaskDialogIndirect, dllComCtl32);
+ }
+
+ return s_TaskDialogIndirect;
+}
+
+#endif // wxHAS_MSW_TASKDIALOG
+
+bool wxMSWMessageDialog::HasNativeTaskDialog()
+{
+#ifdef wxHAS_MSW_TASKDIALOG
+ if ( wxGetWinVersion() >= wxWinVersion_6 )
+ {
+ if ( wxMSWMessageDialog::GetTaskDialogIndirectFunc() )
+ return true;
+ }
+#endif // wxHAS_MSW_TASKDIALOG
+
+ return false;
+}
+
+int wxMSWMessageDialog::MSWTranslateReturnCode(int msAns)
+{