X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dfad0599246651d4994e348d868a3e65613c7379..71b8c213cb2c676b4715ef37e6155da3601f7881:/src/msw/app.cpp diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 2af264ff65..ba4a42af25 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -10,14 +10,14 @@ ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ - #pragma implementation "app.h" +#pragma implementation "app.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #if defined(__BORLANDC__) - #pragma hdrstop +#pragma hdrstop #endif #ifndef WX_PRECOMP @@ -33,39 +33,50 @@ #include "wx/dc.h" #include "wx/dialog.h" #include "wx/msgdlg.h" + #include "wx/intl.h" + #include "wx/dynarray.h" #endif #include "wx/msw/private.h" #include "wx/log.h" #include "wx/module.h" +#if wxUSE_THREADS + #include "wx/thread.h" + + // define the array of MSG strutures + WX_DECLARE_OBJARRAY(MSG, wxMsgArray); + + #include "wx/arrimpl.cpp" + + WX_DEFINE_OBJARRAY(wxMsgArray); +#endif // wxUSE_THREADS + #if wxUSE_WX_RESOURCES #include "wx/resource.h" #endif +// To UG: there's no point in putting this #if here +// if you don't do the same for the Ole calls further down. +// Also, OLE is used not just for drag and drop (it's used by automatn.cpp). +// #if wxUSE_DRAG_AND_DROP +#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__) + #include +#endif + #include #include -#if defined(__WIN95__) && !defined(__GNUWIN32__) +#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) #include #endif -// use debug CRT functions for memory leak detections in VC++ -/* This still doesn't work for me, Vadim. -#if defined(__WXDEBUG__) && defined(_MSC_VER) - // VC++ uses this macro as debug/release mode indicator - #ifndef _DEBUG - #define _DEBUG - #endif - - #include -#endif -*/ +#include "wx/msw/msvcrt.h" extern char *wxBuffer; extern char *wxOsVersion; extern wxList *wxWinHandleList; -extern wxList wxPendingDelete; +extern wxList WXDLLEXPORT wxPendingDelete; extern void wxSetKeyboardHook(bool doIt); extern wxCursor *g_globalCursor; @@ -80,15 +91,15 @@ char wxMDIChildFrameClassName[] = "wxMDIChildFrameClass"; char wxPanelClassName[] = "wxPanelClass"; char wxCanvasClassName[] = "wxCanvasClass"; -HICON wxSTD_FRAME_ICON = NULL; -HICON wxSTD_MDICHILDFRAME_ICON = NULL; -HICON wxSTD_MDIPARENTFRAME_ICON = NULL; +HICON wxSTD_FRAME_ICON = (HICON) NULL; +HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL; +HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL; -HICON wxDEFAULT_FRAME_ICON = NULL; -HICON wxDEFAULT_MDICHILDFRAME_ICON = NULL; -HICON wxDEFAULT_MDIPARENTFRAME_ICON = NULL; +HICON wxDEFAULT_FRAME_ICON = (HICON) NULL; +HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL; +HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL; -HBRUSH wxDisableButtonBrush = 0; +HBRUSH wxDisableButtonBrush = (HBRUSH) 0; LRESULT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM); @@ -97,121 +108,136 @@ LRESULT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM); BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) EVT_IDLE(wxApp::OnIdle) + EVT_END_SESSION(wxApp::OnEndSession) + EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession) END_EVENT_TABLE() #endif long wxApp::sm_lastMessageTime = 0; -#ifdef __WIN95__ - static HINSTANCE gs_hRichEdit = NULL; +#if defined(__WIN95__) && !defined(__TWIN32__) +#define wxUSE_RICHEDIT 1 +#else +#define wxUSE_RICHEDIT 0 +#endif + +#if wxUSE_RICHEDIT + static HINSTANCE gs_hRichEdit = (HINSTANCE) NULL; #endif //// Initialize bool wxApp::Initialize() { - wxBuffer = new char[1500]; - -/* - #if defined(__WXDEBUG__) && defined(_MSC_VER) - // do check for memory leaks on program exit - // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free - // deallocated memory which may be used to simulate low-memory condition) - _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); - #endif // debug build under MS VC++ -*/ - - #if (WXDEBUG && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT - #if defined(_WINDLL) - streambuf* sBuf = NULL; - #else // EXE - streambuf* sBuf = new wxDebugStreamBuf; - #endif // DLL + // Some people may wish to use this, but + // probably it shouldn't be here by default. +#ifdef __WXDEBUG__ +// wxRedirectIOToConsole(); +#endif - ostream* oStr = new ostream(sBuf) ; - wxDebugContext::SetStream(oStr, sBuf); - #endif // wxUSE_MEMORY_TRACING + wxBuffer = new char[1500]; - wxClassInfo::InitializeClasses(); + wxClassInfo::InitializeClasses(); - #if wxUSE_RESOURCES +#if wxUSE_RESOURCES wxGetResource("wxWindows", "OsVersion", &wxOsVersion); - #endif +#endif - wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING); - wxTheColourDatabase->Initialize(); + wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING); + wxTheColourDatabase->Initialize(); - wxInitializeStockLists(); - wxInitializeStockObjects(); + wxInitializeStockLists(); + wxInitializeStockObjects(); - #if wxUSE_WX_RESOURCES +#if wxUSE_WX_RESOURCES wxInitializeResourceSystem(); - #endif +#endif - wxBitmap::InitStandardHandlers(); + wxBitmap::InitStandardHandlers(); - #if defined(__WIN95__) +#if defined(__WIN95__) InitCommonControls(); + +#if wxUSE_RICHEDIT gs_hRichEdit = LoadLibrary("RICHED32.DLL"); - if (gs_hRichEdit == NULL) + if (gs_hRichEdit == (HINSTANCE) NULL) { wxMessageBox("Could not initialise Rich Edit DLL"); } - #endif +#endif + +#endif + + int iMsg = 96; + + // for OLE, enlarge message queue to be as large as possible + while (!SetMessageQueue(iMsg) && (iMsg -= 8)); + +/* + DWORD dwOleVer; + dwOleVer = CoBuildVersion(); + + // check the OLE library version + if (rmm != HIWORD(dwOleVer)) + { + wxMessageBox("Incorrect version of OLE libraries."); + return FALSE; + } +*/ - #if defined(WX_DRAG_DROP) +#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__) // we need to initialize OLE library if ( FAILED(::OleInitialize(NULL)) ) wxFatalError(_("Cannot initialize OLE")); - #endif +#endif - #if CTL3D +#if wxUSE_CTL3D if (!Ctl3dRegister(wxhInstance)) wxFatalError("Cannot register CTL3D"); Ctl3dAutoSubclass(wxhInstance); - #endif +#endif - g_globalCursor = new wxCursor; + g_globalCursor = new wxCursor; - wxSTD_FRAME_ICON = LoadIcon(wxhInstance, "wxSTD_FRAME"); - wxSTD_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, "wxSTD_MDIPARENTFRAME"); - wxSTD_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, "wxSTD_MDICHILDFRAME"); + wxSTD_FRAME_ICON = LoadIcon(wxhInstance, "wxSTD_FRAME"); + wxSTD_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, "wxSTD_MDIPARENTFRAME"); + wxSTD_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, "wxSTD_MDICHILDFRAME"); - wxDEFAULT_FRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_FRAME"); - wxDEFAULT_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_MDIPARENTFRAME"); - wxDEFAULT_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_MDICHILDFRAME"); + wxDEFAULT_FRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_FRAME"); + wxDEFAULT_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_MDIPARENTFRAME"); + wxDEFAULT_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_MDICHILDFRAME"); - RegisterWindowClasses(); + RegisterWindowClasses(); - // Create the brush for disabling bitmap buttons + // Create the brush for disabling bitmap buttons - LOGBRUSH lb ; - lb.lbStyle = BS_PATTERN; - lb.lbHatch = (int)LoadBitmap( wxhInstance, "wxDISABLE_BUTTON_BITMAP" ) ; - wxDisableButtonBrush = ::CreateBrushIndirect( & lb ) ; - ::DeleteObject( (HGDIOBJ)lb.lbHatch ) ; + LOGBRUSH lb ; + lb.lbStyle = BS_PATTERN; + lb.lbHatch = (int)LoadBitmap( wxhInstance, "wxDISABLE_BUTTON_BITMAP" ) ; + wxDisableButtonBrush = ::CreateBrushIndirect( & lb ) ; + ::DeleteObject( (HGDIOBJ)lb.lbHatch ) ; - #if wxUSE_PENWINDOWS +#if wxUSE_PENWINDOWS wxRegisterPenWin(); - #endif +#endif - wxWinHandleList = new wxList(wxKEY_INTEGER); + wxWinHandleList = new wxList(wxKEY_INTEGER); - // This is to foil optimizations in Visual C++ that - // throw out dummy.obj. - #if (_MSC_VER >= 800) && !defined(WXMAKINGDLL) + // This is to foil optimizations in Visual C++ that throw out dummy.obj. + // PLEASE DO NOT ALTER THIS. +#if defined(__VISUALC__) && !defined(WXMAKINGDLL) extern char wxDummyChar; if (wxDummyChar) wxDummyChar++; - #endif +#endif - wxSetKeyboardHook(TRUE); + wxSetKeyboardHook(TRUE); - wxModule::RegisterModules(); - if (!wxModule::InitializeModules()) - return FALSE; - return TRUE; + wxModule::RegisterModules(); + if (!wxModule::InitializeModules()) + return FALSE; + return TRUE; } //// RegisterWindowClasses @@ -222,13 +248,13 @@ bool wxApp::RegisterWindowClasses() // Register the frame window class. WNDCLASS wndclass; // Structure used to register Windows class. - wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ; wndclass.lpfnWndProc = (WNDPROC)wxWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = sizeof( DWORD ); // was 4 wndclass.hInstance = wxhInstance; - wndclass.hIcon = NULL; // wxSTD_FRAME_ICON; - wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); + wndclass.hIcon = (HICON) NULL; // wxSTD_FRAME_ICON; + wndclass.hCursor = LoadCursor( (HINSTANCE) NULL, IDC_ARROW ); wndclass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1) ; // wndclass.hbrBackground = GetStockObject( WHITE_BRUSH ); wndclass.lpszMenuName = NULL; @@ -246,15 +272,15 @@ bool wxApp::RegisterWindowClasses() // Register the MDI frame window class. WNDCLASS wndclass1; // Structure used to register Windows class. - wndclass1.style = CS_HREDRAW | CS_VREDRAW; + wndclass1.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ; wndclass1.lpfnWndProc = (WNDPROC)wxWndProc; wndclass1.cbClsExtra = 0; wndclass1.cbWndExtra = sizeof( DWORD ); // was 4 wndclass1.hInstance = wxhInstance; - wndclass1.hIcon = NULL; // wxSTD_MDIPARENTFRAME_ICON; - wndclass1.hCursor = LoadCursor( NULL, IDC_ARROW ); + wndclass1.hIcon = (HICON) NULL; // wxSTD_MDIPARENTFRAME_ICON; + wndclass1.hCursor = LoadCursor( (HINSTANCE) NULL, IDC_ARROW ); // wndclass1.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1) ; - wndclass1.hbrBackground = NULL; + wndclass1.hbrBackground = (HBRUSH) NULL; wndclass1.lpszMenuName = NULL; wndclass1.lpszClassName = wxMDIFrameClassName; @@ -268,13 +294,13 @@ bool wxApp::RegisterWindowClasses() // Register the MDI child frame window class. WNDCLASS wndclass4; // Structure used to register Windows class. - wndclass4.style = CS_HREDRAW | CS_VREDRAW; + wndclass4.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ; wndclass4.lpfnWndProc = (WNDPROC)wxWndProc; wndclass4.cbClsExtra = 0; wndclass4.cbWndExtra = sizeof( DWORD ); // was 4 wndclass4.hInstance = wxhInstance; - wndclass4.hIcon = NULL; // wxSTD_MDICHILDFRAME_ICON; - wndclass4.hCursor = LoadCursor( NULL, IDC_ARROW ); + wndclass4.hIcon = (HICON) NULL; // wxSTD_MDICHILDFRAME_ICON; + wndclass4.hCursor = LoadCursor( (HINSTANCE) NULL, IDC_ARROW ); // TODO: perhaps this should be NULL so that Windows doesn't // paint the background itself (would OnEraseBackground duplicate // this?) @@ -293,15 +319,13 @@ bool wxApp::RegisterWindowClasses() // Register the panel window class. WNDCLASS wndclass2; // Structure used to register Windows class. memset(&wndclass2, 0, sizeof(WNDCLASS)); // start with NULL defaults - // Use CS_OWNDC to avoid messing about restoring the context - // for every graphic operation. - wndclass2.style = CS_HREDRAW | CS_VREDRAW; + wndclass2.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ; wndclass2.lpfnWndProc = (WNDPROC)wxWndProc; wndclass2.cbClsExtra = 0; wndclass2.cbWndExtra = sizeof( DWORD ); // was 4 wndclass2.hInstance = wxhInstance; - wndclass2.hIcon = NULL; - wndclass2.hCursor = NULL; + wndclass2.hIcon = (HICON) NULL; + wndclass2.hCursor = (HCURSOR) NULL; // wndclass2.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ; wndclass2.hbrBackground = (HBRUSH) GetStockObject( LTGRAY_BRUSH ); wndclass2.lpszMenuName = NULL; @@ -325,10 +349,10 @@ bool wxApp::RegisterWindowClasses() wndclass3.cbClsExtra = 0; wndclass3.cbWndExtra = sizeof( DWORD ); // was 4 wndclass3.hInstance = wxhInstance; - wndclass3.hIcon = NULL; - wndclass3.hCursor = NULL; + wndclass3.hIcon = (HICON) NULL; + wndclass3.hCursor = (HCURSOR) NULL; // wndclass3.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ; - wndclass3.hbrBackground = NULL; + wndclass3.hbrBackground = (HBRUSH) NULL; wndclass3.lpszMenuName = NULL; wndclass3.lpszClassName = wxCanvasClassName; if (!RegisterClass( &wndclass3)) @@ -342,83 +366,77 @@ bool wxApp::RegisterWindowClasses() //// Convert Windows to argc, argv style -// FIXME this code should be rewritten (use wxArrayString instead...) void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine) { - // Split command line into tokens, as in usual main(argc, argv) - char **command = new char*[50]; // VZ: sure? why not 25 or 73 and a half?? - - int count = 0; - char *buf = new char[strlen(lpCmdLine) + 1]; + wxStringList args; - /* Model independent strcpy */ - int i; - for (i = 0; (buf[i] = lpCmdLine[i]) != 0; i++) - { - /* loop */; - } + wxString cmdLine(lpCmdLine); + int count = 0; - // Get application name - char name[260]; // 260 is MAX_PATH value from windef.h - ::GetModuleFileName(wxhInstance, name, WXSIZEOF(name)); + // Get application name + char name[260]; // 260 is MAX_PATH value from windef.h + ::GetModuleFileName(wxhInstance, name, WXSIZEOF(name)); - // Is it only 16-bit Borland that already copies the program name - // to the first argv index? -#if !defined(__GNUWIN32__) -// #if ! (defined(__BORLANDC__) && !defined(__WIN32__)) - command[count++] = copystring(name); -// #endif + // GNUWIN32 already fills in the first arg with the application name. + // JACS: apparently not now (b20 and above?) +#if 0 // !defined(__GNUWIN32__) + args.Add(name); + count ++; #endif - strcpy(name, wxFileNameFromPath(name)); - wxStripExtension(name); - wxTheApp->SetAppName(name); + strcpy(name, wxFileNameFromPath(name)); + wxStripExtension(name); + wxTheApp->SetAppName(name); - /* Break up string */ - // Treat strings enclosed in double-quotes as single arguments - char* str = buf; - while (*str) - { -/* - if ( count == WXSIZEOF(command) ) + // Break up string + // Treat strings enclosed in double-quotes as single arguments + int i = 0; + int len = cmdLine.Length(); + while (i < len) { - wxFAIL_MSG("too many command line args."); - break; - } -*/ - while ( *str && isspace(*str) ) // skip whitespace - str++; + // Skip whitespace + while ((i < len) && isspace(cmdLine.GetChar(i))) + i ++; - if (*str == '"') - { - str++; - command[count++] = str; - while (*str && *str != '"') - str++; + if (i < len) + { + if (cmdLine.GetChar(i) == '"') // We found the start of a string + { + i ++; + int first = i; + while ((i < len) && (cmdLine.GetChar(i) != '"')) + i ++; + + wxString arg(cmdLine.Mid(first, (i - first))); + + args.Add(arg); + count ++; + + if (i < len) + i ++; // Skip past 2nd quote + } + else // Unquoted argument + { + int first = i; + while ((i < len) && !isspace(cmdLine.GetChar(i))) + i ++; + + wxString arg(cmdLine.Mid(first, (i - first))); + + args.Add(arg); + count ++; + } + } } - else if (*str) + + wxTheApp->argv = new char*[count + 1]; + for (i = 0; i < count; i++) { - command[count++] = str; - while (*str && !isspace(*str)) - str++; + wxString arg(args[i]); + wxTheApp->argv[i] = copystring((const char*)arg); } - if (*str) - *str++ = '\0'; - } - - wxTheApp->argv = new char*[count + 1]; - wxTheApp->argv[count] = NULL; /* argv[] is NULL terminated list! */ - wxTheApp->argc = count; - - for (i = 0; i < count; i++) - { - wxTheApp->argv[i] = copystring(command[i]); - - delete [] command[i]; - } - - delete [] command; - delete [] buf; + wxTheApp->argv[count] = NULL; // argv[] is a NULL-terminated list + wxTheApp->argc = count; } //// Cleans up any wxWindows internal structures left lying around @@ -426,6 +444,15 @@ void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine) void wxApp::CleanUp() { //// COMMON CLEANUP + + // flush the logged messages if any + wxLog *pLog = wxLog::GetActiveTarget(); + if ( pLog != NULL && pLog->HasPendingMessages() ) + pLog->Flush(); + + // One last chance for pending objects to be cleaned up + wxTheApp->DeletePendingObjects(); + wxModule::CleanUpModules(); #if wxUSE_WX_RESOURCES @@ -459,10 +486,14 @@ void wxApp::CleanUp() wxSetKeyboardHook(FALSE); #ifdef __WIN95__ - if (gs_hRichEdit != NULL) + +#if wxUSE_RICHEDIT + if (gs_hRichEdit != (HINSTANCE) NULL) FreeLibrary(gs_hRichEdit); #endif +#endif + #if wxUSE_PENWINDOWS wxCleanUpPenWin(); #endif @@ -484,11 +515,11 @@ void wxApp::CleanUp() if ( wxDisableButtonBrush ) ::DeleteObject( wxDisableButtonBrush ) ; -#if defined(WX_DRAG_DROP) +#if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__) ::OleUninitialize(); #endif -#if CTL3D +#if wxUSE_CTL3D Ctl3dUnregister(wxhInstance); #endif @@ -497,6 +528,23 @@ void wxApp::CleanUp() wxClassInfo::CleanUpClasses(); + delete wxTheApp; + wxTheApp = NULL; + +#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT + // At this point we want to check if there are any memory + // blocks that aren't part of the wxDebugContext itself, + // as a special case. Then when dumping we need to ignore + // wxDebugContext, too. + if (wxDebugContext::CountObjectsLeft() > 0) + { + wxLogDebug("There were memory leaks."); + wxDebugContext::Dump(); + wxDebugContext::PrintStatistics(); + } +// wxDebugContext::SetStream(NULL, NULL); +#endif + // do it as the very last thing because everything else can log messages wxLog::DontCreateOnDemand(); delete wxLog::SetActiveTarget(NULL); @@ -504,6 +552,11 @@ void wxApp::CleanUp() #if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL)) +// temporarily disable this warning +#ifdef __VISUALC__ + #pragma warning(disable: 4715) // not all control paths return a value +#endif // Visual C++ + //// Main wxWindows entry point int wxEntry(WXHINSTANCE hInstance, WXHINSTANCE WXUNUSED(hPrevInstance), @@ -511,8 +564,21 @@ int wxEntry(WXHINSTANCE hInstance, int nCmdShow, bool enterLoop) { -#ifndef __WXDEBUG__ // take everything into a try-except block in release build - try { + // do check for memory leaks on program exit + // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free + // deallocated memory which may be used to simulate low-memory condition) + wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF); + + // take everything into a try-except block in release build + // FIXME other compilers must support Win32 SEH (structured exception + // handling) too, just find the appropriate keyword in their docs! + // Please note that it's _not_ the same as C++ exceptions! +#if !defined(__WXDEBUG__) && defined(__VISUALC__) + #define CATCH_PROGRAM_EXCEPTIONS + + __try { +#else + #undef CATCH_PROGRAM_EXCEPTIONS #endif wxhInstance = (HINSTANCE) hInstance; @@ -550,6 +616,9 @@ int wxEntry(WXHINSTANCE hInstance, { retValue = wxTheApp->OnRun(); } + else + // We want to initialize, but not run or exit immediately. + return 1; } //else: app initialization failed, so we skipped OnRun() @@ -571,39 +640,31 @@ int wxEntry(WXHINSTANCE hInstance, } wxTheApp->OnExit(); - wxApp::CleanUp(); - delete wxTheApp; - wxTheApp = NULL; - -#if (WXDEBUG && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT - // At this point we want to check if there are any memory - // blocks that aren't part of the wxDebugContext itself, - // as a special case. Then when dumping we need to ignore - // wxDebugContext, too. - if (wxDebugContext::CountObjectsLeft() > 0) - { - wxTrace("There were memory leaks.\n"); - wxDebugContext::Dump(); - wxDebugContext::PrintStatistics(); - } - wxDebugContext::SetStream(NULL, NULL); -#endif + wxApp::CleanUp(); return retValue; -#ifndef __WXDEBUG__ // catch exceptions only in release build + +#ifdef CATCH_PROGRAM_EXCEPTIONS } - except ( EXCEPTION_EXECUTE_HANDLER ) { + __except ( EXCEPTION_EXECUTE_HANDLER ) { /* if ( wxTheApp ) wxTheApp->OnFatalException(); */ ::ExitProcess(3); // the same exit code as abort() + + // NOTREACHED } -#endif //debug +#endif // CATCH_PROGRAM_EXCEPTIONS } +// restore warning state +#ifdef __VISUALC__ + #pragma warning(default: 4715) // not all control paths return a value +#endif // Visual C++ + #else /* _WINDLL */ //// Entry point for DLLs @@ -678,7 +739,7 @@ wxApp::~wxApp() { delete[] argv[i]; } - delete argv; + delete[] argv; } bool wxApp::Initialized() @@ -696,24 +757,88 @@ bool wxApp::Initialized() /* * Get and process a message, returning FALSE if WM_QUIT - * received. + * received (and also set the flag telling the app to exit the main loop) * */ bool wxApp::DoMessage() { - if (!::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0)) - { - return FALSE; - } + BOOL rc = ::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0); + if ( rc == 0 ) + { + // got WM_QUIT + m_keepGoing = FALSE; - // Process the message - if (!ProcessMessage((WXMSG *)&s_currentMsg)) - { - ::TranslateMessage(&s_currentMsg); - wxApp::sm_lastMessageTime = s_currentMsg.time; /* MATTHEW: timeStamp impl. */ - ::DispatchMessage(&s_currentMsg); - } - return TRUE; + return FALSE; + } + else if ( rc == -1 ) + { + // should never happen, but let's test for it nevertheless + wxLogLastError("GetMessage"); + } + else + { +#if wxUSE_THREADS + wxASSERT_MSG( wxThread::IsMain(), + "only the main thread can process Windows messages" ); + + static bool s_hadGuiLock = TRUE; + static wxMsgArray s_aSavedMessages; + + // if a secondary thread owns is doing GUI calls, save all messages for + // later processing - we can't process them right now because it will + // lead to recursive library calls (and we're not reentrant) + if ( !wxGuiOwnedByMainThread() ) + { + s_hadGuiLock = FALSE; + + // leave out WM_COMMAND messages: too dangerous, sometimes + // the message will be processed twice + if ( !wxIsWaitingForThread() || + s_currentMsg.message != WM_COMMAND ) + { + s_aSavedMessages.Add(s_currentMsg); + } + + return TRUE; + } + else + { + // have we just regained the GUI lock? if so, post all of the saved + // messages + // + // FIXME of course, it's not _exactly_ the same as processing the + // messages normally - expect some things to break... + if ( !s_hadGuiLock ) + { + s_hadGuiLock = TRUE; + + size_t count = s_aSavedMessages.Count(); + for ( size_t n = 0; n < count; n++ ) + { + MSG& msg = s_aSavedMessages[n]; + + if ( !ProcessMessage((WXMSG *)&msg) ) + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + } + + s_aSavedMessages.Empty(); + } + } +#endif // wxUSE_THREADS + + // Process the message + if ( !ProcessMessage((WXMSG *)&s_currentMsg) ) + { + ::TranslateMessage(&s_currentMsg); + wxApp::sm_lastMessageTime = s_currentMsg.time; /* MATTHEW: timeStamp impl. */ + ::DispatchMessage(&s_currentMsg); + } + } + + return TRUE; } /* @@ -733,12 +858,19 @@ bool wxApp::DoMessage() int wxApp::MainLoop() { m_keepGoing = TRUE; - while (m_keepGoing) + + while ( m_keepGoing ) { - while (!::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) && - ProcessIdle()) {} - if (!DoMessage()) - m_keepGoing = FALSE; + #if wxUSE_THREADS + wxMutexGuiLeaveOrEnter(); + #endif // wxUSE_THREADS + + while ( !::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) && + ProcessIdle() ) + { + } + + DoMessage(); } return s_currentMsg.wParam; @@ -766,8 +898,7 @@ bool wxApp::Pending() void wxApp::Dispatch() { - if (!DoMessage()) - m_keepGoing = FALSE; + DoMessage(); } /* @@ -783,7 +914,7 @@ bool wxApp::ProcessMessage(WXMSG *Msg) // Try translations first; find the youngest window with // a translation table. - for (hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) + for (hWnd = msg->hwnd; hWnd != (HWND) NULL; hWnd = ::GetParent(hWnd)) { wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd); if (wnd) @@ -794,7 +925,7 @@ bool wxApp::ProcessMessage(WXMSG *Msg) } // Anyone for a non-translation message? Try youngest descendants first. - for (hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) + for (hWnd = msg->hwnd; hWnd != (HWND) NULL; hWnd = ::GetParent(hWnd)) { wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd); if (wnd) @@ -808,45 +939,47 @@ bool wxApp::ProcessMessage(WXMSG *Msg) void wxApp::OnIdle(wxIdleEvent& event) { - static bool inOnIdle = FALSE; + static bool s_inOnIdle = FALSE; - // Avoid recursion (via ProcessEvent default case) - if (inOnIdle) - return; + // Avoid recursion (via ProcessEvent default case) + if ( s_inOnIdle ) + return; - inOnIdle = TRUE; + s_inOnIdle = TRUE; - // 'Garbage' collection of windows deleted with Close(). - DeletePendingObjects(); - - // flush the logged messages if any - wxLog *pLog = wxLog::GetActiveTarget(); - if ( pLog != NULL && pLog->HasPendingMessages() ) - pLog->Flush(); + // 'Garbage' collection of windows deleted with Close(). + DeletePendingObjects(); - // Send OnIdle events to all windows - bool needMore = SendIdleEvents(); -// bool needMore = FALSE; + // flush the logged messages if any + wxLog *pLog = wxLog::GetActiveTarget(); + if ( pLog != NULL && pLog->HasPendingMessages() ) + pLog->Flush(); - if (needMore) - event.RequestMore(TRUE); + // Send OnIdle events to all windows + if ( SendIdleEvents() ) + { + // SendIdleEvents() returns TRUE if at least one window requested more + // idle events + event.RequestMore(TRUE); + } - inOnIdle = FALSE; + s_inOnIdle = FALSE; } // Send idle event to all top-level windows bool wxApp::SendIdleEvents() { bool needMore = FALSE; - wxNode* node = wxTopLevelWindows.First(); - while (node) - { - wxWindow* win = (wxWindow*) node->Data(); - if (SendIdleEvents(win)) + wxNode* node = wxTopLevelWindows.First(); + while (node) + { + wxWindow* win = (wxWindow*) node->Data(); + if (SendIdleEvents(win)) needMore = TRUE; - node = node->Next(); - } + node = node->Next(); + } + return needMore; } @@ -857,12 +990,12 @@ bool wxApp::SendIdleEvents(wxWindow* win) wxIdleEvent event; event.SetEventObject(win); - win->ProcessEvent(event); + win->GetEventHandler()->ProcessEvent(event); if (event.MoreRequested()) needMore = TRUE; - wxNode* node = win->GetChildren()->First(); + wxNode* node = win->GetChildren().First(); while (node) { wxWindow* win = (wxWindow*) node->Data(); @@ -892,6 +1025,23 @@ void wxApp::DeletePendingObjects() } } +void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event)) +{ + if (GetTopWindow()) + GetTopWindow()->Close(TRUE); +} + +// Default behaviour: close the application with prompts. The +// user can veto the close, and therefore the end session. +void wxApp::OnQueryEndSession(wxCloseEvent& event) +{ + if (GetTopWindow()) + { + if (!GetTopWindow()->Close(!event.CanVeto())) + event.Veto(TRUE); + } +} + wxLog* wxApp::CreateLogTarget() { return new wxLogGui; @@ -964,7 +1114,7 @@ bool wxYield() // if we see a WM_QUIT. (?) while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT) { - if (!wxTheApp->DoMessage()) + if ( !wxTheApp->DoMessage() ) break; } @@ -976,8 +1126,13 @@ HINSTANCE wxGetInstance() return wxhInstance; } +void wxSetInstance(HINSTANCE hInst) +{ + wxhInstance = hInst; +} + // 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(_MSC_VER) && !defined(__WIN32__)) || defined(__GNUWIN32__) +#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__)) #include "main.cpp" #endif