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