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