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