1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "app.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  19 #if defined(__BORLANDC__) 
  27   #include "wx/gdicmn.h" 
  30   #include "wx/cursor.h" 
  32   #include "wx/palette.h" 
  34   #include "wx/dialog.h" 
  35   #include "wx/msgdlg.h" 
  38 #include "wx/msw/private.h" 
  40 #include "wx/module.h" 
  42 #if wxUSE_WX_RESOURCES 
  43   #include "wx/resource.h" 
  46 // To UG: there's no point in putting this #if here 
  47 // if you don't do the same for the Ole calls further down. 
  48 // Also, OLE is used not just for drag and drop (it's used by automatn.cpp). 
  49 // #if wxUSE_DRAG_AND_DROP 
  58 #if defined(__WIN95__) && !defined(__GNUWIN32__) 
  62 // use debug CRT functions for memory leak detections in VC++ if we're not 
  63 // using wxWindows own methods 
  64 #if defined(__WXDEBUG__) && defined(_MSC_VER) && !wxUSE_GLOBAL_MEMORY_OPERATORS && !defined(__NO_VC_CRTDBG__) 
  65     #define wxUSE_VC_CRTDBG 
  67     #undef wxUSE_VC_CRTDBG 
  70 #ifdef wxUSE_VC_CRTDBG 
  71   // VC++ uses this macro as debug/release mode indicator 
  76   /* Need to undef new if including crtdbg.h */ 
  83   #if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS && wxUSE_DEBUG_NEW_ALWAYS 
  84   #define new new(__FILE__,__LINE__) 
  89 extern char *wxBuffer
; 
  90 extern char *wxOsVersion
; 
  91 extern wxList 
*wxWinHandleList
; 
  92 extern wxList wxPendingDelete
; 
  93 extern void wxSetKeyboardHook(bool doIt
); 
  94 extern wxCursor 
*g_globalCursor
; 
  96 HINSTANCE wxhInstance 
= 0; 
  97 static MSG s_currentMsg
; 
  98 wxApp 
*wxTheApp 
= NULL
; 
 100 // @@ why not const? and not static? 
 101 char wxFrameClassName
[]         = "wxFrameClass"; 
 102 char wxMDIFrameClassName
[]      = "wxMDIFrameClass"; 
 103 char wxMDIChildFrameClassName
[] = "wxMDIChildFrameClass"; 
 104 char wxPanelClassName
[]         = "wxPanelClass"; 
 105 char wxCanvasClassName
[]        = "wxCanvasClass"; 
 107 HICON wxSTD_FRAME_ICON 
= NULL
; 
 108 HICON wxSTD_MDICHILDFRAME_ICON 
= NULL
; 
 109 HICON wxSTD_MDIPARENTFRAME_ICON 
= NULL
; 
 111 HICON wxDEFAULT_FRAME_ICON 
= NULL
; 
 112 HICON wxDEFAULT_MDICHILDFRAME_ICON 
= NULL
; 
 113 HICON wxDEFAULT_MDIPARENTFRAME_ICON 
= NULL
; 
 115 HBRUSH wxDisableButtonBrush 
= 0; 
 117 LRESULT APIENTRY 
wxWndProc(HWND
, UINT
, WPARAM
, LPARAM
); 
 119 #if !USE_SHARED_LIBRARY 
 120   IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
) 
 122   BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
) 
 123       EVT_IDLE(wxApp::OnIdle
) 
 124       EVT_END_SESSION(wxApp::OnEndSession
) 
 125       EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
) 
 129 long wxApp::sm_lastMessageTime 
= 0; 
 132   static HINSTANCE gs_hRichEdit 
= NULL
; 
 137 bool wxApp::Initialize() 
 139     // Some people may wish to use this, but 
 140     // probably it shouldn't be here by default. 
 142 //    wxRedirectIOToConsole(); 
 145     wxBuffer 
= new char[1500]; 
 147 #ifdef wxUSE_VC_CRTDBG 
 148     // do check for memory leaks on program exit 
 149     // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free 
 150     //  deallocated memory which may be used to simulate low-memory condition) 
 151     _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG
) | _CRTDBG_LEAK_CHECK_DF
); 
 152 #endif // debug build under MS VC++ 
 154     wxClassInfo::InitializeClasses(); 
 157     wxGetResource("wxWindows", "OsVersion", &wxOsVersion
); 
 160     wxTheColourDatabase 
= new wxColourDatabase(wxKEY_STRING
); 
 161     wxTheColourDatabase
->Initialize(); 
 163     wxInitializeStockLists(); 
 164     wxInitializeStockObjects(); 
 166 #if wxUSE_WX_RESOURCES 
 167     wxInitializeResourceSystem(); 
 170     wxBitmap::InitStandardHandlers(); 
 172 #if defined(__WIN95__) 
 173     InitCommonControls(); 
 174     gs_hRichEdit 
= LoadLibrary("RICHED32.DLL"); 
 176     if (gs_hRichEdit 
== NULL
) 
 178       wxMessageBox("Could not initialise Rich Edit DLL"); 
 184    // for OLE, enlarge message queue to be as large as possible 
 185    while (!SetMessageQueue(iMsg
) && (iMsg 
-= 8)); 
 189     dwOleVer = CoBuildVersion(); 
 191     // check the OLE library version 
 192     if (rmm != HIWORD(dwOleVer)) 
 194         wxMessageBox("Incorrect version of OLE libraries."); 
 200     // we need to initialize OLE library 
 201     if ( FAILED(::OleInitialize(NULL
)) ) 
 202       wxFatalError(_("Cannot initialize OLE")); 
 206     if (!Ctl3dRegister(wxhInstance
)) 
 207       wxFatalError("Cannot register CTL3D"); 
 209     Ctl3dAutoSubclass(wxhInstance
); 
 212     g_globalCursor 
= new wxCursor
; 
 214     wxSTD_FRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_FRAME"); 
 215     wxSTD_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_MDIPARENTFRAME"); 
 216     wxSTD_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_MDICHILDFRAME"); 
 218     wxDEFAULT_FRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_FRAME"); 
 219     wxDEFAULT_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_MDIPARENTFRAME"); 
 220     wxDEFAULT_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_MDICHILDFRAME"); 
 222     RegisterWindowClasses(); 
 224     // Create the brush for disabling bitmap buttons 
 227     lb
.lbStyle 
= BS_PATTERN
; 
 228     lb
.lbHatch 
= (int)LoadBitmap( wxhInstance
, "wxDISABLE_BUTTON_BITMAP" ) ; 
 229     wxDisableButtonBrush 
= ::CreateBrushIndirect( & lb 
) ; 
 230     ::DeleteObject( (HGDIOBJ
)lb
.lbHatch 
) ; 
 236     wxWinHandleList 
= new wxList(wxKEY_INTEGER
); 
 238     // This is to foil optimizations in Visual C++ that 
 239     // throw out dummy.obj. 
 240 #if (_MSC_VER >= 800) && !defined(WXMAKINGDLL) 
 241     extern char wxDummyChar
; 
 242     if (wxDummyChar
) wxDummyChar
++; 
 245     wxSetKeyboardHook(TRUE
); 
 247     wxModule::RegisterModules(); 
 248     if (!wxModule::InitializeModules()) 
 253 //// RegisterWindowClasses 
 255 bool wxApp::RegisterWindowClasses() 
 257 /////////////////////////////////////////////////////////////////////// 
 258 // Register the frame window class. 
 259   WNDCLASS wndclass
;   // Structure used to register Windows class. 
 261   wndclass
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 262   wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 263   wndclass
.cbClsExtra    
= 0; 
 264   wndclass
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 265   wndclass
.hInstance     
= wxhInstance
; 
 266   wndclass
.hIcon         
= NULL
;        // wxSTD_FRAME_ICON; 
 267   wndclass
.hCursor       
= LoadCursor( NULL
, IDC_ARROW 
); 
 268   wndclass
.hbrBackground 
=  (HBRUSH
)(COLOR_APPWORKSPACE
+1) ; 
 269 //  wndclass.hbrBackground = GetStockObject( WHITE_BRUSH ); 
 270   wndclass
.lpszMenuName  
= NULL
; 
 271 #ifdef _MULTIPLE_INSTANCES 
 272   sprintf( wxFrameClassName
,"wxFrameClass%d", wxhInstance 
); 
 274   wndclass
.lpszClassName 
= wxFrameClassName
; 
 276   if (!RegisterClass( &wndclass 
)) 
 278     // wxFatalError("Can't register Frame Window class"); 
 281 /////////////////////////////////////////////////////////////////////// 
 282 // Register the MDI frame window class. 
 283   WNDCLASS wndclass1
;   // Structure used to register Windows class. 
 285   wndclass1
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 286   wndclass1
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 287   wndclass1
.cbClsExtra    
= 0; 
 288   wndclass1
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 289   wndclass1
.hInstance     
= wxhInstance
; 
 290   wndclass1
.hIcon         
= NULL
; // wxSTD_MDIPARENTFRAME_ICON; 
 291   wndclass1
.hCursor       
= LoadCursor( NULL
, IDC_ARROW 
); 
 292 //  wndclass1.hbrBackground =  (HBRUSH)(COLOR_APPWORKSPACE+1) ; 
 293   wndclass1
.hbrBackground 
= NULL
; 
 294   wndclass1
.lpszMenuName  
= NULL
; 
 296   wndclass1
.lpszClassName 
= wxMDIFrameClassName
; 
 297   if (!RegisterClass( &wndclass1 
)) 
 299 //    wxFatalError("Can't register MDI Frame window class"); 
 303 /////////////////////////////////////////////////////////////////////// 
 304 // Register the MDI child frame window class. 
 305   WNDCLASS wndclass4
;   // Structure used to register Windows class. 
 307   wndclass4
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 308   wndclass4
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 309   wndclass4
.cbClsExtra    
= 0; 
 310   wndclass4
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 311   wndclass4
.hInstance     
= wxhInstance
; 
 312   wndclass4
.hIcon         
= NULL
;       // wxSTD_MDICHILDFRAME_ICON; 
 313   wndclass4
.hCursor       
= LoadCursor( NULL
, IDC_ARROW 
); 
 314   // TODO: perhaps this should be NULL so that Windows doesn't 
 315   // paint the background itself (would OnEraseBackground duplicate 
 317   wndclass4
.hbrBackground 
=  (HBRUSH
)(COLOR_WINDOW
+1) ; 
 318 //  wndclass4.hbrBackground = NULL; 
 319   wndclass4
.lpszMenuName  
= NULL
; 
 320   wndclass4
.lpszClassName 
= wxMDIChildFrameClassName
; 
 322   if (!RegisterClass( &wndclass4 
)) 
 324 //   wxFatalError("Can't register MDI child frame window class"); 
 328 /////////////////////////////////////////////////////////////////////// 
 329 // Register the panel window class. 
 330   WNDCLASS wndclass2
;   // Structure used to register Windows class. 
 331   memset(&wndclass2
, 0, sizeof(WNDCLASS
));   // start with NULL defaults 
 332   // Use CS_OWNDC to avoid messing about restoring the context 
 333   // for every graphic operation. 
 334   wndclass2
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 335   wndclass2
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 336   wndclass2
.cbClsExtra    
= 0; 
 337   wndclass2
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 338   wndclass2
.hInstance     
= wxhInstance
; 
 339   wndclass2
.hIcon         
= NULL
; 
 340   wndclass2
.hCursor       
= NULL
; 
 341 //  wndclass2.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ; 
 342   wndclass2
.hbrBackground 
= (HBRUSH
) GetStockObject( LTGRAY_BRUSH 
); 
 343   wndclass2
.lpszMenuName  
= NULL
; 
 344   wndclass2
.lpszClassName 
= wxPanelClassName
; 
 345   if (!RegisterClass( &wndclass2 
)) 
 347 //   wxFatalError("Can't register Panel Window class"); 
 351 /////////////////////////////////////////////////////////////////////// 
 352 // Register the canvas and textsubwindow class name 
 353   WNDCLASS wndclass3
;   // Structure used to register Windows class. 
 354   memset(&wndclass3
, 0, sizeof(WNDCLASS
));   // start with NULL defaults 
 355   // Use CS_OWNDC to avoid messing about restoring the context 
 356   // for every graphic operation. 
 357 //  wndclass3.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS ; 
 359   wndclass3
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
; 
 360   wndclass3
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 361   wndclass3
.cbClsExtra    
= 0; 
 362   wndclass3
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 363   wndclass3
.hInstance     
= wxhInstance
; 
 364   wndclass3
.hIcon         
= NULL
; 
 365   wndclass3
.hCursor       
= NULL
; 
 366 //  wndclass3.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ; 
 367   wndclass3
.hbrBackground 
= NULL
; 
 368   wndclass3
.lpszMenuName  
= NULL
; 
 369   wndclass3
.lpszClassName 
= wxCanvasClassName
; 
 370   if (!RegisterClass( &wndclass3
)) 
 372 //   wxFatalError("Can't register Canvas class"); 
 379 //// Convert Windows to argc, argv style 
 381 void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine
) 
 385     wxString 
cmdLine(lpCmdLine
); 
 388     // Get application name 
 389     char name
[260]; // 260 is MAX_PATH value from windef.h 
 390     ::GetModuleFileName(wxhInstance
, name
, WXSIZEOF(name
)); 
 392     // GNUWIN32 already fills in the first arg with the application name. 
 393 #if !defined(__GNUWIN32__) 
 398     strcpy(name
, wxFileNameFromPath(name
)); 
 399     wxStripExtension(name
); 
 400     wxTheApp
->SetAppName(name
); 
 403     // Treat strings enclosed in double-quotes as single arguments 
 405     int len 
= cmdLine
.Length(); 
 409         while ((i 
< len
) && isspace(cmdLine
.GetChar(i
))) 
 414             if (cmdLine
.GetChar(i
) == '"') // We found the start of a string 
 418                 while ((i 
< len
) && (cmdLine
.GetChar(i
) != '"')) 
 421                 wxString 
arg(cmdLine
.Mid(first
, (i 
- first
))); 
 427                     i 
++; // Skip past 2nd quote 
 429             else // Unquoted argument 
 432                 while ((i 
< len
) && !isspace(cmdLine
.GetChar(i
))) 
 435                 wxString 
arg(cmdLine
.Mid(first
, (i 
- first
))); 
 443     wxTheApp
->argv 
= new char*[count 
+ 1]; 
 444     for (i 
= 0; i 
< count
; i
++) 
 446         wxString 
arg(args
[i
]); 
 447         wxTheApp
->argv
[i
] = copystring((const char*)arg
); 
 449     wxTheApp
->argv
[count
] = NULL
; // argv[] is a NULL-terminated list 
 450     wxTheApp
->argc 
= count
; 
 453 //// Cleans up any wxWindows internal structures left lying around 
 455 void wxApp::CleanUp() 
 458   wxModule::CleanUpModules(); 
 460 #if wxUSE_WX_RESOURCES 
 461   wxCleanUpResourceSystem(); 
 463 //  wxDefaultResourceTable->ClearTable(); 
 466   // Indicate that the cursor can be freed, 
 467   // so that cursor won't be deleted by deleting 
 468   // the bitmap list before g_globalCursor goes out 
 469   // of scope (double deletion of the cursor). 
 470   wxSetCursor(wxNullCursor
); 
 471   delete g_globalCursor
; 
 473   wxDeleteStockObjects() ; 
 475   // Destroy all GDI lists, etc. 
 476   wxDeleteStockLists(); 
 478   delete wxTheColourDatabase
; 
 479   wxTheColourDatabase 
= NULL
; 
 481   wxBitmap::CleanUpHandlers(); 
 486   //// WINDOWS-SPECIFIC CLEANUP 
 488   wxSetKeyboardHook(FALSE
); 
 491   if (gs_hRichEdit 
!= NULL
) 
 492     FreeLibrary(gs_hRichEdit
); 
 499   if (wxSTD_FRAME_ICON
) 
 500     DestroyIcon(wxSTD_FRAME_ICON
); 
 501   if (wxSTD_MDICHILDFRAME_ICON
) 
 502     DestroyIcon(wxSTD_MDICHILDFRAME_ICON
); 
 503   if (wxSTD_MDIPARENTFRAME_ICON
) 
 504     DestroyIcon(wxSTD_MDIPARENTFRAME_ICON
); 
 506   if (wxDEFAULT_FRAME_ICON
) 
 507     DestroyIcon(wxDEFAULT_FRAME_ICON
); 
 508   if (wxDEFAULT_MDICHILDFRAME_ICON
) 
 509     DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON
); 
 510   if (wxDEFAULT_MDIPARENTFRAME_ICON
) 
 511     DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON
); 
 513   if ( wxDisableButtonBrush 
) 
 514     ::DeleteObject( wxDisableButtonBrush 
) ; 
 521   Ctl3dUnregister(wxhInstance
); 
 525     delete wxWinHandleList 
; 
 527   wxClassInfo::CleanUpClasses(); 
 532 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 533   // At this point we want to check if there are any memory 
 534   // blocks that aren't part of the wxDebugContext itself, 
 535   // as a special case. Then when dumping we need to ignore 
 536   // wxDebugContext, too. 
 537   if (wxDebugContext::CountObjectsLeft() > 0) 
 539       wxLogDebug("There were memory leaks."); 
 540       wxDebugContext::Dump(); 
 541       wxDebugContext::PrintStatistics(); 
 543 //  wxDebugContext::SetStream(NULL, NULL); 
 546   // do it as the very last thing because everything else can log messages 
 547   wxLog::DontCreateOnDemand(); 
 548   delete wxLog::SetActiveTarget(NULL
); 
 551 #if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL)) 
 553 //// Main wxWindows entry point 
 554 int wxEntry(WXHINSTANCE hInstance
, 
 555             WXHINSTANCE 
WXUNUSED(hPrevInstance
), 
 560 #ifndef __WXDEBUG__ // take everything into a try-except block in release build 
 564   wxhInstance 
= (HINSTANCE
) hInstance
; 
 566   if (!wxApp::Initialize()) 
 569   // create the application object or ensure that one already exists 
 572     // The app may have declared a global application object, but we recommend 
 573     // the IMPLEMENT_APP macro is used instead, which sets an initializer 
 574     // function for delayed, dynamic app object construction. 
 575     wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 576                  "No initializer - use IMPLEMENT_APP macro." ); 
 578     wxTheApp 
= (*wxApp::GetInitializerFunction()) (); 
 581   wxCHECK_MSG( wxTheApp
, 0, "You have to define an instance of wxApp!" ); 
 583   // save the WinMain() parameters 
 584   wxTheApp
->ConvertToStandardCommandArgs(lpCmdLine
); 
 585   wxTheApp
->m_nCmdShow 
= nCmdShow
; 
 587   // GUI-specific initialisation. In fact on Windows we don't have any, 
 588   // but this call is provided for compatibility across platforms. 
 589   wxTheApp
->OnInitGui() ; 
 593   if ( wxTheApp
->OnInit() ) 
 597           retValue 
= wxTheApp
->OnRun(); 
 600   //else: app initialization failed, so we skipped OnRun() 
 602   wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 605       // Forcibly delete the window. 
 606       if ( topWindow
->IsKindOf(CLASSINFO(wxFrame
)) || 
 607            topWindow
->IsKindOf(CLASSINFO(wxDialog
)) ) 
 609           topWindow
->Close(TRUE
); 
 610           wxTheApp
->DeletePendingObjects(); 
 615           wxTheApp
->SetTopWindow(NULL
); 
 621   // flush the logged messages if any 
 622   wxLog 
*pLog 
= wxLog::GetActiveTarget(); 
 623   if ( pLog 
!= NULL 
&& pLog
->HasPendingMessages() ) 
 630 #ifndef __WXDEBUG__ // catch exceptions only in release build 
 632   except ( EXCEPTION_EXECUTE_HANDLER 
) { 
 635       wxTheApp->OnFatalException(); 
 638     ::ExitProcess(3); // the same exit code as abort() 
 645 //// Entry point for DLLs 
 647 int wxEntry(WXHINSTANCE hInstance
) 
 649   wxhInstance 
= (HINSTANCE
) hInstance
; 
 652   // The app may have declared a global application object, but we recommend 
 653   // the IMPLEMENT_APP macro is used instead, which sets an initializer function 
 654   // for delayed, dynamic app object construction. 
 658     if (!wxApp::GetInitializerFunction()) 
 660       MessageBox(NULL
, "No initializer - use IMPLEMENT_APP macro.", "wxWindows Error", MB_APPLMODAL 
| MB_ICONSTOP 
| MB_OK
); 
 664     wxTheApp 
= (* wxApp::GetInitializerFunction()) (); 
 668     MessageBox(NULL
, "You have to define an instance of wxApp!", "wxWindows Error", MB_APPLMODAL 
| MB_ICONSTOP 
| MB_OK
); 
 673   wxTheApp
->argv 
= NULL
; 
 675   wxTheApp
->OnInitGui(); 
 679   if (wxTheApp
->GetTopWindow() && wxTheApp
->GetTopWindow()->GetHWND()) { 
 680     wxTheApp
->GetTopWindow()->Show(TRUE
); 
 687 //// Static member initialization 
 689 wxAppInitializerFunction 
wxApp::m_appInitFn 
= (wxAppInitializerFunction
) NULL
; 
 696   m_wantDebugOutput 
= TRUE 
; 
 701   m_printMode 
= wxPRINT_WINDOWS
; 
 703   m_printMode 
= wxPRINT_POSTSCRIPT
; 
 705   m_exitOnFrameDelete 
= TRUE
; 
 711   // Delete command-line args 
 713   for (i 
= 0; i 
< argc
; i
++) 
 720 bool wxApp::Initialized() 
 728 #ifdef _WINDLL // Assume initialized if DLL (no way of telling) 
 734  * Get and process a message, returning FALSE if WM_QUIT 
 738 bool wxApp::DoMessage() 
 740   if (!::GetMessage(&s_currentMsg
, (HWND
) NULL
, 0, 0)) 
 745   // Process the message 
 746   if (!ProcessMessage((WXMSG 
*)&s_currentMsg
)) 
 748     ::TranslateMessage(&s_currentMsg
); 
 749     wxApp::sm_lastMessageTime 
= s_currentMsg
.time
; /* MATTHEW: timeStamp impl. */ 
 750     ::DispatchMessage(&s_currentMsg
); 
 756  * Keep trying to process messages until WM_QUIT 
 759  * If there are messages to be processed, they will all be 
 760  * processed and OnIdle will not be called. 
 761  * When there are no more messages, OnIdle is called. 
 762  * If OnIdle requests more time, 
 763  * it will be repeatedly called so long as there are no pending messages. 
 764  * A 'feature' of this is that once OnIdle has decided that no more processing 
 765  * is required, then it won't get processing time until further messages 
 766  * are processed (it'll sit in DoMessage). 
 769 int wxApp::MainLoop() 
 774     while (!::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) && 
 780   return s_currentMsg
.wParam
; 
 783 // Returns TRUE if more time is needed. 
 784 bool wxApp::ProcessIdle() 
 787     event
.SetEventObject(this); 
 790     return event
.MoreRequested(); 
 793 void wxApp::ExitMainLoop() 
 798 bool wxApp::Pending() 
 800   return (::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) != 0) ; 
 803 void wxApp::Dispatch() 
 810  * Give all windows a chance to preprocess 
 811  * the message. Some may have accelerator tables, or have 
 814 bool wxApp::ProcessMessage(WXMSG 
*Msg
) 
 816   MSG 
*msg 
= (MSG 
*)Msg
; 
 820   // Try translations first; find the youngest window with 
 821   // a translation table. 
 822   for (hWnd 
= msg
->hwnd
; hWnd 
!= NULL
; hWnd 
= ::GetParent(hWnd
)) 
 824     wxWindow 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
 827        if (wnd
->MSWTranslateMessage(Msg
)) 
 832   // Anyone for a non-translation message? Try youngest descendants first. 
 833   for (hWnd 
= msg
->hwnd
; hWnd 
!= NULL
; hWnd 
= ::GetParent(hWnd
)) 
 835     wxWindow 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
 838        if (wnd
->MSWProcessMessage(Msg
)) 
 845 void wxApp::OnIdle(wxIdleEvent
& event
) 
 847   static bool inOnIdle 
= FALSE
; 
 849   // Avoid recursion (via ProcessEvent default case) 
 855   // 'Garbage' collection of windows deleted with Close(). 
 856   DeletePendingObjects(); 
 858   // flush the logged messages if any 
 859   wxLog 
*pLog 
= wxLog::GetActiveTarget(); 
 860   if ( pLog 
!= NULL 
&& pLog
->HasPendingMessages() ) 
 863   // Send OnIdle events to all windows 
 864   bool needMore 
= SendIdleEvents(); 
 865 //  bool needMore = FALSE; 
 868     event
.RequestMore(TRUE
); 
 873 // Send idle event to all top-level windows 
 874 bool wxApp::SendIdleEvents() 
 876     bool needMore 
= FALSE
; 
 877   wxNode
* node 
= wxTopLevelWindows
.First(); 
 880     wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 881     if (SendIdleEvents(win
)) 
 889 // Send idle event to window and all subwindows 
 890 bool wxApp::SendIdleEvents(wxWindow
* win
) 
 892   bool needMore 
= FALSE
; 
 895   event
.SetEventObject(win
); 
 896   win
->GetEventHandler()->ProcessEvent(event
); 
 898   if (event
.MoreRequested()) 
 901   wxNode
* node 
= win
->GetChildren().First(); 
 904     wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 905     if (SendIdleEvents(win
)) 
 913 void wxApp::DeletePendingObjects() 
 915   wxNode 
*node 
= wxPendingDelete
.First(); 
 918     wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
 922     if (wxPendingDelete
.Member(obj
)) 
 925     // Deleting one object may have deleted other pending 
 926     // objects, so start from beginning of list again. 
 927     node 
= wxPendingDelete
.First(); 
 931 void wxApp::OnEndSession(wxCloseEvent
& event
) 
 934         GetTopWindow()->Close(TRUE
); 
 937 // Default behaviour: close the application with prompts. The 
 938 // user can veto the close, and therefore the end session. 
 939 void wxApp::OnQueryEndSession(wxCloseEvent
& event
) 
 943         if (!GetTopWindow()->Close(!event
.CanVeto())) 
 948 wxLog
* wxApp::CreateLogTarget() 
 953 wxWindow
* wxApp::GetTopWindow() const 
 957     else if (wxTopLevelWindows
.Number() > 0) 
 958         return (wxWindow
*) wxTopLevelWindows
.First()->Data(); 
 963 int wxApp::GetComCtl32Version() const 
 965     // have we loaded COMCTL32 yet? 
 966     HMODULE theModule 
= ::GetModuleHandle("COMCTL32"); 
 969     // if so, then we can check for the version 
 972         // InitCommonControlsEx is unique to 4.7 and later 
 973         FARPROC theProc 
= ::GetProcAddress(theModule
, "InitCommonControlsEx"); 
 976         {                    // not found, must be 4.00 
 981       // The following symbol are unique to 4.71 
 983       //   FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos 
 984       //   FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo 
 985       //   FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange 
 986       //   FlatSB_ShowScrollBar 
 987       //   _DrawIndirectImageList _DuplicateImageList 
 989       //   UninitializeFlatSB 
 990       // we could check for any of these - I chose DllInstall 
 991       FARPROC theProc 
= ::GetProcAddress(theModule
, "DllInstall"); 
 994         // not found, must be 4.70 
 998       {                         // found, must be 4.71 
1009   FatalAppExit(0, "Fatal error: exiting"); 
1012 // Yield to incoming messages 
1016   // We want to go back to the main message loop 
1017   // if we see a WM_QUIT. (?) 
1018   while (PeekMessage(&msg
, NULL
, 0, 0, PM_NOREMOVE
) && msg
.message 
!= WM_QUIT
) 
1020     if (!wxTheApp
->DoMessage()) 
1027 HINSTANCE 
wxGetInstance() 
1032 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly 
1033 // if in a separate file. So include it here to ensure it's linked. 
1034 #if (defined(_MSC_VER) && !defined(__WIN32__)) || defined(__GNUWIN32__)