virtual int ShowModal();
protected:
+ // Creates a message dialog taking any options that have been set after
+ // object creation into account such as custom labels.
+ void DoCreateMsgdialog();
+
void OnYes(wxCommandEvent& event);
void OnNo(wxCommandEvent& event);
void OnCancel(wxCommandEvent& event);
-private:
- void DoCreateMsgdialog();
+ // can be overridden to provide more contents to the dialog
+ virtual void AddMessageDialogCheckBox(wxSizer *WXUNUSED(sizer)) { }
+ virtual void AddMessageDialogDetails(wxSizer *WXUNUSED(sizer)) { }
+private:
wxPoint m_pos;
bool m_created;
#ifndef _WX_GTK_MSGDLG_H_
#define _WX_GTK_MSGDLG_H_
-class WXDLLIMPEXP_CORE wxMessageDialog : public wxMessageDialogWithCustomLabels
+class WXDLLIMPEXP_CORE wxMessageDialog : public wxMessageDialogBase
{
public:
wxMessageDialog(wxWindow *parent, const wxString& message,
const int m_stockId;
};
-
// ctors
wxMessageDialogBase() { m_dialogStyle = 0; }
wxMessageDialogBase(wxWindow *parent,
// virtual dtor for the base class
virtual ~wxMessageDialogBase() { }
-
- // methods for setting up more custom message dialogs -- all functions
- // return false if they're not implemented
- virtual bool SetYesNoLabels(const ButtonLabel& WXUNUSED(yes),
- const ButtonLabel& WXUNUSED(no))
- {
- return false;
- }
-
- virtual bool SetYesNoCancelLabels(const ButtonLabel& WXUNUSED(yes),
- const ButtonLabel& WXUNUSED(no),
- const ButtonLabel& WXUNUSED(cancel))
- {
- return false;
- }
-
- virtual bool SetOKLabel(const ButtonLabel& WXUNUSED(ok))
- {
- return false;
- }
-
- virtual bool SetOKCancelLabels(const ButtonLabel& WXUNUSED(ok),
- const ButtonLabel& WXUNUSED(cancel))
- {
- return false;
- }
+ wxString GetCaption() const { return m_caption; }
virtual void SetMessage(const wxString& message)
{
m_message = message;
}
- virtual void SetExtendedMessage(const wxString& extendedMessage)
+ wxString GetMessage() const { return m_message; }
+
+ void SetExtendedMessage(const wxString& extendedMessage)
{
m_extendedMessage = extendedMessage;
}
+ wxString GetExtendedMessage() const { return m_extendedMessage; }
+
// change the dialog style flag
void SetMessageDialogStyle(long style)
{
m_dialogStyle = style;
}
-protected:
long GetMessageDialogStyle() const { return m_dialogStyle; }
- // based on message dialog style, returns exactly one of: wxICON_NONE,
- // wxICON_ERROR, wxICON_WARNING, wxICON_QUESTION, wxICON_INFORMATION
- long GetEffectiveIcon() const
- {
- if ( m_dialogStyle & wxICON_NONE )
- return wxICON_NONE;
- else if ( m_dialogStyle & wxICON_ERROR )
- return wxICON_ERROR;
- else if ( m_dialogStyle & wxICON_WARNING )
- return wxICON_WARNING;
- else if ( m_dialogStyle & wxICON_QUESTION )
- return wxICON_QUESTION;
- else if ( m_dialogStyle & wxICON_INFORMATION )
- return wxICON_INFORMATION;
- else if ( m_dialogStyle & wxYES )
- return wxICON_QUESTION;
- else
- return wxICON_INFORMATION;
- }
-
-
- // for the platforms not supporting separate main and extended messages
- // this function should be used to combine both of them in a single string
- wxString GetFullMessage() const
- {
- wxString msg = m_message;
- if ( !m_extendedMessage.empty() )
- msg << "\n\n" << m_extendedMessage;
-
- return msg;
- }
-
- wxString m_message,
- m_extendedMessage,
- m_caption;
- long m_dialogStyle;
-
- wxDECLARE_NO_COPY_CLASS(wxMessageDialogBase);
-};
-
-// this is a helper class for native wxMessageDialog implementations which need
-// to store the custom button labels as member variables and then use them in
-// ShowModal() (there could conceivably be a port which would have some native
-// functions for setting these labels immediately and we also don't need to
-// store them at all if custom labels are not supported, which is why we do
-// this in a separate class and not wxMessageDialogBase itself)
-#if defined(__WXCOCOA__) || \
- defined(__WXGTK20__) || \
- defined(__WXMAC__) || \
- defined(__WXMSW__)
-
-class WXDLLIMPEXP_CORE wxMessageDialogWithCustomLabels
- : public wxMessageDialogBase
-{
-public:
- // ctors
- wxMessageDialogWithCustomLabels() { }
- wxMessageDialogWithCustomLabels(wxWindow *parent,
- const wxString& message,
- const wxString& caption,
- long style)
- : wxMessageDialogBase(parent, message, caption, style)
- {
- }
-
// customization of the message box buttons
virtual bool SetYesNoLabels(const ButtonLabel& yes,const ButtonLabel& no)
{
return true;
}
-protected:
// test if any custom labels were set
bool HasCustomLabels() const
{
wxString GetCancelLabel() const
{ return m_cancel.empty() ? GetDefaultCancelLabel() : m_cancel; }
+ // based on message dialog style, returns exactly one of: wxICON_NONE,
+ // wxICON_ERROR, wxICON_WARNING, wxICON_QUESTION, wxICON_INFORMATION
+ long GetEffectiveIcon() const
+ {
+ if ( m_dialogStyle & wxICON_NONE )
+ return wxICON_NONE;
+ else if ( m_dialogStyle & wxICON_ERROR )
+ return wxICON_ERROR;
+ else if ( m_dialogStyle & wxICON_WARNING )
+ return wxICON_WARNING;
+ else if ( m_dialogStyle & wxICON_QUESTION )
+ return wxICON_QUESTION;
+ else if ( m_dialogStyle & wxICON_INFORMATION )
+ return wxICON_INFORMATION;
+ else if ( m_dialogStyle & wxYES )
+ return wxICON_QUESTION;
+ else
+ return wxICON_INFORMATION;
+ }
+
+protected:
+ // for the platforms not supporting separate main and extended messages
+ // this function should be used to combine both of them in a single string
+ wxString GetFullMessage() const
+ {
+ wxString msg = m_message;
+ if ( !m_extendedMessage.empty() )
+ msg << "\n\n" << m_extendedMessage;
+
+ return msg;
+ }
+
+ wxString m_message,
+ m_extendedMessage,
+ m_caption;
+ long m_dialogStyle;
+
// this function is called by our public SetXXXLabels() and should assign
// the value to var with possibly some transformation (e.g. Cocoa version
// currently uses this to remove any accelerators from the button strings
m_ok,
m_cancel;
- wxDECLARE_NO_COPY_CLASS(wxMessageDialogWithCustomLabels);
+ wxDECLARE_NO_COPY_CLASS(wxMessageDialogBase);
};
-#endif // ports needing wxMessageDialogWithCustomLabels
+#include "wx/generic/msgdlgg.h"
#if defined(__WX_COMPILING_MSGDLGG_CPP__) || \
defined(__WXUNIVERSAL__) || defined(__WXGPE__) || \
(defined(__WXGTK__) && !defined(__WXGTK20__))
- #include "wx/generic/msgdlgg.h"
#define wxMessageDialog wxGenericMessageDialog
#elif defined(__WXCOCOA__)
#ifndef _WX_MSGBOXDLG_H_
#define _WX_MSGBOXDLG_H_
-class WXDLLIMPEXP_CORE wxMessageDialog : public wxMessageDialogWithCustomLabels
+class WXDLLIMPEXP_CORE wxMessageDialog : public wxMessageDialogBase
{
public:
wxMessageDialog(wxWindow *parent,
const wxString& caption = wxMessageBoxCaptionStr,
long style = wxOK|wxCENTRE,
const wxPoint& WXUNUSED(pos) = wxDefaultPosition)
- : wxMessageDialogWithCustomLabels(parent, message, caption, style)
+ : wxMessageDialogBase(parent, message, caption, style)
{
m_hook = NULL;
}
// offset all buttons starting from the first one given by dx to the right
void OffsetButtonsStartingFrom(int first, int dx);
+ // used by ShowModal() to display a message box when task dialogs
+ // aren't available.
+ int ShowMessageBox();
+
+ // used by ShowModal() to display a task dialog.
+ int ShowTaskDialog();
WXHANDLE m_hook; // HHOOK used to position the message box
- DECLARE_DYNAMIC_CLASS(wxMessageDialog)
- wxDECLARE_NO_COPY_CLASS(wxMessageDialog);
+ wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxMessageDialog);
};
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/msw/private/msgdlg.h
+// Purpose: helper functions used with native message dialog
+// Author: Rickard Westerlund
+// Created: 2010-07-12
+// RCS-ID: $Id$
+// Copyright: (c) 2010 wxWidgets team
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_MSW_PRIVATE_MSGDLG_H_
+#define _WX_MSW_PRIVATE_MSGDLG_H_
+
+#include "wx/msw/wrapcctl.h"
+#include "wx/scopedarray.h"
+
+// Macro to help identify if task dialogs are available: we rely on
+// TD_WARNING_ICON being defined in the headers for this as this symbol is used
+// by the task dialogs only. Also notice that task dialogs are available for
+// Unicode applications only.
+#if defined(TD_WARNING_ICON) && wxUSE_UNICODE
+ #define wxHAS_MSW_TASKDIALOG
+#endif
+
+// Provides methods for creating a task dialog.
+namespace wxMSWMessageDialog
+{
+
+#ifdef wxHAS_MSW_TASKDIALOG
+ class wxMSWTaskDialogConfig
+ {
+ public:
+ wxMSWTaskDialogConfig()
+ : buttons(new TASKDIALOG_BUTTON[3]),
+ parent(NULL),
+ iconId(0),
+ style(0),
+ useCustomLabels(false)
+ { }
+
+ // initializes the object from a message dialog.
+ wxMSWTaskDialogConfig(const wxMessageDialogBase& dlg);
+
+ wxScopedArray<TASKDIALOG_BUTTON> buttons;
+ wxWindow *parent;
+ wxString caption;
+ wxString message;
+ wxString extendedMessage;
+ long iconId;
+ long style;
+ bool useCustomLabels;
+ wxString btnYesLabel;
+ wxString btnNoLabel;
+ wxString btnOKLabel;
+ wxString btnCancelLabel;
+
+ // Will create a task dialog with it's paremeters for it's creation
+ // stored in the provided TASKDIALOGCONFIG parameter.
+ // NOTE: The wxMSWTaskDialogConfig object needs to remain accessible
+ // during the subsequent call to TaskDialogIndirect().
+ void MSWCommonTaskDialogInit(TASKDIALOGCONFIG &tdc);
+
+ // Used by MSWCommonTaskDialogInit() to add a regular button or a
+ // button with a custom label if used.
+ void AddTaskDialogButton(TASKDIALOGCONFIG &tdc,
+ int btnCustomId,
+ int btnCommonId,
+ const wxString& customLabel);
+ }; // class wxMSWTaskDialogConfig
+
+
+ typedef HRESULT (WINAPI *TaskDialogIndirect_t)(const TASKDIALOGCONFIG *,
+ int *, int *, BOOL *);
+
+ // Return the pointer to TaskDialogIndirect(). This should only be called
+ // if HasNativeTaskDialog() returned true and is normally guaranteed to
+ // succeed in this case.
+ TaskDialogIndirect_t GetTaskDialogIndirectFunc();
+#endif // wxHAS_MSW_TASKDIALOG
+
+
+ // Check if the task dialog is available: this simply checks the OS version
+ // as we know that it's only present in Vista and later.
+ bool HasNativeTaskDialog();
+
+ // Translates standard MSW button IDs like IDCANCEL into an equivalent
+ // wx constant such as wxCANCEL.
+ int MSWTranslateReturnCode(int msAns);
+}; // namespace wxMSWMessageDialog
+
+#endif // _WX_MSW_PRIVATE_MSGDLG_H_
#ifndef _WX_MSGBOXDLG_H_
#define _WX_MSGBOXDLG_H_
-class WXDLLIMPEXP_CORE wxMessageDialog : public wxMessageDialogWithCustomLabels
+class WXDLLIMPEXP_CORE wxMessageDialog : public wxMessageDialogBase
{
public:
wxMessageDialog(wxWindow *parent,
@style{wxICON_QUESTION}
Displays a question mark symbol. This icon is automatically used
with @c wxYES_NO so it's usually unnecessary to specify it explicitly.
+ This style is not supported for MSW task dialogs, as question icons do
+ not follow the guidelines. No icon will be displayed in this case.
@style{wxICON_INFORMATION}
Displays an information symbol. This icon is used by default if
@c wxYES_NO is not given so it is usually unnecessary to specify it
just its parent (currently implemented only under MSW and GTK).
@style{wxCENTRE}
Centre the message box on its parent or on the screen if parent is not
- specified (currently only implemented under MSW).
+ specified.
+ Setting this style under MSW makes no differences as the dialog is
+ always centered on the parent.
@endStyleTable
@library{wxcore}
#pragma hdrstop
#endif
-#if wxUSE_MSGDLG && (!defined(__WXGTK20__) || defined(__WXUNIVERSAL__) || defined(__WXGPE__))
+#if wxUSE_MSGDLG
#ifndef WX_PRECOMP
#include "wx/utils.h"
topsizer->Add( icon_text, 1, wxCENTER | wxLEFT|wxRIGHT|wxTOP, 10 );
#endif // wxUSE_STATTEXT
- // 3) buttons
+ // 3) optional checkbox and detailed text
+ AddMessageDialogCheckBox( topsizer );
+ AddMessageDialogDetails( topsizer );
+
+ // 4) buttons
int center_flag = wxEXPAND;
if (m_dialogStyle & wxYES_NO)
center_flag = wxALIGN_CENTRE;
return wxMessageDialogBase::ShowModal();
}
-#endif // wxUSE_MSGDLG && !defined(__WXGTK20__)
+#endif // wxUSE_MSGDLG
const wxString& caption,
long style,
const wxPoint& WXUNUSED(pos))
- : wxMessageDialogWithCustomLabels
+ : wxMessageDialogBase
(
GetParentForModalDialog(parent, style),
message,
int stockId = label.GetStockId();
if ( stockId == wxID_NONE )
{
- wxMessageDialogWithCustomLabels::DoSetCustomLabel(var, label);
+ wxMessageDialogBase::DoSetCustomLabel(var, label);
var = wxConvertMnemonicsToGTK(var);
}
else // stock label
#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
return wxNativeFontInfo(ncm.lfMessageFont);
}
-int wxMessageDialog::ShowModal()
+int wxMessageDialog::ShowMessageBox()
{
if ( !wxTheApp->GetTopWindow() )
{
// 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;
}
const wxString& caption,
long style,
const wxPoint& WXUNUSED(pos))
- : wxMessageDialogWithCustomLabels(parent, message, caption, style)
+ : wxMessageDialogBase(parent, message, caption, style)
{
}
const wxString& caption,
long style,
const wxPoint& WXUNUSED(pos))
- : wxMessageDialogWithCustomLabels(parent, message, caption, style)
+ : wxMessageDialogBase(parent, message, caption, style)
{
}
const wxString& caption,
long style,
const wxPoint& WXUNUSED(pos))
- : wxMessageDialogWithCustomLabels(parent, message, caption, style)
+ : wxMessageDialogBase(parent, message, caption, style)
{
}