#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
#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"
#include "wx/msw/wince/missing.h"
#endif
+using namespace wxMSWMessageDialog;
+
IMPLEMENT_CLASS(wxMessageDialog, wxDialog)
#if wxUSE_MSGBOX_HOOK
// ignored by the static control but result in extra lines and hence extra
// scrollbar position in the edit one
wxString text(wxGetWindowText(hwndStatic));
- for ( wxString::iterator i = text.end() - 1; i != text.begin(); --i )
+ for ( wxString::reverse_iterator i = text.rbegin(); i != text.rend(); ++i )
{
if ( *i != '\n' )
{
- text.erase(i + 1, text.end());
+ // found last non-newline char, remove everything after it and stop
+ text.erase(i.base() + 1, text.end());
break;
}
}
rc.right - rc.left, rc.bottom - rc.top,
GetHwnd(),
NULL,
- wxhInstance,
+ wxGetInstance(),
NULL
);
return wxNativeFontInfo(ncm.lfMessageFont);
}
-int wxMessageDialog::ShowModal()
+int wxMessageDialog::ShowMessageBox()
{
if ( !wxTheApp->GetTopWindow() )
{
}
// 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
}
}
- if (wxStyle & wxICON_EXCLAMATION)
- msStyle |= MB_ICONEXCLAMATION;
- else if (wxStyle & wxICON_HAND)
- msStyle |= MB_ICONHAND;
- else if (wxStyle & wxICON_INFORMATION)
- msStyle |= MB_ICONINFORMATION;
- else if (wxStyle & wxICON_QUESTION)
- msStyle |= MB_ICONQUESTION;
+ // set the icon style
+ switch ( GetEffectiveIcon() )
+ {
+ case wxICON_ERROR:
+ msStyle |= MB_ICONHAND;
+ break;
+
+ case wxICON_WARNING:
+ msStyle |= MB_ICONEXCLAMATION;
+ break;
+
+ case wxICON_QUESTION:
+ msStyle |= MB_ICONQUESTION;
+ break;
+
+ case wxICON_INFORMATION:
+ msStyle |= MB_ICONINFORMATION;
+ break;
+ }
if ( wxStyle & wxSTAY_ON_TOP )
msStyle |= MB_TOPMOST;
// 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<TASKDIALOGCONFIG> 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:
ans = wxID_NO;
break;
}
+
return ans;
}