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