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"
43 #if wxUSE_WX_RESOURCES
44 #include "wx/resource.h"
50 #if defined(__WIN95__) && !defined(__GNUWIN32__)
54 // use debug CRT functions for memory leak detections in VC++
55 /* This still doesn't work for me, Vadim.
56 #if defined(__WXDEBUG__) && defined(_MSC_VER)
57 // VC++ uses this macro as debug/release mode indicator
66 extern char *wxBuffer
;
67 extern char *wxOsVersion
;
68 extern wxList
*wxWinHandleList
;
69 extern wxList wxPendingDelete
;
70 extern void wxSetKeyboardHook(bool doIt
);
71 extern wxCursor
*g_globalCursor
;
73 HINSTANCE wxhInstance
= 0;
74 static MSG s_currentMsg
;
75 wxApp
*wxTheApp
= NULL
;
77 // @@ why not const? and not static?
78 char wxFrameClassName
[] = "wxFrameClass";
79 char wxMDIFrameClassName
[] = "wxMDIFrameClass";
80 char wxMDIChildFrameClassName
[] = "wxMDIChildFrameClass";
81 char wxPanelClassName
[] = "wxPanelClass";
82 char wxCanvasClassName
[] = "wxCanvasClass";
84 HICON wxSTD_FRAME_ICON
= NULL
;
85 HICON wxSTD_MDICHILDFRAME_ICON
= NULL
;
86 HICON wxSTD_MDIPARENTFRAME_ICON
= NULL
;
88 HICON wxDEFAULT_FRAME_ICON
= NULL
;
89 HICON wxDEFAULT_MDICHILDFRAME_ICON
= NULL
;
90 HICON wxDEFAULT_MDIPARENTFRAME_ICON
= NULL
;
92 HBRUSH wxDisableButtonBrush
= 0;
94 LRESULT APIENTRY
wxWndProc(HWND
, UINT
, WPARAM
, LPARAM
);
96 #if !USE_SHARED_LIBRARY
97 IMPLEMENT_DYNAMIC_CLASS(wxApp
, wxEvtHandler
)
99 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
100 EVT_IDLE(wxApp::OnIdle
)
104 long wxApp::sm_lastMessageTime
= 0;
107 static HINSTANCE gs_hRichEdit
= NULL
;
112 bool wxApp::Initialize()
114 wxBuffer
= new char[1500];
117 #if defined(__WXDEBUG__) && defined(_MSC_VER)
118 // do check for memory leaks on program exit
119 // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free
120 // deallocated memory which may be used to simulate low-memory condition)
121 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
122 #endif // debug build under MS VC++
125 #if (WXDEBUG && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
127 streambuf
* sBuf
= NULL
;
129 streambuf
* sBuf
= new wxDebugStreamBuf
;
132 ostream
* oStr
= new ostream(sBuf
) ;
133 wxDebugContext::SetStream(oStr
, sBuf
);
134 #endif // wxUSE_MEMORY_TRACING
136 wxClassInfo::InitializeClasses();
139 wxGetResource("wxWindows", "OsVersion", &wxOsVersion
);
142 wxTheColourDatabase
= new wxColourDatabase(wxKEY_STRING
);
143 wxTheColourDatabase
->Initialize();
145 wxInitializeStockLists();
146 wxInitializeStockObjects();
148 #if wxUSE_WX_RESOURCES
149 wxInitializeResourceSystem();
152 // For PostScript printing
154 wxInitializePrintSetupData();
155 wxThePrintPaperDatabase
= new wxPrintPaperDatabase
;
156 wxThePrintPaperDatabase
->CreateDatabase();
159 wxBitmap::InitStandardHandlers();
161 #if defined(__WIN95__)
162 InitCommonControls();
163 gs_hRichEdit
= LoadLibrary("RICHED32.DLL");
165 if (gs_hRichEdit
== NULL
)
167 wxMessageBox("Could not initialise Rich Edit DLL");
171 #if defined(WX_DRAG_DROP)
172 // we need to initialize OLE library
173 if ( FAILED(::OleInitialize(NULL
)) )
174 wxFatalError(_("Cannot initialize OLE"));
178 if (!Ctl3dRegister(wxhInstance
))
179 wxFatalError("Cannot register CTL3D");
181 Ctl3dAutoSubclass(wxhInstance
);
184 g_globalCursor
= new wxCursor
;
186 wxSTD_FRAME_ICON
= LoadIcon(wxhInstance
, "wxSTD_FRAME");
187 wxSTD_MDIPARENTFRAME_ICON
= LoadIcon(wxhInstance
, "wxSTD_MDIPARENTFRAME");
188 wxSTD_MDICHILDFRAME_ICON
= LoadIcon(wxhInstance
, "wxSTD_MDICHILDFRAME");
190 wxDEFAULT_FRAME_ICON
= LoadIcon(wxhInstance
, "wxDEFAULT_FRAME");
191 wxDEFAULT_MDIPARENTFRAME_ICON
= LoadIcon(wxhInstance
, "wxDEFAULT_MDIPARENTFRAME");
192 wxDEFAULT_MDICHILDFRAME_ICON
= LoadIcon(wxhInstance
, "wxDEFAULT_MDICHILDFRAME");
194 RegisterWindowClasses();
196 // Create the brush for disabling bitmap buttons
199 lb
.lbStyle
= BS_PATTERN
;
200 lb
.lbHatch
= (int)LoadBitmap( wxhInstance
, "wxDISABLE_BUTTON_BITMAP" ) ;
201 wxDisableButtonBrush
= ::CreateBrushIndirect( & lb
) ;
202 ::DeleteObject( (HGDIOBJ
)lb
.lbHatch
) ;
208 wxWinHandleList
= new wxList(wxKEY_INTEGER
);
210 // This is to foil optimizations in Visual C++ that
211 // throw out dummy.obj.
212 #if (_MSC_VER >= 800) && !defined(WXMAKINGDLL)
213 extern char wxDummyChar
;
214 if (wxDummyChar
) wxDummyChar
++;
217 wxSetKeyboardHook(TRUE
);
219 wxModule::RegisterModules();
220 if (!wxModule::InitializeModules())
225 //// RegisterWindowClasses
227 bool wxApp::RegisterWindowClasses()
229 ///////////////////////////////////////////////////////////////////////
230 // Register the frame window class.
231 WNDCLASS wndclass
; // Structure used to register Windows class.
233 wndclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
234 wndclass
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
235 wndclass
.cbClsExtra
= 0;
236 wndclass
.cbWndExtra
= sizeof( DWORD
); // was 4
237 wndclass
.hInstance
= wxhInstance
;
238 wndclass
.hIcon
= NULL
; // wxSTD_FRAME_ICON;
239 wndclass
.hCursor
= LoadCursor( NULL
, IDC_ARROW
);
240 wndclass
.hbrBackground
= (HBRUSH
)(COLOR_APPWORKSPACE
+1) ;
241 // wndclass.hbrBackground = GetStockObject( WHITE_BRUSH );
242 wndclass
.lpszMenuName
= NULL
;
243 #ifdef _MULTIPLE_INSTANCES
244 sprintf( wxFrameClassName
,"wxFrameClass%d", wxhInstance
);
246 wndclass
.lpszClassName
= wxFrameClassName
;
248 if (!RegisterClass( &wndclass
))
250 // wxFatalError("Can't register Frame Window class");
253 ///////////////////////////////////////////////////////////////////////
254 // Register the MDI frame window class.
255 WNDCLASS wndclass1
; // Structure used to register Windows class.
257 wndclass1
.style
= CS_HREDRAW
| CS_VREDRAW
;
258 wndclass1
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
259 wndclass1
.cbClsExtra
= 0;
260 wndclass1
.cbWndExtra
= sizeof( DWORD
); // was 4
261 wndclass1
.hInstance
= wxhInstance
;
262 wndclass1
.hIcon
= NULL
; // wxSTD_MDIPARENTFRAME_ICON;
263 wndclass1
.hCursor
= LoadCursor( NULL
, IDC_ARROW
);
264 // wndclass1.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1) ;
265 wndclass1
.hbrBackground
= NULL
;
266 wndclass1
.lpszMenuName
= NULL
;
268 wndclass1
.lpszClassName
= wxMDIFrameClassName
;
269 if (!RegisterClass( &wndclass1
))
271 // wxFatalError("Can't register MDI Frame window class");
275 ///////////////////////////////////////////////////////////////////////
276 // Register the MDI child frame window class.
277 WNDCLASS wndclass4
; // Structure used to register Windows class.
279 wndclass4
.style
= CS_HREDRAW
| CS_VREDRAW
;
280 wndclass4
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
281 wndclass4
.cbClsExtra
= 0;
282 wndclass4
.cbWndExtra
= sizeof( DWORD
); // was 4
283 wndclass4
.hInstance
= wxhInstance
;
284 wndclass4
.hIcon
= NULL
; // wxSTD_MDICHILDFRAME_ICON;
285 wndclass4
.hCursor
= LoadCursor( NULL
, IDC_ARROW
);
286 // TODO: perhaps this should be NULL so that Windows doesn't
287 // paint the background itself (would OnEraseBackground duplicate
289 wndclass4
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1) ;
290 // wndclass4.hbrBackground = NULL;
291 wndclass4
.lpszMenuName
= NULL
;
292 wndclass4
.lpszClassName
= wxMDIChildFrameClassName
;
294 if (!RegisterClass( &wndclass4
))
296 // wxFatalError("Can't register MDI child frame window class");
300 ///////////////////////////////////////////////////////////////////////
301 // Register the panel window class.
302 WNDCLASS wndclass2
; // Structure used to register Windows class.
303 memset(&wndclass2
, 0, sizeof(WNDCLASS
)); // start with NULL defaults
304 // Use CS_OWNDC to avoid messing about restoring the context
305 // for every graphic operation.
306 wndclass2
.style
= CS_HREDRAW
| CS_VREDRAW
;
307 wndclass2
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
308 wndclass2
.cbClsExtra
= 0;
309 wndclass2
.cbWndExtra
= sizeof( DWORD
); // was 4
310 wndclass2
.hInstance
= wxhInstance
;
311 wndclass2
.hIcon
= NULL
;
312 wndclass2
.hCursor
= NULL
;
313 // wndclass2.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ;
314 wndclass2
.hbrBackground
= (HBRUSH
) GetStockObject( LTGRAY_BRUSH
);
315 wndclass2
.lpszMenuName
= NULL
;
316 wndclass2
.lpszClassName
= wxPanelClassName
;
317 if (!RegisterClass( &wndclass2
))
319 // wxFatalError("Can't register Panel Window class");
323 ///////////////////////////////////////////////////////////////////////
324 // Register the canvas and textsubwindow class name
325 WNDCLASS wndclass3
; // Structure used to register Windows class.
326 memset(&wndclass3
, 0, sizeof(WNDCLASS
)); // start with NULL defaults
327 // Use CS_OWNDC to avoid messing about restoring the context
328 // for every graphic operation.
329 // wndclass3.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS ;
331 wndclass3
.style
= CS_HREDRAW
| CS_VREDRAW
| CS_DBLCLKS
;
332 wndclass3
.lpfnWndProc
= (WNDPROC
)wxWndProc
;
333 wndclass3
.cbClsExtra
= 0;
334 wndclass3
.cbWndExtra
= sizeof( DWORD
); // was 4
335 wndclass3
.hInstance
= wxhInstance
;
336 wndclass3
.hIcon
= NULL
;
337 wndclass3
.hCursor
= NULL
;
338 // wndclass3.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ;
339 wndclass3
.hbrBackground
= NULL
;
340 wndclass3
.lpszMenuName
= NULL
;
341 wndclass3
.lpszClassName
= wxCanvasClassName
;
342 if (!RegisterClass( &wndclass3
))
344 // wxFatalError("Can't register Canvas class");
351 //// Convert Windows to argc, argv style
353 // FIXME this code should be rewritten (use wxArrayString instead...)
354 void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine
)
356 // Split command line into tokens, as in usual main(argc, argv)
357 char **command
= new char*[50]; // VZ: sure? why not 25 or 73 and a half??
360 char *buf
= new char[strlen(lpCmdLine
) + 1];
362 /* Model independent strcpy */
364 for (i
= 0; (buf
[i
] = lpCmdLine
[i
]) != 0; i
++)
369 // Get application name
370 char name
[260]; // 260 is MAX_PATH value from windef.h
371 ::GetModuleFileName(wxhInstance
, name
, WXSIZEOF(name
));
373 // Is it only 16-bit Borland that already copies the program name
374 // to the first argv index?
375 #if !defined(__GNUWIN32__)
376 // #if ! (defined(__BORLANDC__) && !defined(__WIN32__))
377 command
[count
++] = copystring(name
);
381 strcpy(name
, wxFileNameFromPath(name
));
382 wxStripExtension(name
);
383 wxTheApp
->SetAppName(name
);
385 /* Break up string */
386 // Treat strings enclosed in double-quotes as single arguments
390 if ( count
== WXSIZEOF(command
) )
392 wxFAIL_MSG("too many command line args.");
396 while ( *str
&& isspace(*str
) ) // skip whitespace
402 command
[count
++] = str
;
403 while (*str
&& *str
!= '"')
408 command
[count
++] = str
;
409 while (*str
&& !isspace(*str
))
416 wxTheApp
->argv
= new char*[count
+ 1];
417 wxTheApp
->argv
[count
] = NULL
; /* argv[] is NULL terminated list! */
418 wxTheApp
->argc
= count
;
420 for (i
= 0; i
< count
; i
++)
422 wxTheApp
->argv
[i
] = copystring(command
[i
]);
424 delete [] command
[i
];
431 //// Cleans up any wxWindows internal structures left lying around
433 void wxApp::CleanUp()
436 wxModule::CleanUpModules();
438 #if wxUSE_WX_RESOURCES
439 wxCleanUpResourceSystem();
441 // wxDefaultResourceTable->ClearTable();
444 // Indicate that the cursor can be freed,
445 // so that cursor won't be deleted by deleting
446 // the bitmap list before g_globalCursor goes out
447 // of scope (double deletion of the cursor).
448 wxSetCursor(wxNullCursor
);
449 delete g_globalCursor
;
451 wxDeleteStockObjects() ;
453 // Destroy all GDI lists, etc.
454 wxDeleteStockLists();
456 delete wxTheColourDatabase
;
457 wxTheColourDatabase
= NULL
;
460 wxInitializePrintSetupData(FALSE
);
461 delete wxThePrintPaperDatabase
;
462 wxThePrintPaperDatabase
= NULL
;
465 wxBitmap::CleanUpHandlers();
470 //// WINDOWS-SPECIFIC CLEANUP
472 wxSetKeyboardHook(FALSE
);
475 if (gs_hRichEdit
!= NULL
)
476 FreeLibrary(gs_hRichEdit
);
483 if (wxSTD_FRAME_ICON
)
484 DestroyIcon(wxSTD_FRAME_ICON
);
485 if (wxSTD_MDICHILDFRAME_ICON
)
486 DestroyIcon(wxSTD_MDICHILDFRAME_ICON
);
487 if (wxSTD_MDIPARENTFRAME_ICON
)
488 DestroyIcon(wxSTD_MDIPARENTFRAME_ICON
);
490 if (wxDEFAULT_FRAME_ICON
)
491 DestroyIcon(wxDEFAULT_FRAME_ICON
);
492 if (wxDEFAULT_MDICHILDFRAME_ICON
)
493 DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON
);
494 if (wxDEFAULT_MDIPARENTFRAME_ICON
)
495 DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON
);
497 if ( wxDisableButtonBrush
)
498 ::DeleteObject( wxDisableButtonBrush
) ;
500 #if defined(WX_DRAG_DROP)
505 Ctl3dUnregister(wxhInstance
);
509 delete wxWinHandleList
;
511 wxClassInfo::CleanUpClasses();
513 // do it as the very last thing because everything else can log messages
514 wxLog::DontCreateOnDemand();
515 delete wxLog::SetActiveTarget(NULL
);
518 #if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
520 //// Main wxWindows entry point
521 int wxEntry(WXHINSTANCE hInstance
,
522 WXHINSTANCE
WXUNUSED(hPrevInstance
),
527 #ifndef __WXDEBUG__ // take everything into a try-except block in release build
531 wxhInstance
= (HINSTANCE
) hInstance
;
533 if (!wxApp::Initialize())
536 // create the application object or ensure that one already exists
539 // The app may have declared a global application object, but we recommend
540 // the IMPLEMENT_APP macro is used instead, which sets an initializer
541 // function for delayed, dynamic app object construction.
542 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
543 "No initializer - use IMPLEMENT_APP macro." );
545 wxTheApp
= (*wxApp::GetInitializerFunction()) ();
548 wxCHECK_MSG( wxTheApp
, 0, "You have to define an instance of wxApp!" );
550 // save the WinMain() parameters
551 wxTheApp
->ConvertToStandardCommandArgs(lpCmdLine
);
552 wxTheApp
->m_nCmdShow
= nCmdShow
;
554 // GUI-specific initialisation. In fact on Windows we don't have any,
555 // but this call is provided for compatibility across platforms.
556 wxTheApp
->OnInitGui() ;
560 if ( wxTheApp
->OnInit() )
564 retValue
= wxTheApp
->OnRun();
567 //else: app initialization failed, so we skipped OnRun()
569 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
572 // Forcibly delete the window.
573 if ( topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
574 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
576 topWindow
->Close(TRUE
);
577 wxTheApp
->DeletePendingObjects();
582 wxTheApp
->SetTopWindow(NULL
);
592 #if (WXDEBUG && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
593 // At this point we want to check if there are any memory
594 // blocks that aren't part of the wxDebugContext itself,
595 // as a special case. Then when dumping we need to ignore
596 // wxDebugContext, too.
597 if (wxDebugContext::CountObjectsLeft() > 0)
599 wxTrace("There were memory leaks.\n");
600 wxDebugContext::Dump();
601 wxDebugContext::PrintStatistics();
603 wxDebugContext::SetStream(NULL
, NULL
);
607 #ifndef __WXDEBUG__ // catch exceptions only in release build
609 __except ( EXCEPTION_EXECUTE_HANDLER
) {
612 wxTheApp->OnFatalException();
615 ::ExitProcess(3); // the same exit code as abort()
622 //// Entry point for DLLs
624 int wxEntry(WXHINSTANCE hInstance
)
626 wxhInstance
= (HINSTANCE
) hInstance
;
629 // The app may have declared a global application object, but we recommend
630 // the IMPLEMENT_APP macro is used instead, which sets an initializer function
631 // for delayed, dynamic app object construction.
635 if (!wxApp::GetInitializerFunction())
637 MessageBox(NULL
, "No initializer - use IMPLEMENT_APP macro.", "wxWindows Error", MB_APPLMODAL
| MB_ICONSTOP
| MB_OK
);
641 wxTheApp
= (* wxApp::GetInitializerFunction()) ();
645 MessageBox(NULL
, "You have to define an instance of wxApp!", "wxWindows Error", MB_APPLMODAL
| MB_ICONSTOP
| MB_OK
);
650 wxTheApp
->argv
= NULL
;
652 wxTheApp
->OnInitGui();
656 if (wxTheApp
->GetTopWindow() && wxTheApp
->GetTopWindow()->GetHWND()) {
657 wxTheApp
->GetTopWindow()->Show(TRUE
);
664 //// Static member initialization
666 wxAppInitializerFunction
wxApp::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
673 m_wantDebugOutput
= TRUE
;
678 m_printMode
= wxPRINT_WINDOWS
;
680 m_printMode
= wxPRINT_POSTSCRIPT
;
682 m_exitOnFrameDelete
= TRUE
;
688 // Delete command-line args
690 for (i
= 0; i
< argc
; i
++)
697 bool wxApp::Initialized()
705 #ifdef _WINDLL // Assume initialized if DLL (no way of telling)
711 * Get and process a message, returning FALSE if WM_QUIT
715 bool wxApp::DoMessage()
717 if (!::GetMessage(&s_currentMsg
, (HWND
) NULL
, 0, 0))
722 // Process the message
723 if (!ProcessMessage((WXMSG
*)&s_currentMsg
))
725 ::TranslateMessage(&s_currentMsg
);
726 wxApp::sm_lastMessageTime
= s_currentMsg
.time
; /* MATTHEW: timeStamp impl. */
727 ::DispatchMessage(&s_currentMsg
);
733 * Keep trying to process messages until WM_QUIT
736 * If there are messages to be processed, they will all be
737 * processed and OnIdle will not be called.
738 * When there are no more messages, OnIdle is called.
739 * If OnIdle requests more time,
740 * it will be repeatedly called so long as there are no pending messages.
741 * A 'feature' of this is that once OnIdle has decided that no more processing
742 * is required, then it won't get processing time until further messages
743 * are processed (it'll sit in DoMessage).
746 int wxApp::MainLoop()
751 while (!::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) &&
757 return s_currentMsg
.wParam
;
760 // Returns TRUE if more time is needed.
761 bool wxApp::ProcessIdle()
764 event
.SetEventObject(this);
767 return event
.MoreRequested();
770 void wxApp::ExitMainLoop()
775 bool wxApp::Pending()
777 return (::PeekMessage(&s_currentMsg
, 0, 0, 0, PM_NOREMOVE
) != 0) ;
780 void wxApp::Dispatch()
787 * Give all windows a chance to preprocess
788 * the message. Some may have accelerator tables, or have
791 bool wxApp::ProcessMessage(WXMSG
*Msg
)
793 MSG
*msg
= (MSG
*)Msg
;
797 // Try translations first; find the youngest window with
798 // a translation table.
799 for (hWnd
= msg
->hwnd
; hWnd
!= NULL
; hWnd
= ::GetParent(hWnd
))
801 wxWindow
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
804 if (wnd
->MSWTranslateMessage(Msg
))
809 // Anyone for a non-translation message? Try youngest descendants first.
810 for (hWnd
= msg
->hwnd
; hWnd
!= NULL
; hWnd
= ::GetParent(hWnd
))
812 wxWindow
*wnd
= wxFindWinFromHandle((WXHWND
) hWnd
);
815 if (wnd
->MSWProcessMessage(Msg
))
822 void wxApp::OnIdle(wxIdleEvent
& event
)
824 static bool inOnIdle
= FALSE
;
826 // Avoid recursion (via ProcessEvent default case)
832 // 'Garbage' collection of windows deleted with Close().
833 DeletePendingObjects();
835 // flush the logged messages if any
836 wxLog
*pLog
= wxLog::GetActiveTarget();
837 if ( pLog
!= NULL
&& pLog
->HasPendingMessages() )
840 // Send OnIdle events to all windows
841 bool needMore
= SendIdleEvents();
842 // bool needMore = FALSE;
845 event
.RequestMore(TRUE
);
850 // Send idle event to all top-level windows
851 bool wxApp::SendIdleEvents()
853 bool needMore
= FALSE
;
854 wxNode
* node
= wxTopLevelWindows
.First();
857 wxWindow
* win
= (wxWindow
*) node
->Data();
858 if (SendIdleEvents(win
))
866 // Send idle event to window and all subwindows
867 bool wxApp::SendIdleEvents(wxWindow
* win
)
869 bool needMore
= FALSE
;
872 event
.SetEventObject(win
);
873 win
->ProcessEvent(event
);
875 if (event
.MoreRequested())
878 wxNode
* node
= win
->GetChildren()->First();
881 wxWindow
* win
= (wxWindow
*) node
->Data();
882 if (SendIdleEvents(win
))
890 void wxApp::DeletePendingObjects()
892 wxNode
*node
= wxPendingDelete
.First();
895 wxObject
*obj
= (wxObject
*)node
->Data();
899 if (wxPendingDelete
.Member(obj
))
902 // Deleting one object may have deleted other pending
903 // objects, so start from beginning of list again.
904 node
= wxPendingDelete
.First();
908 wxLog
* wxApp::CreateLogTarget()
913 wxWindow
* wxApp::GetTopWindow() const
917 else if (wxTopLevelWindows
.Number() > 0)
918 return (wxWindow
*) wxTopLevelWindows
.First()->Data();
923 int wxApp::GetComCtl32Version() const
925 // have we loaded COMCTL32 yet?
926 HMODULE theModule
= ::GetModuleHandle("COMCTL32");
929 // if so, then we can check for the version
932 // InitCommonControlsEx is unique to 4.7 and later
933 FARPROC theProc
= ::GetProcAddress(theModule
, "InitCommonControlsEx");
936 { // not found, must be 4.00
941 // The following symbol are unique to 4.71
943 // FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos
944 // FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo
945 // FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange
946 // FlatSB_ShowScrollBar
947 // _DrawIndirectImageList _DuplicateImageList
949 // UninitializeFlatSB
950 // we could check for any of these - I chose DllInstall
951 FARPROC theProc
= ::GetProcAddress(theModule
, "DllInstall");
954 // not found, must be 4.70
958 { // found, must be 4.71
969 FatalAppExit(0, "Fatal error: exiting");
972 // Yield to incoming messages
976 // We want to go back to the main message loop
977 // if we see a WM_QUIT. (?)
978 while (PeekMessage(&msg
, NULL
, 0, 0, PM_NOREMOVE
) && msg
.message
!= WM_QUIT
)
980 if (!wxTheApp
->DoMessage())
987 HINSTANCE
wxGetInstance()
992 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly
993 // if in a separate file. So include it here to ensure it's linked.
994 #if (defined(_MSC_VER) && !defined(__WIN32__)) || defined(__GNUWIN32__)