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