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" 
  37   #include "wx/dynarray.h" 
  40 #include "wx/msw/private.h" 
  42 #include "wx/module.h" 
  45     #include "wx/thread.h" 
  47     // define the array of MSG strutures 
  48     WX_DECLARE_OBJARRAY(MSG
, wxMsgArray
); 
  50     #include "wx/arrimpl.cpp" 
  52     WX_DEFINE_OBJARRAY(wxMsgArray
); 
  53 #endif // wxUSE_THREADS 
  55 #if wxUSE_WX_RESOURCES 
  56   #include "wx/resource.h" 
  59 // To UG: there's no point in putting this #if here 
  60 // if you don't do the same for the Ole calls further down. 
  61 // Also, OLE is used not just for drag and drop (it's used by automatn.cpp). 
  62 // #if wxUSE_DRAG_AND_DROP 
  63 #if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__) 
  70 #if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) 
  74 #include "wx/msw/msvcrt.h" 
  76 extern char *wxBuffer
; 
  77 extern char *wxOsVersion
; 
  78 extern wxList 
*wxWinHandleList
; 
  79 extern wxList WXDLLEXPORT wxPendingDelete
; 
  80 extern void wxSetKeyboardHook(bool doIt
); 
  81 extern wxCursor 
*g_globalCursor
; 
  83 HINSTANCE wxhInstance 
= 0; 
  84 static MSG s_currentMsg
; 
  85 wxApp 
*wxTheApp 
= NULL
; 
  87 // @@ why not const? and not static? 
  88 char wxFrameClassName
[]         = "wxFrameClass"; 
  89 char wxMDIFrameClassName
[]      = "wxMDIFrameClass"; 
  90 char wxMDIChildFrameClassName
[] = "wxMDIChildFrameClass"; 
  91 char wxPanelClassName
[]         = "wxPanelClass"; 
  92 char wxCanvasClassName
[]        = "wxCanvasClass"; 
  94 HICON wxSTD_FRAME_ICON 
= (HICON
) NULL
; 
  95 HICON wxSTD_MDICHILDFRAME_ICON 
= (HICON
) NULL
; 
  96 HICON wxSTD_MDIPARENTFRAME_ICON 
= (HICON
) NULL
; 
  98 HICON wxDEFAULT_FRAME_ICON 
= (HICON
) NULL
; 
  99 HICON wxDEFAULT_MDICHILDFRAME_ICON 
= (HICON
) NULL
; 
 100 HICON wxDEFAULT_MDIPARENTFRAME_ICON 
= (HICON
) NULL
; 
 102 HBRUSH wxDisableButtonBrush 
= (HBRUSH
) 0; 
 104 LRESULT APIENTRY 
wxWndProc(HWND
, UINT
, WPARAM
, LPARAM
); 
 106 #if !USE_SHARED_LIBRARY 
 107   IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
) 
 109   BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
) 
 110       EVT_IDLE(wxApp::OnIdle
) 
 111       EVT_END_SESSION(wxApp::OnEndSession
) 
 112       EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession
) 
 116 long wxApp::sm_lastMessageTime 
= 0; 
 118 #if defined(__WIN95__) && !defined(__TWIN32__) 
 119 #define wxUSE_RICHEDIT 1 
 121 #define wxUSE_RICHEDIT 0 
 125   static HINSTANCE gs_hRichEdit 
= (HINSTANCE
) NULL
; 
 130 bool wxApp::Initialize() 
 132     // Some people may wish to use this, but 
 133     // probably it shouldn't be here by default. 
 135 //    wxRedirectIOToConsole(); 
 138     wxBuffer 
= new char[1500]; 
 140     wxClassInfo::InitializeClasses(); 
 143     wxGetResource("wxWindows", "OsVersion", &wxOsVersion
); 
 146     wxTheColourDatabase 
= new wxColourDatabase(wxKEY_STRING
); 
 147     wxTheColourDatabase
->Initialize(); 
 149     wxInitializeStockLists(); 
 150     wxInitializeStockObjects(); 
 152 #if wxUSE_WX_RESOURCES 
 153     wxInitializeResourceSystem(); 
 156     wxBitmap::InitStandardHandlers(); 
 158 #if defined(__WIN95__) 
 159     InitCommonControls(); 
 162     gs_hRichEdit 
= LoadLibrary("RICHED32.DLL"); 
 164     if (gs_hRichEdit 
== (HINSTANCE
) NULL
) 
 166       wxMessageBox("Could not initialise Rich Edit DLL"); 
 174    // for OLE, enlarge message queue to be as large as possible 
 175    while (!SetMessageQueue(iMsg
) && (iMsg 
-= 8)); 
 179     dwOleVer = CoBuildVersion(); 
 181     // check the OLE library version 
 182     if (rmm != HIWORD(dwOleVer)) 
 184         wxMessageBox("Incorrect version of OLE libraries."); 
 189 #if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__) 
 190     // we need to initialize OLE library 
 191     if ( FAILED(::OleInitialize(NULL
)) ) 
 192       wxFatalError(_("Cannot initialize OLE")); 
 196     if (!Ctl3dRegister(wxhInstance
)) 
 197       wxFatalError("Cannot register CTL3D"); 
 199     Ctl3dAutoSubclass(wxhInstance
); 
 202     g_globalCursor 
= new wxCursor
; 
 204     wxSTD_FRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_FRAME"); 
 205     wxSTD_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_MDIPARENTFRAME"); 
 206     wxSTD_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, "wxSTD_MDICHILDFRAME"); 
 208     wxDEFAULT_FRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_FRAME"); 
 209     wxDEFAULT_MDIPARENTFRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_MDIPARENTFRAME"); 
 210     wxDEFAULT_MDICHILDFRAME_ICON 
= LoadIcon(wxhInstance
, "wxDEFAULT_MDICHILDFRAME"); 
 212     RegisterWindowClasses(); 
 214     // Create the brush for disabling bitmap buttons 
 217     lb
.lbStyle 
= BS_PATTERN
; 
 218     lb
.lbHatch 
= (int)LoadBitmap( wxhInstance
, "wxDISABLE_BUTTON_BITMAP" ) ; 
 219     wxDisableButtonBrush 
= ::CreateBrushIndirect( & lb 
) ; 
 220     ::DeleteObject( (HGDIOBJ
)lb
.lbHatch 
) ; 
 226     wxWinHandleList 
= new wxList(wxKEY_INTEGER
); 
 228     // This is to foil optimizations in Visual C++ that throw out dummy.obj. 
 229     // PLEASE DO NOT ALTER THIS. 
 230 #if defined(__VISUALC__) && !defined(WXMAKINGDLL) 
 231     extern char wxDummyChar
; 
 232     if (wxDummyChar
) wxDummyChar
++; 
 235     wxSetKeyboardHook(TRUE
); 
 237     wxModule::RegisterModules(); 
 238     if (!wxModule::InitializeModules()) 
 243 //// RegisterWindowClasses 
 245 bool wxApp::RegisterWindowClasses() 
 247 /////////////////////////////////////////////////////////////////////// 
 248 // Register the frame window class. 
 249   WNDCLASS wndclass
;   // Structure used to register Windows class. 
 251   wndclass
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
; 
 252   wndclass
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 253   wndclass
.cbClsExtra    
= 0; 
 254   wndclass
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 255   wndclass
.hInstance     
= wxhInstance
; 
 256   wndclass
.hIcon         
= (HICON
) NULL
;        // wxSTD_FRAME_ICON; 
 257   wndclass
.hCursor       
= LoadCursor( (HINSTANCE
) NULL
, IDC_ARROW 
); 
 258   wndclass
.hbrBackground 
=  (HBRUSH
)(COLOR_APPWORKSPACE
+1) ; 
 259 //  wndclass.hbrBackground = GetStockObject( WHITE_BRUSH ); 
 260   wndclass
.lpszMenuName  
= NULL
; 
 261 #ifdef _MULTIPLE_INSTANCES 
 262   sprintf( wxFrameClassName
,"wxFrameClass%d", wxhInstance 
); 
 264   wndclass
.lpszClassName 
= wxFrameClassName
; 
 266   if (!RegisterClass( &wndclass 
)) 
 268     // wxFatalError("Can't register Frame Window class"); 
 271 /////////////////////////////////////////////////////////////////////// 
 272 // Register the MDI frame window class. 
 273   WNDCLASS wndclass1
;   // Structure used to register Windows class. 
 275   wndclass1
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
; 
 276   wndclass1
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 277   wndclass1
.cbClsExtra    
= 0; 
 278   wndclass1
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 279   wndclass1
.hInstance     
= wxhInstance
; 
 280   wndclass1
.hIcon         
= (HICON
) NULL
; // wxSTD_MDIPARENTFRAME_ICON; 
 281   wndclass1
.hCursor       
= LoadCursor( (HINSTANCE
) NULL
, IDC_ARROW 
); 
 282 //  wndclass1.hbrBackground =  (HBRUSH)(COLOR_APPWORKSPACE+1) ; 
 283   wndclass1
.hbrBackground 
= (HBRUSH
) NULL
; 
 284   wndclass1
.lpszMenuName  
= NULL
; 
 286   wndclass1
.lpszClassName 
= wxMDIFrameClassName
; 
 287   if (!RegisterClass( &wndclass1 
)) 
 289 //    wxFatalError("Can't register MDI Frame window class"); 
 293 /////////////////////////////////////////////////////////////////////// 
 294 // Register the MDI child frame window class. 
 295   WNDCLASS wndclass4
;   // Structure used to register Windows class. 
 297   wndclass4
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
; 
 298   wndclass4
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 299   wndclass4
.cbClsExtra    
= 0; 
 300   wndclass4
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 301   wndclass4
.hInstance     
= wxhInstance
; 
 302   wndclass4
.hIcon         
= (HICON
) NULL
;       // wxSTD_MDICHILDFRAME_ICON; 
 303   wndclass4
.hCursor       
= LoadCursor( (HINSTANCE
) NULL
, IDC_ARROW 
); 
 304   // TODO: perhaps this should be NULL so that Windows doesn't 
 305   // paint the background itself (would OnEraseBackground duplicate 
 307   wndclass4
.hbrBackground 
=  (HBRUSH
)(COLOR_WINDOW
+1) ; 
 308 //  wndclass4.hbrBackground = NULL; 
 309   wndclass4
.lpszMenuName  
= NULL
; 
 310   wndclass4
.lpszClassName 
= wxMDIChildFrameClassName
; 
 312   if (!RegisterClass( &wndclass4 
)) 
 314 //   wxFatalError("Can't register MDI child frame window class"); 
 318 /////////////////////////////////////////////////////////////////////// 
 319 // Register the panel window class. 
 320   WNDCLASS wndclass2
;   // Structure used to register Windows class. 
 321   memset(&wndclass2
, 0, sizeof(WNDCLASS
));   // start with NULL defaults 
 322   wndclass2
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
; 
 323   wndclass2
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 324   wndclass2
.cbClsExtra    
= 0; 
 325   wndclass2
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 326   wndclass2
.hInstance     
= wxhInstance
; 
 327   wndclass2
.hIcon         
= (HICON
) NULL
; 
 328   wndclass2
.hCursor       
= (HCURSOR
) NULL
; 
 329 //  wndclass2.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ; 
 330   wndclass2
.hbrBackground 
= (HBRUSH
) GetStockObject( LTGRAY_BRUSH 
); 
 331   wndclass2
.lpszMenuName  
= NULL
; 
 332   wndclass2
.lpszClassName 
= wxPanelClassName
; 
 333   if (!RegisterClass( &wndclass2 
)) 
 335 //   wxFatalError("Can't register Panel Window class"); 
 339 /////////////////////////////////////////////////////////////////////// 
 340 // Register the canvas and textsubwindow class name 
 341   WNDCLASS wndclass3
;   // Structure used to register Windows class. 
 342   memset(&wndclass3
, 0, sizeof(WNDCLASS
));   // start with NULL defaults 
 343   // Use CS_OWNDC to avoid messing about restoring the context 
 344   // for every graphic operation. 
 345 //  wndclass3.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS ; 
 347   wndclass3
.style         
= CS_HREDRAW 
| CS_VREDRAW 
| CS_DBLCLKS 
; 
 348   wndclass3
.lpfnWndProc   
= (WNDPROC
)wxWndProc
; 
 349   wndclass3
.cbClsExtra    
= 0; 
 350   wndclass3
.cbWndExtra    
= sizeof( DWORD 
); // was 4 
 351   wndclass3
.hInstance     
= wxhInstance
; 
 352   wndclass3
.hIcon         
= (HICON
) NULL
; 
 353   wndclass3
.hCursor       
= (HCURSOR
) NULL
; 
 354 //  wndclass3.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ; 
 355   wndclass3
.hbrBackground 
= (HBRUSH
) NULL
; 
 356   wndclass3
.lpszMenuName  
= NULL
; 
 357   wndclass3
.lpszClassName 
= wxCanvasClassName
; 
 358   if (!RegisterClass( &wndclass3
)) 
 360 //   wxFatalError("Can't register Canvas class"); 
 367 //// Convert Windows to argc, argv style 
 369 void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine
) 
 373     wxString 
cmdLine(lpCmdLine
); 
 376     // Get application name 
 377     char name
[260]; // 260 is MAX_PATH value from windef.h 
 378     ::GetModuleFileName(wxhInstance
, name
, WXSIZEOF(name
)); 
 380     // GNUWIN32 already fills in the first arg with the application name. 
 381 #if !defined(__GNUWIN32__) 
 386     strcpy(name
, wxFileNameFromPath(name
)); 
 387     wxStripExtension(name
); 
 388     wxTheApp
->SetAppName(name
); 
 391     // Treat strings enclosed in double-quotes as single arguments 
 393     int len 
= cmdLine
.Length(); 
 397         while ((i 
< len
) && isspace(cmdLine
.GetChar(i
))) 
 402             if (cmdLine
.GetChar(i
) == '"') // We found the start of a string 
 406                 while ((i 
< len
) && (cmdLine
.GetChar(i
) != '"')) 
 409                 wxString 
arg(cmdLine
.Mid(first
, (i 
- first
))); 
 415                     i 
++; // Skip past 2nd quote 
 417             else // Unquoted argument 
 420                 while ((i 
< len
) && !isspace(cmdLine
.GetChar(i
))) 
 423                 wxString 
arg(cmdLine
.Mid(first
, (i 
- first
))); 
 431     wxTheApp
->argv 
= new char*[count 
+ 1]; 
 432     for (i 
= 0; i 
< count
; i
++) 
 434         wxString 
arg(args
[i
]); 
 435         wxTheApp
->argv
[i
] = copystring((const char*)arg
); 
 437     wxTheApp
->argv
[count
] = NULL
; // argv[] is a NULL-terminated list 
 438     wxTheApp
->argc 
= count
; 
 441 //// Cleans up any wxWindows internal structures left lying around 
 443 void wxApp::CleanUp() 
 447   // flush the logged messages if any 
 448   wxLog 
*pLog 
= wxLog::GetActiveTarget(); 
 449   if ( pLog 
!= NULL 
&& pLog
->HasPendingMessages() ) 
 452   // One last chance for pending objects to be cleaned up 
 453   wxTheApp
->DeletePendingObjects(); 
 455   wxModule::CleanUpModules(); 
 457 #if wxUSE_WX_RESOURCES 
 458   wxCleanUpResourceSystem(); 
 460 //  wxDefaultResourceTable->ClearTable(); 
 463   // Indicate that the cursor can be freed, 
 464   // so that cursor won't be deleted by deleting 
 465   // the bitmap list before g_globalCursor goes out 
 466   // of scope (double deletion of the cursor). 
 467   wxSetCursor(wxNullCursor
); 
 468   delete g_globalCursor
; 
 470   wxDeleteStockObjects() ; 
 472   // Destroy all GDI lists, etc. 
 473   wxDeleteStockLists(); 
 475   delete wxTheColourDatabase
; 
 476   wxTheColourDatabase 
= NULL
; 
 478   wxBitmap::CleanUpHandlers(); 
 483   //// WINDOWS-SPECIFIC CLEANUP 
 485   wxSetKeyboardHook(FALSE
); 
 490   if (gs_hRichEdit 
!= (HINSTANCE
) NULL
) 
 491     FreeLibrary(gs_hRichEdit
); 
 500   if (wxSTD_FRAME_ICON
) 
 501     DestroyIcon(wxSTD_FRAME_ICON
); 
 502   if (wxSTD_MDICHILDFRAME_ICON
) 
 503     DestroyIcon(wxSTD_MDICHILDFRAME_ICON
); 
 504   if (wxSTD_MDIPARENTFRAME_ICON
) 
 505     DestroyIcon(wxSTD_MDIPARENTFRAME_ICON
); 
 507   if (wxDEFAULT_FRAME_ICON
) 
 508     DestroyIcon(wxDEFAULT_FRAME_ICON
); 
 509   if (wxDEFAULT_MDICHILDFRAME_ICON
) 
 510     DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON
); 
 511   if (wxDEFAULT_MDIPARENTFRAME_ICON
) 
 512     DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON
); 
 514   if ( wxDisableButtonBrush 
) 
 515     ::DeleteObject( wxDisableButtonBrush 
) ; 
 517 #if !defined(__GNUWIN32__) && !defined(__SC__) && !defined(__SALFORDC__) 
 522   Ctl3dUnregister(wxhInstance
); 
 526     delete wxWinHandleList 
; 
 528   wxClassInfo::CleanUpClasses(); 
 533 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
 534   // At this point we want to check if there are any memory 
 535   // blocks that aren't part of the wxDebugContext itself, 
 536   // as a special case. Then when dumping we need to ignore 
 537   // wxDebugContext, too. 
 538   if (wxDebugContext::CountObjectsLeft() > 0) 
 540       wxLogDebug("There were memory leaks."); 
 541       wxDebugContext::Dump(); 
 542       wxDebugContext::PrintStatistics(); 
 544 //  wxDebugContext::SetStream(NULL, NULL); 
 547   // do it as the very last thing because everything else can log messages 
 548   wxLog::DontCreateOnDemand(); 
 549   delete wxLog::SetActiveTarget(NULL
); 
 552 #if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL)) 
 554 // temporarily disable this warning 
 556     #pragma warning(disable: 4715) // not all control paths return a value 
 559 //// Main wxWindows entry point 
 560 int wxEntry(WXHINSTANCE hInstance
, 
 561             WXHINSTANCE 
WXUNUSED(hPrevInstance
), 
 566     // do check for memory leaks on program exit 
 567     // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free 
 568     //  deallocated memory which may be used to simulate low-memory condition) 
 569     wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF
); 
 571   // take everything into a try-except block in release build 
 572   // FIXME other compilers must support Win32 SEH (structured exception 
 573   //       handling) too, just find the appropriate keyword in their docs! 
 574   //       Please note that it's _not_ the same as C++ exceptions! 
 575 #if !defined(__WXDEBUG__) && defined(__VISUALC__) 
 576     #define CATCH_PROGRAM_EXCEPTIONS 
 580     #undef  CATCH_PROGRAM_EXCEPTIONS 
 583   wxhInstance 
= (HINSTANCE
) hInstance
; 
 585   if (!wxApp::Initialize()) 
 588   // create the application object or ensure that one already exists 
 591     // The app may have declared a global application object, but we recommend 
 592     // the IMPLEMENT_APP macro is used instead, which sets an initializer 
 593     // function for delayed, dynamic app object construction. 
 594     wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, 
 595                  "No initializer - use IMPLEMENT_APP macro." ); 
 597     wxTheApp 
= (*wxApp::GetInitializerFunction()) (); 
 600   wxCHECK_MSG( wxTheApp
, 0, "You have to define an instance of wxApp!" ); 
 602   // save the WinMain() parameters 
 603   wxTheApp
->ConvertToStandardCommandArgs(lpCmdLine
); 
 604   wxTheApp
->m_nCmdShow 
= nCmdShow
; 
 606   // GUI-specific initialisation. In fact on Windows we don't have any, 
 607   // but this call is provided for compatibility across platforms. 
 608   wxTheApp
->OnInitGui() ; 
 612   if ( wxTheApp
->OnInit() ) 
 616           retValue 
= wxTheApp
->OnRun(); 
 619         // We want to initialize, but not run or exit immediately. 
 622   //else: app initialization failed, so we skipped OnRun() 
 624   wxWindow 
*topWindow 
= wxTheApp
->GetTopWindow(); 
 627       // Forcibly delete the window. 
 628       if ( topWindow
->IsKindOf(CLASSINFO(wxFrame
)) || 
 629            topWindow
->IsKindOf(CLASSINFO(wxDialog
)) ) 
 631           topWindow
->Close(TRUE
); 
 632           wxTheApp
->DeletePendingObjects(); 
 637           wxTheApp
->SetTopWindow(NULL
); 
 647 #ifdef CATCH_PROGRAM_EXCEPTIONS 
 649   __except ( EXCEPTION_EXECUTE_HANDLER 
) { 
 652       wxTheApp->OnFatalException(); 
 655     ::ExitProcess(3); // the same exit code as abort() 
 659 #endif // CATCH_PROGRAM_EXCEPTIONS 
 662 // restore warning state 
 664     #pragma warning(default: 4715) // not all control paths return a value 
 669 //// Entry point for DLLs 
 671 int wxEntry(WXHINSTANCE hInstance
) 
 673   wxhInstance 
= (HINSTANCE
) hInstance
; 
 676   // The app may have declared a global application object, but we recommend 
 677   // the IMPLEMENT_APP macro is used instead, which sets an initializer function 
 678   // for delayed, dynamic app object construction. 
 682     if (!wxApp::GetInitializerFunction()) 
 684       MessageBox(NULL
, "No initializer - use IMPLEMENT_APP macro.", "wxWindows Error", MB_APPLMODAL 
| MB_ICONSTOP 
| MB_OK
); 
 688     wxTheApp 
= (* wxApp::GetInitializerFunction()) (); 
 692     MessageBox(NULL
, "You have to define an instance of wxApp!", "wxWindows Error", MB_APPLMODAL 
| MB_ICONSTOP 
| MB_OK
); 
 697   wxTheApp
->argv 
= NULL
; 
 699   wxTheApp
->OnInitGui(); 
 703   if (wxTheApp
->GetTopWindow() && wxTheApp
->GetTopWindow()->GetHWND()) { 
 704     wxTheApp
->GetTopWindow()->Show(TRUE
); 
 711 //// Static member initialization 
 713 wxAppInitializerFunction 
wxApp::m_appInitFn 
= (wxAppInitializerFunction
) NULL
; 
 720   m_wantDebugOutput 
= TRUE 
; 
 725   m_printMode 
= wxPRINT_WINDOWS
; 
 727   m_printMode 
= wxPRINT_POSTSCRIPT
; 
 729   m_exitOnFrameDelete 
= TRUE
; 
 735   // Delete command-line args 
 737   for (i 
= 0; i 
< argc
; i
++) 
 744 bool wxApp::Initialized() 
 752 #ifdef _WINDLL // Assume initialized if DLL (no way of telling) 
 758  * Get and process a message, returning FALSE if WM_QUIT 
 759  * received (and also set the flag telling the app to exit the main loop) 
 762 bool wxApp::DoMessage() 
 764     BOOL rc 
= ::GetMessage(&s_currentMsg
, (HWND
) NULL
, 0, 0); 
 774         // should never happen, but let's test for it nevertheless 
 775         wxLogLastError("GetMessage"); 
 780         wxASSERT_MSG( wxThread::IsMain(), 
 781                       "only the main thread can process Windows messages" ); 
 783         static bool s_hadGuiLock 
= TRUE
; 
 784         static wxMsgArray s_aSavedMessages
; 
 786         // if a secondary thread owns is doing GUI calls, save all messages for 
 787         // later processing - we can't process them right now because it will 
 788         // lead to recursive library calls (and we're not reentrant) 
 789         if ( !wxGuiOwnedByMainThread() ) 
 791             s_hadGuiLock 
= FALSE
; 
 793             // leave out WM_COMMAND messages: too dangerous, sometimes 
 794             // the message will be processed twice 
 795             if ( !wxIsWaitingForThread() || 
 796                  s_currentMsg
.message 
!= WM_COMMAND 
) 
 798                 s_aSavedMessages
.Add(s_currentMsg
); 
 805             // have we just regained the GUI lock? if so, post all of the saved 
 808             // FIXME of course, it's not _exactly_ the same as processing the 
 809             //       messages normally - expect some things to break... 
 814                 size_t count 
= s_aSavedMessages
.Count(); 
 815                 for ( size_t n 
= 0; n 
< count
; n
++ ) 
 817                     MSG
& msg 
= s_aSavedMessages
[n
]; 
 819                     if ( !ProcessMessage((WXMSG 
*)&msg
) ) 
 821                         ::TranslateMessage(&msg
); 
 822                         ::DispatchMessage(&msg
); 
 826                 s_aSavedMessages
.Empty(); 
 829 #endif // wxUSE_THREADS 
 831         // Process the message 
 832         if ( !ProcessMessage((WXMSG 
*)&s_currentMsg
) ) 
 834             ::TranslateMessage(&s_currentMsg
); 
 835             wxApp::sm_lastMessageTime 
= s_currentMsg
.time
; /* MATTHEW: timeStamp impl. */ 
 836             ::DispatchMessage(&s_currentMsg
); 
 844  * Keep trying to process messages until WM_QUIT 
 847  * If there are messages to be processed, they will all be 
 848  * processed and OnIdle will not be called. 
 849  * When there are no more messages, OnIdle is called. 
 850  * If OnIdle requests more time, 
 851  * it will be repeatedly called so long as there are no pending messages. 
 852  * A 'feature' of this is that once OnIdle has decided that no more processing 
 853  * is required, then it won't get processing time until further messages 
 854  * are processed (it'll sit in DoMessage). 
 857 int wxApp::MainLoop() 
 861   while ( m_keepGoing 
) 
 864         wxMutexGuiLeaveOrEnter(); 
 865     #endif // wxUSE_THREADS 
 867     while ( !::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) && 
 875   return s_currentMsg
.wParam
; 
 878 // Returns TRUE if more time is needed. 
 879 bool wxApp::ProcessIdle() 
 882     event
.SetEventObject(this); 
 885     return event
.MoreRequested(); 
 888 void wxApp::ExitMainLoop() 
 893 bool wxApp::Pending() 
 895   return (::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) != 0) ; 
 898 void wxApp::Dispatch() 
 904  * Give all windows a chance to preprocess 
 905  * the message. Some may have accelerator tables, or have 
 908 bool wxApp::ProcessMessage(WXMSG 
*Msg
) 
 910   MSG 
*msg 
= (MSG 
*)Msg
; 
 914   // Try translations first; find the youngest window with 
 915   // a translation table. 
 916   for (hWnd 
= msg
->hwnd
; hWnd 
!= (HWND
) NULL
; hWnd 
= ::GetParent(hWnd
)) 
 918     wxWindow 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
 921        if (wnd
->MSWTranslateMessage(Msg
)) 
 926   // Anyone for a non-translation message? Try youngest descendants first. 
 927   for (hWnd 
= msg
->hwnd
; hWnd 
!= (HWND
) NULL
; hWnd 
= ::GetParent(hWnd
)) 
 929     wxWindow 
*wnd 
= wxFindWinFromHandle((WXHWND
) hWnd
); 
 932        if (wnd
->MSWProcessMessage(Msg
)) 
 939 void wxApp::OnIdle(wxIdleEvent
& event
) 
 941     static bool s_inOnIdle 
= FALSE
; 
 943     // Avoid recursion (via ProcessEvent default case) 
 949     // 'Garbage' collection of windows deleted with Close(). 
 950     DeletePendingObjects(); 
 952     // flush the logged messages if any 
 953     wxLog 
*pLog 
= wxLog::GetActiveTarget(); 
 954     if ( pLog 
!= NULL 
&& pLog
->HasPendingMessages() ) 
 957     // Send OnIdle events to all windows 
 958     if ( SendIdleEvents() ) 
 960         // SendIdleEvents() returns TRUE if at least one window requested more 
 962         event
.RequestMore(TRUE
); 
 968 // Send idle event to all top-level windows 
 969 bool wxApp::SendIdleEvents() 
 971     bool needMore 
= FALSE
; 
 972     wxNode
* node 
= wxTopLevelWindows
.First(); 
 975         wxWindow
* win 
= (wxWindow
*) node
->Data(); 
 976         if (SendIdleEvents(win
)) 
 985 // Send idle event to window and all subwindows 
 986 bool wxApp::SendIdleEvents(wxWindow
* win
) 
 988   bool needMore 
= FALSE
; 
 991   event
.SetEventObject(win
); 
 992   win
->GetEventHandler()->ProcessEvent(event
); 
 994   if (event
.MoreRequested()) 
 997   wxNode
* node 
= win
->GetChildren().First(); 
1000     wxWindow
* win 
= (wxWindow
*) node
->Data(); 
1001     if (SendIdleEvents(win
)) 
1004     node 
= node
->Next(); 
1009 void wxApp::DeletePendingObjects() 
1011   wxNode 
*node 
= wxPendingDelete
.First(); 
1014     wxObject 
*obj 
= (wxObject 
*)node
->Data(); 
1018     if (wxPendingDelete
.Member(obj
)) 
1021     // Deleting one object may have deleted other pending 
1022     // objects, so start from beginning of list again. 
1023     node 
= wxPendingDelete
.First(); 
1027 void wxApp::OnEndSession(wxCloseEvent
& WXUNUSED(event
)) 
1030         GetTopWindow()->Close(TRUE
); 
1033 // Default behaviour: close the application with prompts. The 
1034 // user can veto the close, and therefore the end session. 
1035 void wxApp::OnQueryEndSession(wxCloseEvent
& event
) 
1039         if (!GetTopWindow()->Close(!event
.CanVeto())) 
1044 wxLog
* wxApp::CreateLogTarget() 
1046     return new wxLogGui
; 
1049 wxWindow
* wxApp::GetTopWindow() const 
1053     else if (wxTopLevelWindows
.Number() > 0) 
1054         return (wxWindow
*) wxTopLevelWindows
.First()->Data(); 
1059 int wxApp::GetComCtl32Version() const 
1061     // have we loaded COMCTL32 yet? 
1062     HMODULE theModule 
= ::GetModuleHandle("COMCTL32"); 
1065     // if so, then we can check for the version 
1068         // InitCommonControlsEx is unique to 4.7 and later 
1069         FARPROC theProc 
= ::GetProcAddress(theModule
, "InitCommonControlsEx"); 
1072         {                    // not found, must be 4.00 
1077       // The following symbol are unique to 4.71 
1079       //   FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos 
1080       //   FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo 
1081       //   FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange 
1082       //   FlatSB_ShowScrollBar 
1083       //   _DrawIndirectImageList _DuplicateImageList 
1085       //   UninitializeFlatSB 
1086       // we could check for any of these - I chose DllInstall 
1087       FARPROC theProc 
= ::GetProcAddress(theModule
, "DllInstall"); 
1090         // not found, must be 4.70 
1094       {                         // found, must be 4.71 
1105   FatalAppExit(0, "Fatal error: exiting"); 
1108 // Yield to incoming messages 
1112   // We want to go back to the main message loop 
1113   // if we see a WM_QUIT. (?) 
1114   while (PeekMessage(&msg
, NULL
, 0, 0, PM_NOREMOVE
) && msg
.message 
!= WM_QUIT
) 
1116     if ( !wxTheApp
->DoMessage() ) 
1123 HINSTANCE 
wxGetInstance() 
1128 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly 
1129 // if in a separate file. So include it here to ensure it's linked. 
1130 #if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__))