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