Fix using wxMemoryDC without a GUI wxApp instance
This used to work, at least in wxMSW, but stopped working after the
(perfectly valid, on their own) changes of 2508efdd6e (Initialize
wxMemoryDC with a default font, 2019-08-13), as this resulted in calling
wxApp::GetTopWindow() that can only be called from the GUI code.
Fix this by adding wxApp::GetGUIInstance() and using it in
GetMainTopWindow(), so that we only call GetTopWindow() if we actually
have a GUI wxApp object on which to call it.
Implement this in terms of a new virtual IsGUI() which seems slightly
better than, although roughly equivalent to, using wxDynamicCast().
Closes https://github.com/wxWidgets/wxWidgets/pull/2617
Closes #19343.
This commit is contained in:
@@ -462,6 +462,9 @@ public:
|
|||||||
static wxAppConsole *GetInstance() { return ms_appInstance; }
|
static wxAppConsole *GetInstance() { return ms_appInstance; }
|
||||||
static void SetInstance(wxAppConsole *app) { ms_appInstance = app; }
|
static void SetInstance(wxAppConsole *app) { ms_appInstance = app; }
|
||||||
|
|
||||||
|
// returns true for GUI wxApp subclasses
|
||||||
|
virtual bool IsGUI() const { return false; }
|
||||||
|
|
||||||
|
|
||||||
// command line arguments (public for backwards compatibility)
|
// command line arguments (public for backwards compatibility)
|
||||||
int argc;
|
int argc;
|
||||||
@@ -684,6 +687,19 @@ public:
|
|||||||
// deactivated
|
// deactivated
|
||||||
virtual void SetActive(bool isActive, wxWindow *lastFocus);
|
virtual void SetActive(bool isActive, wxWindow *lastFocus);
|
||||||
|
|
||||||
|
virtual bool IsGUI() const wxOVERRIDE { return true; }
|
||||||
|
|
||||||
|
// returns non-null pointer only if we have a GUI application object: this
|
||||||
|
// is only useful in the rare cases when the same code can be used in both
|
||||||
|
// console and GUI applications, but needs to use GUI-specific functions if
|
||||||
|
// the GUI is available
|
||||||
|
static wxAppBase *GetGUIInstance()
|
||||||
|
{
|
||||||
|
return ms_appInstance && ms_appInstance->IsGUI()
|
||||||
|
? static_cast<wxAppBase*>(ms_appInstance)
|
||||||
|
: NULL;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// override base class method to use GUI traits
|
// override base class method to use GUI traits
|
||||||
virtual wxAppTraits *CreateTraits() wxOVERRIDE;
|
virtual wxAppTraits *CreateTraits() wxOVERRIDE;
|
||||||
@@ -761,7 +777,7 @@ protected:
|
|||||||
// return the object of the correct type (i.e. MyApp and not wxApp)
|
// return the object of the correct type (i.e. MyApp and not wxApp)
|
||||||
//
|
//
|
||||||
// the cast is safe as in GUI build we only use wxApp, not wxAppConsole, and in
|
// the cast is safe as in GUI build we only use wxApp, not wxAppConsole, and in
|
||||||
// console mode it does nothing at all
|
// console mode it does nothing at all (but see also wxApp::GetGUIInstance())
|
||||||
#define wxTheApp static_cast<wxApp*>(wxApp::GetInstance())
|
#define wxTheApp static_cast<wxApp*>(wxApp::GetInstance())
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ public:
|
|||||||
Returns the one and only global application object.
|
Returns the one and only global application object.
|
||||||
Usually ::wxTheApp is used instead.
|
Usually ::wxTheApp is used instead.
|
||||||
|
|
||||||
@see SetInstance()
|
@see SetInstance(), wxApp::GetGUIInstance()
|
||||||
*/
|
*/
|
||||||
static wxAppConsole* GetInstance();
|
static wxAppConsole* GetInstance();
|
||||||
|
|
||||||
@@ -838,6 +838,35 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual wxVideoMode GetDisplayMode() const;
|
virtual wxVideoMode GetDisplayMode() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the current GUI wxApp object if any or @NULL otherwise.
|
||||||
|
|
||||||
|
This function should only be used in the rare cases when the same code
|
||||||
|
needs to work in both console and GUI applications, but needs to use
|
||||||
|
GUI-specific functionality if it is available, and so just calling
|
||||||
|
wxAppConsole::GetInstance() is insufficient while using ::wxTheApp is
|
||||||
|
incorrect, as the application object is not always a GUI wxApp.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
@code
|
||||||
|
WXWidget handle = 0;
|
||||||
|
if ( wxApp* const app = wxApp::GetGUIInstance() ) {
|
||||||
|
if ( wxWindow* const w = app->GetTopWindow() ) {
|
||||||
|
handle = w->GetHandle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//else: no window to use
|
||||||
|
|
||||||
|
some_native_function_taking_a_window_handle(handle);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Note that in this particular example, you could use GetMainTopWindow()
|
||||||
|
which already does the same thing instead of doing it yourself.
|
||||||
|
|
||||||
|
@since 3.1.6
|
||||||
|
*/
|
||||||
|
static wxAppConsole* GetGUIInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns @true if the application will exit when the top-level frame is deleted.
|
Returns @true if the application will exit when the top-level frame is deleted.
|
||||||
|
|
||||||
@@ -1213,7 +1242,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
The global pointer to the singleton wxApp object.
|
The global pointer to the singleton wxApp object.
|
||||||
|
|
||||||
@see wxApp::GetInstance()
|
This pointer can only be used in the GUI applications.
|
||||||
|
|
||||||
|
@see wxAppConsole::GetInstance(), wxApp::GetGUIInstance()
|
||||||
*/
|
*/
|
||||||
wxApp *wxTheApp;
|
wxApp *wxTheApp;
|
||||||
|
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ wxWindow* wxAppBase::GetTopWindow() const
|
|||||||
/* static */
|
/* static */
|
||||||
wxWindow* wxAppBase::GetMainTopWindow()
|
wxWindow* wxAppBase::GetMainTopWindow()
|
||||||
{
|
{
|
||||||
const wxAppBase* const app = static_cast<wxAppBase*>(GetInstance());
|
const wxAppBase* const app = GetGUIInstance();
|
||||||
|
|
||||||
return app ? app->GetTopWindow() : NULL;
|
return app ? app->GetTopWindow() : NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user