#if wxUSE_MSGDLG
-#include "wx/ptr_scpd.h"
-
// there is no hook support under CE so we can't use the code for message box
// positioning there
#ifndef __WXWINCE__
#endif
#ifndef WX_PRECOMP
+ #include "wx/msgdlg.h"
#include "wx/app.h"
#include "wx/intl.h"
#include "wx/utils.h"
- #include "wx/dialog.h"
+ #include "wx/msw/private.h"
#if wxUSE_MSGBOX_HOOK
#include "wx/hashmap.h"
#endif
#endif
+#include "wx/ptr_scpd.h"
#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"
{
if ( *i != '\n' )
{
- // found last non-newline char, remove everything after it and stop
- text.erase(i.base() + 1, text.end());
+ // found last non-newline char, remove anything after it if
+ // necessary and stop in any case
+ if ( i != text.rbegin() )
+ text.erase(i.base() + 1, text.end());
break;
}
}
return MSWTranslateReturnCode(msAns);
}
-int wxMessageDialog::ShowTaskDialog()
+int wxMessageDialog::ShowModal()
{
#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) )
+ if ( HasNativeTaskDialog() )
{
- wxLogApiError( "TaskDialogIndirect", hr );
- return wxID_CANCEL;
- }
+ TaskDialogIndirect_t taskDialogIndirect = GetTaskDialogIndirectFunc();
+ wxCHECK_MSG( taskDialogIndirect, wxID_CANCEL, wxS("no task dialog?") );
- return MSWTranslateReturnCode( msAns );
-#else
- wxFAIL_MSG( "Task dialogs are unavailable." );
+ WinStruct<TASKDIALOGCONFIG> tdc;
+ wxMSWTaskDialogConfig wxTdc( *this );
+ wxTdc.MSWCommonTaskDialogInit( tdc );
- return wxID_CANCEL;
-#endif // wxHAS_MSW_TASKDIALOG
-}
+ int msAns;
+ HRESULT hr = taskDialogIndirect( &tdc, &msAns, NULL, NULL );
+ if ( FAILED(hr) )
+ {
+ wxLogApiError( "TaskDialogIndirect", hr );
+ return wxID_CANCEL;
+ }
+ return MSWTranslateReturnCode( msAns );
+ }
+#endif // wxHAS_MSW_TASKDIALOG
+ return ShowMessageBox();
+}
-int wxMessageDialog::ShowModal()
+void wxMessageDialog::DoCentre(int dir)
{
+#ifdef wxHAS_MSW_TASKDIALOG
+ // Task dialog is always centered on its parent window and trying to center
+ // it manually doesn't work because its HWND is not created yet so don't
+ // even try as this would only result in (debug) error messages.
if ( HasNativeTaskDialog() )
- return ShowTaskDialog();
+ return;
+#endif // wxHAS_MSW_TASKDIALOG
- return ShowMessageBox();
+ wxMessageDialogBase::DoCentre(dir);
}
// ----------------------------------------------------------------------------
caption = dlg.GetCaption();
message = dlg.GetMessage();
extendedMessage = dlg.GetExtendedMessage();
+
+ // Before wxMessageDialog added support for extended message it was common
+ // practice to have long multiline texts in the message box with the first
+ // line playing the role of the main message and the rest of the extended
+ // one. Try to detect such usage automatically here by synthesizing the
+ // extended message on our own if it wasn't given.
+ if ( extendedMessage.empty() )
+ {
+ // Check if there is a blank separating line after the first line (this
+ // is not the same as searching for "\n\n" as we want the automatically
+ // recognized main message be single line to avoid embarrassing false
+ // positives).
+ const size_t posNL = message.find('\n');
+ if ( posNL != wxString::npos &&
+ posNL < message.length() - 1 &&
+ message[posNL + 1 ] == '\n' )
+ {
+ extendedMessage.assign(message, posNL + 2, wxString::npos);
+ message.erase(posNL);
+ }
+ }
+
iconId = dlg.GetEffectiveIcon();
style = dlg.GetMessageDialogStyle();
useCustomLabels = dlg.HasCustomLabels();
if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
tdc.dwFlags |= TDF_RTL_LAYOUT;
- tdc.pszMainInstruction = message.wx_str();
- tdc.pszContent = extendedMessage.wx_str();
+
+ // 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.wx_str();
+ tdc.pszContent = extendedMessage.wx_str();
+ }
+ else
+ {
+ tdc.pszContent = message.wx_str();
+ }
// set an icon to be used, if possible
switch ( iconId )
}
else // without Yes/No we're going to have an OK button
{
- AddTaskDialogButton(tdc, IDOK, TDCBF_OK_BUTTON, btnOKLabel);
-
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);
+ }
}
}
TaskDialogIndirect_t wxMSWMessageDialog::GetTaskDialogIndirectFunc()
{
- static TaskDialogIndirect_t s_TaskDialogIndirect = NULL;
+ // 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 )
+ if ( s_TaskDialogIndirect == INVALID_TASKDIALOG_FUNC )
{
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;
bool wxMSWMessageDialog::HasNativeTaskDialog()
{
#ifdef wxHAS_MSW_TASKDIALOG
- return wxGetWinVersion() >= wxWinVersion_6;
-#else
+ if ( wxGetWinVersion() >= wxWinVersion_6 )
+ {
+ if ( wxMSWMessageDialog::GetTaskDialogIndirectFunc() )
+ return true;
+ }
+#endif // wxHAS_MSW_TASKDIALOG
+
return false;
-#endif
}
int wxMSWMessageDialog::MSWTranslateReturnCode(int msAns)