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