Problem with wxMSW and setting the module instance handle.
Jurko Gospodnetić
jurko_for_boost at mail.inet.hr
Sun May 20 15:21:51 PDT 2007
Hi Vadim.
> JG> Just wanted to report that there is a bit problematic detail with
> JG> wxMSW application startup design. There wxEntry() sets the Windows
> JG> module instance handle using the internal wxWidgets wxSetInstance() API
> JG> found in the msw/private.h header.
>
> This is indeed a problem but it's not clear what to do about it. We can,
> of course, define an alternative wxEntryStart() taking HINSTANCE but how
> useful will it be? And other than that where are we supposed to get the
> HINSTANCE from?
>
> For an EXE it's easy enough: we can use GetModuleHandle(NULL). But if wx
> is a static library linked into a DLL, this would return a wrong handle.
> And I don't really know how to get the right one. Apparently Microsoft
> linker provides __ImageBase pseudo variable which contains HINSTANCE but
> this is for MSVC only. There is also GetModuleHandleEx() but it only works
> on XP and later. So there is nothing which works in all cases other than
> using the parameter to WinMain.
>
> So, again, while we should probably add wxEntryStart() with the same
> signature as WinMain() anyhow, I don't see any good way of solving this
> problem.
I have been thinking about the problem a bit so here are my thoughts
on the subject. Note though that most API names above have been
constructed on-demand and I am not sure if they would be acceptable or
would have to be renamed. Also... not all details have been ironed out :-).
If you add a new wxEntryStart() for each new application startup type
(e.g. with and without HINSTANCE) then each wxEntryStart() needs to be
wrapped with a separate wxEntry() function. This would also obviously be
platform specific.
Another idea that could possibly lead to a cleaner solution is to
drop the current 'wxApp class derivable for specific applications'
approach and have applications initialize/run/finalize wxWidgets by
calling wxInitialize()/wxRun()/wxFinalize(). Then wxApp may be freely
derived from internally for each platform (wxAppMSW/wxAppGTK/...).
Then, for instance, wxAppMSW could contain as many platform specific
constructors or initializers (e.g. setInstance(), setArgcArgv(),
setCommandLine(), etc.) as needed and platform specific
initialization/finalization code could be wrapped inside virtual (and
private) member functions initialize()/finalize() taking no parameters.
Such functions would then adapt to whichever startup parameters got set
in their application object.
Customized application startup/shutdown code could access the
wxWidgets platform specific application object using some wxGetApp()
function similar to how this is done now.
Platform independent wxInitialize()/wxFinalize() would call the
platform dependent wxApp::initialize()/finalize() virtual functions plus
trigger what ever other platform-independent magic they need. wxRun()
would simply call wxApp::OnRun(). (These functions could possibly be
implemented as wxApp member functions instead of stand-alone ones.)
Simple use-cases such as most wxWidgets demos and applications not
requiring customized wxWidgets startup/shutdown could be implemented
similar to how they have been implemented so far - using an
IMPLEMENT_APP() macro which would either create an object derived from
some ApplicationBase class (used only to call a virtual application
defined initialization member function after initializing wxWidgets) or
simply take an initialization function parameter. It would then prepare
a WinMain()/main()/... startup function triggering tasks similar to what
wxEntry() does now:
1. Create the platform specific wxApp object and set its startup
parameters.
2. wxInitialize().
3. Call the application specific initialization function (not needed
in case of customized startup/shutdown code as then the custom code
already knows when wxInitialize() terminates).
4. wxRun().
5. wxFinalize().
On MSW this leaves a question of SEH handling which I think should be
handled similar to how it is handled now - using a documented API/macro
system for wrapping application code in a SEH exception safety wrapper.
In simple cases wxWidgets defined startup function would implement this
wrapper automatically and any customized applications would need to
decide for themselves whether they need it.
Some pluses for this design are:
* Works the same even for (imaginary) platforms using strings to
identify application instances or other such platform dependent data.
* Platform dependent wxWidgets application objects hold platform
specific data instead of having it stored in separate global objects as
it is now.
* No more 'undocumented hacks' such as wxSetInstance() on MSW, not
intuitive from standard code (so much that even demo applications have
errors related to using them). Each application needing customized
wxWidgets initialization on a specific platform simply needs to check
the platform specific wxApp derived class documentation and related
startup settings can be checked in that class's initialize() function so
any startup configuration mistakes may be detected as soon as possible.
* 'Standard' wxWidgets applications, not needing any startup/shutdown
customization, could be written as they have been. If they need their
own application object - they may provide it independent of the
wxWidgets application class.
I would like to hear other's thoughts on this.
Best regards,
Jurko Gospodnetić
More information about the wx-dev
mailing list