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