extracted code calling {Ole|Co}[Un]Initialize() to wxOle[Un]Initialize() functions...
[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
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "app.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #if defined(__BORLANDC__)
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/frame.h"
33 #include "wx/app.h"
34 #include "wx/utils.h"
35 #include "wx/gdicmn.h"
36 #include "wx/pen.h"
37 #include "wx/brush.h"
38 #include "wx/cursor.h"
39 #include "wx/icon.h"
40 #include "wx/palette.h"
41 #include "wx/dc.h"
42 #include "wx/dialog.h"
43 #include "wx/msgdlg.h"
44 #include "wx/intl.h"
45 #include "wx/dynarray.h"
46 #include "wx/wxchar.h"
47 #include "wx/icon.h"
48 #include "wx/log.h"
49 #endif
50
51 #include "wx/apptrait.h"
52 #include "wx/filename.h"
53 #include "wx/module.h"
54 #include "wx/dynlib.h"
55
56 #include "wx/msw/private.h"
57 #include "wx/msw/ole/oleutils.h"
58
59 #if wxUSE_TOOLTIPS
60 #include "wx/tooltip.h"
61 #endif // wxUSE_TOOLTIPS
62
63 // OLE is used for drag-and-drop, clipboard, OLE Automation..., but some
64 // compilers don't support it (missing headers, libs, ...)
65 #if defined(__GNUWIN32_OLD__) || defined(__SYMANTEC__) || defined(__SALFORDC__)
66 #undef wxUSE_OLE
67
68 #define wxUSE_OLE 0
69 #endif // broken compilers
70
71 #if wxUSE_OLE
72 #include <ole2.h>
73 #endif
74
75 #include <string.h>
76 #include <ctype.h>
77
78 #include "wx/msw/wrapcctl.h"
79
80 // For MB_TASKMODAL
81 #ifdef __WXWINCE__
82 #include "wx/msw/wince/missing.h"
83 #endif
84
85 #if (!defined(__MINGW32__) || wxCHECK_W32API_VERSION( 2, 0 )) && \
86 !defined(__CYGWIN__) && !defined(__DIGITALMARS__) && !defined(__WXWINCE__) && \
87 (!defined(_MSC_VER) || (_MSC_VER > 1100))
88 #include <shlwapi.h>
89 #endif
90
91 // ---------------------------------------------------------------------------
92 // global variables
93 // ---------------------------------------------------------------------------
94
95 extern wxList WXDLLEXPORT wxPendingDelete;
96
97 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
98 extern void wxSetKeyboardHook(bool doIt);
99 #endif
100
101 // NB: all "NoRedraw" classes must have the same names as the "normal" classes
102 // with NR suffix - wxWindow::MSWCreate() supposes this
103 #ifdef __WXWINCE__
104 WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
105 WXDLLIMPEXP_CORE wxChar *wxCanvasClassNameNR;
106 #else
107 WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName = wxT("wxWindowClass");
108 WXDLLIMPEXP_CORE const wxChar *wxCanvasClassNameNR = wxT("wxWindowClassNR");
109 #endif
110 WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassName = wxT("wxMDIFrameClass");
111 WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassNameNoRedraw = wxT("wxMDIFrameClassNR");
112 WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
113 WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
114
115 // ----------------------------------------------------------------------------
116 // private functions
117 // ----------------------------------------------------------------------------
118
119 LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
120
121 // ===========================================================================
122 // wxGUIAppTraits implementation
123 // ===========================================================================
124
125 // private class which we use to pass parameters from BeforeChildWaitLoop() to
126 // AfterChildWaitLoop()
127 struct ChildWaitLoopData
128 {
129 ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *winActive_)
130 {
131 wd = wd_;
132 winActive = winActive_;
133 }
134
135 wxWindowDisabler *wd;
136 wxWindow *winActive;
137 };
138
139 void *wxGUIAppTraits::BeforeChildWaitLoop()
140 {
141 /*
142 We use a dirty hack here to disable all application windows (which we
143 must do because otherwise the calls to wxYield() could lead to some very
144 unexpected reentrancies in the users code) but to avoid losing
145 focus/activation entirely when the child process terminates which would
146 happen if we simply disabled everything using wxWindowDisabler. Indeed,
147 remember that Windows will never activate a disabled window and when the
148 last childs window is closed and Windows looks for a window to activate
149 all our windows are still disabled. There is no way to enable them in
150 time because we don't know when the childs windows are going to be
151 closed, so the solution we use here is to keep one special tiny frame
152 enabled all the time. Then when the child terminates it will get
153 activated and when we close it below -- after reenabling all the other
154 windows! -- the previously active window becomes activated again and
155 everything is ok.
156 */
157 wxBeginBusyCursor();
158
159 // first disable all existing windows
160 wxWindowDisabler *wd = new wxWindowDisabler;
161
162 // then create an "invisible" frame: it has minimal size, is positioned
163 // (hopefully) outside the screen and doesn't appear on the taskbar
164 wxWindow *winActive = new wxFrame
165 (
166 wxTheApp->GetTopWindow(),
167 wxID_ANY,
168 wxEmptyString,
169 wxPoint(32600, 32600),
170 wxSize(1, 1),
171 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR
172 );
173 winActive->Show();
174
175 return new ChildWaitLoopData(wd, winActive);
176 }
177
178 void wxGUIAppTraits::AlwaysYield()
179 {
180 wxYield();
181 }
182
183 void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig)
184 {
185 wxEndBusyCursor();
186
187 ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig;
188
189 delete data->wd;
190
191 // finally delete the dummy frame and, as wd has been already destroyed and
192 // the other windows reenabled, the activation is going to return to the
193 // window which had had it before
194 data->winActive->Destroy();
195
196 // also delete the temporary data object itself
197 delete data;
198 }
199
200 bool wxGUIAppTraits::DoMessageFromThreadWait()
201 {
202 // we should return false only if the app should exit, i.e. only if
203 // Dispatch() determines that the main event loop should terminate
204 return !wxTheApp || wxTheApp->Dispatch();
205 }
206
207 wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
208 {
209 static wxToolkitInfo info;
210 wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo();
211 info.versionMajor = baseInfo.versionMajor;
212 info.versionMinor = baseInfo.versionMinor;
213 info.os = baseInfo.os;
214 info.shortName = _T("msw");
215 info.name = _T("wxMSW");
216 #ifdef __WXUNIVERSAL__
217 info.shortName << _T("univ");
218 info.name << _T("/wxUniversal");
219 #endif
220 return info;
221 }
222
223 // ===========================================================================
224 // wxApp implementation
225 // ===========================================================================
226
227 int wxApp::m_nCmdShow = SW_SHOWNORMAL;
228
229 // ---------------------------------------------------------------------------
230 // wxWin macros
231 // ---------------------------------------------------------------------------
232
233 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
234
235 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
236 EVT_IDLE(wxApp::OnIdle)
237 EVT_END_SESSION(wxApp::OnEndSession)
238 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
239 END_EVENT_TABLE()
240
241 // class to ensure that wxAppBase::CleanUp() is called if our Initialize()
242 // fails
243 class wxCallBaseCleanup
244 {
245 public:
246 wxCallBaseCleanup(wxApp *app) : m_app(app) { }
247 ~wxCallBaseCleanup() { if ( m_app ) m_app->wxAppBase::CleanUp(); }
248
249 void Dismiss() { m_app = NULL; }
250
251 private:
252 wxApp *m_app;
253 };
254
255 //// Initialize
256 bool wxApp::Initialize(int& argc, wxChar **argv)
257 {
258 if ( !wxAppBase::Initialize(argc, argv) )
259 return false;
260
261 // ensure that base cleanup is done if we return too early
262 wxCallBaseCleanup callBaseCleanup(this);
263
264 #ifdef __WXWINCE__
265 wxString tmp = GetAppName();
266 tmp += wxT("ClassName");
267 wxCanvasClassName = wxStrdup( tmp.c_str() );
268 tmp += wxT("NR");
269 wxCanvasClassNameNR = wxStrdup( tmp.c_str() );
270 HWND hWnd = FindWindow( wxCanvasClassNameNR, NULL );
271 if (hWnd)
272 {
273 SetForegroundWindow( (HWND)(((DWORD)hWnd)|0x01) );
274 return false;
275 }
276 #endif
277
278 // the first thing to do is to check if we're trying to run an Unicode
279 // program under Win9x w/o MSLU emulation layer - if so, abort right now
280 // as it has no chance to work
281 #if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
282 if ( wxGetOsVersion() != wxWINDOWS_NT && wxGetOsVersion() != wxWINDOWS_CE )
283 {
284 // note that we can use MessageBoxW() as it's implemented even under
285 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
286 // used by wxLocale are not
287 ::MessageBox
288 (
289 NULL,
290 _T("This program uses Unicode and requires Windows NT/2000/XP/CE.\nProgram aborted."),
291 _T("wxWidgets Fatal Error"),
292 MB_ICONERROR | MB_OK
293 );
294
295 return false;
296 }
297 #endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
298
299 #if defined(__WIN95__) && !defined(__WXMICROWIN__)
300 InitCommonControls();
301 #endif // __WIN95__
302
303 wxOleInitialize();
304
305 RegisterWindowClasses();
306
307 #if wxUSE_PENWINDOWS
308 wxRegisterPenWin();
309 #endif
310
311 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
312
313 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
314 wxSetKeyboardHook(true);
315 #endif
316
317 callBaseCleanup.Dismiss();
318
319 return true;
320 }
321
322 // ---------------------------------------------------------------------------
323 // RegisterWindowClasses
324 // ---------------------------------------------------------------------------
325
326 // TODO we should only register classes really used by the app. For this it
327 // would be enough to just delay the class registration until an attempt
328 // to create a window of this class is made.
329 bool wxApp::RegisterWindowClasses()
330 {
331 WNDCLASS wndclass;
332 wxZeroMemory(wndclass);
333
334 // for each class we register one with CS_(V|H)REDRAW style and one
335 // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
336 static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
337 static const long styleNoRedraw = CS_DBLCLKS;
338
339 // the fields which are common to all classes
340 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
341 wndclass.hInstance = wxhInstance;
342 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
343
344 // register the class for all normal windows
345 wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
346 wndclass.lpszClassName = wxCanvasClassName;
347 wndclass.style = styleNormal;
348
349 if ( !RegisterClass(&wndclass) )
350 {
351 wxLogLastError(wxT("RegisterClass(frame)"));
352 }
353
354 // "no redraw" frame
355 wndclass.lpszClassName = wxCanvasClassNameNR;
356 wndclass.style = styleNoRedraw;
357
358 if ( !RegisterClass(&wndclass) )
359 {
360 wxLogLastError(wxT("RegisterClass(no redraw frame)"));
361 }
362
363 // Register the MDI frame window class.
364 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
365 wndclass.lpszClassName = wxMDIFrameClassName;
366 wndclass.style = styleNormal;
367
368 if ( !RegisterClass(&wndclass) )
369 {
370 wxLogLastError(wxT("RegisterClass(MDI parent)"));
371 }
372
373 // "no redraw" MDI frame
374 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
375 wndclass.style = styleNoRedraw;
376
377 if ( !RegisterClass(&wndclass) )
378 {
379 wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)"));
380 }
381
382 // Register the MDI child frame window class.
383 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
384 wndclass.lpszClassName = wxMDIChildFrameClassName;
385 wndclass.style = styleNormal;
386
387 if ( !RegisterClass(&wndclass) )
388 {
389 wxLogLastError(wxT("RegisterClass(MDI child)"));
390 }
391
392 // "no redraw" MDI child frame
393 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
394 wndclass.style = styleNoRedraw;
395
396 if ( !RegisterClass(&wndclass) )
397 {
398 wxLogLastError(wxT("RegisterClass(no redraw MDI child)"));
399 }
400
401 return true;
402 }
403
404 // ---------------------------------------------------------------------------
405 // UnregisterWindowClasses
406 // ---------------------------------------------------------------------------
407
408 bool wxApp::UnregisterWindowClasses()
409 {
410 bool retval = true;
411
412 #ifndef __WXMICROWIN__
413 // MDI frame window class.
414 if ( !::UnregisterClass(wxMDIFrameClassName, wxhInstance) )
415 {
416 wxLogLastError(wxT("UnregisterClass(MDI parent)"));
417
418 retval = false;
419 }
420
421 // "no redraw" MDI frame
422 if ( !::UnregisterClass(wxMDIFrameClassNameNoRedraw, wxhInstance) )
423 {
424 wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)"));
425
426 retval = false;
427 }
428
429 // MDI child frame window class.
430 if ( !::UnregisterClass(wxMDIChildFrameClassName, wxhInstance) )
431 {
432 wxLogLastError(wxT("UnregisterClass(MDI child)"));
433
434 retval = false;
435 }
436
437 // "no redraw" MDI child frame
438 if ( !::UnregisterClass(wxMDIChildFrameClassNameNoRedraw, wxhInstance) )
439 {
440 wxLogLastError(wxT("UnregisterClass(no redraw MDI child)"));
441
442 retval = false;
443 }
444
445 // canvas class name
446 if ( !::UnregisterClass(wxCanvasClassName, wxhInstance) )
447 {
448 wxLogLastError(wxT("UnregisterClass(canvas)"));
449
450 retval = false;
451 }
452
453 if ( !::UnregisterClass(wxCanvasClassNameNR, wxhInstance) )
454 {
455 wxLogLastError(wxT("UnregisterClass(no redraw canvas)"));
456
457 retval = false;
458 }
459 #endif // __WXMICROWIN__
460
461 return retval;
462 }
463
464 void wxApp::CleanUp()
465 {
466 // all objects pending for deletion must be deleted first, otherwise we
467 // would crash when they use wxWinHandleHash (and UnregisterWindowClasses()
468 // call wouldn't succeed as long as any windows still exist), so call the
469 // base class method first and only then do our clean up
470 wxAppBase::CleanUp();
471
472 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
473 wxSetKeyboardHook(false);
474 #endif
475
476 #if wxUSE_PENWINDOWS
477 wxCleanUpPenWin();
478 #endif
479
480 wxOleUninitialize();
481
482 // for an EXE the classes are unregistered when it terminates but DLL may
483 // be loaded several times (load/unload/load) into the same process in
484 // which case the registration will fail after the first time if we don't
485 // unregister the classes now
486 UnregisterWindowClasses();
487
488 delete wxWinHandleHash;
489 wxWinHandleHash = NULL;
490
491 #ifdef __WXWINCE__
492 free( wxCanvasClassName );
493 free( wxCanvasClassNameNR );
494 #endif
495 }
496
497 // ----------------------------------------------------------------------------
498 // wxApp ctor/dtor
499 // ----------------------------------------------------------------------------
500
501 wxApp::wxApp()
502 {
503 m_printMode = wxPRINT_WINDOWS;
504 }
505
506 wxApp::~wxApp()
507 {
508 // our cmd line arguments are allocated inside wxEntry(HINSTANCE), they
509 // don't come from main(), so we have to free them
510
511 while ( argc )
512 {
513 // m_argv elements were allocated by wxStrdup()
514 free(argv[--argc]);
515 }
516
517 // but m_argv itself -- using new[]
518 delete [] argv;
519 }
520
521 // ----------------------------------------------------------------------------
522 // wxApp idle handling
523 // ----------------------------------------------------------------------------
524
525 void wxApp::OnIdle(wxIdleEvent& event)
526 {
527 wxAppBase::OnIdle(event);
528
529 #if wxUSE_DC_CACHEING
530 // automated DC cache management: clear the cached DCs and bitmap
531 // if it's likely that the app has finished with them, that is, we
532 // get an idle event and we're not dragging anything.
533 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
534 wxDC::ClearCache();
535 #endif // wxUSE_DC_CACHEING
536 }
537
538 void wxApp::WakeUpIdle()
539 {
540 // Send the top window a dummy message so idle handler processing will
541 // start up again. Doing it this way ensures that the idle handler
542 // wakes up in the right thread (see also wxWakeUpMainThread() which does
543 // the same for the main app thread only)
544 wxWindow *topWindow = wxTheApp->GetTopWindow();
545 if ( topWindow )
546 {
547 if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
548 {
549 // should never happen
550 wxLogLastError(wxT("PostMessage(WM_NULL)"));
551 }
552 }
553 }
554
555 // ----------------------------------------------------------------------------
556 // other wxApp event hanlders
557 // ----------------------------------------------------------------------------
558
559 void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
560 {
561 if (GetTopWindow())
562 GetTopWindow()->Close(true);
563 }
564
565 // Default behaviour: close the application with prompts. The
566 // user can veto the close, and therefore the end session.
567 void wxApp::OnQueryEndSession(wxCloseEvent& event)
568 {
569 if (GetTopWindow())
570 {
571 if (!GetTopWindow()->Close(!event.CanVeto()))
572 event.Veto(true);
573 }
574 }
575
576 // ----------------------------------------------------------------------------
577 // miscellaneous
578 // ----------------------------------------------------------------------------
579
580 /* static */
581 int wxApp::GetComCtl32Version()
582 {
583 #if defined(__WXMICROWIN__) || defined(__WXWINCE__)
584 return 0;
585 #else
586 // cache the result
587 //
588 // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice,
589 // but as its value should be the same both times it doesn't matter
590 static int s_verComCtl32 = -1;
591
592 if ( s_verComCtl32 == -1 )
593 {
594 // initally assume no comctl32.dll at all
595 s_verComCtl32 = 0;
596
597 // we're prepared to handle the errors
598 wxLogNull noLog;
599
600 // do we have it?
601 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
602
603 // if so, then we can check for the version
604 if ( dllComCtl32.IsLoaded() )
605 {
606 #ifdef DLLVER_PLATFORM_WINDOWS
607 // try to use DllGetVersion() if available in _headers_
608 wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 );
609 if ( pfnDllGetVersion )
610 {
611 DLLVERSIONINFO dvi;
612 dvi.cbSize = sizeof(dvi);
613
614 HRESULT hr = (*pfnDllGetVersion)(&dvi);
615 if ( FAILED(hr) )
616 {
617 wxLogApiError(_T("DllGetVersion"), hr);
618 }
619 else
620 {
621 // this is incompatible with _WIN32_IE values, but
622 // compatible with the other values returned by
623 // GetComCtl32Version()
624 s_verComCtl32 = 100*dvi.dwMajorVersion +
625 dvi.dwMinorVersion;
626 }
627 }
628 #endif
629
630 // if DllGetVersion() is unavailable either during compile or
631 // run-time, try to guess the version otherwise
632 if ( !s_verComCtl32 )
633 {
634 // InitCommonControlsEx is unique to 4.70 and later
635 void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx"));
636 if ( !pfn )
637 {
638 // not found, must be 4.00
639 s_verComCtl32 = 400;
640 }
641 else // 4.70+
642 {
643 // many symbols appeared in comctl32 4.71, could use any of
644 // them except may be DllInstall()
645 pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB"));
646 if ( !pfn )
647 {
648 // not found, must be 4.70
649 s_verComCtl32 = 470;
650 }
651 else
652 {
653 // found, must be 4.71 or later
654 s_verComCtl32 = 471;
655 }
656 }
657 }
658 }
659 }
660
661 return s_verComCtl32;
662 #endif // Microwin/!Microwin
663 }
664
665 // Yield to incoming messages
666
667 bool wxApp::Yield(bool onlyIfNeeded)
668 {
669 // MT-FIXME
670 static bool s_inYield = false;
671
672 #if wxUSE_LOG
673 // disable log flushing from here because a call to wxYield() shouldn't
674 // normally result in message boxes popping up &c
675 wxLog::Suspend();
676 #endif // wxUSE_LOG
677
678 if ( s_inYield )
679 {
680 if ( !onlyIfNeeded )
681 {
682 wxFAIL_MSG( wxT("wxYield called recursively" ) );
683 }
684
685 return false;
686 }
687
688 s_inYield = true;
689
690 // we don't want to process WM_QUIT from here - it should be processed in
691 // the main event loop in order to stop it
692 MSG msg;
693 while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
694 msg.message != WM_QUIT )
695 {
696 #if wxUSE_THREADS
697 wxMutexGuiLeaveOrEnter();
698 #endif // wxUSE_THREADS
699
700 if ( !wxTheApp->Dispatch() )
701 break;
702 }
703
704 // if there are pending events, we must process them.
705 ProcessPendingEvents();
706
707 #if wxUSE_LOG
708 // let the logs be flashed again
709 wxLog::Resume();
710 #endif // wxUSE_LOG
711
712 s_inYield = false;
713
714 return true;
715 }
716
717 #if wxUSE_EXCEPTIONS
718
719 // ----------------------------------------------------------------------------
720 // exception handling
721 // ----------------------------------------------------------------------------
722
723 bool wxApp::OnExceptionInMainLoop()
724 {
725 // ask the user about what to do: use the Win32 API function here as it
726 // could be dangerous to use any wxWidgets code in this state
727 switch (
728 ::MessageBox
729 (
730 NULL,
731 _T("An unhandled exception occurred. Press \"Abort\" to \
732 terminate the program,\r\n\
733 \"Retry\" to exit the program normally and \"Ignore\" to try to continue."),
734 _T("Unhandled exception"),
735 MB_ABORTRETRYIGNORE |
736 MB_ICONERROR|
737 MB_TASKMODAL
738 )
739 )
740 {
741 case IDABORT:
742 throw;
743
744 default:
745 wxFAIL_MSG( _T("unexpected MessageBox() return code") );
746 // fall through
747
748 case IDRETRY:
749 return false;
750
751 case IDIGNORE:
752 return true;
753 }
754 }
755
756 #endif // wxUSE_EXCEPTIONS
757
758 // ----------------------------------------------------------------------------
759 // deprecated event loop functions
760 // ----------------------------------------------------------------------------
761
762 #if WXWIN_COMPATIBILITY_2_4
763
764 #include "wx/evtloop.h"
765
766 void wxApp::DoMessage(WXMSG *pMsg)
767 {
768 wxEventLoop *evtLoop = wxEventLoop::GetActive();
769 if ( evtLoop )
770 evtLoop->ProcessMessage(pMsg);
771 }
772
773 bool wxApp::DoMessage()
774 {
775 wxEventLoop *evtLoop = wxEventLoop::GetActive();
776 return evtLoop ? evtLoop->Dispatch() : false;
777 }
778
779 bool wxApp::ProcessMessage(WXMSG* pMsg)
780 {
781 wxEventLoop *evtLoop = wxEventLoop::GetActive();
782 return evtLoop && evtLoop->PreProcessMessage(pMsg);
783 }
784
785 #endif // WXWIN_COMPATIBILITY_2_4
786