RegisterWindowClasses();
- wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
-
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
wxSetKeyboardHook(true);
#endif
void wxApp::CleanUp()
{
- // all objects pending for deletion must be deleted first, otherwise we
- // would crash when they use wxWinHandleHash (and UnregisterWindowClasses()
- // call wouldn't succeed as long as any windows still exist), so call the
- // base class method first and only then do our clean up
+ // all objects pending for deletion must be deleted first, otherwise
+ // UnregisterWindowClasses() call wouldn't succeed (because windows
+ // using the classes being unregistered still exist), so call the base
+ // class method first and only then do our clean up
wxAppBase::CleanUp();
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
// unregister the classes now
UnregisterWindowClasses();
- delete wxWinHandleHash;
- wxWinHandleHash = NULL;
-
#ifdef __WXWINCE__
free( wxCanvasClassName );
free( wxCanvasClassNameNR );
// start up again. Doing it this way ensures that the idle handler
// wakes up in the right thread (see also wxWakeUpMainThread() which does
// the same for the main app thread only)
- wxWindow *topWindow = wxTheApp->GetTopWindow();
+ wxWindow * const topWindow = wxTheApp->GetTopWindow();
if ( topWindow )
{
- if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
+ HWND hwndTop = GetHwndOf(topWindow);
+
+ // Do not post WM_NULL if there's already a pending WM_NULL to avoid
+ // overflowing the message queue.
+ //
+ // Notice that due to a limitation of PeekMessage() API (which handles
+ // 0,0 range specially), we have to check the range from 0-1 instead.
+ // This still makes it possible to overflow the queue with WM_NULLs by
+ // interspersing the calles to WakeUpIdle() with windows creation but
+ // it should be rather hard to do it accidentally.
+ MSG msg;
+ if ( !::PeekMessage(&msg, hwndTop, 0, 1, PM_NOREMOVE) ||
+ ::PeekMessage(&msg, hwndTop, 1, 1, PM_NOREMOVE) )
{
- // should never happen
- wxLogLastError(wxT("PostMessage(WM_NULL)"));
+ if ( !::PostMessage(hwndTop, WM_NULL, 0, 0) )
+ {
+ // should never happen
+ wxLogLastError(wxT("PostMessage(WM_NULL)"));
+ }
}
}
}
void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
{
- if (GetTopWindow())
- GetTopWindow()->Close(true);
+ // Windows will terminate the process soon after we return from
+ // WM_ENDSESSION handler anyhow, so make sure we at least execute our
+ // cleanup code before
+ const int rc = OnExit();
+
+ wxEntryCleanup();
+
+ // calling exit() instead of ExitProcess() or not doing anything at all and
+ // being killed by Windows has the advantage of executing the dtors of
+ // global objects
+ exit(rc);
}
// Default behaviour: close the application with prompts. The
// system DLL versions
// ----------------------------------------------------------------------------
+// these functions have trivial inline implementations for CE
+#ifndef __WXWINCE__
+
#if wxUSE_DYNLIB_CLASS
namespace
#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS
+#endif // !__WXWINCE__
+
// ----------------------------------------------------------------------------
// Yield to incoming messages
// ----------------------------------------------------------------------------