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