X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7c9955d147ed92cdd79d795ed94d6e03fca06a52..c15d9c859c64f28c56d1e61b7d031a74e6018583:/src/msw/app.cpp diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 94b3dfb59f..1b2e4f96ba 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -48,6 +48,7 @@ #include "wx/log.h" #endif +#include "wx/apptrait.h" #include "wx/cmdline.h" #include "wx/filename.h" #include "wx/module.h" @@ -71,7 +72,7 @@ // OLE is used for drag-and-drop, clipboard, OLE Automation..., but some // compilers don't support it (missing headers, libs, ...) -#if defined(__GNUWIN32_OLD__) || defined(__SC__) || defined(__SALFORDC__) +#if defined(__GNUWIN32_OLD__) || defined(__SYMANTEC__) || defined(__SALFORDC__) #undef wxUSE_OLE #define wxUSE_OLE 0 @@ -84,7 +85,7 @@ #include #include -#if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__) || defined(__WXMICROWIN__)) && !defined(__CYGWIN10__)) +#if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__WXMICROWIN__)) && !defined(__CYGWIN10__)) #include #endif @@ -130,7 +131,6 @@ extern void wxSetKeyboardHook(bool doIt); #endif MSG s_currentMsg; -wxApp *wxTheApp = NULL; // NB: all "NoRedraw" classes must have the same names as the "normal" classes // with NR suffix - wxWindow::MSWCreate() supposes this @@ -168,11 +168,92 @@ LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM); #endif // =========================================================================== -// implementation +// wxGUIAppTraits implementation +// =========================================================================== + +// private class which we use to pass parameters from BeforeChildWaitLoop() to +// AfterChildWaitLoop() +struct ChildWaitLoopData +{ + ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *winActive_) + { + wd = wd_; + winActive = winActive_; + } + + wxWindowDisabler *wd; + wxWindow *winActive; +}; + +void *wxGUIAppTraits::BeforeChildWaitLoop() +{ + /* + We use a dirty hack here to disable all application windows (which we + must do because otherwise the calls to wxYield() could lead to some very + unexpected reentrancies in the users code) but to avoid losing + focus/activation entirely when the child process terminates which would + happen if we simply disabled everything using wxWindowDisabler. Indeed, + remember that Windows will never activate a disabled window and when the + last childs window is closed and Windows looks for a window to activate + all our windows are still disabled. There is no way to enable them in + time because we don't know when the childs windows are going to be + closed, so the solution we use here is to keep one special tiny frame + enabled all the time. Then when the child terminates it will get + activated and when we close it below -- after reenabling all the other + windows! -- the previously active window becomes activated again and + everything is ok. + */ + wxBeginBusyCursor(); + + // first disable all existing windows + wxWindowDisabler *wd = new wxWindowDisabler; + + // then create an "invisible" frame: it has minimal size, is positioned + // (hopefully) outside the screen and doesn't appear on the taskbar + wxWindow *winActive = new wxFrame + ( + wxTheApp->GetTopWindow(), + -1, + _T(""), + wxPoint(32600, 32600), + wxSize(1, 1), + wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR + ); + winActive->Show(); + + return new ChildWaitLoopData(wd, winActive); +} + +void wxGUIAppTraits::AlwaysYield() +{ + wxYield(); +} + +void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig) +{ + wxEndBusyCursor(); + + const ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig; + + delete data->wd; + + // finally delete the dummy frame and, as wd has been already destroyed and + // the other windows reenabled, the activation is going to return to the + // window which had had it before + data->winActive->Destroy(); +} + +bool wxGUIAppTraits::DoMessageFromThreadWait() +{ + return !wxTheApp || wxTheApp->DoMessage(); +} + +// =========================================================================== +// wxApp implementation // =========================================================================== // --------------------------------------------------------------------------- -// wxApp +// wxWin macros // --------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) @@ -560,13 +641,14 @@ void wxApp::CleanUp() #endif delete wxWinHandleHash; + wxWinHandleHash = NULL; // Set to null in case anything later tries to ref it. - // GL: I'm annoyed ... I don't know where to put this and I don't want to - // create a module for that as it's part of the core. delete wxPendingEvents; + wxPendingEvents = NULL; // Set to null because wxAppBase::wxEvtHandler is destroyed later. #if wxUSE_THREADS delete wxPendingEventsLocker; + wxPendingEventsLocker = NULL; // Set to null because wxAppBase::wxEvtHandler is destroyed later. // If we don't do the following, we get an apparent memory leak #if wxUSE_VALIDATORS ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker(); @@ -798,8 +880,6 @@ int wxEntry(WXHINSTANCE hInstance) //// Static member initialization -wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL; - wxApp::wxApp() { argc = 0; @@ -1145,6 +1225,23 @@ bool wxApp::SendIdleEvents(wxWindow* win) return needMore; } +void wxApp::WakeUpIdle() +{ + // Send the top window a dummy message so idle handler processing will + // 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(); + if ( topWindow ) + { + if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) ) + { + // should never happen + wxLogLastError(wxT("PostMessage(WM_NULL)")); + } + } +} + void wxApp::DeletePendingObjects() { wxNode *node = wxPendingDelete.GetFirst(); @@ -1180,6 +1277,17 @@ void wxApp::OnQueryEndSession(wxCloseEvent& event) } } +typedef struct _WXADllVersionInfo +{ + DWORD cbSize; + DWORD dwMajorVersion; // Major version + DWORD dwMinorVersion; // Minor version + DWORD dwBuildNumber; // Build number + DWORD dwPlatformID; // DLLVER_PLATFORM_* +} WXADLLVERSIONINFO; + +typedef HRESULT (CALLBACK* WXADLLGETVERSIONPROC)(WXADLLVERSIONINFO *); + /* static */ int wxApp::GetComCtl32Version() { @@ -1199,17 +1307,25 @@ int wxApp::GetComCtl32Version() // do we have it? HMODULE hModuleComCtl32 = ::GetModuleHandle(wxT("COMCTL32")); + BOOL bFreeComCtl32 = FALSE ; + if(!hModuleComCtl32) + { + hModuleComCtl32 = ::LoadLibrary(wxT("COMCTL32.DLL")) ; + if(hModuleComCtl32) + { + bFreeComCtl32 = TRUE ; + } + } // if so, then we can check for the version if ( hModuleComCtl32 ) { // try to use DllGetVersion() if available in _headers_ - #ifdef DLLVER_PLATFORM_WINDOWS // defined in shlwapi.h - DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC) + WXADLLGETVERSIONPROC pfnDllGetVersion = (WXADLLGETVERSIONPROC) ::GetProcAddress(hModuleComCtl32, "DllGetVersion"); if ( pfnDllGetVersion ) { - DLLVERSIONINFO dvi; + WXADLLVERSIONINFO dvi; dvi.cbSize = sizeof(dvi); HRESULT hr = (*pfnDllGetVersion)(&dvi); @@ -1226,7 +1342,6 @@ int wxApp::GetComCtl32Version() dvi.dwMinorVersion; } } - #endif // DllGetVersion() unavailable either during compile or // run-time, try to guess the version otherwise if ( !s_verComCtl32 ) @@ -1265,25 +1380,17 @@ int wxApp::GetComCtl32Version() } } } + + if(bFreeComCtl32) + { + ::FreeLibrary(hModuleComCtl32) ; + } } return s_verComCtl32; #endif } -void wxExit() -{ - if ( wxTheApp ) - { - wxTheApp->ExitMainLoop(); - } - else - { - // what else can we do? - exit(-1); - } -} - // Yield to incoming messages bool wxApp::Yield(bool onlyIfNeeded) @@ -1351,31 +1458,10 @@ bool wxHandleFatalExceptions(bool doit) #endif } -//----------------------------------------------------------------------------- -// wxWakeUpIdle -//----------------------------------------------------------------------------- - -void wxWakeUpIdle() -{ - // Send the top window a dummy message so idle handler processing will - // 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(); - if ( topWindow ) - { - if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) ) - { - // should never happen - wxLogLastError(wxT("PostMessage(WM_NULL)")); - } - } -} - //----------------------------------------------------------------------------- // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly // if in a separate file. So include it here to ensure it's linked. -#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__WINE__) && !defined(__TWIN32__) && !defined(WXMAKINGDLL)) +#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__WINE__) && !defined(WXMAKINGDLL)) #include "main.cpp" #endif