X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a4578b0ceda90e103620894d3aa86284178ab1cd..0a9c5e3564ed35162bb8cab5af62a98405364fb8:/src/msw/msgdlg.cpp diff --git a/src/msw/msgdlg.cpp b/src/msw/msgdlg.cpp index feddca7521..50191c6f77 100644 --- a/src/msw/msgdlg.cpp +++ b/src/msw/msgdlg.cpp @@ -18,7 +18,7 @@ #if wxUSE_MSGDLG -#include "wx/msgdlg.h" +#include "wx/ptr_scpd.h" // there is no hook support under CE so we can't use the code for message box // positioning there @@ -38,9 +38,12 @@ #endif #endif +#include "wx/dynlib.h" #include "wx/msw/private.h" #include "wx/msw/private/button.h" #include "wx/msw/private/metrics.h" +#include "wx/msw/private/msgdlg.h" +#include "wx/msgdlg.h" #if wxUSE_MSGBOX_HOOK #include "wx/fontutil.h" @@ -53,6 +56,8 @@ #include "wx/msw/wince/missing.h" #endif +using namespace wxMSWMessageDialog; + IMPLEMENT_CLASS(wxMessageDialog, wxDialog) #if wxUSE_MSGBOX_HOOK @@ -430,7 +435,7 @@ wxFont wxMessageDialog::GetMessageFont() return wxNativeFontInfo(ncm.lfMessageFont); } -int wxMessageDialog::ShowModal() +int wxMessageDialog::ShowMessageBox() { if ( !wxTheApp->GetTopWindow() ) { @@ -443,8 +448,7 @@ int wxMessageDialog::ShowModal() } // use the top level window as parent if none specified - if ( !m_parent ) - m_parent = GetParentForModalDialog(); + m_parent = GetParentForModalDialog(); HWND hWnd = m_parent ? GetHwndOf(m_parent) : NULL; #if wxUSE_INTL @@ -565,11 +569,194 @@ int wxMessageDialog::ShowModal() // do show the dialog int msAns = MessageBox(hWnd, message.wx_str(), m_caption.wx_str(), msStyle); + + return MSWTranslateReturnCode(msAns); +} + +int wxMessageDialog::ShowTaskDialog() +{ +#ifdef wxHAS_MSW_TASKDIALOG + TaskDialogIndirect_t taskDialogIndirect = GetTaskDialogIndirectFunc(); + if ( !taskDialogIndirect ) + return wxID_CANCEL; + + WinStruct tdc; + wxMSWTaskDialogConfig wxTdc( *this ); + wxTdc.MSWCommonTaskDialogInit( tdc ); + + int msAns; + HRESULT hr = taskDialogIndirect( &tdc, &msAns, NULL, NULL ); + if ( FAILED(hr) ) + { + wxLogApiError( "TaskDialogIndirect", hr ); + return wxID_CANCEL; + } + + return MSWTranslateReturnCode( msAns ); +#else + wxFAIL_MSG( "Task dialogs are unavailable." ); + + return wxID_CANCEL; +#endif // wxHAS_MSW_TASKDIALOG +} + + + +int wxMessageDialog::ShowModal() +{ + if ( HasNativeTaskDialog() ) + return ShowTaskDialog(); + + return ShowMessageBox(); +} + +// ---------------------------------------------------------------------------- +// Helpers of the wxMSWMessageDialog namespace +// ---------------------------------------------------------------------------- + +#ifdef wxHAS_MSW_TASKDIALOG + +wxMSWTaskDialogConfig::wxMSWTaskDialogConfig(const wxMessageDialogBase& dlg) + : buttons(new TASKDIALOG_BUTTON[3]) +{ + parent = dlg.GetParentForModalDialog(); + caption = dlg.GetCaption(); + message = dlg.GetMessage(); + extendedMessage = dlg.GetExtendedMessage(); + iconId = dlg.GetEffectiveIcon(); + style = dlg.GetMessageDialogStyle(); + useCustomLabels = dlg.HasCustomLabels(); + btnYesLabel = dlg.GetYesLabel(); + btnNoLabel = dlg.GetNoLabel(); + btnOKLabel = dlg.GetOKLabel(); + btnCancelLabel = dlg.GetCancelLabel(); +} + +void wxMSWTaskDialogConfig::MSWCommonTaskDialogInit(TASKDIALOGCONFIG &tdc) +{ + tdc.dwFlags = TDF_EXPAND_FOOTER_AREA | TDF_POSITION_RELATIVE_TO_WINDOW; + tdc.hInstance = wxGetInstance(); + tdc.pszWindowTitle = caption.wx_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; + tdc.pszMainInstruction = message.wx_str(); + tdc.pszContent = extendedMessage.wx_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 + { + AddTaskDialogButton(tdc, IDOK, TDCBF_OK_BUTTON, btnOKLabel); + + if ( style & wxCANCEL ) + { + AddTaskDialogButton(tdc, IDCANCEL, + TDCBF_CANCEL_BUTTON, btnCancelLabel); + + if ( style & wxCANCEL_DEFAULT ) + tdc.nDefaultButton = IDCANCEL; + } + } +} + +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.wx_str(); + tdc.cButtons++; + } + 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() +{ + static TaskDialogIndirect_t s_TaskDialogIndirect = NULL; + + wxCRIT_SECT_LOCKER(lock, gs_csTaskDialogIndirect); + + if ( !s_TaskDialogIndirect ) + { + wxLoadedDLL dllComCtl32("comctl32.dll"); + wxDL_INIT_FUNC(s_, TaskDialogIndirect, dllComCtl32); + + // We must always succeed as this code is only executed under Vista and + // later which must have task dialog support. + wxASSERT_MSG( s_TaskDialogIndirect, + "Task dialog support unexpectedly not available" ); + } + + return s_TaskDialogIndirect; +} + +#endif // wxHAS_MSW_TASKDIALOG + +bool wxMSWMessageDialog::HasNativeTaskDialog() +{ +#ifdef wxHAS_MSW_TASKDIALOG + return wxGetWinVersion() >= wxWinVersion_6; +#else + return false; +#endif +} + +int wxMSWMessageDialog::MSWTranslateReturnCode(int msAns) +{ int ans; switch (msAns) { default: - wxFAIL_MSG(wxT("unexpected ::MessageBox() return code")); + wxFAIL_MSG(wxT("unexpected return code")); // fall through case IDCANCEL: @@ -585,6 +772,7 @@ int wxMessageDialog::ShowModal() ans = wxID_NO; break; } + return ans; }