X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3e3d05fc8601ef8d6eb2a695aba83d48ac1ca1b2..9d5507f7a2701395e1d5c121bd877bb9066ee6ea:/src/msw/app.cpp?ds=sidebyside diff --git a/src/msw/app.cpp b/src/msw/app.cpp index d3d3e62a5c..ef5379e82b 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: app.cpp +// Name: src/msw/app.cpp // Purpose: wxApp // Author: Julian Smart // Modified by: @@ -17,10 +17,6 @@ // headers // --------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "app.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -29,6 +25,8 @@ #endif #ifndef WX_PRECOMP + #include "wx/msw/wrapcctl.h" + #include "wx/dynarray.h" #include "wx/frame.h" #include "wx/app.h" #include "wx/utils.h" @@ -42,19 +40,20 @@ #include "wx/dialog.h" #include "wx/msgdlg.h" #include "wx/intl.h" - #include "wx/dynarray.h" - #include "wx/wxchar.h" - #include "wx/icon.h" + #include "wx/crt.h" #include "wx/log.h" + #include "wx/module.h" #endif #include "wx/apptrait.h" #include "wx/filename.h" -#include "wx/module.h" #include "wx/dynlib.h" +#include "wx/evtloop.h" +#include "wx/thread.h" #include "wx/msw/private.h" #include "wx/msw/ole/oleutils.h" +#include "wx/msw/private/timer.h" #if wxUSE_TOOLTIPS #include "wx/tooltip.h" @@ -69,7 +68,8 @@ #endif // broken compilers #if defined(__POCKETPC__) || defined(__SMARTPHONE__) -#include + #include + #include #endif #if wxUSE_OLE @@ -79,19 +79,34 @@ #include #include -#include "wx/msw/wrapcctl.h" +#include "wx/msw/missing.h" + +// instead of including which is not part of the core SDK and not +// shipped at all with other compilers, we always define the parts of it we +// need here ourselves +// +// NB: DLLVER_PLATFORM_WINDOWS will be defined if shlwapi.h had been somehow +// included already +#ifndef DLLVER_PLATFORM_WINDOWS + // hopefully we don't need to change packing as DWORDs should be already + // correctly aligned + struct DLLVERSIONINFO + { + DWORD cbSize; + DWORD dwMajorVersion; // Major version + DWORD dwMinorVersion; // Minor version + DWORD dwBuildNumber; // Build number + DWORD dwPlatformID; // DLLVER_PLATFORM_* + }; + + typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *); +#endif // defined(DLLVERSIONINFO) -// For MB_TASKMODAL -#ifdef __WXWINCE__ -#include "wx/msw/wince/missing.h" -#endif // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- -extern wxList WXDLLEXPORT wxPendingDelete; - #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) extern void wxSetKeyboardHook(bool doIt); #endif @@ -199,23 +214,71 @@ bool wxGUIAppTraits::DoMessageFromThreadWait() { // we should return false only if the app should exit, i.e. only if // Dispatch() determines that the main event loop should terminate - return !wxTheApp || wxTheApp->Dispatch(); + wxEventLoopBase * const evtLoop = wxEventLoop::GetActive(); + if ( !evtLoop || !evtLoop->Pending() ) + { + // no events means no quit event + return true; + } + + return evtLoop->Dispatch(); +} + +DWORD wxGUIAppTraits::WaitForThread(WXHANDLE hThread) +{ + // if we don't have a running event loop, we shouldn't wait for the + // messages as we never remove them from the message queue and so we enter + // an infinite loop as MsgWaitForMultipleObjects() keeps returning + // WAIT_OBJECT_0 + 1 + if ( !wxEventLoop::GetActive() ) + return DoSimpleWaitForThread(hThread); + + return ::MsgWaitForMultipleObjects + ( + 1, // number of objects to wait for + (HANDLE *)&hThread, // the objects + false, // wait for any objects, not all + INFINITE, // no timeout + QS_ALLINPUT | // return as soon as there are any events + QS_ALLPOSTMESSAGE + ); } -wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo() +wxPortId wxGUIAppTraits::GetToolkitVersion(int *majVer, int *minVer) const { - static wxToolkitInfo info; - wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo(); - info.versionMajor = baseInfo.versionMajor; - info.versionMinor = baseInfo.versionMinor; - info.os = baseInfo.os; - info.shortName = _T("msw"); - info.name = _T("wxMSW"); -#ifdef __WXUNIVERSAL__ - info.shortName << _T("univ"); - info.name << _T("/wxUniversal"); + OSVERSIONINFO info; + wxZeroMemory(info); + + // on Windows, the toolkit version is the same of the OS version + // as Windows integrates the OS kernel with the GUI toolkit. + info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if ( ::GetVersionEx(&info) ) + { + if ( majVer ) + *majVer = info.dwMajorVersion; + if ( minVer ) + *minVer = info.dwMinorVersion; + } + +#if defined(__WXHANDHELD__) || defined(__WXWINCE__) + return wxPORT_WINCE; +#else + return wxPORT_MSW; #endif - return info; +} + +#if wxUSE_TIMER + +wxTimerImpl *wxGUIAppTraits::CreateTimerImpl(wxTimer *timer) +{ + return new wxMSWTimerImpl(timer); +} + +#endif // wxUSE_TIMER + +wxEventLoopBase* wxGUIAppTraits::CreateEventLoop() +{ + return new wxEventLoop; } // =========================================================================== @@ -262,9 +325,9 @@ bool wxApp::Initialize(int& argc, wxChar **argv) #ifdef __WXWINCE__ wxString tmp = GetAppName(); tmp += wxT("ClassName"); - wxCanvasClassName = wxStrdup( tmp.c_str() ); + wxCanvasClassName = wxStrdup( tmp.wc_str() ); tmp += wxT("NR"); - wxCanvasClassNameNR = wxStrdup( tmp.c_str() ); + wxCanvasClassNameNR = wxStrdup( tmp.wc_str() ); HWND hWnd = FindWindow( wxCanvasClassNameNR, NULL ); if (hWnd) { @@ -273,43 +336,24 @@ bool wxApp::Initialize(int& argc, wxChar **argv) } #endif - // the first thing to do is to check if we're trying to run an Unicode - // program under Win9x w/o MSLU emulation layer - if so, abort right now - // as it has no chance to work -#if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU - if ( wxGetOsVersion() != wxWINDOWS_NT && wxGetOsVersion() != wxWINDOWS_CE && wxGetOsVersion() != wxWINDOWS_SMARTPHONE && wxGetOsVersion() != wxWINDOWS_POCKETPC ) - { - // note that we can use MessageBoxW() as it's implemented even under - // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs - // used by wxLocale are not - ::MessageBox - ( - NULL, - _T("This program uses Unicode and requires Windows NT/2000/XP/CE.\nProgram aborted."), - _T("wxWidgets Fatal Error"), - MB_ICONERROR | MB_OK - ); - - return false; - } -#endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU - -#if defined(__WIN95__) && !defined(__WXMICROWIN__) +#if !defined(__WXMICROWIN__) InitCommonControls(); -#endif // __WIN95__ +#endif // !defined(__WXMICROWIN__) #if defined(__SMARTPHONE__) || defined(__POCKETPC__) SHInitExtraControls(); #endif +#ifndef __WXWINCE__ + // Don't show a message box if a function such as SHGetFileInfo + // fails to find a device. + SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); +#endif + wxOleInitialize(); RegisterWindowClasses(); -#if wxUSE_PENWINDOWS - wxRegisterPenWin(); -#endif - wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100); #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__) @@ -475,10 +519,6 @@ void wxApp::CleanUp() wxSetKeyboardHook(false); #endif -#if wxUSE_PENWINDOWS - wxCleanUpPenWin(); -#endif - wxOleUninitialize(); // for an EXE the classes are unregistered when it terminates but DLL may @@ -489,7 +529,7 @@ void wxApp::CleanUp() delete wxWinHandleHash; wxWinHandleHash = NULL; - + #ifdef __WXWINCE__ free( wxCanvasClassName ); free( wxCanvasClassNameNR ); @@ -507,33 +547,20 @@ wxApp::wxApp() wxApp::~wxApp() { - // our cmd line arguments are allocated inside wxEntry(HINSTANCE), they - // don't come from main(), so we have to free them - - while ( argc ) - { - // m_argv elements were allocated by wxStrdup() - free(argv[--argc]); - } - - // but m_argv itself -- using new[] - delete [] argv; } // ---------------------------------------------------------------------------- // wxApp idle handling // ---------------------------------------------------------------------------- -void wxApp::OnIdle(wxIdleEvent& event) +void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event)) { - wxAppBase::OnIdle(event); - #if wxUSE_DC_CACHEING // automated DC cache management: clear the cached DCs and bitmap // if it's likely that the app has finished with them, that is, we // get an idle event and we're not dragging anything. if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON)) - wxDC::ClearCache(); + wxMSWDCImpl::ClearCache(); #endif // wxUSE_DC_CACHEING } @@ -576,15 +603,42 @@ void wxApp::OnQueryEndSession(wxCloseEvent& event) } // ---------------------------------------------------------------------------- -// miscellaneous +// system DLL versions // ---------------------------------------------------------------------------- +#if wxUSE_DYNLIB_CLASS + +namespace +{ + +// helper function: retrieve the DLL version by using DllGetVersion(), returns +// 0 if the DLL doesn't export such function +int CallDllGetVersion(wxDynamicLibrary& dll) +{ + // now check if the function is available during run-time + wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dll ); + if ( !pfnDllGetVersion ) + return 0; + + DLLVERSIONINFO dvi; + dvi.cbSize = sizeof(dvi); + + HRESULT hr = (*pfnDllGetVersion)(&dvi); + if ( FAILED(hr) ) + { + wxLogApiError(_T("DllGetVersion"), hr); + + return 0; + } + + return 100*dvi.dwMajorVersion + dvi.dwMinorVersion; +} + +} // anonymous namespace + /* static */ int wxApp::GetComCtl32Version() { -#if defined(__WXMICROWIN__) || defined(__WXWINCE__) - return 0; -#else // cache the result // // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice, @@ -593,78 +647,103 @@ int wxApp::GetComCtl32Version() if ( s_verComCtl32 == -1 ) { - // initally assume no comctl32.dll at all - s_verComCtl32 = 0; - // we're prepared to handle the errors wxLogNull noLog; - // do we have it? + // the DLL should really be available wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM); + if ( !dllComCtl32.IsLoaded() ) + { + s_verComCtl32 = 0; + return 0; + } + + // try DllGetVersion() for recent DLLs + s_verComCtl32 = CallDllGetVersion(dllComCtl32); - // if so, then we can check for the version - if ( dllComCtl32.IsLoaded() ) + // if DllGetVersion() is unavailable either during compile or + // run-time, try to guess the version otherwise + if ( !s_verComCtl32 ) { -#ifdef DLLVER_PLATFORM_WINDOWS - // try to use DllGetVersion() if available in _headers_ - wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 ); - if ( pfnDllGetVersion ) + // InitCommonControlsEx is unique to 4.70 and later + void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx")); + if ( !pfn ) { - DLLVERSIONINFO dvi; - dvi.cbSize = sizeof(dvi); - - HRESULT hr = (*pfnDllGetVersion)(&dvi); - if ( FAILED(hr) ) - { - wxLogApiError(_T("DllGetVersion"), hr); - } - else - { - // this is incompatible with _WIN32_IE values, but - // compatible with the other values returned by - // GetComCtl32Version() - s_verComCtl32 = 100*dvi.dwMajorVersion + - dvi.dwMinorVersion; - } + // not found, must be 4.00 + s_verComCtl32 = 400; } -#endif - - // if DllGetVersion() is unavailable either during compile or - // run-time, try to guess the version otherwise - if ( !s_verComCtl32 ) + else // 4.70+ { - // InitCommonControlsEx is unique to 4.70 and later - void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx")); + // many symbols appeared in comctl32 4.71, could use any of + // them except may be DllInstall() + pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB")); if ( !pfn ) { - // not found, must be 4.00 - s_verComCtl32 = 400; + // not found, must be 4.70 + s_verComCtl32 = 470; } - else // 4.70+ + else { - // many symbols appeared in comctl32 4.71, could use any of - // them except may be DllInstall() - pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB")); - if ( !pfn ) - { - // not found, must be 4.70 - s_verComCtl32 = 470; - } - else - { - // found, must be 4.71 or later - s_verComCtl32 = 471; - } + // found, must be 4.71 or later + s_verComCtl32 = 471; } } } } return s_verComCtl32; -#endif // Microwin/!Microwin } +/* static */ +int wxApp::GetShell32Version() +{ + static int s_verShell32 = -1; + if ( s_verShell32 == -1 ) + { + // we're prepared to handle the errors + wxLogNull noLog; + + wxDynamicLibrary dllShell32(_T("shell32.dll"), wxDL_VERBATIM); + if ( dllShell32.IsLoaded() ) + { + s_verShell32 = CallDllGetVersion(dllShell32); + + if ( !s_verShell32 ) + { + // there doesn't seem to be any way to distinguish between 4.00 + // and 4.70 (starting from 4.71 we have DllGetVersion()) so + // just assume it is 4.0 + s_verShell32 = 400; + } + } + else // failed load the DLL? + { + s_verShell32 = 0; + } + } + + return s_verShell32; +} + +#else // !wxUSE_DYNLIB_CLASS + +/* static */ +int wxApp::GetComCtl32Version() +{ + return 0; +} + +/* static */ +int wxApp::GetShell32Version() +{ + return 0; +} + +#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS + +// ---------------------------------------------------------------------------- // Yield to incoming messages +// ---------------------------------------------------------------------------- bool wxApp::Yield(bool onlyIfNeeded) { @@ -735,7 +814,7 @@ terminate the program,\r\n\ \"Retry\" to exit the program normally and \"Ignore\" to try to continue."), _T("Unhandled exception"), MB_ABORTRETRYIGNORE | - MB_ICONERROR| + MB_ICONERROR| MB_TASKMODAL ) ) @@ -756,33 +835,3 @@ terminate the program,\r\n\ } #endif // wxUSE_EXCEPTIONS - -// ---------------------------------------------------------------------------- -// deprecated event loop functions -// ---------------------------------------------------------------------------- - -#if WXWIN_COMPATIBILITY_2_4 - -#include "wx/evtloop.h" - -void wxApp::DoMessage(WXMSG *pMsg) -{ - wxEventLoop *evtLoop = wxEventLoop::GetActive(); - if ( evtLoop ) - evtLoop->ProcessMessage(pMsg); -} - -bool wxApp::DoMessage() -{ - wxEventLoop *evtLoop = wxEventLoop::GetActive(); - return evtLoop ? evtLoop->Dispatch() : false; -} - -bool wxApp::ProcessMessage(WXMSG* pMsg) -{ - wxEventLoop *evtLoop = wxEventLoop::GetActive(); - return evtLoop && evtLoop->PreProcessMessage(pMsg); -} - -#endif // WXWIN_COMPATIBILITY_2_4 -