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" 
  39 #include "wx/postscrp.h" 
  41 #include "wx/module.h" 
  44   #include "wx/resource.h" 
  50 #if defined(__WIN95__) && !defined(__GNUWIN32__) 
  54 // use debug CRT functions for memory leak detections in VC++ 
  55 #if defined(__WXDEBUG__) && defined(_MSC_VER) 
  56   // VC++ uses this macro as debug/release mode indicator 
  64 extern char *wxBuffer
; 
  65 extern char *wxOsVersion
; 
  66 extern wxList 
*wxWinHandleList
; 
  67 extern wxList wxPendingDelete
; 
  68 extern void wxSetKeyboardHook(bool doIt
); 
  69 extern wxCursor 
*g_globalCursor
; 
  71 HINSTANCE wxhInstance 
= 0; 
  72 static MSG s_currentMsg
; 
  73 wxApp 
*wxTheApp 
= NULL
; 
  75 // @@ why not const? and not static? 
  76 char wxFrameClassName
[]         = "wxFrameClass"; 
  77 char wxMDIFrameClassName
[]      = "wxMDIFrameClass"; 
  78 char wxMDIChildFrameClassName
[] = "wxMDIChildFrameClass"; 
  79 char wxPanelClassName
[]         = "wxPanelClass"; 
  80 char wxCanvasClassName
[]        = "wxCanvasClass"; 
  82 HICON wxSTD_FRAME_ICON 
= NULL
; 
  83 HICON wxSTD_MDICHILDFRAME_ICON 
= NULL
; 
  84 HICON wxSTD_MDIPARENTFRAME_ICON 
= NULL
; 
  86 HICON wxDEFAULT_FRAME_ICON 
= NULL
; 
  87 HICON wxDEFAULT_MDICHILDFRAME_ICON 
= NULL
; 
  88 HICON wxDEFAULT_MDIPARENTFRAME_ICON 
= NULL
; 
  90 HBRUSH wxDisableButtonBrush 
= 0; 
  92 LRESULT APIENTRY 
wxWndProc(HWND
, UINT
, WPARAM
, LPARAM
); 
  94 #if !USE_SHARED_LIBRARY 
  95   IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
) 
  97   BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
) 
  98       EVT_IDLE(wxApp::OnIdle
) 
 102 long wxApp::sm_lastMessageTime 
= 0; 
 105   static HINSTANCE gs_hRichEdit 
= NULL
; 
 110 bool wxApp::Initialize() 
 112   wxBuffer 
= new char[1500]; 
 114   #if defined(__WXDEBUG__) && defined(_MSC_VER) 
 115     // do check for memory leaks on program exit 
 116     // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free 
 117     //  deallocated memory which may be used to simulate low-memory condition) 
 118     _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG
) | _CRTDBG_LEAK_CHECK_DF
); 
 119   #endif // debug build under MS VC++ 
 121   #if (WXDEBUG && USE_MEMORY_TRACING) || USE_DEBUG_CONTEXT 
 123       streambuf
* sBuf 
= NULL
; 
 125       streambuf
* sBuf 
= new wxDebugStreamBuf
; 
 128     ostream
* oStr 
= new ostream(sBuf
) ; 
 129     wxDebugContext::SetStream(oStr
, sBuf
); 
 130   #endif  // USE_MEMORY_TRACING 
 132   wxClassInfo::InitializeClasses(); 
 135     wxGetResource("wxWindows", "OsVersion", &wxOsVersion
); 
 138   wxTheColourDatabase 
= new wxColourDatabase(wxKEY_STRING
); 
 139   wxTheColourDatabase
->Initialize(); 
 141   wxInitializeStockLists(); 
 142   wxInitializeStockObjects(); 
 145     wxInitializeResourceSystem(); 
 148   // For PostScript printing 
 150     wxInitializePrintSetupData(); 
 151     wxThePrintPaperDatabase 
= new wxPrintPaperDatabase
; 
 152     wxThePrintPaperDatabase
->CreateDatabase(); 
 155   wxBitmap::InitStandardHandlers(); 
 157   #if defined(__WIN95__) 
 158     InitCommonControls(); 
 159     gs_hRichEdit 
= LoadLibrary("RICHED32.DLL"); 
 161     if (gs_hRichEdit 
== NULL
) 
 163       wxMessageBox("Could not initialise Rich Edit DLL"); 
 167   #if  defined(WX_DRAG_DROP) 
 168     // we need to initialize OLE library 
 169     if ( FAILED(::OleInitialize(NULL
)) ) 
 170       wxFatalError(_("Cannot initialize OLE")); 
 174     if (!Ctl3dRegister(wxhInstance
)) 
 175       wxFatalError("Cannot register CTL3D"); 
 177     Ctl3dAutoSubclass(wxhInstance
); 
 180   g_globalCursor 
= new wxCursor
; 
 182   wxSTD_FRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_FRAME"); 
 183   wxSTD_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_MDIPARENTFRAME"); 
 184   wxSTD_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_MDICHILDFRAME"); 
 186   wxDEFAULT_FRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_FRAME"); 
 187   wxDEFAULT_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_MDIPARENTFRAME"); 
 188   wxDEFAULT_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_MDICHILDFRAME"); 
 190   RegisterWindowClasses(); 
 192   // Create the brush for disabling bitmap buttons 
 195   lb
.lbStyle 
= BS_PATTERN
; 
 196   lb
.lbHatch 
= (int)LoadBitmap( wxhInstance
, "wxDISABLE_BUTTON_BITMAP" ) ; 
 197   wxDisableButtonBrush 
= ::CreateBrushIndirect( & lb 
) ; 
 198   ::DeleteObject( (HGDIOBJ
)lb
.lbHatch 
) ; 
 204   wxWinHandleList 
= new wxList(wxKEY_INTEGER
); 
 206   // This is to foil optimizations in Visual C++ that 
 207   // throw out dummy.obj. 
 208   #if (_MSC_VER >= 800) && !defined(WXMAKINGDLL) 
 209     extern char wxDummyChar
; 
 210     if (wxDummyChar
) wxDummyChar
++; 
 213   wxSetKeyboardHook(TRUE
); 
 215   wxModule::RegisterModules(); 
 216   if (!wxModule::InitializeModules()) 
 221 //// RegisterWindowClasses 
 223 bool wxApp::RegisterWindowClasses() 
 225 /////////////////////////////////////////////////////////////////////// 
 226 // Register the frame window class. 
 227   WNDCLASS wndclass
;   // Structure used to register Windows class. 
 229   wndclass
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 230   wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 231   wndclass
.cbClsExtra    
= 0; 
 232   wndclass
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 233   wndclass
.hInstance     
= wxhInstance
; 
 234   wndclass
.hIcon         
= NULL
;        // wxSTD_FRAME_ICON; 
 235   wndclass
.hCursor       
= LoadCursor( NULL
, IDC_ARROW 
); 
 236   wndclass
.hbrBackground 
=  (HBRUSH
)(COLOR_APPWORKSPACE
+1) ; 
 237 //  wndclass.hbrBackground = GetStockObject( WHITE_BRUSH ); 
 238   wndclass
.lpszMenuName  
= NULL
; 
 239 #ifdef _MULTIPLE_INSTANCES 
 240   sprintf( wxFrameClassName
,"wxFrameClass%d", wxhInstance 
); 
 242   wndclass
.lpszClassName 
= wxFrameClassName
; 
 244   if (!RegisterClass( &wndclass 
)) 
 246     // wxFatalError("Can't register Frame Window class"); 
 249 /////////////////////////////////////////////////////////////////////// 
 250 // Register the MDI frame window class. 
 251   WNDCLASS wndclass1
;   // Structure used to register Windows class. 
 253   wndclass1
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 254   wndclass1
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 255   wndclass1
.cbClsExtra    
= 0; 
 256   wndclass1
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 257   wndclass1
.hInstance     
= wxhInstance
; 
 258   wndclass1
.hIcon         
= NULL
; // wxSTD_MDIPARENTFRAME_ICON; 
 259   wndclass1
.hCursor       
= LoadCursor( NULL
, IDC_ARROW 
); 
 260 //  wndclass1.hbrBackground =  (HBRUSH)(COLOR_APPWORKSPACE+1) ; 
 261   wndclass1
.hbrBackground 
= NULL
; 
 262   wndclass1
.lpszMenuName  
= NULL
; 
 264   wndclass1
.lpszClassName 
= wxMDIFrameClassName
; 
 265   if (!RegisterClass( &wndclass1 
)) 
 267 //    wxFatalError("Can't register MDI Frame window class"); 
 271 /////////////////////////////////////////////////////////////////////// 
 272 // Register the MDI child frame window class. 
 273   WNDCLASS wndclass4
;   // Structure used to register Windows class. 
 275   wndclass4
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 276   wndclass4
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 277   wndclass4
.cbClsExtra    
= 0; 
 278   wndclass4
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 279   wndclass4
.hInstance     
= wxhInstance
; 
 280   wndclass4
.hIcon         
= NULL
;       // wxSTD_MDICHILDFRAME_ICON; 
 281   wndclass4
.hCursor       
= LoadCursor( NULL
, IDC_ARROW 
); 
 282   // TODO: perhaps this should be NULL so that Windows doesn't 
 283   // paint the background itself (would OnEraseBackground duplicate 
 285   wndclass4
.hbrBackground 
=  (HBRUSH
)(COLOR_WINDOW
+1) ; 
 286 //  wndclass4.hbrBackground = NULL; 
 287   wndclass4
.lpszMenuName  
= NULL
; 
 288   wndclass4
.lpszClassName 
= wxMDIChildFrameClassName
; 
 290   if (!RegisterClass( &wndclass4 
)) 
 292 //   wxFatalError("Can't register MDI child frame window class"); 
 296 /////////////////////////////////////////////////////////////////////// 
 297 // Register the panel window class. 
 298   WNDCLASS wndclass2
;   // Structure used to register Windows class. 
 299   memset(&wndclass2
, 0, sizeof(WNDCLASS
));   // start with NULL defaults 
 300   // Use CS_OWNDC to avoid messing about restoring the context 
 301   // for every graphic operation. 
 302   wndclass2
.style         
= CS_HREDRAW 
| CS_VREDRAW
; 
 303   wndclass2
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 304   wndclass2
.cbClsExtra    
= 0; 
 305   wndclass2
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 306   wndclass2
.hInstance     
= wxhInstance
; 
 307   wndclass2
.hIcon         
= NULL
; 
 308   wndclass2
.hCursor       
= NULL
; 
 309 //  wndclass2.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ; 
 310   wndclass2
.hbrBackground 
= (HBRUSH
) GetStockObject( LTGRAY_BRUSH 
); 
 311   wndclass2
.lpszMenuName  
= NULL
; 
 312   wndclass2
.lpszClassName 
= wxPanelClassName
; 
 313   if (!RegisterClass( &wndclass2 
)) 
 315 //   wxFatalError("Can't register Panel Window class"); 
 319 /////////////////////////////////////////////////////////////////////// 
 320 // Register the canvas and textsubwindow class name 
 321   WNDCLASS wndclass3
;   // Structure used to register Windows class. 
 322   memset(&wndclass3
, 0, sizeof(WNDCLASS
));   // start with NULL defaults 
 323   // Use CS_OWNDC to avoid messing about restoring the context 
 324   // for every graphic operation. 
 325 //  wndclass3.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS ; 
 327   wndclass3
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
; 
 328   wndclass3
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 329   wndclass3
.cbClsExtra    
= 0; 
 330   wndclass3
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 331   wndclass3
.hInstance     
= wxhInstance
; 
 332   wndclass3
.hIcon         
= NULL
; 
 333   wndclass3
.hCursor       
= NULL
; 
 334 //  wndclass3.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ; 
 335   wndclass3
.hbrBackground 
= NULL
; 
 336   wndclass3
.lpszMenuName  
= NULL
; 
 337   wndclass3
.lpszClassName 
= wxCanvasClassName
; 
 338   if (!RegisterClass( &wndclass3
)) 
 340 //   wxFatalError("Can't register Canvas class"); 
 347 //// Convert Windows to argc, argv style 
 349 // FIXME this code should be rewritten (use wxArrayString instead...) 
 350 void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine
) 
 352   // Split command line into tokens, as in usual main(argc, argv) 
 353   char **command 
= new char*[50]; // VZ: sure? why not 25 or 73 and a half?? 
 356   char *buf 
= new char[strlen(lpCmdLine
) + 1]; 
 358   /* Model independent strcpy */ 
 360   for (i 
= 0; (buf
[i
] = lpCmdLine
[i
]) != 0; i
++) 
 365   // Get application name 
 366   char name
[260]; // 260 is MAX_PATH value from windef.h 
 367   ::GetModuleFileName(wxhInstance
, name
, WXSIZEOF(name
)); 
 369   // Is it only 16-bit Borland that already copies the program name 
 370   // to the first argv index? 
 371 #if !defined(__GNUWIN32__) 
 372 // #if ! (defined(__BORLANDC__) && !defined(__WIN32__)) 
 373   command
[count
++] = copystring(name
); 
 377   strcpy(name
, wxFileNameFromPath(name
)); 
 378   wxStripExtension(name
); 
 379   wxTheApp
->SetAppName(name
); 
 381   /* Break up string */ 
 382   // Treat strings enclosed in double-quotes as single arguments 
 386     if ( count 
== WXSIZEOF(command
) ) 
 388       wxFAIL_MSG("too many command line args."); 
 392     while ( *str 
&& isspace(*str
) )  // skip whitespace 
 398       command
[count
++] = str
; 
 399       while (*str 
&& *str 
!= '"') 
 404       command
[count
++] = str
; 
 405       while (*str 
&& !isspace(*str
)) 
 412   wxTheApp
->argv 
= new char*[count 
+ 1]; 
 413   wxTheApp
->argv
[count
] = NULL
; /* argv[] is NULL terminated list! */ 
 414   wxTheApp
->argc 
= count
; 
 416   for (i 
= 0; i 
< count
; i
++) 
 418     wxTheApp
->argv
[i
] = copystring(command
[i
]); 
 420     delete [] command
[i
]; 
 427 //// Cleans up any wxWindows internal structures left lying around 
 429 void wxApp::CleanUp() 
 432   wxModule::CleanUpModules(); 
 435   wxCleanUpResourceSystem(); 
 437 //  wxDefaultResourceTable->ClearTable(); 
 440   // Indicate that the cursor can be freed, 
 441   // so that cursor won't be deleted by deleting 
 442   // the bitmap list before g_globalCursor goes out 
 443   // of scope (double deletion of the cursor). 
 444   wxSetCursor(wxNullCursor
); 
 445   delete g_globalCursor
; 
 447   wxDeleteStockObjects() ; 
 449   // Destroy all GDI lists, etc. 
 450   wxDeleteStockLists(); 
 452   delete wxTheColourDatabase
; 
 453   wxTheColourDatabase 
= NULL
; 
 456   wxInitializePrintSetupData(FALSE
); 
 457   delete wxThePrintPaperDatabase
; 
 458   wxThePrintPaperDatabase 
= NULL
; 
 461   wxBitmap::CleanUpHandlers(); 
 466   //// WINDOWS-SPECIFIC CLEANUP 
 468   wxSetKeyboardHook(FALSE
); 
 471   if (gs_hRichEdit 
!= NULL
) 
 472     FreeLibrary(gs_hRichEdit
); 
 479   if (wxSTD_FRAME_ICON
) 
 480     DestroyIcon(wxSTD_FRAME_ICON
); 
 481   if (wxSTD_MDICHILDFRAME_ICON
) 
 482     DestroyIcon(wxSTD_MDICHILDFRAME_ICON
); 
 483   if (wxSTD_MDIPARENTFRAME_ICON
) 
 484     DestroyIcon(wxSTD_MDIPARENTFRAME_ICON
); 
 486   if (wxDEFAULT_FRAME_ICON
) 
 487     DestroyIcon(wxDEFAULT_FRAME_ICON
); 
 488   if (wxDEFAULT_MDICHILDFRAME_ICON
) 
 489     DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON
); 
 490   if (wxDEFAULT_MDIPARENTFRAME_ICON
) 
 491     DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON
); 
 493   if ( wxDisableButtonBrush 
) 
 494     ::DeleteObject( wxDisableButtonBrush 
) ; 
 496 #if     defined(WX_DRAG_DROP) 
 501   Ctl3dUnregister(wxhInstance
); 
 505     delete wxWinHandleList 
; 
 507   wxClassInfo::CleanUpClasses(); 
 509   // do it as the very last thing because everything else can log messages 
 510   wxLog::DontCreateOnDemand(); 
 511   delete wxLog::SetActiveTarget(NULL
); 
 514 #if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL)) 
 516 //// Main wxWindows entry point 
 517 int wxEntry(WXHINSTANCE hInstance
, 
 518             WXHINSTANCE 
WXUNUSED(hPrevInstance
), 
 523 #ifndef __WXDEBUG__ // take everything into a try-except block in release build 
 527   wxhInstance 
= (HINSTANCE
) hInstance
; 
 529   if (!wxApp::Initialize()) 
 532   // create the application object or ensure that one already exists 
 535     // The app may have declared a global application object, but we recommend 
 536     // the IMPLEMENT_APP macro is used instead, which sets an initializer 
 537     // function for delayed, dynamic app object construction. 
 538     wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 539                  "No initializer - use IMPLEMENT_APP macro." ); 
 541     wxTheApp 
= (*wxApp::GetInitializerFunction()) (); 
 544   wxCHECK_MSG( wxTheApp
, 0, "You have to define an instance of wxApp!" ); 
 546   // save the WinMain() parameters 
 547   wxTheApp
->ConvertToStandardCommandArgs(lpCmdLine
); 
 548   wxTheApp
->m_nCmdShow 
= nCmdShow
; 
 550   // GUI-specific initialisation. In fact on Windows we don't have any, 
 551   // but this call is provided for compatibility across platforms. 
 552   wxTheApp
->OnInitGui() ; 
 556   if ( wxTheApp
->OnInit() ) 
 560           retValue 
= wxTheApp
->OnRun(); 
 563   //else: app initialization failed, so we skipped OnRun() 
 565   wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 568       // Forcibly delete the window. 
 569       if ( topWindow
->IsKindOf(CLASSINFO(wxFrame
)) || 
 570            topWindow
->IsKindOf(CLASSINFO(wxDialog
)) ) 
 572           topWindow
->Close(TRUE
); 
 573           wxTheApp
->DeletePendingObjects(); 
 578           wxTheApp
->SetTopWindow(NULL
); 
 588 #if (WXDEBUG && USE_MEMORY_TRACING) || USE_DEBUG_CONTEXT 
 589   // At this point we want to check if there are any memory 
 590   // blocks that aren't part of the wxDebugContext itself, 
 591   // as a special case. Then when dumping we need to ignore 
 592   // wxDebugContext, too. 
 593   if (wxDebugContext::CountObjectsLeft() > 0) 
 595       wxTrace("There were memory leaks.\n"); 
 596       wxDebugContext::Dump(); 
 597       wxDebugContext::PrintStatistics(); 
 599   wxDebugContext::SetStream(NULL
, NULL
); 
 603 #ifndef __WXDEBUG__ // catch exceptions only in release build 
 605   __except ( EXCEPTION_EXECUTE_HANDLER 
) { 
 608       wxTheApp->OnFatalException(); 
 611     ::ExitProcess(3); // the same exit code as abort() 
 618 //// Entry point for DLLs 
 620 int wxEntry(WXHINSTANCE hInstance
) 
 622   wxhInstance 
= (HINSTANCE
) hInstance
; 
 625   // The app may have declared a global application object, but we recommend 
 626   // the IMPLEMENT_APP macro is used instead, which sets an initializer function 
 627   // for delayed, dynamic app object construction. 
 631     if (!wxApp::GetInitializerFunction()) 
 633       MessageBox(NULL
, "No initializer - use IMPLEMENT_APP macro.", "wxWindows Error", MB_APPLMODAL 
| MB_ICONSTOP 
| MB_OK
); 
 637     wxTheApp 
= (* wxApp::GetInitializerFunction()) (); 
 641     MessageBox(NULL
, "You have to define an instance of wxApp!", "wxWindows Error", MB_APPLMODAL 
| MB_ICONSTOP 
| MB_OK
); 
 646   wxTheApp
->argv 
= NULL
; 
 648   wxTheApp
->OnInitGui(); 
 652   if (wxTheApp
->GetTopWindow() && wxTheApp
->GetTopWindow()->GetHWND()) { 
 653     wxTheApp
->GetTopWindow()->Show(TRUE
); 
 660 //// Static member initialization 
 662 wxAppInitializerFunction 
wxApp::m_appInitFn 
= (wxAppInitializerFunction
) NULL
; 
 669   m_wantDebugOutput 
= TRUE 
; 
 674   m_printMode 
= wxPRINT_WINDOWS
; 
 676   m_printMode 
= wxPRINT_POSTSCRIPT
; 
 678   m_exitOnFrameDelete 
= TRUE
; 
 684   // Delete command-line args 
 686   for (i 
= 0; i 
< argc
; i
++) 
 693 bool wxApp::Initialized() 
 701 #ifdef _WINDLL // Assume initialized if DLL (no way of telling) 
 707  * Get and process a message, returning FALSE if WM_QUIT 
 711 bool wxApp::DoMessage() 
 713   if (!::GetMessage(&s_currentMsg
, (HWND
) NULL
, 0, 0)) 
 718   // Process the message 
 719   if (!ProcessMessage((WXMSG 
*)&s_currentMsg
)) 
 721     ::TranslateMessage(&s_currentMsg
); 
 722     wxApp::sm_lastMessageTime 
= s_currentMsg
.time
; /* MATTHEW: timeStamp impl. */ 
 723     ::DispatchMessage(&s_currentMsg
); 
 729  * Keep trying to process messages until WM_QUIT 
 732  * If there are messages to be processed, they will all be 
 733  * processed and OnIdle will not be called. 
 734  * When there are no more messages, OnIdle is called. 
 735  * If OnIdle requests more time, 
 736  * it will be repeatedly called so long as there are no pending messages. 
 737  * A 'feature' of this is that once OnIdle has decided that no more processing 
 738  * is required, then it won't get processing time until further messages 
 739  * are processed (it'll sit in DoMessage). 
 742 int wxApp::MainLoop() 
 747     while (!::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) && 
 753   return s_currentMsg
.wParam
; 
 756 // Returns TRUE if more time is needed. 
 757 bool wxApp::ProcessIdle() 
 760     event
.SetEventObject(this); 
 763     return event
.MoreRequested(); 
 766 void wxApp::ExitMainLoop() 
 771 bool wxApp::Pending() 
 773   return (::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) != 0) ; 
 776 void wxApp::Dispatch() 
 783  * Give all windows a chance to preprocess 
 784  * the message. Some may have accelerator tables, or have 
 787 bool wxApp::ProcessMessage(WXMSG 
*Msg
) 
 789   MSG 
*msg 
= (MSG 
*)Msg
; 
 793   // Try translations first; find the youngest window with 
 794   // a translation table. 
 795   for (hWnd 
= msg
->hwnd
; hWnd 
!= NULL
; hWnd 
= ::GetParent(hWnd
)) 
 797     wxWindow 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
 800        if (wnd
->MSWTranslateMessage(Msg
)) 
 805   // Anyone for a non-translation message? Try youngest descendants first. 
 806   for (hWnd 
= msg
->hwnd
; hWnd 
!= NULL
; hWnd 
= ::GetParent(hWnd
)) 
 808     wxWindow 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
 811        if (wnd
->MSWProcessMessage(Msg
)) 
 818 void wxApp::OnIdle(wxIdleEvent
& event
) 
 820   static bool inOnIdle 
= FALSE
; 
 822   // Avoid recursion (via ProcessEvent default case) 
 828   // 'Garbage' collection of windows deleted with Close(). 
 829   DeletePendingObjects(); 
 831   // flush the logged messages if any 
 832   wxLog 
*pLog 
= wxLog::GetActiveTarget(); 
 833   if ( pLog 
!= NULL 
&& pLog
->HasPendingMessages() ) 
 836   // Send OnIdle events to all windows 
 837   bool needMore 
= SendIdleEvents(); 
 838 //  bool needMore = FALSE; 
 841     event
.RequestMore(TRUE
); 
 846 // Send idle event to all top-level windows 
 847 bool wxApp::SendIdleEvents() 
 849     bool needMore 
= FALSE
; 
 850   wxNode
* node 
= wxTopLevelWindows
.First(); 
 853     wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 854     if (SendIdleEvents(win
)) 
 862 // Send idle event to window and all subwindows 
 863 bool wxApp::SendIdleEvents(wxWindow
* win
) 
 865   bool needMore 
= FALSE
; 
 868   event
.SetEventObject(win
); 
 869   win
->ProcessEvent(event
); 
 871   if (event
.MoreRequested()) 
 874   wxNode
* node 
= win
->GetChildren()->First(); 
 877     wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 878     if (SendIdleEvents(win
)) 
 886 void wxApp::DeletePendingObjects() 
 888   wxNode 
*node 
= wxPendingDelete
.First(); 
 891     wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
 895     if (wxPendingDelete
.Member(obj
)) 
 898     // Deleting one object may have deleted other pending 
 899     // objects, so start from beginning of list again. 
 900     node 
= wxPendingDelete
.First(); 
 904 wxLog
* wxApp::CreateLogTarget() 
 909 wxWindow
* wxApp::GetTopWindow() const 
 913     else if (wxTopLevelWindows
.Number() > 0) 
 914         return (wxWindow
*) wxTopLevelWindows
.First()->Data(); 
 919 int wxApp::GetComCtl32Version() const 
 921     // have we loaded COMCTL32 yet? 
 922     HMODULE theModule 
= ::GetModuleHandle("COMCTL32"); 
 925     // if so, then we can check for the version 
 928         // InitCommonControlsEx is unique to 4.7 and later 
 929         FARPROC theProc 
= ::GetProcAddress(theModule
, "InitCommonControlsEx"); 
 932         {                    // not found, must be 4.00 
 937       // The following symbol are unique to 4.71 
 939       //   FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos 
 940       //   FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo 
 941       //   FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange 
 942       //   FlatSB_ShowScrollBar 
 943       //   _DrawIndirectImageList _DuplicateImageList 
 945       //   UninitializeFlatSB 
 946       // we could check for any of these - I chose DllInstall 
 947       FARPROC theProc 
= ::GetProcAddress(theModule
, "DllInstall"); 
 950         // not found, must be 4.70 
 954       {                         // found, must be 4.71 
 965   FatalAppExit(0, "Fatal error: exiting"); 
 968 // Yield to incoming messages 
 972   // We want to go back to the main message loop 
 973   // if we see a WM_QUIT. (?) 
 974   while (PeekMessage(&msg
, NULL
, 0, 0, PM_NOREMOVE
) && msg
.message 
!= WM_QUIT
) 
 976     if (!wxTheApp
->DoMessage()) 
 983 HINSTANCE 
wxGetInstance() 
 988 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly 
 989 // if in a separate file. So include it here to ensure it's linked. 
 990 #if (defined(_MSC_VER) && !defined(__WIN32__)) || defined(__GNUWIN32__)