]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
Fixed VC++ compile error in mstream; formatted window.cpp.
[wxWidgets.git] / src / msw / app.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
a5e0e655 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
a5e0e655 13 #pragma implementation "app.h"
2bda0e17
KB
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
2bda0e17
KB
17#include "wx/wxprec.h"
18
19#if defined(__BORLANDC__)
a5e0e655 20 #pragma hdrstop
2bda0e17
KB
21#endif
22
23#ifndef WX_PRECOMP
a5e0e655
VZ
24 #include "wx/frame.h"
25 #include "wx/app.h"
26 #include "wx/utils.h"
27 #include "wx/gdicmn.h"
28 #include "wx/pen.h"
29 #include "wx/brush.h"
30 #include "wx/cursor.h"
31 #include "wx/icon.h"
32 #include "wx/palette.h"
33 #include "wx/dc.h"
34 #include "wx/dialog.h"
35 #include "wx/msgdlg.h"
2bda0e17
KB
36#endif
37
38#include "wx/msw/private.h"
2bda0e17
KB
39#include "wx/log.h"
40#include "wx/module.h"
41
47d67540 42#if wxUSE_WX_RESOURCES
a5e0e655 43 #include "wx/resource.h"
2bda0e17
KB
44#endif
45
2bda0e17 46#include <string.h>
a5e0e655 47#include <ctype.h>
2bda0e17
KB
48
49#if defined(__WIN95__) && !defined(__GNUWIN32__)
a5e0e655 50 #include <commctrl.h>
2bda0e17
KB
51#endif
52
370382c7 53// use debug CRT functions for memory leak detections in VC++
e096774d 54/* This still doesn't work for me, Vadim.
370382c7 55#if defined(__WXDEBUG__) && defined(_MSC_VER)
a5e0e655
VZ
56 // VC++ uses this macro as debug/release mode indicator
57 #ifndef _DEBUG
58 #define _DEBUG
59 #endif
60
370382c7
VZ
61 #include <crtdbg.h>
62#endif
e096774d 63*/
370382c7 64
2bda0e17
KB
65extern char *wxBuffer;
66extern char *wxOsVersion;
67extern wxList *wxWinHandleList;
68extern wxList wxPendingDelete;
69extern void wxSetKeyboardHook(bool doIt);
70extern wxCursor *g_globalCursor;
71
c4e7c2aa 72HINSTANCE wxhInstance = 0;
2bda0e17
KB
73static MSG s_currentMsg;
74wxApp *wxTheApp = NULL;
75
a5e0e655 76// @@ why not const? and not static?
2bda0e17
KB
77char wxFrameClassName[] = "wxFrameClass";
78char wxMDIFrameClassName[] = "wxMDIFrameClass";
79char wxMDIChildFrameClassName[] = "wxMDIChildFrameClass";
80char wxPanelClassName[] = "wxPanelClass";
81char wxCanvasClassName[] = "wxCanvasClass";
82
83HICON wxSTD_FRAME_ICON = NULL;
84HICON wxSTD_MDICHILDFRAME_ICON = NULL;
85HICON wxSTD_MDIPARENTFRAME_ICON = NULL;
86
87HICON wxDEFAULT_FRAME_ICON = NULL;
88HICON wxDEFAULT_MDICHILDFRAME_ICON = NULL;
89HICON wxDEFAULT_MDIPARENTFRAME_ICON = NULL;
90
91HBRUSH wxDisableButtonBrush = 0;
92
93LRESULT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
94
95#if !USE_SHARED_LIBRARY
a5e0e655
VZ
96 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
97
98 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
99 EVT_IDLE(wxApp::OnIdle)
387a3b02
JS
100 EVT_END_SESSION(wxApp::OnEndSession)
101 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
a5e0e655 102 END_EVENT_TABLE()
2bda0e17
KB
103#endif
104
105long wxApp::sm_lastMessageTime = 0;
106
107#ifdef __WIN95__
a5e0e655 108 static HINSTANCE gs_hRichEdit = NULL;
2bda0e17
KB
109#endif
110
589f0e3e
JS
111//// Initialize
112
113bool wxApp::Initialize()
2bda0e17 114{
589f0e3e
JS
115 wxBuffer = new char[1500];
116
e096774d 117/*
589f0e3e
JS
118 #if defined(__WXDEBUG__) && defined(_MSC_VER)
119 // do check for memory leaks on program exit
120 // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free
121 // deallocated memory which may be used to simulate low-memory condition)
122 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
123 #endif // debug build under MS VC++
e096774d 124*/
589f0e3e 125
47d67540 126 #if (WXDEBUG && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
a5e0e655
VZ
127 #if defined(_WINDLL)
128 streambuf* sBuf = NULL;
129 #else // EXE
130 streambuf* sBuf = new wxDebugStreamBuf;
131 #endif // DLL
589f0e3e 132
a5e0e655
VZ
133 ostream* oStr = new ostream(sBuf) ;
134 wxDebugContext::SetStream(oStr, sBuf);
47d67540 135 #endif // wxUSE_MEMORY_TRACING
589f0e3e
JS
136
137 wxClassInfo::InitializeClasses();
138
47d67540 139 #if wxUSE_RESOURCES
a5e0e655
VZ
140 wxGetResource("wxWindows", "OsVersion", &wxOsVersion);
141 #endif
589f0e3e
JS
142
143 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
144 wxTheColourDatabase->Initialize();
145
146 wxInitializeStockLists();
147 wxInitializeStockObjects();
148
47d67540 149 #if wxUSE_WX_RESOURCES
a5e0e655
VZ
150 wxInitializeResourceSystem();
151 #endif
2bda0e17 152
589f0e3e 153 wxBitmap::InitStandardHandlers();
2bda0e17 154
a5e0e655
VZ
155 #if defined(__WIN95__)
156 InitCommonControls();
157 gs_hRichEdit = LoadLibrary("RICHED32.DLL");
2bda0e17 158
a5e0e655
VZ
159 if (gs_hRichEdit == NULL)
160 {
161 wxMessageBox("Could not initialise Rich Edit DLL");
162 }
163 #endif
2bda0e17 164
a5e0e655
VZ
165 #if defined(WX_DRAG_DROP)
166 // we need to initialize OLE library
167 if ( FAILED(::OleInitialize(NULL)) )
168 wxFatalError(_("Cannot initialize OLE"));
169 #endif
2bda0e17 170
a5e0e655
VZ
171 #if CTL3D
172 if (!Ctl3dRegister(wxhInstance))
173 wxFatalError("Cannot register CTL3D");
2bda0e17 174
a5e0e655
VZ
175 Ctl3dAutoSubclass(wxhInstance);
176 #endif
2bda0e17 177
589f0e3e
JS
178 g_globalCursor = new wxCursor;
179
180 wxSTD_FRAME_ICON = LoadIcon(wxhInstance, "wxSTD_FRAME");
181 wxSTD_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, "wxSTD_MDIPARENTFRAME");
182 wxSTD_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, "wxSTD_MDICHILDFRAME");
2bda0e17 183
589f0e3e
JS
184 wxDEFAULT_FRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_FRAME");
185 wxDEFAULT_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_MDIPARENTFRAME");
186 wxDEFAULT_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, "wxDEFAULT_MDICHILDFRAME");
2bda0e17
KB
187
188 RegisterWindowClasses();
189
190 // Create the brush for disabling bitmap buttons
191
192 LOGBRUSH lb ;
193 lb.lbStyle = BS_PATTERN;
589f0e3e 194 lb.lbHatch = (int)LoadBitmap( wxhInstance, "wxDISABLE_BUTTON_BITMAP" ) ;
2bda0e17
KB
195 wxDisableButtonBrush = ::CreateBrushIndirect( & lb ) ;
196 ::DeleteObject( (HGDIOBJ)lb.lbHatch ) ;
197
47d67540 198 #if wxUSE_PENWINDOWS
a5e0e655
VZ
199 wxRegisterPenWin();
200 #endif
2bda0e17
KB
201
202 wxWinHandleList = new wxList(wxKEY_INTEGER);
203
204 // This is to foil optimizations in Visual C++ that
205 // throw out dummy.obj.
a5e0e655
VZ
206 #if (_MSC_VER >= 800) && !defined(WXMAKINGDLL)
207 extern char wxDummyChar;
208 if (wxDummyChar) wxDummyChar++;
209 #endif
210
2bda0e17
KB
211 wxSetKeyboardHook(TRUE);
212
213 wxModule::RegisterModules();
214 if (!wxModule::InitializeModules())
215 return FALSE;
216 return TRUE;
217}
218
589f0e3e
JS
219//// RegisterWindowClasses
220
bb6290e3 221bool wxApp::RegisterWindowClasses()
2bda0e17
KB
222{
223///////////////////////////////////////////////////////////////////////
224// Register the frame window class.
225 WNDCLASS wndclass; // Structure used to register Windows class.
226
227 wndclass.style = CS_HREDRAW | CS_VREDRAW;
228 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
229 wndclass.cbClsExtra = 0;
230 wndclass.cbWndExtra = sizeof( DWORD ); // was 4
231 wndclass.hInstance = wxhInstance;
232 wndclass.hIcon = NULL; // wxSTD_FRAME_ICON;
233 wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
234 wndclass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1) ;
235// wndclass.hbrBackground = GetStockObject( WHITE_BRUSH );
236 wndclass.lpszMenuName = NULL;
237#ifdef _MULTIPLE_INSTANCES
589f0e3e 238 sprintf( wxFrameClassName,"wxFrameClass%d", wxhInstance );
2bda0e17
KB
239#endif
240 wndclass.lpszClassName = wxFrameClassName;
241
242 if (!RegisterClass( &wndclass ))
243 {
244 // wxFatalError("Can't register Frame Window class");
245 }
246
247///////////////////////////////////////////////////////////////////////
248// Register the MDI frame window class.
249 WNDCLASS wndclass1; // Structure used to register Windows class.
250
251 wndclass1.style = CS_HREDRAW | CS_VREDRAW;
252 wndclass1.lpfnWndProc = (WNDPROC)wxWndProc;
253 wndclass1.cbClsExtra = 0;
254 wndclass1.cbWndExtra = sizeof( DWORD ); // was 4
255 wndclass1.hInstance = wxhInstance;
256 wndclass1.hIcon = NULL; // wxSTD_MDIPARENTFRAME_ICON;
257 wndclass1.hCursor = LoadCursor( NULL, IDC_ARROW );
258// wndclass1.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1) ;
259 wndclass1.hbrBackground = NULL;
260 wndclass1.lpszMenuName = NULL;
261
262 wndclass1.lpszClassName = wxMDIFrameClassName;
263 if (!RegisterClass( &wndclass1 ))
264 {
265// wxFatalError("Can't register MDI Frame window class");
a5e0e655 266// return FALSE;
2bda0e17
KB
267 }
268
269///////////////////////////////////////////////////////////////////////
270// Register the MDI child frame window class.
271 WNDCLASS wndclass4; // Structure used to register Windows class.
272
273 wndclass4.style = CS_HREDRAW | CS_VREDRAW;
274 wndclass4.lpfnWndProc = (WNDPROC)wxWndProc;
275 wndclass4.cbClsExtra = 0;
276 wndclass4.cbWndExtra = sizeof( DWORD ); // was 4
277 wndclass4.hInstance = wxhInstance;
278 wndclass4.hIcon = NULL; // wxSTD_MDICHILDFRAME_ICON;
279 wndclass4.hCursor = LoadCursor( NULL, IDC_ARROW );
280 // TODO: perhaps this should be NULL so that Windows doesn't
281 // paint the background itself (would OnEraseBackground duplicate
282 // this?)
283 wndclass4.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ;
284// wndclass4.hbrBackground = NULL;
285 wndclass4.lpszMenuName = NULL;
286 wndclass4.lpszClassName = wxMDIChildFrameClassName;
287
288 if (!RegisterClass( &wndclass4 ))
289 {
290// wxFatalError("Can't register MDI child frame window class");
291// return FALSE;
292 }
293
294///////////////////////////////////////////////////////////////////////
295// Register the panel window class.
296 WNDCLASS wndclass2; // Structure used to register Windows class.
297 memset(&wndclass2, 0, sizeof(WNDCLASS)); // start with NULL defaults
298 // Use CS_OWNDC to avoid messing about restoring the context
299 // for every graphic operation.
300 wndclass2.style = CS_HREDRAW | CS_VREDRAW;
301 wndclass2.lpfnWndProc = (WNDPROC)wxWndProc;
302 wndclass2.cbClsExtra = 0;
303 wndclass2.cbWndExtra = sizeof( DWORD ); // was 4
304 wndclass2.hInstance = wxhInstance;
305 wndclass2.hIcon = NULL;
306 wndclass2.hCursor = NULL;
307// wndclass2.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1) ;
c4e7c2aa 308 wndclass2.hbrBackground = (HBRUSH) GetStockObject( LTGRAY_BRUSH );
2bda0e17
KB
309 wndclass2.lpszMenuName = NULL;
310 wndclass2.lpszClassName = wxPanelClassName;
311 if (!RegisterClass( &wndclass2 ))
312 {
313// wxFatalError("Can't register Panel Window class");
314// return FALSE;
315 }
316
317///////////////////////////////////////////////////////////////////////
318// Register the canvas and textsubwindow class name
319 WNDCLASS wndclass3; // Structure used to register Windows class.
320 memset(&wndclass3, 0, sizeof(WNDCLASS)); // start with NULL defaults
321 // Use CS_OWNDC to avoid messing about restoring the context
322 // for every graphic operation.
d50b2a58 323// wndclass3.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS ;
2bda0e17 324 // wxWin 2.0
d50b2a58 325 wndclass3.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
2bda0e17
KB
326 wndclass3.lpfnWndProc = (WNDPROC)wxWndProc;
327 wndclass3.cbClsExtra = 0;
328 wndclass3.cbWndExtra = sizeof( DWORD ); // was 4
329 wndclass3.hInstance = wxhInstance;
330 wndclass3.hIcon = NULL;
331 wndclass3.hCursor = NULL;
332// wndclass3.hbrBackground = (HBRUSH)(COLOR_WINDOW+1) ;
333 wndclass3.hbrBackground = NULL;
334 wndclass3.lpszMenuName = NULL;
335 wndclass3.lpszClassName = wxCanvasClassName;
336 if (!RegisterClass( &wndclass3))
337 {
338// wxFatalError("Can't register Canvas class");
339// return FALSE;
340 }
341
342 return TRUE;
343}
344
589f0e3e
JS
345//// Convert Windows to argc, argv style
346
347void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine)
348{
da36f544 349 wxStringList args;
589f0e3e 350
da36f544
JS
351 wxString cmdLine(lpCmdLine);
352 int count = 0;
589f0e3e 353
da36f544
JS
354 // Get application name
355 char name[500];
356 ::GetModuleFileName(wxhInstance, name, WXSIZEOF(name));
357
358 // GNUWIN32 already fills in the first arg with the application name.
589f0e3e 359#if !defined(__GNUWIN32__)
da36f544
JS
360 args.Add(name);
361 count ++;
589f0e3e
JS
362#endif
363
da36f544
JS
364 strcpy(name, wxFileNameFromPath(name));
365 wxStripExtension(name);
366 wxTheApp->SetAppName(name);
589f0e3e 367
da36f544
JS
368 // Break up string
369 // Treat strings enclosed in double-quotes as single arguments
370 int i = 0;
371 int len = cmdLine.Length();
372 while (i < len)
a5e0e655 373 {
da36f544
JS
374 // Skip whitespace
375 while ((i < len) && isspace(cmdLine.GetChar(i)))
376 i ++;
377
378 if (i < len)
379 {
380 if (cmdLine.GetChar(i) == '"') // We found the start of a string
381 {
382 i ++;
383 int first = i;
384 while ((i < len) && (cmdLine.GetChar(i) != '"'))
385 i ++;
386
387 wxString arg(cmdLine.Mid(first, (i - first)));
388
389 args.Add(arg);
390 count ++;
391
392 if (i < len)
393 i ++; // Skip past 2nd quote
394 }
395 else // Unquoted argument
396 {
397 int first = i;
398 while ((i < len) && !isspace(cmdLine.GetChar(i)))
399 i ++;
400
401 wxString arg(cmdLine.Mid(first, (i - first)));
402
403 args.Add(arg);
404 count ++;
405 }
406 }
a5e0e655 407 }
a5e0e655 408
da36f544
JS
409 wxTheApp->argv = new char*[count + 1];
410 for (i = 0; i < count; i++)
a5e0e655 411 {
da36f544
JS
412 wxString arg(args[i]);
413 wxTheApp->argv[i] = copystring((const char*)arg);
a5e0e655 414 }
da36f544
JS
415 wxTheApp->argv[count] = NULL; // argv[] is a NULL-terminated list
416 wxTheApp->argc = count;
589f0e3e
JS
417}
418
419//// Cleans up any wxWindows internal structures left lying around
420
bb6290e3 421void wxApp::CleanUp()
2bda0e17 422{
589f0e3e 423 //// COMMON CLEANUP
2bda0e17
KB
424 wxModule::CleanUpModules();
425
47d67540 426#if wxUSE_WX_RESOURCES
589f0e3e
JS
427 wxCleanUpResourceSystem();
428
429// wxDefaultResourceTable->ClearTable();
430#endif
431
432 // Indicate that the cursor can be freed,
433 // so that cursor won't be deleted by deleting
434 // the bitmap list before g_globalCursor goes out
435 // of scope (double deletion of the cursor).
436 wxSetCursor(wxNullCursor);
437 delete g_globalCursor;
438
439 wxDeleteStockObjects() ;
440
441 // Destroy all GDI lists, etc.
442 wxDeleteStockLists();
443
444 delete wxTheColourDatabase;
445 wxTheColourDatabase = NULL;
446
589f0e3e
JS
447 wxBitmap::CleanUpHandlers();
448
449 delete[] wxBuffer;
450 wxBuffer = NULL;
451
452 //// WINDOWS-SPECIFIC CLEANUP
2bda0e17
KB
453
454 wxSetKeyboardHook(FALSE);
455
456#ifdef __WIN95__
457 if (gs_hRichEdit != NULL)
458 FreeLibrary(gs_hRichEdit);
459#endif
460
47d67540 461#if wxUSE_PENWINDOWS
2bda0e17
KB
462 wxCleanUpPenWin();
463#endif
464
465 if (wxSTD_FRAME_ICON)
466 DestroyIcon(wxSTD_FRAME_ICON);
467 if (wxSTD_MDICHILDFRAME_ICON)
468 DestroyIcon(wxSTD_MDICHILDFRAME_ICON);
469 if (wxSTD_MDIPARENTFRAME_ICON)
470 DestroyIcon(wxSTD_MDIPARENTFRAME_ICON);
471
472 if (wxDEFAULT_FRAME_ICON)
473 DestroyIcon(wxDEFAULT_FRAME_ICON);
474 if (wxDEFAULT_MDICHILDFRAME_ICON)
475 DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON);
476 if (wxDEFAULT_MDIPARENTFRAME_ICON)
477 DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
478
479 if ( wxDisableButtonBrush )
480 ::DeleteObject( wxDisableButtonBrush ) ;
481
482#if defined(WX_DRAG_DROP)
483 ::OleUninitialize();
484#endif
485
486#if CTL3D
487 Ctl3dUnregister(wxhInstance);
488#endif
489
490 if (wxWinHandleList)
491 delete wxWinHandleList ;
d50b2a58 492
0c32066b
JS
493 wxClassInfo::CleanUpClasses();
494
c54f78a2 495 // do it as the very last thing because everything else can log messages
370382c7 496 wxLog::DontCreateOnDemand();
c54f78a2 497 delete wxLog::SetActiveTarget(NULL);
2bda0e17
KB
498}
499
2bda0e17
KB
500#if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
501
589f0e3e 502//// Main wxWindows entry point
a5e0e655
VZ
503int wxEntry(WXHINSTANCE hInstance,
504 WXHINSTANCE WXUNUSED(hPrevInstance),
505 char *lpCmdLine,
506 int nCmdShow,
507 bool enterLoop)
2bda0e17 508{
a5e0e655 509#ifndef __WXDEBUG__ // take everything into a try-except block in release build
dfad0599 510 try {
a5e0e655
VZ
511#endif
512
2bda0e17
KB
513 wxhInstance = (HINSTANCE) hInstance;
514
589f0e3e 515 if (!wxApp::Initialize())
2bda0e17
KB
516 return 0;
517
a5e0e655 518 // create the application object or ensure that one already exists
2bda0e17
KB
519 if (!wxTheApp)
520 {
a5e0e655
VZ
521 // The app may have declared a global application object, but we recommend
522 // the IMPLEMENT_APP macro is used instead, which sets an initializer
523 // function for delayed, dynamic app object construction.
524 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
525 "No initializer - use IMPLEMENT_APP macro." );
2bda0e17 526
a5e0e655 527 wxTheApp = (*wxApp::GetInitializerFunction()) ();
2bda0e17
KB
528 }
529
a5e0e655 530 wxCHECK_MSG( wxTheApp, 0, "You have to define an instance of wxApp!" );
2bda0e17 531
a5e0e655 532 // save the WinMain() parameters
589f0e3e 533 wxTheApp->ConvertToStandardCommandArgs(lpCmdLine);
2bda0e17
KB
534 wxTheApp->m_nCmdShow = nCmdShow;
535
536 // GUI-specific initialisation. In fact on Windows we don't have any,
537 // but this call is provided for compatibility across platforms.
538 wxTheApp->OnInitGui() ;
539
a5e0e655 540 int retValue = 0;
2bda0e17 541
a5e0e655
VZ
542 if ( wxTheApp->OnInit() )
543 {
544 if ( enterLoop )
545 {
546 retValue = wxTheApp->OnRun();
547 }
2bda0e17 548 }
a5e0e655 549 //else: app initialization failed, so we skipped OnRun()
2bda0e17 550
a5e0e655
VZ
551 wxWindow *topWindow = wxTheApp->GetTopWindow();
552 if ( topWindow )
2bda0e17 553 {
a5e0e655
VZ
554 // Forcibly delete the window.
555 if ( topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
556 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
557 {
558 topWindow->Close(TRUE);
559 wxTheApp->DeletePendingObjects();
560 }
561 else
562 {
563 delete topWindow;
564 wxTheApp->SetTopWindow(NULL);
565 }
2bda0e17 566 }
d50b2a58 567
2bda0e17
KB
568 wxTheApp->OnExit();
569 wxApp::CleanUp();
570
571 delete wxTheApp;
572 wxTheApp = NULL;
573
47d67540 574#if (WXDEBUG && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
2bda0e17
KB
575 // At this point we want to check if there are any memory
576 // blocks that aren't part of the wxDebugContext itself,
577 // as a special case. Then when dumping we need to ignore
578 // wxDebugContext, too.
579 if (wxDebugContext::CountObjectsLeft() > 0)
580 {
a5e0e655
VZ
581 wxTrace("There were memory leaks.\n");
582 wxDebugContext::Dump();
583 wxDebugContext::PrintStatistics();
2bda0e17
KB
584 }
585 wxDebugContext::SetStream(NULL, NULL);
586#endif
587
588 return retValue;
a5e0e655
VZ
589#ifndef __WXDEBUG__ // catch exceptions only in release build
590 }
dfad0599 591 except ( EXCEPTION_EXECUTE_HANDLER ) {
a5e0e655
VZ
592 /*
593 if ( wxTheApp )
594 wxTheApp->OnFatalException();
595 */
596
597 ::ExitProcess(3); // the same exit code as abort()
598 }
599#endif //debug
2bda0e17
KB
600}
601
602#else /* _WINDLL */
603
589f0e3e
JS
604//// Entry point for DLLs
605
2bda0e17
KB
606int wxEntry(WXHINSTANCE hInstance)
607{
608 wxhInstance = (HINSTANCE) hInstance;
589f0e3e 609 wxApp::Initialize();
2bda0e17
KB
610
611 // The app may have declared a global application object, but we recommend
612 // the IMPLEMENT_APP macro is used instead, which sets an initializer function
613 // for delayed, dynamic app object construction.
614
615 if (!wxTheApp)
616 {
a5e0e655
VZ
617 if (!wxApp::GetInitializerFunction())
618 {
619 MessageBox(NULL, "No initializer - use IMPLEMENT_APP macro.", "wxWindows Error", MB_APPLMODAL | MB_ICONSTOP | MB_OK);
620 return 0;
621 }
2bda0e17 622
a5e0e655 623 wxTheApp = (* wxApp::GetInitializerFunction()) ();
2bda0e17
KB
624 }
625
626 if (!wxTheApp) {
627 MessageBox(NULL, "You have to define an instance of wxApp!", "wxWindows Error", MB_APPLMODAL | MB_ICONSTOP | MB_OK);
628 return 0;
629 }
630
631 wxTheApp->argc = 0;
632 wxTheApp->argv = NULL;
633
634 wxTheApp->OnInitGui();
635
636 wxTheApp->OnInit();
637
638 if (wxTheApp->GetTopWindow() && wxTheApp->GetTopWindow()->GetHWND()) {
639 wxTheApp->GetTopWindow()->Show(TRUE);
640 }
641
642 return 1;
643}
644#endif // _WINDLL
645
589f0e3e
JS
646//// Static member initialization
647
2bda0e17
KB
648wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
649
bb6290e3 650wxApp::wxApp()
2bda0e17
KB
651{
652 m_topWindow = NULL;
653 wxTheApp = this;
2bda0e17 654 m_className = "";
2bda0e17
KB
655 m_wantDebugOutput = TRUE ;
656 m_appName = "";
657 argc = 0;
658 argv = NULL;
2049ba38 659#ifdef __WXMSW__
2bda0e17
KB
660 m_printMode = wxPRINT_WINDOWS;
661#else
662 m_printMode = wxPRINT_POSTSCRIPT;
663#endif
2bda0e17 664 m_exitOnFrameDelete = TRUE;
2bda0e17
KB
665 m_auto3D = TRUE;
666}
667
589f0e3e
JS
668wxApp::~wxApp()
669{
670 // Delete command-line args
671 int i;
672 for (i = 0; i < argc; i++)
673 {
674 delete[] argv[i];
675 }
da36f544 676 delete[] argv;
589f0e3e
JS
677}
678
bb6290e3 679bool wxApp::Initialized()
2bda0e17
KB
680{
681#ifndef _WINDLL
682 if (GetTopWindow())
683 return TRUE;
684 else
685 return FALSE;
686#endif
687#ifdef _WINDLL // Assume initialized if DLL (no way of telling)
688 return TRUE;
689#endif
690}
691
692/*
693 * Get and process a message, returning FALSE if WM_QUIT
694 * received.
695 *
696 */
bb6290e3 697bool wxApp::DoMessage()
2bda0e17
KB
698{
699 if (!::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0))
700 {
701 return FALSE;
702 }
d50b2a58 703
2bda0e17
KB
704 // Process the message
705 if (!ProcessMessage((WXMSG *)&s_currentMsg))
706 {
707 ::TranslateMessage(&s_currentMsg);
708 wxApp::sm_lastMessageTime = s_currentMsg.time; /* MATTHEW: timeStamp impl. */
709 ::DispatchMessage(&s_currentMsg);
710 }
711 return TRUE;
712}
713
714/*
715 * Keep trying to process messages until WM_QUIT
716 * received.
717 *
718 * If there are messages to be processed, they will all be
719 * processed and OnIdle will not be called.
720 * When there are no more messages, OnIdle is called.
721 * If OnIdle requests more time,
722 * it will be repeatedly called so long as there are no pending messages.
723 * A 'feature' of this is that once OnIdle has decided that no more processing
724 * is required, then it won't get processing time until further messages
725 * are processed (it'll sit in DoMessage).
726 */
727
bb6290e3 728int wxApp::MainLoop()
2bda0e17
KB
729{
730 m_keepGoing = TRUE;
731 while (m_keepGoing)
732 {
733 while (!::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) &&
734 ProcessIdle()) {}
735 if (!DoMessage())
736 m_keepGoing = FALSE;
737 }
738
739 return s_currentMsg.wParam;
740}
741
742// Returns TRUE if more time is needed.
bb6290e3 743bool wxApp::ProcessIdle()
2bda0e17
KB
744{
745 wxIdleEvent event;
746 event.SetEventObject(this);
747 ProcessEvent(event);
748
749 return event.MoreRequested();
750}
751
bb6290e3 752void wxApp::ExitMainLoop()
2bda0e17
KB
753{
754 m_keepGoing = FALSE;
755}
756
bb6290e3 757bool wxApp::Pending()
2bda0e17
KB
758{
759 return (::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) != 0) ;
760}
761
bb6290e3 762void wxApp::Dispatch()
2bda0e17
KB
763{
764 if (!DoMessage())
765 m_keepGoing = FALSE;
766}
767
768/*
769 * Give all windows a chance to preprocess
770 * the message. Some may have accelerator tables, or have
771 * MDI complications.
772 */
773bool wxApp::ProcessMessage(WXMSG *Msg)
774{
775 MSG *msg = (MSG *)Msg;
776
777 HWND hWnd;
778
57a7b7c1
JS
779 // Try translations first; find the youngest window with
780 // a translation table.
2bda0e17
KB
781 for (hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
782 {
783 wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd);
784 if (wnd)
785 {
57a7b7c1 786 if (wnd->MSWTranslateMessage(Msg))
2bda0e17 787 return TRUE;
2bda0e17
KB
788 }
789 }
790
57a7b7c1
JS
791 // Anyone for a non-translation message? Try youngest descendants first.
792 for (hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
793 {
794 wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd);
795 if (wnd)
796 {
797 if (wnd->MSWProcessMessage(Msg))
798 return TRUE;
799 }
800 }
801 return FALSE;
2bda0e17
KB
802}
803
804void wxApp::OnIdle(wxIdleEvent& event)
805{
806 static bool inOnIdle = FALSE;
807
808 // Avoid recursion (via ProcessEvent default case)
809 if (inOnIdle)
810 return;
811
812 inOnIdle = TRUE;
813
814 // 'Garbage' collection of windows deleted with Close().
815 DeletePendingObjects();
816
c54f78a2
VZ
817 // flush the logged messages if any
818 wxLog *pLog = wxLog::GetActiveTarget();
819 if ( pLog != NULL && pLog->HasPendingMessages() )
820 pLog->Flush();
821
2bda0e17
KB
822 // Send OnIdle events to all windows
823 bool needMore = SendIdleEvents();
1c089c47 824// bool needMore = FALSE;
2bda0e17
KB
825
826 if (needMore)
827 event.RequestMore(TRUE);
828
829 inOnIdle = FALSE;
830}
831
832// Send idle event to all top-level windows
bb6290e3 833bool wxApp::SendIdleEvents()
2bda0e17
KB
834{
835 bool needMore = FALSE;
a5e0e655
VZ
836 wxNode* node = wxTopLevelWindows.First();
837 while (node)
838 {
839 wxWindow* win = (wxWindow*) node->Data();
840 if (SendIdleEvents(win))
2bda0e17
KB
841 needMore = TRUE;
842
a5e0e655
VZ
843 node = node->Next();
844 }
2bda0e17
KB
845 return needMore;
846}
847
848// Send idle event to window and all subwindows
849bool wxApp::SendIdleEvents(wxWindow* win)
850{
a5e0e655 851 bool needMore = FALSE;
2bda0e17 852
a5e0e655
VZ
853 wxIdleEvent event;
854 event.SetEventObject(win);
855 win->ProcessEvent(event);
2bda0e17 856
a5e0e655
VZ
857 if (event.MoreRequested())
858 needMore = TRUE;
2bda0e17 859
a5e0e655
VZ
860 wxNode* node = win->GetChildren()->First();
861 while (node)
862 {
863 wxWindow* win = (wxWindow*) node->Data();
864 if (SendIdleEvents(win))
865 needMore = TRUE;
2bda0e17 866
a5e0e655
VZ
867 node = node->Next();
868 }
869 return needMore ;
2bda0e17
KB
870}
871
bb6290e3 872void wxApp::DeletePendingObjects()
2bda0e17
KB
873{
874 wxNode *node = wxPendingDelete.First();
875 while (node)
876 {
877 wxObject *obj = (wxObject *)node->Data();
d50b2a58 878
2bda0e17
KB
879 delete obj;
880
881 if (wxPendingDelete.Member(obj))
882 delete node;
883
884 // Deleting one object may have deleted other pending
885 // objects, so start from beginning of list again.
886 node = wxPendingDelete.First();
887 }
888}
889
387a3b02
JS
890void wxApp::OnEndSession(wxCloseEvent& event)
891{
892 if (GetTopWindow())
893 GetTopWindow()->Close(TRUE);
894}
895
896// Default behaviour: close the application with prompts. The
897// user can veto the close, and therefore the end session.
898void wxApp::OnQueryEndSession(wxCloseEvent& event)
899{
900 if (GetTopWindow())
901 {
902 if (!GetTopWindow()->Close(!event.CanVeto()))
903 event.Veto(TRUE);
904 }
905}
906
bb6290e3 907wxLog* wxApp::CreateLogTarget()
2bda0e17
KB
908{
909 return new wxLogGui;
910}
911
bb6290e3 912wxWindow* wxApp::GetTopWindow() const
2bda0e17
KB
913{
914 if (m_topWindow)
915 return m_topWindow;
916 else if (wxTopLevelWindows.Number() > 0)
917 return (wxWindow*) wxTopLevelWindows.First()->Data();
918 else
919 return NULL;
920}
921
bb6290e3
JS
922int wxApp::GetComCtl32Version() const
923{
924 // have we loaded COMCTL32 yet?
925 HMODULE theModule = ::GetModuleHandle("COMCTL32");
926 int version = 0;
d50b2a58 927
bb6290e3
JS
928 // if so, then we can check for the version
929 if (theModule)
930 {
931 // InitCommonControlsEx is unique to 4.7 and later
932 FARPROC theProc = ::GetProcAddress(theModule, "InitCommonControlsEx");
d50b2a58 933
bb6290e3
JS
934 if (! theProc)
935 { // not found, must be 4.00
a5e0e655 936 version = 400;
bb6290e3
JS
937 }
938 else
939 {
a5e0e655
VZ
940 // The following symbol are unique to 4.71
941 // DllInstall
942 // FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos
943 // FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo
944 // FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange
945 // FlatSB_ShowScrollBar
946 // _DrawIndirectImageList _DuplicateImageList
947 // InitializeFlatSB
948 // UninitializeFlatSB
949 // we could check for any of these - I chose DllInstall
950 FARPROC theProc = ::GetProcAddress(theModule, "DllInstall");
951 if (! theProc)
952 {
953 // not found, must be 4.70
954 version = 470;
955 }
956 else
957 { // found, must be 4.71
958 version = 471;
959 }
bb6290e3
JS
960 }
961 }
962 return version;
963}
964
965void wxExit()
2bda0e17
KB
966{
967 wxApp::CleanUp();
968 FatalAppExit(0, "Fatal error: exiting");
969}
970
971// Yield to incoming messages
bb6290e3 972bool wxYield()
2bda0e17
KB
973{
974 MSG msg;
975 // We want to go back to the main message loop
976 // if we see a WM_QUIT. (?)
977 while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
978 {
979 if (!wxTheApp->DoMessage())
980 break;
981 }
982
983 return TRUE;
984}
985
986HINSTANCE wxGetInstance()
987{
a5e0e655 988 return wxhInstance;
2bda0e17
KB
989}
990
991// For some reason, with MSVC++ 1.5, WinMain isn't linked in properly
992// if in a separate file. So include it here to ensure it's linked.
993#if (defined(_MSC_VER) && !defined(__WIN32__)) || defined(__GNUWIN32__)
a5e0e655 994 #include "main.cpp"
2bda0e17 995#endif