Use new wxAppTraits::SafeMessageBox() in wxSafeShowMessage()
This allows to show message boxes in ports other than wxMSW too by doing it only when it is safe, i.e. when the GUI is initialized, while still keeping the old code directly using the native MessageBox() function for MSW for maximal robustness.
This commit is contained in:
@@ -88,6 +88,16 @@ public:
|
|||||||
// return true to suppress subsequent asserts, false to continue as before
|
// return true to suppress subsequent asserts, false to continue as before
|
||||||
virtual bool ShowAssertDialog(const wxString& msg) = 0;
|
virtual bool ShowAssertDialog(const wxString& msg) = 0;
|
||||||
|
|
||||||
|
// show the message safely to the user, i.e. show it in a message box if
|
||||||
|
// possible (even in a console application!) or return false if we can't do
|
||||||
|
// it (e.g. GUI is not initialized at all)
|
||||||
|
//
|
||||||
|
// note that this function can be called even when wxApp doesn't exist, as
|
||||||
|
// it's supposed to be always safe to call -- hence the name
|
||||||
|
//
|
||||||
|
// return true if the message box was shown, false if nothing was done
|
||||||
|
virtual bool SafeMessageBox(const wxString& text, const wxString& title) = 0;
|
||||||
|
|
||||||
// return true if fprintf(stderr) goes somewhere, false otherwise
|
// return true if fprintf(stderr) goes somewhere, false otherwise
|
||||||
virtual bool HasStderr() = 0;
|
virtual bool HasStderr() = 0;
|
||||||
|
|
||||||
@@ -208,6 +218,8 @@ public:
|
|||||||
|
|
||||||
virtual bool ShowAssertDialog(const wxString& msg) wxOVERRIDE;
|
virtual bool ShowAssertDialog(const wxString& msg) wxOVERRIDE;
|
||||||
virtual bool HasStderr() wxOVERRIDE;
|
virtual bool HasStderr() wxOVERRIDE;
|
||||||
|
virtual bool SafeMessageBox(const wxString& text,
|
||||||
|
const wxString& title) wxOVERRIDE;
|
||||||
|
|
||||||
// the GetToolkitVersion for console application is always the same
|
// the GetToolkitVersion for console application is always the same
|
||||||
wxPortId GetToolkitVersion(int *verMaj = NULL,
|
wxPortId GetToolkitVersion(int *verMaj = NULL,
|
||||||
@@ -248,6 +260,13 @@ public:
|
|||||||
virtual bool ShowAssertDialog(const wxString& msg) wxOVERRIDE;
|
virtual bool ShowAssertDialog(const wxString& msg) wxOVERRIDE;
|
||||||
virtual bool HasStderr() wxOVERRIDE;
|
virtual bool HasStderr() wxOVERRIDE;
|
||||||
|
|
||||||
|
// Win32 has its own implementation using native message box directly in
|
||||||
|
// the base class, don't override it.
|
||||||
|
#ifndef __WIN32__
|
||||||
|
virtual bool SafeMessageBox(const wxString& text,
|
||||||
|
const wxString& title) wxOVERRIDE;
|
||||||
|
#endif // !__WIN32__
|
||||||
|
|
||||||
virtual bool IsUsingUniversalWidgets() const wxOVERRIDE
|
virtual bool IsUsingUniversalWidgets() const wxOVERRIDE
|
||||||
{
|
{
|
||||||
#ifdef __WXUNIVERSAL__
|
#ifdef __WXUNIVERSAL__
|
||||||
|
@@ -61,6 +61,10 @@ public:
|
|||||||
// return the main application window or 0 if none
|
// return the main application window or 0 if none
|
||||||
virtual WXHWND GetMainHWND() const = 0;
|
virtual WXHWND GetMainHWND() const = 0;
|
||||||
|
|
||||||
|
// implement this base class function for both console and GUI applications
|
||||||
|
virtual bool SafeMessageBox(const wxString& text,
|
||||||
|
const wxString& title) wxOVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
// implementation of WaitForThread() for the console applications which is
|
// implementation of WaitForThread() for the console applications which is
|
||||||
|
@@ -133,5 +133,28 @@ public:
|
|||||||
Returns @true to suppress subsequent asserts, @false to continue as before.
|
Returns @true to suppress subsequent asserts, @false to continue as before.
|
||||||
*/
|
*/
|
||||||
virtual bool ShowAssertDialog(const wxString& msg) = 0;
|
virtual bool ShowAssertDialog(const wxString& msg) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Shows a message box with the given text and title if possible.
|
||||||
|
|
||||||
|
In some ports, e.g. wxMSW, a message box will always be shown, while in
|
||||||
|
the other ones it will be only done if the GUI is available (e.g. X11
|
||||||
|
display was successfully opened for X11-based ports) and the function
|
||||||
|
simply returns @false without doing anything otherwise.
|
||||||
|
|
||||||
|
This function is safe in the sense that it can always be called, even
|
||||||
|
before creating wxApp, similarly to wxSafeShowMessage() which is
|
||||||
|
implemented by calling this function and then logging the message to
|
||||||
|
standard error stream if it returned @false.
|
||||||
|
|
||||||
|
@since 3.1.5
|
||||||
|
|
||||||
|
@param text
|
||||||
|
The text to show to the user.
|
||||||
|
@param title
|
||||||
|
The title of the message box shown to the user.
|
||||||
|
@return @true if the message box was shown or @false otherwise.
|
||||||
|
*/
|
||||||
|
virtual bool SafeMessageBox(const wxString& text, const wxString& title) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -944,6 +944,14 @@ bool wxConsoleAppTraitsBase::HasStderr()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wxConsoleAppTraitsBase::SafeMessageBox(const wxString& WXUNUSED(text),
|
||||||
|
const wxString& WXUNUSED(title))
|
||||||
|
{
|
||||||
|
// console applications don't show message boxes by default, although this
|
||||||
|
// can be done in platform-specific cases
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxAppTraits
|
// wxAppTraits
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include "wx/window.h"
|
#include "wx/window.h"
|
||||||
#include "wx/bitmap.h"
|
#include "wx/bitmap.h"
|
||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
|
#include "wx/module.h"
|
||||||
#include "wx/msgdlg.h"
|
#include "wx/msgdlg.h"
|
||||||
#include "wx/confbase.h"
|
#include "wx/confbase.h"
|
||||||
#include "wx/utils.h"
|
#include "wx/utils.h"
|
||||||
@@ -584,3 +585,21 @@ bool wxGUIAppTraitsBase::HasStderr()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __WIN32__
|
||||||
|
|
||||||
|
bool wxGUIAppTraitsBase::SafeMessageBox(const wxString& text,
|
||||||
|
const wxString& title)
|
||||||
|
{
|
||||||
|
// The modules are initialized only after a successful call to
|
||||||
|
// wxApp::Initialize() in wxEntryStart, so it can be used as a proxy for
|
||||||
|
// GUI availability (note that the mere existence of wxTheApp is not enough
|
||||||
|
// for this).
|
||||||
|
if ( !wxModule::AreInitialized() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxMessageBox(text, title, wxOK | wxICON_ERROR);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__WIN32__
|
||||||
|
@@ -182,34 +182,11 @@ private:
|
|||||||
|
|
||||||
void wxSafeShowMessage(const wxString& title, const wxString& text)
|
void wxSafeShowMessage(const wxString& title, const wxString& text)
|
||||||
{
|
{
|
||||||
#ifdef __WINDOWS__
|
if ( !wxApp::GetValidTraits().SafeMessageBox(text, title) )
|
||||||
const wxAppTraits* const traits = wxApp::GetTraitsIfExists();
|
{
|
||||||
const HWND hwndParent = traits ? traits->GetMainHWND() : NULL;
|
wxFprintf(stderr, wxS("%s: %s\n"), title.c_str(), text.c_str());
|
||||||
int flags = MB_OK | MB_ICONSTOP;
|
fflush(stderr);
|
||||||
|
}
|
||||||
// Using MB_TASKMODAL with valid parent doesn't work well because it
|
|
||||||
// prevents the typical behaviour of modal message boxes, e.g. the message
|
|
||||||
// box doesn't come up to front when the parent is clicked. But if we don't
|
|
||||||
// have any parent anyhow, we can just as well use it, as we don't lose
|
|
||||||
// anything and it has a useful side effect of disabling any existing TLWs
|
|
||||||
// if there are any.
|
|
||||||
//
|
|
||||||
// Note that we also might have chosen to always use MB_TASKMODAL and NULL
|
|
||||||
// parent. This would have the advantage of always disabling all the window
|
|
||||||
// which, but at the cost of the behaviour mentioned above and other
|
|
||||||
// related problems, e.g. showing ugly default icon in Alt-Tab list and an
|
|
||||||
// extra taskbar button for the message box, so we don't do this, although
|
|
||||||
// perhaps we still should, at least in case when there is more than one
|
|
||||||
// TLW (but we can't check for this easily as this is non-GUI code and
|
|
||||||
// wxTopLevelWindows is not accessible from it).
|
|
||||||
if ( !hwndParent )
|
|
||||||
flags |= MB_TASKMODAL;
|
|
||||||
|
|
||||||
::MessageBox(hwndParent, text.t_str(), title.t_str(), flags);
|
|
||||||
#else
|
|
||||||
wxFprintf(stderr, wxS("%s: %s\n"), title.c_str(), text.c_str());
|
|
||||||
fflush(stderr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -39,6 +39,35 @@
|
|||||||
// wxAppTraits implementation
|
// wxAppTraits implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
bool wxAppTraits::SafeMessageBox(const wxString& text,
|
||||||
|
const wxString& title)
|
||||||
|
{
|
||||||
|
const HWND hwndParent = GetMainHWND();
|
||||||
|
int flags = MB_OK | MB_ICONSTOP;
|
||||||
|
|
||||||
|
// Using MB_TASKMODAL with valid parent doesn't work well because it
|
||||||
|
// prevents the typical behaviour of modal message boxes, e.g. the message
|
||||||
|
// box doesn't come up to front when the parent is clicked. But if we don't
|
||||||
|
// have any parent anyhow, we can just as well use it, as we don't lose
|
||||||
|
// anything and it has a useful side effect of disabling any existing TLWs
|
||||||
|
// if there are any.
|
||||||
|
//
|
||||||
|
// Note that we also might have chosen to always use MB_TASKMODAL and NULL
|
||||||
|
// parent. This would have the advantage of always disabling all the window
|
||||||
|
// which, but at the cost of the behaviour mentioned above and other
|
||||||
|
// related problems, e.g. showing ugly default icon in Alt-Tab list and an
|
||||||
|
// extra taskbar button for the message box, so we don't do this, although
|
||||||
|
// perhaps we still should, at least in case when there is more than one
|
||||||
|
// TLW (but we can't check for this easily as this is non-GUI code and
|
||||||
|
// wxTopLevelWindows is not accessible from it).
|
||||||
|
if ( !hwndParent )
|
||||||
|
flags |= MB_TASKMODAL;
|
||||||
|
|
||||||
|
::MessageBox(hwndParent, text.t_str(), title.t_str(), flags);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
WXDWORD wxAppTraits::DoSimpleWaitForThread(WXHANDLE hThread)
|
WXDWORD wxAppTraits::DoSimpleWaitForThread(WXHANDLE hThread)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user