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