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