1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  21     #pragma implementation "app.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  27 #if defined(__BORLANDC__) 
  35     #include "wx/gdicmn.h" 
  38     #include "wx/cursor.h" 
  40     #include "wx/palette.h" 
  42     #include "wx/dialog.h" 
  43     #include "wx/msgdlg.h" 
  45     #include "wx/dynarray.h" 
  46     #include "wx/wxchar.h" 
  51 #include "wx/cmdline.h" 
  52 #include "wx/filename.h" 
  53 #include "wx/module.h" 
  55 #include "wx/msw/private.h" 
  58     #include "wx/thread.h" 
  60     // define the array of MSG strutures 
  61     WX_DECLARE_OBJARRAY(MSG
, wxMsgArray
); 
  63     #include "wx/arrimpl.cpp" 
  65     WX_DEFINE_OBJARRAY(wxMsgArray
); 
  66 #endif // wxUSE_THREADS 
  68 #if wxUSE_WX_RESOURCES 
  69     #include "wx/resource.h" 
  73     #include "wx/tooltip.h" 
  74 #endif // wxUSE_TOOLTIPS 
  76 // OLE is used for drag-and-drop, clipboard, OLE Automation..., but some 
  77 // compilers don't support it (missing headers, libs, ...) 
  78 #if defined(__GNUWIN32_OLD__) || defined(__SC__) || defined(__SALFORDC__) 
  82 #endif // broken compilers 
  91 #if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__) || defined(__WXMICROWIN__)) && !defined(__CYGWIN10__)) 
  95 #ifndef __WXMICROWIN__ 
  96 #include "wx/msw/msvcrt.h" 
  99 // ---------------------------------------------------------------------------- 
 100 // conditional compilation 
 101 // ---------------------------------------------------------------------------- 
 103 // The macro _WIN32_IE is defined by commctrl.h (unless it had already been 
 104 // defined before) and shows us what common control features are available 
 105 // during the compile time (it doesn't mean that they will be available during 
 106 // the run-time, use GetComCtl32Version() to test for them!). The possible 
 109 // 0x0200     for comctl32.dll 4.00 shipped with Win95/NT 4.0 
 110 // 0x0300                      4.70              IE 3.x 
 111 // 0x0400                      4.71              IE 4.0 
 112 // 0x0401                      4.72              IE 4.01 and Win98 
 113 // 0x0500                      5.00              IE 5.x and NT 5.0 (Win2000) 
 116     // minimal set of features by default 
 117     #define _WIN32_IE 0x0200 
 120 #if _WIN32_IE >= 0x0300 && !defined(__MINGW32__) 
 124 // --------------------------------------------------------------------------- 
 126 // --------------------------------------------------------------------------- 
 128 extern wxChar 
*wxBuffer
; 
 129 extern wxList WXDLLEXPORT wxPendingDelete
; 
 130 #ifndef __WXMICROWIN__ 
 131 extern void wxSetKeyboardHook(bool doIt
); 
 135 wxApp 
*wxTheApp 
= NULL
; 
 137 // NB: all "NoRedraw" classes must have the same names as the "normal" classes 
 138 //     with NR suffix - wxWindow::MSWCreate() supposes this 
 139 const wxChar 
*wxCanvasClassName        
= wxT("wxWindowClass"); 
 140 const wxChar 
*wxCanvasClassNameNR      
= wxT("wxWindowClassNR"); 
 141 const wxChar 
*wxMDIFrameClassName      
= wxT("wxMDIFrameClass"); 
 142 const wxChar 
*wxMDIFrameClassNameNoRedraw 
= wxT("wxMDIFrameClassNR"); 
 143 const wxChar 
*wxMDIChildFrameClassName 
= wxT("wxMDIChildFrameClass"); 
 144 const wxChar 
*wxMDIChildFrameClassNameNoRedraw 
= wxT("wxMDIChildFrameClassNR"); 
 146 HICON wxSTD_FRAME_ICON 
= (HICON
) NULL
; 
 147 HICON wxSTD_MDICHILDFRAME_ICON 
= (HICON
) NULL
; 
 148 HICON wxSTD_MDIPARENTFRAME_ICON 
= (HICON
) NULL
; 
 150 HICON wxDEFAULT_FRAME_ICON 
= (HICON
) NULL
; 
 151 HICON wxDEFAULT_MDICHILDFRAME_ICON 
= (HICON
) NULL
; 
 152 HICON wxDEFAULT_MDIPARENTFRAME_ICON 
= (HICON
) NULL
; 
 154 HBRUSH wxDisableButtonBrush 
= (HBRUSH
) 0; 
 156 LRESULT WXDLLEXPORT APIENTRY 
wxWndProc(HWND
, UINT
, WPARAM
, LPARAM
); 
 158 // FIXME wxUSE_ON_FATAL_EXCEPTION is only supported for VC++ now because it 
 159 //       needs compiler support for Win32 SEH. Others (especially Borland) 
 160 //       probably have it too, but I'm not sure about how it works 
 161 // JACS: get 'Cannot use __try in functions that require unwinding 
 162 // in Unicode mode, so disabling. 
 163 #if !defined(__VISUALC__) || defined(__WIN16__) || defined(UNICODE) 
 164     #undef wxUSE_ON_FATAL_EXCEPTION 
 165     #define wxUSE_ON_FATAL_EXCEPTION 0 
 168 #if wxUSE_ON_FATAL_EXCEPTION 
 169     static bool gs_handleExceptions 
= FALSE
; 
 172 // =========================================================================== 
 174 // =========================================================================== 
 176 // --------------------------------------------------------------------------- 
 178 // --------------------------------------------------------------------------- 
 180 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
) 
 182 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
) 
 183     EVT_IDLE(wxApp::OnIdle
) 
 184     EVT_END_SESSION(wxApp::OnEndSession
) 
 185     EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
) 
 189 bool wxApp::Initialize() 
 191     // the first thing to do is to check if we're trying to run an Unicode 
 192     // program under Win9x w/o MSLU emulation layer - if so, abort right now  
 193     // as it has no chance to work 
 194 #if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU 
 195     if ( wxGetOsVersion() != wxWINDOWS_NT 
) 
 197         // note that we can use MessageBoxW() as it's implemented even under 
 198         // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs 
 199         // used by wxLocale are not 
 203          _T("This program uses Unicode and requires Windows NT/2000/XP.\nProgram aborted."), 
 204          _T("wxWindows Fatal Error"), 
 210 #endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU 
 212     wxBuffer 
= new wxChar
[1500]; // FIXME 
 214     wxClassInfo::InitializeClasses(); 
 217     wxPendingEventsLocker 
= new wxCriticalSection
; 
 220     wxTheColourDatabase 
= new wxColourDatabase(wxKEY_STRING
); 
 221     wxTheColourDatabase
->Initialize(); 
 223     wxInitializeStockLists(); 
 224     wxInitializeStockObjects(); 
 226 #if wxUSE_WX_RESOURCES 
 227     wxInitializeResourceSystem(); 
 230     wxBitmap::InitStandardHandlers(); 
 232 #if defined(__WIN95__) && !defined(__WXMICROWIN__) 
 233     InitCommonControls(); 
 236 #if wxUSE_OLE || wxUSE_DRAG_AND_DROP 
 239     // for OLE, enlarge message queue to be as large as possible 
 241     while (!SetMessageQueue(iMsg
) && (iMsg 
-= 8)) 
 246     // we need to initialize OLE library 
 247     if ( FAILED(::OleInitialize(NULL
)) ) 
 248         wxLogError(_("Cannot initialize OLE")); 
 254     if (!Ctl3dRegister(wxhInstance
)) 
 255         wxLogError(wxT("Cannot register CTL3D")); 
 257     Ctl3dAutoSubclass(wxhInstance
); 
 258 #endif // wxUSE_CTL3D 
 260     // VZ: these icons are not in wx.rc anyhow (but should they?)! 
 262     wxSTD_FRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxSTD_FRAME")); 
 263     wxSTD_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxSTD_MDIPARENTFRAME")); 
 264     wxSTD_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxSTD_MDICHILDFRAME")); 
 266     wxDEFAULT_FRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxDEFAULT_FRAME")); 
 267     wxDEFAULT_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxDEFAULT_MDIPARENTFRAME")); 
 268     wxDEFAULT_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxDEFAULT_MDICHILDFRAME")); 
 271     RegisterWindowClasses(); 
 273 #ifndef __WXMICROWIN__ 
 274     // Create the brush for disabling bitmap buttons 
 277     lb
.lbStyle 
= BS_PATTERN
; 
 279     lb
.lbHatch 
= (int)LoadBitmap( wxhInstance
, wxT("wxDISABLE_BUTTON_BITMAP") ); 
 282         wxDisableButtonBrush 
= ::CreateBrushIndirect( & lb 
); 
 283         ::DeleteObject( (HGDIOBJ
)lb
.lbHatch 
); 
 285     //else: wxWindows resources are probably not linked in 
 292     wxWinHandleHash 
= new wxWinHashTable(wxKEY_INTEGER
, 100); 
 294     // This is to foil optimizations in Visual C++ that throw out dummy.obj. 
 295     // PLEASE DO NOT ALTER THIS. 
 296 #if defined(__VISUALC__) && defined(__WIN16__) && !defined(WXMAKINGDLL) 
 297     extern char wxDummyChar
; 
 298     if (wxDummyChar
) wxDummyChar
++; 
 301 #ifndef __WXMICROWIN__ 
 302     wxSetKeyboardHook(TRUE
); 
 305     wxModule::RegisterModules(); 
 306     if (!wxModule::InitializeModules()) 
 311 // --------------------------------------------------------------------------- 
 312 // RegisterWindowClasses 
 313 // --------------------------------------------------------------------------- 
 315 // TODO we should only register classes really used by the app. For this it 
 316 //      would be enough to just delay the class registration until an attempt 
 317 //      to create a window of this class is made. 
 318 bool wxApp::RegisterWindowClasses() 
 321     wxZeroMemory(wndclass
); 
 323     // for each class we register one with CS_(V|H)REDRAW style and one 
 324     // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag 
 325     static const long styleNormal 
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS
; 
 326     static const long styleNoRedraw 
= CS_DBLCLKS
; 
 328     // the fields which are common to all classes 
 329     wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 330     wndclass
.hInstance     
= wxhInstance
; 
 331     wndclass
.hCursor       
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
); 
 333     // Register the frame window class. 
 334     wndclass
.hbrBackground 
= (HBRUSH
)(COLOR_APPWORKSPACE 
+ 1); 
 335     wndclass
.lpszClassName 
= wxCanvasClassName
; 
 336     wndclass
.style         
= styleNormal
; 
 338     if ( !RegisterClass(&wndclass
) ) 
 340         wxLogLastError(wxT("RegisterClass(frame)")); 
 346     wndclass
.lpszClassName 
= wxCanvasClassNameNR
; 
 347     wndclass
.style         
= styleNoRedraw
; 
 349     if ( !RegisterClass(&wndclass
) ) 
 351         wxLogLastError(wxT("RegisterClass(no redraw frame)")); 
 356     // Register the MDI frame window class. 
 357     wndclass
.hbrBackground 
= (HBRUSH
)NULL
; // paint MDI frame ourselves 
 358     wndclass
.lpszClassName 
= wxMDIFrameClassName
; 
 359     wndclass
.style         
= styleNormal
; 
 361     if ( !RegisterClass(&wndclass
) ) 
 363         wxLogLastError(wxT("RegisterClass(MDI parent)")); 
 368     // "no redraw" MDI frame 
 369     wndclass
.lpszClassName 
= wxMDIFrameClassNameNoRedraw
; 
 370     wndclass
.style         
= styleNoRedraw
; 
 372     if ( !RegisterClass(&wndclass
) ) 
 374         wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)")); 
 379     // Register the MDI child frame window class. 
 380     wndclass
.hbrBackground 
= (HBRUSH
)(COLOR_WINDOW 
+ 1); 
 381     wndclass
.lpszClassName 
= wxMDIChildFrameClassName
; 
 382     wndclass
.style         
= styleNormal
; 
 384     if ( !RegisterClass(&wndclass
) ) 
 386         wxLogLastError(wxT("RegisterClass(MDI child)")); 
 391     // "no redraw" MDI child frame 
 392     wndclass
.lpszClassName 
= wxMDIChildFrameClassNameNoRedraw
; 
 393     wndclass
.style         
= styleNoRedraw
; 
 395     if ( !RegisterClass(&wndclass
) ) 
 397         wxLogLastError(wxT("RegisterClass(no redraw MDI child)")); 
 405 // --------------------------------------------------------------------------- 
 406 // UnregisterWindowClasses 
 407 // --------------------------------------------------------------------------- 
 409 bool wxApp::UnregisterWindowClasses() 
 413 #ifndef __WXMICROWIN__ 
 414     // MDI frame window class. 
 415     if ( !::UnregisterClass(wxMDIFrameClassName
, wxhInstance
) ) 
 417         wxLogLastError(wxT("UnregisterClass(MDI parent)")); 
 422     // "no redraw" MDI frame 
 423     if ( !::UnregisterClass(wxMDIFrameClassNameNoRedraw
, wxhInstance
) ) 
 425         wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)")); 
 430     // MDI child frame window class. 
 431     if ( !::UnregisterClass(wxMDIChildFrameClassName
, wxhInstance
) ) 
 433         wxLogLastError(wxT("UnregisterClass(MDI child)")); 
 438     // "no redraw" MDI child frame 
 439     if ( !::UnregisterClass(wxMDIChildFrameClassNameNoRedraw
, wxhInstance
) ) 
 441         wxLogLastError(wxT("UnregisterClass(no redraw MDI child)")); 
 447     if ( !::UnregisterClass(wxCanvasClassName
, wxhInstance
) ) 
 449         wxLogLastError(wxT("UnregisterClass(canvas)")); 
 454     if ( !::UnregisterClass(wxCanvasClassNameNR
, wxhInstance
) ) 
 456         wxLogLastError(wxT("UnregisterClass(no redraw canvas)")); 
 460 #endif // __WXMICROWIN__ 
 465 // --------------------------------------------------------------------------- 
 466 // Convert Windows to argc, argv style 
 467 // --------------------------------------------------------------------------- 
 469 void wxApp::ConvertToStandardCommandArgs(const char* lpCmdLine
) 
 471     // break the command line in words 
 473         wxCmdLineParser::ConvertStringToArgs(wxConvertMB2WX(lpCmdLine
)); 
 475     // +1 here for the program name 
 476     argc 
= args
.GetCount() + 1; 
 478     // and +1 here for the terminating NULL 
 479     argv 
= new wxChar 
*[argc 
+ 1]; 
 481     argv
[0] = new wxChar
[260]; // 260 is MAX_PATH value from windef.h 
 482     ::GetModuleFileName(wxhInstance
, argv
[0], 260); 
 484     // also set the app name from argv[0] 
 486     wxFileName::SplitPath(argv
[0], NULL
, &name
, NULL
); 
 490     // copy all the other arguments to wxApp::argv[] 
 491     for ( int i 
= 1; i 
< argc
; i
++ ) 
 493         argv
[i
] = copystring(args
[i 
- 1]); 
 496     // argv[] must be NULL-terminated 
 500 //// Cleans up any wxWindows internal structures left lying around 
 502 void wxApp::CleanUp() 
 507     // flush the logged messages if any and install a 'safer' log target: the 
 508     // default one (wxLogGui) can't be used after the resources are freed just 
 509     // below and the user suppliedo ne might be even more unsafe (using any 
 510     // wxWindows GUI function is unsafe starting from now) 
 511     wxLog::DontCreateOnDemand(); 
 513     // this will flush the old messages if any 
 514     delete wxLog::SetActiveTarget(new wxLogStderr
); 
 517     // One last chance for pending objects to be cleaned up 
 518     wxTheApp
->DeletePendingObjects(); 
 520     wxModule::CleanUpModules(); 
 522 #if wxUSE_WX_RESOURCES 
 523     wxCleanUpResourceSystem(); 
 525     //  wxDefaultResourceTable->ClearTable(); 
 528     wxDeleteStockObjects(); 
 530     // Destroy all GDI lists, etc. 
 531     wxDeleteStockLists(); 
 533     delete wxTheColourDatabase
; 
 534     wxTheColourDatabase 
= NULL
; 
 536     wxBitmap::CleanUpHandlers(); 
 541     //// WINDOWS-SPECIFIC CLEANUP 
 543 #ifndef __WXMICROWIN__ 
 544     wxSetKeyboardHook(FALSE
); 
 551     if (wxSTD_FRAME_ICON
) 
 552         DestroyIcon(wxSTD_FRAME_ICON
); 
 553     if (wxSTD_MDICHILDFRAME_ICON
) 
 554         DestroyIcon(wxSTD_MDICHILDFRAME_ICON
); 
 555     if (wxSTD_MDIPARENTFRAME_ICON
) 
 556         DestroyIcon(wxSTD_MDIPARENTFRAME_ICON
); 
 558     if (wxDEFAULT_FRAME_ICON
) 
 559         DestroyIcon(wxDEFAULT_FRAME_ICON
); 
 560     if (wxDEFAULT_MDICHILDFRAME_ICON
) 
 561         DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON
); 
 562     if (wxDEFAULT_MDIPARENTFRAME_ICON
) 
 563         DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON
); 
 565     if ( wxDisableButtonBrush 
) 
 566         ::DeleteObject( wxDisableButtonBrush 
); 
 573     // for an EXE the classes are unregistered when it terminates but DLL may 
 574     // be loaded several times (load/unload/load) into the same process in 
 575     // which case the registration will fail after the first time if we don't 
 576     // unregister the classes now 
 577     UnregisterWindowClasses(); 
 578 #endif // WXMAKINGDLL 
 581     Ctl3dUnregister(wxhInstance
); 
 584     delete wxWinHandleHash
; 
 586     // GL: I'm annoyed ... I don't know where to put this and I don't want to 
 587     // create a module for that as it's part of the core. 
 588     delete wxPendingEvents
; 
 591     delete wxPendingEventsLocker
; 
 592     // If we don't do the following, we get an apparent memory leak 
 594     ((wxEvtHandler
&) wxDefaultValidator
).ClearEventLocker(); 
 595 #endif // wxUSE_VALIDATORS 
 596 #endif // wxUSE_THREADS 
 598     wxClassInfo::CleanUpClasses(); 
 603 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 604     // At this point we want to check if there are any memory 
 605     // blocks that aren't part of the wxDebugContext itself, 
 606     // as a special case. Then when dumping we need to ignore 
 607     // wxDebugContext, too. 
 608     if (wxDebugContext::CountObjectsLeft(TRUE
) > 0) 
 610         wxLogMessage(wxT("There were memory leaks.")); 
 611         wxDebugContext::Dump(); 
 612         wxDebugContext::PrintStatistics(); 
 614     //  wxDebugContext::SetStream(NULL, NULL); 
 618     // do it as the very last thing because everything else can log messages 
 619     delete wxLog::SetActiveTarget(NULL
); 
 623 //---------------------------------------------------------------------- 
 624 // Entry point helpers, used by wxPython 
 625 //---------------------------------------------------------------------- 
 627 int WXDLLEXPORT 
wxEntryStart( int WXUNUSED(argc
), char** WXUNUSED(argv
) ) 
 629     return wxApp::Initialize(); 
 632 int WXDLLEXPORT 
wxEntryInitGui() 
 634     return wxTheApp
->OnInitGui(); 
 637 void WXDLLEXPORT 
wxEntryCleanup() 
 643 #if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL)) 
 645 // temporarily disable this warning which would be generated in release builds 
 648     #pragma warning(disable: 4715) // not all control paths return a value 
 651 //---------------------------------------------------------------------- 
 652 // Main wxWindows entry point 
 653 //---------------------------------------------------------------------- 
 654 int wxEntry(WXHINSTANCE hInstance
, 
 655             WXHINSTANCE 
WXUNUSED(hPrevInstance
), 
 660     // do check for memory leaks on program exit 
 661     // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free 
 662     //  deallocated memory which may be used to simulate low-memory condition) 
 663 #ifndef __WXMICROWIN__ 
 664     wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
); 
 668 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 669     // This seems to be necessary since there are 'rogue' 
 670     // objects present at this point (perhaps global objects?) 
 671     // Setting a checkpoint will ignore them as far as the 
 672     // memory checking facility is concerned. 
 673     // Of course you may argue that memory allocated in globals should be 
 674     // checked, but this is a reasonable compromise. 
 675     wxDebugContext::SetCheckpoint(); 
 679     // take everything into a try-except block to be able to call 
 680     // OnFatalException() if necessary 
 681 #if wxUSE_ON_FATAL_EXCEPTION 
 684         wxhInstance 
= (HINSTANCE
) hInstance
; 
 686         if (!wxEntryStart(0,0)) 
 689         // create the application object or ensure that one already exists 
 692             // The app may have declared a global application object, but we recommend 
 693             // the IMPLEMENT_APP macro is used instead, which sets an initializer 
 694             // function for delayed, dynamic app object construction. 
 695             wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 696                          wxT("No initializer - use IMPLEMENT_APP macro.") ); 
 698             wxTheApp 
= (wxApp
*) (*wxApp::GetInitializerFunction()) (); 
 701         wxCHECK_MSG( wxTheApp
, 0, wxT("You have to define an instance of wxApp!") ); 
 703         // save the WinMain() parameters 
 704         if (lpCmdLine
) // MicroWindows passes NULL 
 705             wxTheApp
->ConvertToStandardCommandArgs(lpCmdLine
); 
 706         wxTheApp
->m_nCmdShow 
= nCmdShow
; 
 708         // We really don't want timestamps by default, because it means 
 709         // we can't simply double-click on the error message and get to that 
 710         // line in the source. So VC++ at least, let's have a sensible default. 
 712         wxLog::SetTimestamp(NULL
); 
 717         // it is common to create a modal dialog in OnInit() (to ask/notify the 
 718         // user about something) but it wouldn't work if we don't change the 
 719         // "exit on delete last frame" flag here as when this dialog is 
 720         // deleted, the app would terminate (it was the last top level window 
 721         // as the main frame wasn't created yet!), so disable this behaviour 
 723         bool exitOnLastFrameDelete 
= wxTheApp
->GetExitOnFrameDelete(); 
 724         wxTheApp
->SetExitOnFrameDelete(FALSE
); 
 727         retValue 
= wxEntryInitGui() && wxTheApp
->OnInit() ? 0 : -1; 
 729         // restore the old flag value 
 730         wxTheApp
->SetExitOnFrameDelete(exitOnLastFrameDelete
); 
 737                 retValue 
= wxTheApp
->OnRun(); 
 741                 // we want to initialize, but not run or exit immediately. 
 745         //else: app initialization failed, so we skipped OnRun() 
 747         wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 750             // Forcibly delete the window. 
 751             if ( topWindow
->IsKindOf(CLASSINFO(wxFrame
)) || 
 752                     topWindow
->IsKindOf(CLASSINFO(wxDialog
)) ) 
 754                 topWindow
->Close(TRUE
); 
 755                 wxTheApp
->DeletePendingObjects(); 
 760                 wxTheApp
->SetTopWindow(NULL
); 
 770 #if wxUSE_ON_FATAL_EXCEPTION 
 772     __except ( gs_handleExceptions 
? EXCEPTION_EXECUTE_HANDLER
 
 773                                    : EXCEPTION_CONTINUE_SEARCH 
) { 
 776            // give the user a chance to do something special about this 
 777            wxTheApp
->OnFatalException(); 
 780         ::ExitProcess(3); // the same exit code as abort() 
 784 #endif // wxUSE_ON_FATAL_EXCEPTION 
 787 // restore warning state 
 789     #pragma warning(default: 4715) // not all control paths return a value 
 794 //---------------------------------------------------------------------- 
 795 // Entry point for wxWindows + the App in a DLL 
 796 //---------------------------------------------------------------------- 
 798 int wxEntry(WXHINSTANCE hInstance
) 
 800     wxhInstance 
= (HINSTANCE
) hInstance
; 
 803     // The app may have declared a global application object, but we recommend 
 804     // the IMPLEMENT_APP macro is used instead, which sets an initializer function 
 805     // for delayed, dynamic app object construction. 
 808         wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 809                      "No initializer - use IMPLEMENT_APP macro." ); 
 811         wxTheApp 
= (* wxApp::GetInitializerFunction()) (); 
 814     wxCHECK_MSG( wxTheApp
, 0, "You have to define an instance of wxApp!" ); 
 817     wxTheApp
->argv 
= NULL
; 
 823     wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 824     if ( topWindow 
&& topWindow
->GetHWND()) 
 826         topWindow
->Show(TRUE
); 
 833 //// Static member initialization 
 835 wxAppInitializerFunction 
wxAppBase::m_appInitFn 
= (wxAppInitializerFunction
) NULL
; 
 841     m_printMode 
= wxPRINT_WINDOWS
; 
 847     // Delete command-line args 
 849     for (i 
= 0; i 
< argc
; i
++) 
 856 bool wxApp::Initialized() 
 863 #else // Assume initialized if DLL (no way of telling) 
 869  * Get and process a message, returning FALSE if WM_QUIT 
 870  * received (and also set the flag telling the app to exit the main loop) 
 873 bool wxApp::DoMessage() 
 875     BOOL rc 
= ::GetMessage(&s_currentMsg
, (HWND
) NULL
, 0, 0); 
 885         // should never happen, but let's test for it nevertheless 
 886         wxLogLastError(wxT("GetMessage")); 
 891         wxASSERT_MSG( wxThread::IsMain(), 
 892                       wxT("only the main thread can process Windows messages") ); 
 894         static bool s_hadGuiLock 
= TRUE
; 
 895         static wxMsgArray s_aSavedMessages
; 
 897         // if a secondary thread owns is doing GUI calls, save all messages for 
 898         // later processing - we can't process them right now because it will 
 899         // lead to recursive library calls (and we're not reentrant) 
 900         if ( !wxGuiOwnedByMainThread() ) 
 902             s_hadGuiLock 
= FALSE
; 
 904             // leave out WM_COMMAND messages: too dangerous, sometimes 
 905             // the message will be processed twice 
 906             if ( !wxIsWaitingForThread() || 
 907                     s_currentMsg
.message 
!= WM_COMMAND 
) 
 909                 s_aSavedMessages
.Add(s_currentMsg
); 
 916             // have we just regained the GUI lock? if so, post all of the saved 
 919             // FIXME of course, it's not _exactly_ the same as processing the 
 920             //       messages normally - expect some things to break... 
 925                 size_t count 
= s_aSavedMessages
.Count(); 
 926                 for ( size_t n 
= 0; n 
< count
; n
++ ) 
 928                     MSG
& msg 
= s_aSavedMessages
[n
]; 
 930                     if ( !ProcessMessage((WXMSG 
*)&msg
) ) 
 932                         ::TranslateMessage(&msg
); 
 933                         ::DispatchMessage(&msg
); 
 937                 s_aSavedMessages
.Empty(); 
 940 #endif // wxUSE_THREADS 
 942         // Process the message 
 943         DoMessage((WXMSG 
*)&s_currentMsg
); 
 949 void wxApp::DoMessage(WXMSG 
*pMsg
) 
 951     if ( !ProcessMessage(pMsg
) ) 
 953         ::TranslateMessage((MSG 
*)pMsg
); 
 954         ::DispatchMessage((MSG 
*)pMsg
); 
 959  * Keep trying to process messages until WM_QUIT 
 962  * If there are messages to be processed, they will all be 
 963  * processed and OnIdle will not be called. 
 964  * When there are no more messages, OnIdle is called. 
 965  * If OnIdle requests more time, 
 966  * it will be repeatedly called so long as there are no pending messages. 
 967  * A 'feature' of this is that once OnIdle has decided that no more processing 
 968  * is required, then it won't get processing time until further messages 
 969  * are processed (it'll sit in DoMessage). 
 972 int wxApp::MainLoop() 
 976     while ( m_keepGoing 
) 
 979         wxMutexGuiLeaveOrEnter(); 
 980 #endif // wxUSE_THREADS 
 982         while ( !Pending() && ProcessIdle() ) 
 985         // a message came or no more idle processing to do 
 989     return s_currentMsg
.wParam
; 
 992 // Returns TRUE if more time is needed. 
 993 bool wxApp::ProcessIdle() 
 996     event
.SetEventObject(this); 
 999     return event
.MoreRequested(); 
1002 void wxApp::ExitMainLoop() 
1004     // VZ: why not ::PostQuitMessage()? 
1005     m_keepGoing 
= FALSE
; 
1008 bool wxApp::Pending() 
1010     return ::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) != 0; 
1013 void wxApp::Dispatch() 
1019  * Give all windows a chance to preprocess 
1020  * the message. Some may have accelerator tables, or have 
1021  * MDI complications. 
1024 bool wxApp::ProcessMessage(WXMSG 
*wxmsg
) 
1026     MSG 
*msg 
= (MSG 
*)wxmsg
; 
1027     HWND hwnd 
= msg
->hwnd
; 
1028     wxWindow 
*wndThis 
= wxGetWindowFromHWND((WXHWND
)hwnd
); 
1030     // this may happen if the event occured in a standard modeless dialog (the 
1031     // only example of which I know of is the find/replace dialog) - then call 
1032     // IsDialogMessage() to make TAB navigation in it work 
1035         // we need to find the dialog containing this control as 
1036         // IsDialogMessage() just eats all the messages (i.e. returns TRUE for 
1037         // them) if we call it for the control itself 
1038         while ( hwnd 
&& ::GetWindowLong(hwnd
, GWL_STYLE
) & WS_CHILD 
) 
1040             hwnd 
= ::GetParent(hwnd
); 
1043         return hwnd 
&& ::IsDialogMessage(hwnd
, msg
) != 0; 
1047     // we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to 
1048     // popup the tooltip bubbles 
1049     if ( (msg
->message 
== WM_MOUSEMOVE
) ) 
1051         wxToolTip 
*tt 
= wndThis
->GetToolTip(); 
1054             tt
->RelayEvent(wxmsg
); 
1057 #endif // wxUSE_TOOLTIPS 
1059     // allow the window to prevent certain messages from being 
1060     // translated/processed (this is currently used by wxTextCtrl to always 
1061     // grab Ctrl-C/V/X, even if they are also accelerators in some parent) 
1062     if ( !wndThis
->MSWShouldPreProcessMessage(wxmsg
) ) 
1067     // try translations first: the accelerators override everything 
1070     for ( wnd 
= wndThis
; wnd
; wnd 
= wnd
->GetParent() ) 
1072         if ( wnd
->MSWTranslateMessage(wxmsg
)) 
1075         // stop at first top level window, i.e. don't try to process the key 
1076         // strokes originating in a dialog using the accelerators of the parent 
1077         // frame - this doesn't make much sense 
1078         if ( wnd
->IsTopLevel() ) 
1082     // now try the other hooks (kbd navigation is handled here): we start from 
1083     // wndThis->GetParent() because wndThis->MSWProcessMessage() was already 
1085     for ( wnd 
= wndThis
->GetParent(); wnd
; wnd 
= wnd
->GetParent() ) 
1087         if ( wnd
->MSWProcessMessage(wxmsg
) ) 
1091     // no special preprocessing for this message, dispatch it normally 
1095 void wxApp::OnIdle(wxIdleEvent
& event
) 
1097     static bool s_inOnIdle 
= FALSE
; 
1099     // Avoid recursion (via ProcessEvent default case) 
1105     // If there are pending events, we must process them: pending events 
1106     // are either events to the threads other than main or events posted 
1107     // with wxPostEvent() functions 
1108     // GRG: I have moved this here so that all pending events are processed 
1109     //   before starting to delete any objects. This behaves better (in 
1110     //   particular, wrt wxPostEvent) and is coherent with wxGTK's current 
1111     //   behaviour. Changed Feb/2000 before 2.1.14 
1112     ProcessPendingEvents(); 
1114     // 'Garbage' collection of windows deleted with Close(). 
1115     DeletePendingObjects(); 
1118     // flush the logged messages if any 
1119     wxLog::FlushActive(); 
1122 #if wxUSE_DC_CACHEING 
1123     // automated DC cache management: clear the cached DCs and bitmap 
1124     // if it's likely that the app has finished with them, that is, we 
1125     // get an idle event and we're not dragging anything. 
1126     if (!::GetKeyState(MK_LBUTTON
) && !::GetKeyState(MK_MBUTTON
) && !::GetKeyState(MK_RBUTTON
)) 
1128 #endif // wxUSE_DC_CACHEING 
1130     // Send OnIdle events to all windows 
1131     if ( SendIdleEvents() ) 
1133         // SendIdleEvents() returns TRUE if at least one window requested more 
1135         event
.RequestMore(TRUE
); 
1141 // Send idle event to all top-level windows 
1142 bool wxApp::SendIdleEvents() 
1144     bool needMore 
= FALSE
; 
1146     wxWindowList::Node
* node 
= wxTopLevelWindows
.GetFirst(); 
1149         wxWindow
* win 
= node
->GetData(); 
1150         if (SendIdleEvents(win
)) 
1152         node 
= node
->GetNext(); 
1158 // Send idle event to window and all subwindows 
1159 bool wxApp::SendIdleEvents(wxWindow
* win
) 
1161     bool needMore 
= FALSE
; 
1164     event
.SetEventObject(win
); 
1165     win
->GetEventHandler()->ProcessEvent(event
); 
1167     if (event
.MoreRequested()) 
1170     wxNode
* node 
= win
->GetChildren().First(); 
1173         wxWindow
* win 
= (wxWindow
*) node
->Data(); 
1174         if (SendIdleEvents(win
)) 
1177         node 
= node
->Next(); 
1182 void wxApp::DeletePendingObjects() 
1184     wxNode 
*node 
= wxPendingDelete
.First(); 
1187         wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
1191         if (wxPendingDelete
.Member(obj
)) 
1194         // Deleting one object may have deleted other pending 
1195         // objects, so start from beginning of list again. 
1196         node 
= wxPendingDelete
.First(); 
1200 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
)) 
1203         GetTopWindow()->Close(TRUE
); 
1206 // Default behaviour: close the application with prompts. The 
1207 // user can veto the close, and therefore the end session. 
1208 void wxApp::OnQueryEndSession(wxCloseEvent
& event
) 
1212         if (!GetTopWindow()->Close(!event
.CanVeto())) 
1218 int wxApp::GetComCtl32Version() 
1220 #ifdef __WXMICROWIN__ 
1224     static int s_verComCtl32 
= -1; 
1226     wxCRIT_SECT_DECLARE(csComCtl32
); 
1227     wxCRIT_SECT_LOCKER(lock
, csComCtl32
); 
1229     if ( s_verComCtl32 
== -1 ) 
1231         // initally assume no comctl32.dll at all 
1235         HMODULE hModuleComCtl32 
= ::GetModuleHandle(wxT("COMCTL32")); 
1237         // if so, then we can check for the version 
1238         if ( hModuleComCtl32 
) 
1240             // try to use DllGetVersion() if available in _headers_ 
1241             #ifdef DLLVER_PLATFORM_WINDOWS // defined in shlwapi.h 
1242                 DLLGETVERSIONPROC pfnDllGetVersion 
= (DLLGETVERSIONPROC
) 
1243                     ::GetProcAddress(hModuleComCtl32
, "DllGetVersion"); 
1244                 if ( pfnDllGetVersion 
) 
1247                     dvi
.cbSize 
= sizeof(dvi
); 
1249                     HRESULT hr 
= (*pfnDllGetVersion
)(&dvi
); 
1252                         wxLogApiError(_T("DllGetVersion"), hr
); 
1256                         // this is incompatible with _WIN32_IE values, but 
1257                         // compatible with the other values returned by 
1258                         // GetComCtl32Version() 
1259                         s_verComCtl32 
= 100*dvi
.dwMajorVersion 
+ 
1264                 // DllGetVersion() unavailable either during compile or 
1265                 // run-time, try to guess the version otherwise 
1266                 if ( !s_verComCtl32 
) 
1268                     // InitCommonControlsEx is unique to 4.70 and later 
1269                     FARPROC theProc 
= ::GetProcAddress
 
1272                                          "InitCommonControlsEx" 
1277                         // not found, must be 4.00 
1278                         s_verComCtl32 
= 400; 
1282                         // many symbols appeared in comctl32 4.71, could use 
1283                         // any of them except may be DllInstall 
1284                         theProc 
= ::GetProcAddress
 
1291                             // not found, must be 4.70 
1292                             s_verComCtl32 
= 470; 
1296                             // found, must be 4.71 
1297                             s_verComCtl32 
= 471; 
1304     return s_verComCtl32
; 
1310     wxLogError(_("Fatal error: exiting")); 
1316 // Yield to incoming messages 
1318 bool wxApp::Yield(bool onlyIfNeeded
) 
1321     static bool s_inYield 
= FALSE
; 
1323     // disable log flushing from here because a call to wxYield() shouldn't 
1324     // normally result in message boxes popping up &c 
1329         if ( !onlyIfNeeded 
) 
1331             wxFAIL_MSG( wxT("wxYield called recursively" ) ); 
1339     // we don't want to process WM_QUIT from here - it should be processed in 
1340     // the main event loop in order to stop it 
1342     while ( PeekMessage(&msg
, (HWND
)0, 0, 0, PM_NOREMOVE
) && 
1343             msg
.message 
!= WM_QUIT 
) 
1346         wxMutexGuiLeaveOrEnter(); 
1347 #endif // wxUSE_THREADS 
1349         if ( !wxTheApp
->DoMessage() ) 
1353     // if there are pending events, we must process them. 
1354     ProcessPendingEvents(); 
1356     // let the logs be flashed again 
1364 bool wxHandleFatalExceptions(bool doit
) 
1366 #if wxUSE_ON_FATAL_EXCEPTION 
1367     // assume this can only be called from the main thread 
1368     gs_handleExceptions 
= doit
; 
1372     wxFAIL_MSG(_T("set wxUSE_ON_FATAL_EXCEPTION to 1 to use this function")); 
1379 //----------------------------------------------------------------------------- 
1381 //----------------------------------------------------------------------------- 
1385     // Send the top window a dummy message so idle handler processing will 
1386     // start up again.  Doing it this way ensures that the idle handler 
1387     // wakes up in the right thread (see also wxWakeUpMainThread() which does 
1388     // the same for the main app thread only) 
1389     wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
1392         if ( !::PostMessage(GetHwndOf(topWindow
), WM_NULL
, 0, 0) ) 
1394             // should never happen 
1395             wxLogLastError(wxT("PostMessage(WM_NULL)")); 
1400 //----------------------------------------------------------------------------- 
1402 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly 
1403 // if in a separate file. So include it here to ensure it's linked. 
1404 #if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__) && !defined(WXMAKINGDLL))