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