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/module.h" 
  54 #include "wx/msw/private.h" 
  57     #include "wx/thread.h" 
  59     // define the array of MSG strutures 
  60     WX_DECLARE_OBJARRAY(MSG
, wxMsgArray
); 
  62     #include "wx/arrimpl.cpp" 
  64     WX_DEFINE_OBJARRAY(wxMsgArray
); 
  65 #endif // wxUSE_THREADS 
  67 #if wxUSE_WX_RESOURCES 
  68     #include "wx/resource.h" 
  72     #include "wx/tooltip.h" 
  73 #endif // wxUSE_TOOLTIPS 
  75 // OLE is used for drag-and-drop, clipboard, OLE Automation..., but some 
  76 // compilers don't support it (missing headers, libs, ...) 
  77 #if defined(__GNUWIN32_OLD__) || defined(__SC__) || defined(__SALFORDC__) 
  81 #endif // broken compilers 
  90 #if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__) || defined(__WXMICROWIN__)) && !defined(__CYGWIN10__)) 
  94 #ifndef __WXMICROWIN__ 
  95 #include "wx/msw/msvcrt.h" 
  98 // ---------------------------------------------------------------------------- 
  99 // conditional compilation 
 100 // ---------------------------------------------------------------------------- 
 102 // The macro _WIN32_IE is defined by commctrl.h (unless it had already been 
 103 // defined before) and shows us what common control features are available 
 104 // during the compile time (it doesn't mean that they will be available during 
 105 // the run-time, use GetComCtl32Version() to test for them!). The possible 
 108 // 0x0200     for comctl32.dll 4.00 shipped with Win95/NT 4.0 
 109 // 0x0300                      4.70              IE 3.x 
 110 // 0x0400                      4.71              IE 4.0 
 111 // 0x0401                      4.72              IE 4.01 and Win98 
 112 // 0x0500                      5.00              IE 5.x and NT 5.0 (Win2000) 
 115     // minimal set of features by default 
 116     #define _WIN32_IE 0x0200 
 119 #if _WIN32_IE >= 0x0300 && !defined(__MINGW32__) 
 123 // --------------------------------------------------------------------------- 
 125 // --------------------------------------------------------------------------- 
 127 extern wxChar 
*wxBuffer
; 
 128 extern wxList WXDLLEXPORT wxPendingDelete
; 
 129 #ifndef __WXMICROWIN__ 
 130 extern void wxSetKeyboardHook(bool doIt
); 
 134 wxApp 
*wxTheApp 
= NULL
; 
 136 // NB: all "NoRedraw" classes must have the same names as the "normal" classes 
 137 //     with NR suffix - wxWindow::MSWCreate() supposes this 
 138 const wxChar 
*wxFrameClassName         
= wxT("wxFrameClass"); 
 139 const wxChar 
*wxFrameClassNameNoRedraw 
= wxT("wxFrameClassNR"); 
 140 const wxChar 
*wxMDIFrameClassName      
= wxT("wxMDIFrameClass"); 
 141 const wxChar 
*wxMDIFrameClassNameNoRedraw 
= wxT("wxMDIFrameClassNR"); 
 142 const wxChar 
*wxMDIChildFrameClassName 
= wxT("wxMDIChildFrameClass"); 
 143 const wxChar 
*wxMDIChildFrameClassNameNoRedraw 
= wxT("wxMDIChildFrameClassNR"); 
 144 const wxChar 
*wxPanelClassName         
= wxT("wxPanelClass"); 
 145 const wxChar 
*wxPanelClassNameNR       
= wxT("wxPanelClassNR"); 
 146 const wxChar 
*wxCanvasClassName        
= wxT("wxCanvasClass"); 
 147 const wxChar 
*wxCanvasClassNameNR      
= wxT("wxCanvasClassNR"); 
 149 HICON wxSTD_FRAME_ICON 
= (HICON
) NULL
; 
 150 HICON wxSTD_MDICHILDFRAME_ICON 
= (HICON
) NULL
; 
 151 HICON wxSTD_MDIPARENTFRAME_ICON 
= (HICON
) NULL
; 
 153 HICON wxDEFAULT_FRAME_ICON 
= (HICON
) NULL
; 
 154 HICON wxDEFAULT_MDICHILDFRAME_ICON 
= (HICON
) NULL
; 
 155 HICON wxDEFAULT_MDIPARENTFRAME_ICON 
= (HICON
) NULL
; 
 157 HBRUSH wxDisableButtonBrush 
= (HBRUSH
) 0; 
 159 LRESULT WXDLLEXPORT APIENTRY 
wxWndProc(HWND
, UINT
, WPARAM
, LPARAM
); 
 161 // FIXME wxUSE_ON_FATAL_EXCEPTION is only supported for VC++ now because it 
 162 //       needs compiler support for Win32 SEH. Others (especially Borland) 
 163 //       probably have it too, but I'm not sure about how it works 
 164 // JACS: get 'Cannot use __try in functions that require unwinding 
 165 // in Unicode mode, so disabling. 
 166 #if !defined(__VISUALC__) || defined(__WIN16__) || defined(UNICODE) 
 167     #undef wxUSE_ON_FATAL_EXCEPTION 
 168     #define wxUSE_ON_FATAL_EXCEPTION 0 
 171 #if wxUSE_ON_FATAL_EXCEPTION 
 172     static bool gs_handleExceptions 
= FALSE
; 
 175 // =========================================================================== 
 177 // =========================================================================== 
 179 // --------------------------------------------------------------------------- 
 181 // --------------------------------------------------------------------------- 
 183 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
) 
 185 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
) 
 186     EVT_IDLE(wxApp::OnIdle
) 
 187     EVT_END_SESSION(wxApp::OnEndSession
) 
 188     EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
) 
 192 bool wxApp::Initialize() 
 194     // the first thing to do is to check if we're trying to run an Unicode 
 195     // program under Win9x - if so, abort right now as it has no chance to 
 198     if ( wxGetOsVersion() != wxWINDOWS_NT 
) 
 200         // note that we can use MessageBoxW() as it's implemented even under 
 201         // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs 
 202         // used by wxLocale are not 
 206          _T("This program uses Unicode and requires Windows NT/2000.\nProgram aborted."), 
 207          _T("wxWindows Fatal Error"), 
 213 #endif // wxUSE_UNICODE 
 215     // Some people may wish to use this, but 
 216     // probably it shouldn't be here by default. 
 218     //    wxRedirectIOToConsole(); 
 221     wxBuffer 
= new wxChar
[1500]; // FIXME 
 223     wxClassInfo::InitializeClasses(); 
 226     wxPendingEventsLocker 
= new wxCriticalSection
; 
 229     wxTheColourDatabase 
= new wxColourDatabase(wxKEY_STRING
); 
 230     wxTheColourDatabase
->Initialize(); 
 232     wxInitializeStockLists(); 
 233     wxInitializeStockObjects(); 
 235 #if wxUSE_WX_RESOURCES 
 236     wxInitializeResourceSystem(); 
 239     wxBitmap::InitStandardHandlers(); 
 241 #if defined(__WIN95__) && !defined(__WXMICROWIN__) 
 242     InitCommonControls(); 
 245 #if wxUSE_OLE || wxUSE_DRAG_AND_DROP 
 248     // for OLE, enlarge message queue to be as large as possible 
 250     while (!SetMessageQueue(iMsg
) && (iMsg 
-= 8)) 
 254     // we need to initialize OLE library 
 255     if ( FAILED(::OleInitialize(NULL
)) ) 
 256         wxLogError(_("Cannot initialize OLE")); 
 261     if (!Ctl3dRegister(wxhInstance
)) 
 262         wxLogError(wxT("Cannot register CTL3D")); 
 264     Ctl3dAutoSubclass(wxhInstance
); 
 265 #endif // wxUSE_CTL3D 
 267     // VZ: these icons are not in wx.rc anyhow (but should they?)! 
 269     wxSTD_FRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxSTD_FRAME")); 
 270     wxSTD_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxSTD_MDIPARENTFRAME")); 
 271     wxSTD_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxSTD_MDICHILDFRAME")); 
 273     wxDEFAULT_FRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxDEFAULT_FRAME")); 
 274     wxDEFAULT_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxDEFAULT_MDIPARENTFRAME")); 
 275     wxDEFAULT_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, wxT("wxDEFAULT_MDICHILDFRAME")); 
 278     RegisterWindowClasses(); 
 280 #ifndef __WXMICROWIN__ 
 281     // Create the brush for disabling bitmap buttons 
 284     lb
.lbStyle 
= BS_PATTERN
; 
 286     lb
.lbHatch 
= (int)LoadBitmap( wxhInstance
, wxT("wxDISABLE_BUTTON_BITMAP") ); 
 289         wxDisableButtonBrush 
= ::CreateBrushIndirect( & lb 
); 
 290         ::DeleteObject( (HGDIOBJ
)lb
.lbHatch 
); 
 292     //else: wxWindows resources are probably not linked in 
 299     wxWinHandleHash 
= new wxWinHashTable(wxKEY_INTEGER
, 100); 
 301     // This is to foil optimizations in Visual C++ that throw out dummy.obj. 
 302     // PLEASE DO NOT ALTER THIS. 
 303 #if defined(__VISUALC__) && defined(__WIN16__) && !defined(WXMAKINGDLL) 
 304     extern char wxDummyChar
; 
 305     if (wxDummyChar
) wxDummyChar
++; 
 308 #ifndef __WXMICROWIN__ 
 309     wxSetKeyboardHook(TRUE
); 
 312     wxModule::RegisterModules(); 
 313     if (!wxModule::InitializeModules()) 
 318 // --------------------------------------------------------------------------- 
 319 // RegisterWindowClasses 
 320 // --------------------------------------------------------------------------- 
 322 // TODO we should only register classes really used by the app. For this it 
 323 //      would be enough to just delay the class registration until an attempt 
 324 //      to create a window of this class is made. 
 325 bool wxApp::RegisterWindowClasses() 
 329     // for each class we register one with CS_(V|H)REDRAW style and one 
 330     // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag 
 331     static const long styleNormal 
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS
; 
 332     static const long styleNoRedraw 
= CS_DBLCLKS
; 
 334     // the fields which are common to all classes 
 335     wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 336     wndclass
.cbClsExtra    
= 0; 
 337     wndclass
.cbWndExtra    
= sizeof( DWORD 
); // VZ: what is this DWORD used for? 
 338     wndclass
.hInstance     
= wxhInstance
; 
 339     wndclass
.hIcon         
= (HICON
) NULL
; 
 340     wndclass
.hCursor       
= ::LoadCursor((HINSTANCE
)NULL
, IDC_ARROW
); 
 341     wndclass
.lpszMenuName  
= NULL
; 
 343     // Register the frame window class. 
 344     wndclass
.hbrBackground 
= (HBRUSH
)(COLOR_APPWORKSPACE 
+ 1); 
 345     wndclass
.lpszClassName 
= wxFrameClassName
; 
 346     wndclass
.style         
= styleNormal
; 
 348     if ( !RegisterClass(&wndclass
) ) 
 350         wxLogLastError(wxT("RegisterClass(frame)")); 
 356     wndclass
.lpszClassName 
= wxFrameClassNameNoRedraw
; 
 357     wndclass
.style         
= styleNoRedraw
; 
 359     if ( !RegisterClass(&wndclass
) ) 
 361         wxLogLastError(wxT("RegisterClass(no redraw frame)")); 
 366     // Register the MDI frame window class. 
 367     wndclass
.hbrBackground 
= (HBRUSH
)NULL
; // paint MDI frame ourselves 
 368     wndclass
.lpszClassName 
= wxMDIFrameClassName
; 
 369     wndclass
.style         
= styleNormal
; 
 371     if ( !RegisterClass(&wndclass
) ) 
 373         wxLogLastError(wxT("RegisterClass(MDI parent)")); 
 378     // "no redraw" MDI frame 
 379     wndclass
.lpszClassName 
= wxMDIFrameClassNameNoRedraw
; 
 380     wndclass
.style         
= styleNoRedraw
; 
 382     if ( !RegisterClass(&wndclass
) ) 
 384         wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)")); 
 389     // Register the MDI child frame window class. 
 390     wndclass
.hbrBackground 
= (HBRUSH
)(COLOR_WINDOW 
+ 1); 
 391     wndclass
.lpszClassName 
= wxMDIChildFrameClassName
; 
 392     wndclass
.style         
= styleNormal
; 
 394     if ( !RegisterClass(&wndclass
) ) 
 396         wxLogLastError(wxT("RegisterClass(MDI child)")); 
 401     // "no redraw" MDI child frame 
 402     wndclass
.lpszClassName 
= wxMDIChildFrameClassNameNoRedraw
; 
 403     wndclass
.style         
= styleNoRedraw
; 
 405     if ( !RegisterClass(&wndclass
) ) 
 407         wxLogLastError(wxT("RegisterClass(no redraw MDI child)")); 
 412     // Register the panel window class. 
 413     wndclass
.hbrBackground 
= (HBRUSH
) GetStockObject( LTGRAY_BRUSH 
); 
 414     wndclass
.lpszClassName 
= wxPanelClassName
; 
 415     wndclass
.style         
= styleNormal
; 
 417     if ( !RegisterClass(&wndclass
) ) 
 419         wxLogLastError(wxT("RegisterClass(panel)")); 
 424     // Register the no redraw panel window class. 
 425     wndclass
.lpszClassName 
= wxPanelClassNameNR
; 
 426     wndclass
.style         
= styleNoRedraw
; 
 428     if ( !RegisterClass(&wndclass
) ) 
 430         wxLogLastError(wxT("RegisterClass(no redraw panel)")); 
 435     // Register the canvas and textsubwindow class name 
 436     wndclass
.hbrBackground 
= (HBRUSH
)NULL
; 
 437     wndclass
.lpszClassName 
= wxCanvasClassName
; 
 439     if ( !RegisterClass(&wndclass
) ) 
 441         wxLogLastError(wxT("RegisterClass(canvas)")); 
 446     wndclass
.lpszClassName 
= wxCanvasClassNameNR
; 
 447     wndclass
.style         
= styleNoRedraw
; 
 448     if ( !RegisterClass(&wndclass
) ) 
 450         wxLogLastError(wxT("RegisterClass(no redraw canvas)")); 
 458 // --------------------------------------------------------------------------- 
 459 // UnregisterWindowClasses 
 460 // --------------------------------------------------------------------------- 
 462 bool wxApp::UnregisterWindowClasses() 
 466 #ifndef __WXMICROWIN__ 
 467     // frame window class. 
 468     if ( !UnregisterClass(wxFrameClassName
, wxhInstance
) ) 
 470         wxLogLastError(wxT("UnregisterClass(frame)")); 
 476     if ( !UnregisterClass(wxFrameClassNameNoRedraw
, wxhInstance
) ) 
 478         wxLogLastError(wxT("UnregisterClass(no redraw frame)")); 
 483     // MDI frame window class. 
 484     if ( !UnregisterClass(wxMDIFrameClassName
, wxhInstance
) ) 
 486         wxLogLastError(wxT("UnregisterClass(MDI parent)")); 
 491     // "no redraw" MDI frame 
 492     if ( !UnregisterClass(wxMDIFrameClassNameNoRedraw
, wxhInstance
) ) 
 494         wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)")); 
 499     // MDI child frame window class. 
 500     if ( !UnregisterClass(wxMDIChildFrameClassName
, wxhInstance
) ) 
 502         wxLogLastError(wxT("UnregisterClass(MDI child)")); 
 507     // "no redraw" MDI child frame 
 508     if ( !UnregisterClass(wxMDIChildFrameClassNameNoRedraw
, wxhInstance
) ) 
 510         wxLogLastError(wxT("UnregisterClass(no redraw MDI child)")); 
 515     // panel window class. 
 516     if ( !UnregisterClass(wxPanelClassName
, wxhInstance
) ) 
 518         wxLogLastError(wxT("UnregisterClass(panel)")); 
 523     // no redraw panel window class. 
 524     if ( !UnregisterClass(wxPanelClassNameNR
, wxhInstance
) ) 
 526         wxLogLastError(wxT("UnregisterClass(no redraw panel)")); 
 531     // canvas and textsubwindow class name 
 532     if ( !UnregisterClass(wxCanvasClassName
, wxhInstance
) ) 
 534         wxLogLastError(wxT("UnregisterClass(canvas)")); 
 539     if ( !UnregisterClass(wxCanvasClassNameNR
, wxhInstance
) ) 
 541         wxLogLastError(wxT("UnregisterClass(no redraw canvas)")); 
 550 // --------------------------------------------------------------------------- 
 551 // Convert Windows to argc, argv style 
 552 // --------------------------------------------------------------------------- 
 554 void wxApp::ConvertToStandardCommandArgs(const char* lpCmdLine
) 
 556     // break the command line in words 
 558         wxCmdLineParser::ConvertStringToArgs(wxConvertMB2WX(lpCmdLine
)); 
 560     // +1 here for the program name 
 561     argc 
= args
.GetCount() + 1; 
 563     // and +1 here for the terminating NULL 
 564     argv 
= new wxChar 
*[argc 
+ 1]; 
 566     argv
[0] = new wxChar
[260]; // 260 is MAX_PATH value from windef.h 
 567     ::GetModuleFileName(wxhInstance
, argv
[0], 260); 
 569     for ( int i 
= 1; i 
< argc
; i
++ ) 
 571         argv
[i
] = copystring(args
[i 
- 1]); 
 574     // argv[] must be NULL-terminated 
 578 //// Cleans up any wxWindows internal structures left lying around 
 580 void wxApp::CleanUp() 
 585     // flush the logged messages if any and install a 'safer' log target: the 
 586     // default one (wxLogGui) can't be used after the resources are freed just 
 587     // below and the user suppliedo ne might be even more unsafe (using any 
 588     // wxWindows GUI function is unsafe starting from now) 
 589     wxLog::DontCreateOnDemand(); 
 591     // this will flush the old messages if any 
 592     delete wxLog::SetActiveTarget(new wxLogStderr
); 
 595     // One last chance for pending objects to be cleaned up 
 596     wxTheApp
->DeletePendingObjects(); 
 598     wxModule::CleanUpModules(); 
 600 #if wxUSE_WX_RESOURCES 
 601     wxCleanUpResourceSystem(); 
 603     //  wxDefaultResourceTable->ClearTable(); 
 606     wxDeleteStockObjects(); 
 608     // Destroy all GDI lists, etc. 
 609     wxDeleteStockLists(); 
 611     delete wxTheColourDatabase
; 
 612     wxTheColourDatabase 
= NULL
; 
 614     wxBitmap::CleanUpHandlers(); 
 619     //// WINDOWS-SPECIFIC CLEANUP 
 621 #ifndef __WXMICROWIN__ 
 622     wxSetKeyboardHook(FALSE
); 
 629     if (wxSTD_FRAME_ICON
) 
 630         DestroyIcon(wxSTD_FRAME_ICON
); 
 631     if (wxSTD_MDICHILDFRAME_ICON
) 
 632         DestroyIcon(wxSTD_MDICHILDFRAME_ICON
); 
 633     if (wxSTD_MDIPARENTFRAME_ICON
) 
 634         DestroyIcon(wxSTD_MDIPARENTFRAME_ICON
); 
 636     if (wxDEFAULT_FRAME_ICON
) 
 637         DestroyIcon(wxDEFAULT_FRAME_ICON
); 
 638     if (wxDEFAULT_MDICHILDFRAME_ICON
) 
 639         DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON
); 
 640     if (wxDEFAULT_MDIPARENTFRAME_ICON
) 
 641         DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON
); 
 643     if ( wxDisableButtonBrush 
) 
 644         ::DeleteObject( wxDisableButtonBrush 
); 
 651     // for an EXE the classes are unregistered when it terminates but DLL may 
 652     // be loaded several times (load/unload/load) into the same process in 
 653     // which case the registration will fail after the first time if we don't 
 654     // unregister the classes now 
 655     UnregisterWindowClasses(); 
 656 #endif // WXMAKINGDLL 
 659     Ctl3dUnregister(wxhInstance
); 
 662     delete wxWinHandleHash
; 
 664     // GL: I'm annoyed ... I don't know where to put this and I don't want to 
 665     // create a module for that as it's part of the core. 
 666     delete wxPendingEvents
; 
 669     delete wxPendingEventsLocker
; 
 670     // If we don't do the following, we get an apparent memory leak 
 672     ((wxEvtHandler
&) wxDefaultValidator
).ClearEventLocker(); 
 673 #endif // wxUSE_VALIDATORS 
 674 #endif // wxUSE_THREADS 
 676     wxClassInfo::CleanUpClasses(); 
 681 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 682     // At this point we want to check if there are any memory 
 683     // blocks that aren't part of the wxDebugContext itself, 
 684     // as a special case. Then when dumping we need to ignore 
 685     // wxDebugContext, too. 
 686     if (wxDebugContext::CountObjectsLeft(TRUE
) > 0) 
 688         wxLogMessage(wxT("There were memory leaks.")); 
 689         wxDebugContext::Dump(); 
 690         wxDebugContext::PrintStatistics(); 
 692     //  wxDebugContext::SetStream(NULL, NULL); 
 696     // do it as the very last thing because everything else can log messages 
 697     delete wxLog::SetActiveTarget(NULL
); 
 701 //---------------------------------------------------------------------- 
 702 // Entry point helpers, used by wxPython 
 703 //---------------------------------------------------------------------- 
 705 int WXDLLEXPORT 
wxEntryStart( int WXUNUSED(argc
), char** WXUNUSED(argv
) ) 
 707     return wxApp::Initialize(); 
 710 int WXDLLEXPORT 
wxEntryInitGui() 
 712     return wxTheApp
->OnInitGui(); 
 715 void WXDLLEXPORT 
wxEntryCleanup() 
 721 #if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL)) 
 723 // temporarily disable this warning which would be generated in release builds 
 726     #pragma warning(disable: 4715) // not all control paths return a value 
 729 //---------------------------------------------------------------------- 
 730 // Main wxWindows entry point 
 731 //---------------------------------------------------------------------- 
 732 int wxEntry(WXHINSTANCE hInstance
, 
 733             WXHINSTANCE 
WXUNUSED(hPrevInstance
), 
 738     // do check for memory leaks on program exit 
 739     // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free 
 740     //  deallocated memory which may be used to simulate low-memory condition) 
 741 #ifndef __WXMICROWIN__ 
 742     wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
); 
 746 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 747     // This seems to be necessary since there are 'rogue' 
 748     // objects present at this point (perhaps global objects?) 
 749     // Setting a checkpoint will ignore them as far as the 
 750     // memory checking facility is concerned. 
 751     // Of course you may argue that memory allocated in globals should be 
 752     // checked, but this is a reasonable compromise. 
 753     wxDebugContext::SetCheckpoint(); 
 757     // take everything into a try-except block to be able to call 
 758     // OnFatalException() if necessary 
 759 #if wxUSE_ON_FATAL_EXCEPTION 
 762         wxhInstance 
= (HINSTANCE
) hInstance
; 
 764         if (!wxEntryStart(0,0)) 
 767         // create the application object or ensure that one already exists 
 770             // The app may have declared a global application object, but we recommend 
 771             // the IMPLEMENT_APP macro is used instead, which sets an initializer 
 772             // function for delayed, dynamic app object construction. 
 773             wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 774                          wxT("No initializer - use IMPLEMENT_APP macro.") ); 
 776             wxTheApp 
= (wxApp
*) (*wxApp::GetInitializerFunction()) (); 
 779         wxCHECK_MSG( wxTheApp
, 0, wxT("You have to define an instance of wxApp!") ); 
 781         // save the WinMain() parameters 
 782         wxTheApp
->ConvertToStandardCommandArgs(lpCmdLine
); 
 783         wxTheApp
->m_nCmdShow 
= nCmdShow
; 
 785         // We really don't want timestamps by default, because it means 
 786         // we can't simply double-click on the error message and get to that 
 787         // line in the source. So VC++ at least, let's have a sensible default. 
 789         wxLog::SetTimestamp(NULL
); 
 794         // it is common to create a modal dialog in OnInit() (to ask/notify the 
 795         // user about something) but it wouldn't work if we don't change the 
 796         // "exit on delete last frame" flag here as when this dialog is 
 797         // deleted, the app would terminate (it was the last top level window 
 798         // as the main frame wasn't created yet!), so disable this behaviour 
 800         bool exitOnLastFrameDelete 
= wxTheApp
->GetExitOnFrameDelete(); 
 801         wxTheApp
->SetExitOnFrameDelete(FALSE
); 
 804         retValue 
= wxEntryInitGui() && wxTheApp
->OnInit() ? 0 : -1; 
 806         // restore the old flag value 
 807         wxTheApp
->SetExitOnFrameDelete(exitOnLastFrameDelete
); 
 814                 retValue 
= wxTheApp
->OnRun(); 
 818                 // we want to initialize, but not run or exit immediately. 
 822         //else: app initialization failed, so we skipped OnRun() 
 824         wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 827             // Forcibly delete the window. 
 828             if ( topWindow
->IsKindOf(CLASSINFO(wxFrame
)) || 
 829                     topWindow
->IsKindOf(CLASSINFO(wxDialog
)) ) 
 831                 topWindow
->Close(TRUE
); 
 832                 wxTheApp
->DeletePendingObjects(); 
 837                 wxTheApp
->SetTopWindow(NULL
); 
 847 #if wxUSE_ON_FATAL_EXCEPTION 
 849     __except ( gs_handleExceptions 
? EXCEPTION_EXECUTE_HANDLER
 
 850                                    : EXCEPTION_CONTINUE_SEARCH 
) { 
 853            // give the user a chance to do something special about this 
 854            wxTheApp
->OnFatalException(); 
 857         ::ExitProcess(3); // the same exit code as abort() 
 861 #endif // wxUSE_ON_FATAL_EXCEPTION 
 864 // restore warning state 
 866     #pragma warning(default: 4715) // not all control paths return a value 
 871 //---------------------------------------------------------------------- 
 872 // Entry point for wxWindows + the App in a DLL 
 873 //---------------------------------------------------------------------- 
 875 int wxEntry(WXHINSTANCE hInstance
) 
 877     wxhInstance 
= (HINSTANCE
) hInstance
; 
 880     // The app may have declared a global application object, but we recommend 
 881     // the IMPLEMENT_APP macro is used instead, which sets an initializer function 
 882     // for delayed, dynamic app object construction. 
 885         wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 886                      "No initializer - use IMPLEMENT_APP macro." ); 
 888         wxTheApp 
= (* wxApp::GetInitializerFunction()) (); 
 891     wxCHECK_MSG( wxTheApp
, 0, "You have to define an instance of wxApp!" ); 
 894     wxTheApp
->argv 
= NULL
; 
 900     wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 901     if ( topWindow 
&& topWindow
->GetHWND()) 
 903         topWindow
->Show(TRUE
); 
 910 //// Static member initialization 
 912 wxAppInitializerFunction 
wxAppBase::m_appInitFn 
= (wxAppInitializerFunction
) NULL
; 
 918     m_printMode 
= wxPRINT_WINDOWS
; 
 924     // Delete command-line args 
 926     for (i 
= 0; i 
< argc
; i
++) 
 933 bool wxApp::Initialized() 
 940 #else // Assume initialized if DLL (no way of telling) 
 946  * Get and process a message, returning FALSE if WM_QUIT 
 947  * received (and also set the flag telling the app to exit the main loop) 
 950 bool wxApp::DoMessage() 
 952     BOOL rc 
= ::GetMessage(&s_currentMsg
, (HWND
) NULL
, 0, 0); 
 962         // should never happen, but let's test for it nevertheless 
 963         wxLogLastError(wxT("GetMessage")); 
 968         wxASSERT_MSG( wxThread::IsMain(), 
 969                       wxT("only the main thread can process Windows messages") ); 
 971         static bool s_hadGuiLock 
= TRUE
; 
 972         static wxMsgArray s_aSavedMessages
; 
 974         // if a secondary thread owns is doing GUI calls, save all messages for 
 975         // later processing - we can't process them right now because it will 
 976         // lead to recursive library calls (and we're not reentrant) 
 977         if ( !wxGuiOwnedByMainThread() ) 
 979             s_hadGuiLock 
= FALSE
; 
 981             // leave out WM_COMMAND messages: too dangerous, sometimes 
 982             // the message will be processed twice 
 983             if ( !wxIsWaitingForThread() || 
 984                     s_currentMsg
.message 
!= WM_COMMAND 
) 
 986                 s_aSavedMessages
.Add(s_currentMsg
); 
 993             // have we just regained the GUI lock? if so, post all of the saved 
 996             // FIXME of course, it's not _exactly_ the same as processing the 
 997             //       messages normally - expect some things to break... 
1000                 s_hadGuiLock 
= TRUE
; 
1002                 size_t count 
= s_aSavedMessages
.Count(); 
1003                 for ( size_t n 
= 0; n 
< count
; n
++ ) 
1005                     MSG
& msg 
= s_aSavedMessages
[n
]; 
1007                     if ( !ProcessMessage((WXMSG 
*)&msg
) ) 
1009                         ::TranslateMessage(&msg
); 
1010                         ::DispatchMessage(&msg
); 
1014                 s_aSavedMessages
.Empty(); 
1017 #endif // wxUSE_THREADS 
1019         // Process the message 
1020         DoMessage((WXMSG 
*)&s_currentMsg
); 
1026 void wxApp::DoMessage(WXMSG 
*pMsg
) 
1028     if ( !ProcessMessage(pMsg
) ) 
1030         ::TranslateMessage((MSG 
*)pMsg
); 
1031         ::DispatchMessage((MSG 
*)pMsg
); 
1036  * Keep trying to process messages until WM_QUIT 
1039  * If there are messages to be processed, they will all be 
1040  * processed and OnIdle will not be called. 
1041  * When there are no more messages, OnIdle is called. 
1042  * If OnIdle requests more time, 
1043  * it will be repeatedly called so long as there are no pending messages. 
1044  * A 'feature' of this is that once OnIdle has decided that no more processing 
1045  * is required, then it won't get processing time until further messages 
1046  * are processed (it'll sit in DoMessage). 
1049 int wxApp::MainLoop() 
1053     while ( m_keepGoing 
) 
1056         wxMutexGuiLeaveOrEnter(); 
1057 #endif // wxUSE_THREADS 
1059         while ( !Pending() && ProcessIdle() ) 
1062         // a message came or no more idle processing to do 
1066     return s_currentMsg
.wParam
; 
1069 // Returns TRUE if more time is needed. 
1070 bool wxApp::ProcessIdle() 
1073     event
.SetEventObject(this); 
1074     ProcessEvent(event
); 
1076     return event
.MoreRequested(); 
1079 void wxApp::ExitMainLoop() 
1081     // VZ: why not ::PostQuitMessage()? 
1082     m_keepGoing 
= FALSE
; 
1085 bool wxApp::Pending() 
1087     return ::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) != 0; 
1090 void wxApp::Dispatch() 
1096  * Give all windows a chance to preprocess 
1097  * the message. Some may have accelerator tables, or have 
1098  * MDI complications. 
1101 bool wxApp::ProcessMessage(WXMSG 
*wxmsg
) 
1103     MSG 
*msg 
= (MSG 
*)wxmsg
; 
1104     HWND hwnd 
= msg
->hwnd
; 
1105     wxWindow 
*wndThis 
= wxGetWindowFromHWND((WXHWND
)hwnd
); 
1107     // this may happen if the event occured in a standard modeless dialog (the 
1108     // only example of which I know of is the find/replace dialog) - then call 
1109     // IsDialogMessage() to make TAB navigation in it work 
1112         // we need to find the dialog containing this control as 
1113         // IsDialogMessage() just eats all the messages (i.e. returns TRUE for 
1114         // them) if we call it for the control itself 
1115         while ( hwnd 
&& ::GetWindowLong(hwnd
, GWL_STYLE
) & WS_CHILD 
) 
1117             hwnd 
= ::GetParent(hwnd
); 
1120         return hwnd 
&& ::IsDialogMessage(hwnd
, msg
) != 0; 
1124     // we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to 
1125     // popup the tooltip bubbles 
1126     if ( (msg
->message 
== WM_MOUSEMOVE
) ) 
1128         wxToolTip 
*tt 
= wndThis
->GetToolTip(); 
1131             tt
->RelayEvent(wxmsg
); 
1134 #endif // wxUSE_TOOLTIPS 
1136     // allow the window to prevent certain messages from being 
1137     // translated/processed (this is currently used by wxTextCtrl to always 
1138     // grab Ctrl-C/V/X, even if they are also accelerators in some parent) 
1139     if ( !wndThis
->MSWShouldPreProcessMessage(wxmsg
) ) 
1144     // try translations first: the accelerators override everything 
1147     for ( wnd 
= wndThis
; wnd
; wnd 
= wnd
->GetParent() ) 
1149         if ( wnd
->MSWTranslateMessage(wxmsg
)) 
1152         // stop at first top level window, i.e. don't try to process the key 
1153         // strokes originating in a dialog using the accelerators of the parent 
1154         // frame - this doesn't make much sense 
1155         if ( wnd
->IsTopLevel() ) 
1159     // now try the other hooks (kbd navigation is handled here): we start from 
1160     // wndThis->GetParent() because wndThis->MSWProcessMessage() was already 
1162     for ( wnd 
= wndThis
->GetParent(); wnd
; wnd 
= wnd
->GetParent() ) 
1164         if ( wnd
->MSWProcessMessage(wxmsg
) ) 
1168     // no special preprocessing for this message, dispatch it normally 
1172 void wxApp::OnIdle(wxIdleEvent
& event
) 
1174     static bool s_inOnIdle 
= FALSE
; 
1176     // Avoid recursion (via ProcessEvent default case) 
1182     // If there are pending events, we must process them: pending events 
1183     // are either events to the threads other than main or events posted 
1184     // with wxPostEvent() functions 
1185     // GRG: I have moved this here so that all pending events are processed 
1186     //   before starting to delete any objects. This behaves better (in 
1187     //   particular, wrt wxPostEvent) and is coherent with wxGTK's current 
1188     //   behaviour. Changed Feb/2000 before 2.1.14 
1189     ProcessPendingEvents(); 
1191     // 'Garbage' collection of windows deleted with Close(). 
1192     DeletePendingObjects(); 
1195     // flush the logged messages if any 
1196     wxLog::FlushActive(); 
1199 #if wxUSE_DC_CACHEING 
1200     // automated DC cache management: clear the cached DCs and bitmap 
1201     // if it's likely that the app has finished with them, that is, we 
1202     // get an idle event and we're not dragging anything. 
1203     if (!::GetKeyState(MK_LBUTTON
) && !::GetKeyState(MK_MBUTTON
) && !::GetKeyState(MK_RBUTTON
)) 
1205 #endif // wxUSE_DC_CACHEING 
1207     // Send OnIdle events to all windows 
1208     if ( SendIdleEvents() ) 
1210         // SendIdleEvents() returns TRUE if at least one window requested more 
1212         event
.RequestMore(TRUE
); 
1218 // Send idle event to all top-level windows 
1219 bool wxApp::SendIdleEvents() 
1221     bool needMore 
= FALSE
; 
1223     wxWindowList::Node
* node 
= wxTopLevelWindows
.GetFirst(); 
1226         wxWindow
* win 
= node
->GetData(); 
1227         if (SendIdleEvents(win
)) 
1229         node 
= node
->GetNext(); 
1235 // Send idle event to window and all subwindows 
1236 bool wxApp::SendIdleEvents(wxWindow
* win
) 
1238     bool needMore 
= FALSE
; 
1241     event
.SetEventObject(win
); 
1242     win
->GetEventHandler()->ProcessEvent(event
); 
1244     if (event
.MoreRequested()) 
1247     wxNode
* node 
= win
->GetChildren().First(); 
1250         wxWindow
* win 
= (wxWindow
*) node
->Data(); 
1251         if (SendIdleEvents(win
)) 
1254         node 
= node
->Next(); 
1259 void wxApp::DeletePendingObjects() 
1261     wxNode 
*node 
= wxPendingDelete
.First(); 
1264         wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
1268         if (wxPendingDelete
.Member(obj
)) 
1271         // Deleting one object may have deleted other pending 
1272         // objects, so start from beginning of list again. 
1273         node 
= wxPendingDelete
.First(); 
1277 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
)) 
1280         GetTopWindow()->Close(TRUE
); 
1283 // Default behaviour: close the application with prompts. The 
1284 // user can veto the close, and therefore the end session. 
1285 void wxApp::OnQueryEndSession(wxCloseEvent
& event
) 
1289         if (!GetTopWindow()->Close(!event
.CanVeto())) 
1295 int wxApp::GetComCtl32Version() 
1297 #ifdef __WXMICROWIN__ 
1301     static int s_verComCtl32 
= -1; 
1303     wxCRIT_SECT_DECLARE(csComCtl32
); 
1304     wxCRIT_SECT_LOCKER(lock
, csComCtl32
); 
1306     if ( s_verComCtl32 
== -1 ) 
1308         // initally assume no comctl32.dll at all 
1312         HMODULE hModuleComCtl32 
= ::GetModuleHandle(wxT("COMCTL32")); 
1314         // if so, then we can check for the version 
1315         if ( hModuleComCtl32 
) 
1317             // try to use DllGetVersion() if available in _headers_ 
1318             #ifdef DLLVER_PLATFORM_WINDOWS // defined in shlwapi.h 
1319                 DLLGETVERSIONPROC pfnDllGetVersion 
= (DLLGETVERSIONPROC
) 
1320                     ::GetProcAddress(hModuleComCtl32
, "DllGetVersion"); 
1321                 if ( pfnDllGetVersion 
) 
1324                     dvi
.cbSize 
= sizeof(dvi
); 
1326                     HRESULT hr 
= (*pfnDllGetVersion
)(&dvi
); 
1329                         wxLogApiError(_T("DllGetVersion"), hr
); 
1333                         // this is incompatible with _WIN32_IE values, but 
1334                         // compatible with the other values returned by 
1335                         // GetComCtl32Version() 
1336                         s_verComCtl32 
= 100*dvi
.dwMajorVersion 
+ 
1341                 // DllGetVersion() unavailable either during compile or 
1342                 // run-time, try to guess the version otherwise 
1343                 if ( !s_verComCtl32 
) 
1345                     // InitCommonControlsEx is unique to 4.70 and later 
1346                     FARPROC theProc 
= ::GetProcAddress
 
1349                                          "InitCommonControlsEx" 
1354                         // not found, must be 4.00 
1355                         s_verComCtl32 
= 400; 
1359                         // many symbols appeared in comctl32 4.71, could use 
1360                         // any of them except may be DllInstall 
1361                         theProc 
= ::GetProcAddress
 
1368                             // not found, must be 4.70 
1369                             s_verComCtl32 
= 470; 
1373                             // found, must be 4.71 
1374                             s_verComCtl32 
= 471; 
1381     return s_verComCtl32
; 
1387     wxLogError(_("Fatal error: exiting")); 
1393 // Yield to incoming messages 
1395 bool wxApp::Yield(bool onlyIfNeeded
) 
1398     static bool s_inYield 
= FALSE
; 
1400     // disable log flushing from here because a call to wxYield() shouldn't 
1401     // normally result in message boxes popping up &c 
1406         if ( !onlyIfNeeded 
) 
1408             wxFAIL_MSG( wxT("wxYield called recursively" ) ); 
1416     // we don't want to process WM_QUIT from here - it should be processed in 
1417     // the main event loop in order to stop it 
1419     while ( PeekMessage(&msg
, (HWND
)0, 0, 0, PM_NOREMOVE
) && 
1420             msg
.message 
!= WM_QUIT 
) 
1423         wxMutexGuiLeaveOrEnter(); 
1424 #endif // wxUSE_THREADS 
1426         if ( !wxTheApp
->DoMessage() ) 
1430     // if there are pending events, we must process them. 
1431     ProcessPendingEvents(); 
1433     // let the logs be flashed again 
1441 bool wxHandleFatalExceptions(bool doit
) 
1443 #if wxUSE_ON_FATAL_EXCEPTION 
1444     // assume this can only be called from the main thread 
1445     gs_handleExceptions 
= doit
; 
1449     wxFAIL_MSG(_T("set wxUSE_ON_FATAL_EXCEPTION to 1 to use this function")); 
1456 //----------------------------------------------------------------------------- 
1458 //----------------------------------------------------------------------------- 
1462     // Send the top window a dummy message so idle handler processing will 
1463     // start up again.  Doing it this way ensures that the idle handler 
1464     // wakes up in the right thread (see also wxWakeUpMainThread() which does 
1465     // the same for the main app thread only) 
1466     wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
1469         if ( !::PostMessage(GetHwndOf(topWindow
), WM_NULL
, 0, 0) ) 
1471             // should never happen 
1472             wxLogLastError(wxT("PostMessage(WM_NULL)")); 
1477 //----------------------------------------------------------------------------- 
1480 wxApp::GetStdIcon(int which
) const 
1484         case wxICON_INFORMATION
: 
1485             return wxIcon("wxICON_INFO"); 
1487         case wxICON_QUESTION
: 
1488             return wxIcon("wxICON_QUESTION"); 
1490         case wxICON_EXCLAMATION
: 
1491             return wxIcon("wxICON_WARNING"); 
1494             wxFAIL_MSG(wxT("requested non existent standard icon")); 
1495             // still fall through 
1498             return wxIcon("wxICON_ERROR"); 
1502 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly 
1503 // if in a separate file. So include it here to ensure it's linked. 
1504 #if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__) && !defined(WXMAKINGDLL))