]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
WinCE fixes
[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
afafd942
JS
71#if defined(__POCKETPC__) || defined(__SMARTPHONE__)
72#include <aygshell.h>
73#endif
74
e5c0b16a 75#if wxUSE_OLE
6e0d9d43 76 #include <ole2.h>
d05237ea 77#endif
ce3ed50d 78
2bda0e17 79#include <string.h>
a5e0e655 80#include <ctype.h>
2bda0e17 81
0d236fd0 82#include "wx/msw/wrapcctl.h"
bdc72a22 83
6046e57a
VZ
84// For MB_TASKMODAL
85#ifdef __WXWINCE__
86#include "wx/msw/wince/missing.h"
87#endif
88
238a6044
JS
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
e5c0b16a
VZ
96// ---------------------------------------------------------------------------
97// global variables
98// ---------------------------------------------------------------------------
99
cde9f08e 100extern wxList WXDLLEXPORT wxPendingDelete;
4676948b
JS
101
102#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2bda0e17 103extern void wxSetKeyboardHook(bool doIt);
04ef50df 104#endif
2bda0e17 105
193fe989
VZ
106// NB: all "NoRedraw" classes must have the same names as the "normal" classes
107// with NR suffix - wxWindow::MSWCreate() supposes this
46fa338b 108#ifdef __WXWINCE__
7a4d2469
RN
109WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
110WXDLLIMPEXP_CORE wxChar *wxCanvasClassNameNR;
46fa338b 111#else
7a4d2469
RN
112WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName = wxT("wxWindowClass");
113WXDLLIMPEXP_CORE const wxChar *wxCanvasClassNameNR = wxT("wxWindowClassNR");
46fa338b 114#endif
7a4d2469
RN
115WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassName = wxT("wxMDIFrameClass");
116WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassNameNoRedraw = wxT("wxMDIFrameClassNR");
117WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
118WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
2bda0e17 119
94826170
VZ
120// ----------------------------------------------------------------------------
121// private functions
122// ----------------------------------------------------------------------------
2bda0e17 123
94826170 124LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
3b415ba4 125
e5c0b16a 126// ===========================================================================
e2478fde
VZ
127// wxGUIAppTraits implementation
128// ===========================================================================
129
130// private class which we use to pass parameters from BeforeChildWaitLoop() to
131// AfterChildWaitLoop()
132struct 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
144void *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(),
fda7962d
JS
172 wxID_ANY,
173 wxEmptyString,
e2478fde
VZ
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
183void wxGUIAppTraits::AlwaysYield()
184{
185 wxYield();
186}
187
188void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig)
189{
190 wxEndBusyCursor();
191
0588f8d7 192 ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig;
e2478fde
VZ
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();
51036b44
VZ
200
201 // also delete the temporary data object itself
202 delete data;
e2478fde
VZ
203}
204
205bool wxGUIAppTraits::DoMessageFromThreadWait()
206{
1bf77ee5
VZ
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();
e2478fde
VZ
210}
211
324899f6 212wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
a8eaaeb2 213{
1bf77ee5 214 static wxToolkitInfo info;
324899f6
VS
215 wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo();
216 info.versionMajor = baseInfo.versionMajor;
217 info.versionMinor = baseInfo.versionMinor;
218 info.os = baseInfo.os;
a8eaaeb2
VS
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
324899f6 225 return info;
a8eaaeb2
VS
226}
227
e2478fde
VZ
228// ===========================================================================
229// wxApp implementation
e5c0b16a 230// ===========================================================================
589f0e3e 231
94826170
VZ
232int wxApp::m_nCmdShow = SW_SHOWNORMAL;
233
e5c0b16a 234// ---------------------------------------------------------------------------
e2478fde 235// wxWin macros
e5c0b16a
VZ
236// ---------------------------------------------------------------------------
237
f6bcfd97 238IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
e5c0b16a 239
f6bcfd97
BP
240BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
241 EVT_IDLE(wxApp::OnIdle)
242 EVT_END_SESSION(wxApp::OnEndSession)
243 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
244END_EVENT_TABLE()
e5c0b16a 245
94826170
VZ
246// class to ensure that wxAppBase::CleanUp() is called if our Initialize()
247// fails
248class wxCallBaseCleanup
249{
250public:
251 wxCallBaseCleanup(wxApp *app) : m_app(app) { }
252 ~wxCallBaseCleanup() { if ( m_app ) m_app->wxAppBase::CleanUp(); }
253
254 void Dismiss() { m_app = NULL; }
255
256private:
257 wxApp *m_app;
258};
259
e5c0b16a 260//// Initialize
05e2b077 261bool wxApp::Initialize(int& argc, wxChar **argv)
2bda0e17 262{
94826170
VZ
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
46fa338b
RR
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
f6bcfd97 283 // the first thing to do is to check if we're trying to run an Unicode
7c9955d1 284 // program under Win9x w/o MSLU emulation layer - if so, abort right now
dfc40ef3 285 // as it has no chance to work
eb5e4d9a 286#if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
c75d190a 287 if ( wxGetOsVersion() != wxWINDOWS_NT && wxGetOsVersion() != wxWINDOWS_CE && wxGetOsVersion() != wxWINDOWS_SMARTPHONE && wxGetOsVersion() != wxWINDOWS_POCKETPC )
f6bcfd97
BP
288 {
289 // note that we can use MessageBoxW() as it's implemented even under
290 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
291 // used by wxLocale are not
292 ::MessageBox
293 (
294 NULL,
f07dc2e2 295 _T("This program uses Unicode and requires Windows NT/2000/XP/CE.\nProgram aborted."),
77ffb593 296 _T("wxWidgets Fatal Error"),
f6bcfd97
BP
297 MB_ICONERROR | MB_OK
298 );
299
77c46f00 300 return false;
f6bcfd97 301 }
eb5e4d9a 302#endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
f6bcfd97 303
04ef50df 304#if defined(__WIN95__) && !defined(__WXMICROWIN__)
a5e0e655 305 InitCommonControls();
e5c0b16a 306#endif // __WIN95__
2bda0e17 307
afafd942
JS
308#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
309 SHInitExtraControls();
310#endif
311
360ae33f 312 wxOleInitialize();
2bda0e17 313
aa0b7e1e 314 RegisterWindowClasses();
2bda0e17 315
aa0b7e1e 316#if wxUSE_PENWINDOWS
a5e0e655 317 wxRegisterPenWin();
aa0b7e1e 318#endif
2bda0e17 319
1bffa913 320 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
2bda0e17 321
4676948b 322#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 323 wxSetKeyboardHook(true);
04ef50df 324#endif
2bda0e17 325
94826170
VZ
326 callBaseCleanup.Dismiss();
327
328 return true;
2bda0e17
KB
329}
330
42e69d6b
VZ
331// ---------------------------------------------------------------------------
332// RegisterWindowClasses
333// ---------------------------------------------------------------------------
589f0e3e 334
b782f2e0
VZ
335// TODO we should only register classes really used by the app. For this it
336// would be enough to just delay the class registration until an attempt
337// to create a window of this class is made.
bb6290e3 338bool wxApp::RegisterWindowClasses()
2bda0e17 339{
42e69d6b 340 WNDCLASS wndclass;
03baf031 341 wxZeroMemory(wndclass);
e5c0b16a 342
193fe989
VZ
343 // for each class we register one with CS_(V|H)REDRAW style and one
344 // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
345 static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
346 static const long styleNoRedraw = CS_DBLCLKS;
347
42e69d6b 348 // the fields which are common to all classes
e5c0b16a 349 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
e5c0b16a 350 wndclass.hInstance = wxhInstance;
42e69d6b 351 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
42e69d6b 352
b9691677
VZ
353 // register the class for all normal windows
354 wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
03baf031 355 wndclass.lpszClassName = wxCanvasClassName;
b782f2e0 356 wndclass.style = styleNormal;
e5c0b16a 357
42e69d6b 358 if ( !RegisterClass(&wndclass) )
e5c0b16a 359 {
f6bcfd97 360 wxLogLastError(wxT("RegisterClass(frame)"));
e5c0b16a
VZ
361 }
362
193fe989 363 // "no redraw" frame
03baf031 364 wndclass.lpszClassName = wxCanvasClassNameNR;
193fe989
VZ
365 wndclass.style = styleNoRedraw;
366
367 if ( !RegisterClass(&wndclass) )
368 {
f6bcfd97 369 wxLogLastError(wxT("RegisterClass(no redraw frame)"));
193fe989
VZ
370 }
371
e5c0b16a 372 // Register the MDI frame window class.
42e69d6b 373 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
b782f2e0
VZ
374 wndclass.lpszClassName = wxMDIFrameClassName;
375 wndclass.style = styleNormal;
42e69d6b
VZ
376
377 if ( !RegisterClass(&wndclass) )
e5c0b16a 378 {
f6bcfd97 379 wxLogLastError(wxT("RegisterClass(MDI parent)"));
e5c0b16a
VZ
380 }
381
193fe989 382 // "no redraw" MDI frame
b782f2e0 383 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
193fe989
VZ
384 wndclass.style = styleNoRedraw;
385
386 if ( !RegisterClass(&wndclass) )
387 {
f6bcfd97 388 wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)"));
193fe989
VZ
389 }
390
e5c0b16a 391 // Register the MDI child frame window class.
42e69d6b
VZ
392 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
393 wndclass.lpszClassName = wxMDIChildFrameClassName;
b782f2e0 394 wndclass.style = styleNormal;
42e69d6b
VZ
395
396 if ( !RegisterClass(&wndclass) )
e5c0b16a 397 {
f6bcfd97 398 wxLogLastError(wxT("RegisterClass(MDI child)"));
e5c0b16a
VZ
399 }
400
193fe989
VZ
401 // "no redraw" MDI child frame
402 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
403 wndclass.style = styleNoRedraw;
404
405 if ( !RegisterClass(&wndclass) )
406 {
f6bcfd97 407 wxLogLastError(wxT("RegisterClass(no redraw MDI child)"));
193fe989
VZ
408 }
409
77c46f00 410 return true;
2bda0e17
KB
411}
412
9787a4b6
VZ
413// ---------------------------------------------------------------------------
414// UnregisterWindowClasses
415// ---------------------------------------------------------------------------
416
417bool wxApp::UnregisterWindowClasses()
418{
77c46f00 419 bool retval = true;
9787a4b6 420
c67d6888 421#ifndef __WXMICROWIN__
9787a4b6 422 // MDI frame window class.
03baf031 423 if ( !::UnregisterClass(wxMDIFrameClassName, wxhInstance) )
9787a4b6
VZ
424 {
425 wxLogLastError(wxT("UnregisterClass(MDI parent)"));
426
77c46f00 427 retval = false;
9787a4b6
VZ
428 }
429
430 // "no redraw" MDI frame
03baf031 431 if ( !::UnregisterClass(wxMDIFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
432 {
433 wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)"));
434
77c46f00 435 retval = false;
9787a4b6
VZ
436 }
437
438 // MDI child frame window class.
03baf031 439 if ( !::UnregisterClass(wxMDIChildFrameClassName, wxhInstance) )
9787a4b6
VZ
440 {
441 wxLogLastError(wxT("UnregisterClass(MDI child)"));
442
77c46f00 443 retval = false;
9787a4b6
VZ
444 }
445
446 // "no redraw" MDI child frame
03baf031 447 if ( !::UnregisterClass(wxMDIChildFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
448 {
449 wxLogLastError(wxT("UnregisterClass(no redraw MDI child)"));
450
77c46f00 451 retval = false;
9787a4b6
VZ
452 }
453
03baf031
VZ
454 // canvas class name
455 if ( !::UnregisterClass(wxCanvasClassName, wxhInstance) )
9787a4b6
VZ
456 {
457 wxLogLastError(wxT("UnregisterClass(canvas)"));
458
77c46f00 459 retval = false;
9787a4b6
VZ
460 }
461
03baf031 462 if ( !::UnregisterClass(wxCanvasClassNameNR, wxhInstance) )
9787a4b6
VZ
463 {
464 wxLogLastError(wxT("UnregisterClass(no redraw canvas)"));
465
77c46f00 466 retval = false;
9787a4b6 467 }
03baf031
VZ
468#endif // __WXMICROWIN__
469
9787a4b6
VZ
470 return retval;
471}
472
bb6290e3 473void wxApp::CleanUp()
2bda0e17 474{
7a9dfa3c
VZ
475 // all objects pending for deletion must be deleted first, otherwise we
476 // would crash when they use wxWinHandleHash (and UnregisterWindowClasses()
477 // call wouldn't succeed as long as any windows still exist), so call the
478 // base class method first and only then do our clean up
479 wxAppBase::CleanUp();
480
4676948b 481#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 482 wxSetKeyboardHook(false);
04ef50df 483#endif
2bda0e17 484
47d67540 485#if wxUSE_PENWINDOWS
e5c0b16a 486 wxCleanUpPenWin();
2bda0e17
KB
487#endif
488
360ae33f 489 wxOleUninitialize();
2bda0e17 490
9787a4b6
VZ
491 // for an EXE the classes are unregistered when it terminates but DLL may
492 // be loaded several times (load/unload/load) into the same process in
493 // which case the registration will fail after the first time if we don't
494 // unregister the classes now
495 UnregisterWindowClasses();
9787a4b6 496
1bffa913 497 delete wxWinHandleHash;
94826170 498 wxWinHandleHash = NULL;
46fa338b
RR
499
500#ifdef __WXWINCE__
501 free( wxCanvasClassName );
502 free( wxCanvasClassNameNR );
503#endif
2bda0e17
KB
504}
505
94826170
VZ
506// ----------------------------------------------------------------------------
507// wxApp ctor/dtor
508// ----------------------------------------------------------------------------
589f0e3e 509
bb6290e3 510wxApp::wxApp()
2bda0e17 511{
e5c0b16a 512 m_printMode = wxPRINT_WINDOWS;
2bda0e17
KB
513}
514
589f0e3e
JS
515wxApp::~wxApp()
516{
94826170
VZ
517 // our cmd line arguments are allocated inside wxEntry(HINSTANCE), they
518 // don't come from main(), so we have to free them
519
520 while ( argc )
e5c0b16a 521 {
94826170
VZ
522 // m_argv elements were allocated by wxStrdup()
523 free(argv[--argc]);
e5c0b16a 524 }
94826170
VZ
525
526 // but m_argv itself -- using new[]
527 delete [] argv;
589f0e3e
JS
528}
529
6046e57a
VZ
530// ----------------------------------------------------------------------------
531// wxApp idle handling
532// ----------------------------------------------------------------------------
533
2bda0e17
KB
534void wxApp::OnIdle(wxIdleEvent& event)
535{
955a9197 536 wxAppBase::OnIdle(event);
c54f78a2 537
aef94d68
JS
538#if wxUSE_DC_CACHEING
539 // automated DC cache management: clear the cached DCs and bitmap
540 // if it's likely that the app has finished with them, that is, we
541 // get an idle event and we're not dragging anything.
4624defa 542 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
aef94d68
JS
543 wxDC::ClearCache();
544#endif // wxUSE_DC_CACHEING
2bda0e17
KB
545}
546
e2478fde
VZ
547void wxApp::WakeUpIdle()
548{
549 // Send the top window a dummy message so idle handler processing will
550 // start up again. Doing it this way ensures that the idle handler
551 // wakes up in the right thread (see also wxWakeUpMainThread() which does
552 // the same for the main app thread only)
553 wxWindow *topWindow = wxTheApp->GetTopWindow();
554 if ( topWindow )
555 {
556 if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
557 {
558 // should never happen
559 wxLogLastError(wxT("PostMessage(WM_NULL)"));
560 }
561 }
562}
563
6046e57a
VZ
564// ----------------------------------------------------------------------------
565// other wxApp event hanlders
566// ----------------------------------------------------------------------------
567
57c208c5 568void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
569{
570 if (GetTopWindow())
77c46f00 571 GetTopWindow()->Close(true);
387a3b02
JS
572}
573
574// Default behaviour: close the application with prompts. The
575// user can veto the close, and therefore the end session.
576void wxApp::OnQueryEndSession(wxCloseEvent& event)
577{
578 if (GetTopWindow())
579 {
580 if (!GetTopWindow()->Close(!event.CanVeto()))
77c46f00 581 event.Veto(true);
387a3b02
JS
582 }
583}
584
6046e57a
VZ
585// ----------------------------------------------------------------------------
586// miscellaneous
587// ----------------------------------------------------------------------------
588
6d167489
VZ
589/* static */
590int wxApp::GetComCtl32Version()
591{
fd7b70bd 592#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
04ef50df
JS
593 return 0;
594#else
6d167489 595 // cache the result
9fc6c21c
VZ
596 //
597 // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice,
598 // but as its value should be the same both times it doesn't matter
bdc72a22
VZ
599 static int s_verComCtl32 = -1;
600
6d167489
VZ
601 if ( s_verComCtl32 == -1 )
602 {
bdc72a22 603 // initally assume no comctl32.dll at all
6d167489
VZ
604 s_verComCtl32 = 0;
605
9fc6c21c
VZ
606 // we're prepared to handle the errors
607 wxLogNull noLog;
608
bdc72a22 609 // do we have it?
9fc6c21c 610 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
6d167489
VZ
611
612 // if so, then we can check for the version
9fc6c21c 613 if ( dllComCtl32.IsLoaded() )
bb6290e3 614 {
f1189604
JS
615#ifndef DLLVER_PLATFORM_WINDOWS
616 typedef struct _DllVersionInfo
617 {
618 DWORD cbSize;
619 DWORD dwMajorVersion; // Major version
620 DWORD dwMinorVersion; // Minor version
621 DWORD dwBuildNumber; // Build number
622 DWORD dwPlatformID; // DLLVER_PLATFORM_*
623 } DLLVERSIONINFO;
624 typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
625#endif
bdc72a22 626 // try to use DllGetVersion() if available in _headers_
9fc6c21c
VZ
627 wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 );
628 if ( pfnDllGetVersion )
629 {
630 DLLVERSIONINFO dvi;
631 dvi.cbSize = sizeof(dvi);
632
633 HRESULT hr = (*pfnDllGetVersion)(&dvi);
634 if ( FAILED(hr) )
6d167489 635 {
9fc6c21c
VZ
636 wxLogApiError(_T("DllGetVersion"), hr);
637 }
638 else
639 {
640 // this is incompatible with _WIN32_IE values, but
641 // compatible with the other values returned by
642 // GetComCtl32Version()
643 s_verComCtl32 = 100*dvi.dwMajorVersion +
644 dvi.dwMinorVersion;
645 }
646 }
bdc72a22 647
9fc6c21c
VZ
648 // if DllGetVersion() is unavailable either during compile or
649 // run-time, try to guess the version otherwise
650 if ( !s_verComCtl32 )
651 {
652 // InitCommonControlsEx is unique to 4.70 and later
653 void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx"));
654 if ( !pfn )
655 {
656 // not found, must be 4.00
657 s_verComCtl32 = 400;
6d167489 658 }
9fc6c21c 659 else // 4.70+
bdc72a22 660 {
9fc6c21c
VZ
661 // many symbols appeared in comctl32 4.71, could use any of
662 // them except may be DllInstall()
663 pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB"));
664 if ( !pfn )
bdc72a22 665 {
9fc6c21c
VZ
666 // not found, must be 4.70
667 s_verComCtl32 = 470;
bdc72a22
VZ
668 }
669 else
670 {
9fc6c21c
VZ
671 // found, must be 4.71 or later
672 s_verComCtl32 = 471;
bdc72a22 673 }
6d167489 674 }
9fc6c21c 675 }
ef094fa0 676 }
bb6290e3 677 }
6d167489
VZ
678
679 return s_verComCtl32;
9fc6c21c 680#endif // Microwin/!Microwin
bb6290e3
JS
681}
682
2bda0e17 683// Yield to incoming messages
cb2713bf 684
8461e4c2 685bool wxApp::Yield(bool onlyIfNeeded)
2bda0e17 686{
8461e4c2 687 // MT-FIXME
77c46f00 688 static bool s_inYield = false;
8461e4c2 689
e30285ab 690#if wxUSE_LOG
2ed3265e
VZ
691 // disable log flushing from here because a call to wxYield() shouldn't
692 // normally result in message boxes popping up &c
693 wxLog::Suspend();
e30285ab 694#endif // wxUSE_LOG
2ed3265e 695
8461e4c2
VZ
696 if ( s_inYield )
697 {
698 if ( !onlyIfNeeded )
699 {
700 wxFAIL_MSG( wxT("wxYield called recursively" ) );
701 }
33ac7e6f 702
77c46f00 703 return false;
8461e4c2
VZ
704 }
705
77c46f00 706 s_inYield = true;
cb2713bf 707
8e193f38
VZ
708 // we don't want to process WM_QUIT from here - it should be processed in
709 // the main event loop in order to stop it
e5c0b16a 710 MSG msg;
8e193f38
VZ
711 while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
712 msg.message != WM_QUIT )
e5c0b16a 713 {
5b615ed8
VZ
714#if wxUSE_THREADS
715 wxMutexGuiLeaveOrEnter();
716#endif // wxUSE_THREADS
717
1bf77ee5 718 if ( !wxTheApp->Dispatch() )
e5c0b16a
VZ
719 break;
720 }
8e193f38 721
8461e4c2
VZ
722 // if there are pending events, we must process them.
723 ProcessPendingEvents();
e5c0b16a 724
e30285ab 725#if wxUSE_LOG
2ed3265e
VZ
726 // let the logs be flashed again
727 wxLog::Resume();
e30285ab 728#endif // wxUSE_LOG
2ed3265e 729
77c46f00 730 s_inYield = false;
cb2713bf 731
77c46f00 732 return true;
2bda0e17 733}
094637f6 734
6046e57a
VZ
735#if wxUSE_EXCEPTIONS
736
737// ----------------------------------------------------------------------------
738// exception handling
739// ----------------------------------------------------------------------------
740
741bool wxApp::OnExceptionInMainLoop()
742{
743 // ask the user about what to do: use the Win32 API function here as it
77ffb593 744 // could be dangerous to use any wxWidgets code in this state
6046e57a
VZ
745 switch (
746 ::MessageBox
747 (
748 NULL,
749 _T("An unhandled exception occurred. Press \"Abort\" to \
750terminate the program,\r\n\
751\"Retry\" to exit the program normally and \"Ignore\" to try to continue."),
752 _T("Unhandled exception"),
753 MB_ABORTRETRYIGNORE |
754 MB_ICONERROR|
755 MB_TASKMODAL
756 )
757 )
758 {
759 case IDABORT:
760 throw;
761
762 default:
763 wxFAIL_MSG( _T("unexpected MessageBox() return code") );
764 // fall through
765
766 case IDRETRY:
767 return false;
768
769 case IDIGNORE:
770 return true;
771 }
772}
773
774#endif // wxUSE_EXCEPTIONS
51036b44
VZ
775
776// ----------------------------------------------------------------------------
777// deprecated event loop functions
778// ----------------------------------------------------------------------------
779
780#if WXWIN_COMPATIBILITY_2_4
781
782#include "wx/evtloop.h"
783
784void wxApp::DoMessage(WXMSG *pMsg)
785{
786 wxEventLoop *evtLoop = wxEventLoop::GetActive();
787 if ( evtLoop )
788 evtLoop->ProcessMessage(pMsg);
789}
790
791bool wxApp::DoMessage()
792{
793 wxEventLoop *evtLoop = wxEventLoop::GetActive();
794 return evtLoop ? evtLoop->Dispatch() : false;
795}
796
797bool wxApp::ProcessMessage(WXMSG* pMsg)
798{
799 wxEventLoop *evtLoop = wxEventLoop::GetActive();
800 return evtLoop && evtLoop->PreProcessMessage(pMsg);
801}
802
803#endif // WXWIN_COMPATIBILITY_2_4
804