]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
adding support for wxCB_SORT, SetString and Insert
[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
e5c0b16a
VZ
89// ---------------------------------------------------------------------------
90// global variables
91// ---------------------------------------------------------------------------
92
cde9f08e 93extern wxList WXDLLEXPORT wxPendingDelete;
4676948b
JS
94
95#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2bda0e17 96extern void wxSetKeyboardHook(bool doIt);
04ef50df 97#endif
2bda0e17 98
193fe989
VZ
99// NB: all "NoRedraw" classes must have the same names as the "normal" classes
100// with NR suffix - wxWindow::MSWCreate() supposes this
46fa338b 101#ifdef __WXWINCE__
7a4d2469
RN
102WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
103WXDLLIMPEXP_CORE wxChar *wxCanvasClassNameNR;
46fa338b 104#else
7a4d2469
RN
105WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName = wxT("wxWindowClass");
106WXDLLIMPEXP_CORE const wxChar *wxCanvasClassNameNR = wxT("wxWindowClassNR");
46fa338b 107#endif
7a4d2469
RN
108WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassName = wxT("wxMDIFrameClass");
109WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassNameNoRedraw = wxT("wxMDIFrameClassNR");
110WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
111WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
2bda0e17 112
94826170
VZ
113// ----------------------------------------------------------------------------
114// private functions
115// ----------------------------------------------------------------------------
2bda0e17 116
94826170 117LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
3b415ba4 118
e5c0b16a 119// ===========================================================================
e2478fde
VZ
120// wxGUIAppTraits implementation
121// ===========================================================================
122
123// private class which we use to pass parameters from BeforeChildWaitLoop() to
124// AfterChildWaitLoop()
125struct 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
137void *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(),
fda7962d
JS
165 wxID_ANY,
166 wxEmptyString,
e2478fde
VZ
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
176void wxGUIAppTraits::AlwaysYield()
177{
178 wxYield();
179}
180
181void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig)
182{
183 wxEndBusyCursor();
184
0588f8d7 185 ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig;
e2478fde
VZ
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();
51036b44
VZ
193
194 // also delete the temporary data object itself
195 delete data;
e2478fde
VZ
196}
197
198bool wxGUIAppTraits::DoMessageFromThreadWait()
199{
1bf77ee5
VZ
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();
e2478fde
VZ
203}
204
324899f6 205wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
a8eaaeb2 206{
1bf77ee5 207 static wxToolkitInfo info;
324899f6
VS
208 wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo();
209 info.versionMajor = baseInfo.versionMajor;
210 info.versionMinor = baseInfo.versionMinor;
211 info.os = baseInfo.os;
a8eaaeb2
VS
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
324899f6 218 return info;
a8eaaeb2
VS
219}
220
e2478fde
VZ
221// ===========================================================================
222// wxApp implementation
e5c0b16a 223// ===========================================================================
589f0e3e 224
94826170
VZ
225int wxApp::m_nCmdShow = SW_SHOWNORMAL;
226
e5c0b16a 227// ---------------------------------------------------------------------------
e2478fde 228// wxWin macros
e5c0b16a
VZ
229// ---------------------------------------------------------------------------
230
f6bcfd97 231IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
e5c0b16a 232
f6bcfd97
BP
233BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
234 EVT_IDLE(wxApp::OnIdle)
235 EVT_END_SESSION(wxApp::OnEndSession)
236 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
237END_EVENT_TABLE()
e5c0b16a 238
94826170
VZ
239// class to ensure that wxAppBase::CleanUp() is called if our Initialize()
240// fails
241class wxCallBaseCleanup
242{
243public:
244 wxCallBaseCleanup(wxApp *app) : m_app(app) { }
245 ~wxCallBaseCleanup() { if ( m_app ) m_app->wxAppBase::CleanUp(); }
246
247 void Dismiss() { m_app = NULL; }
248
249private:
250 wxApp *m_app;
251};
252
e5c0b16a 253//// Initialize
05e2b077 254bool wxApp::Initialize(int& argc, wxChar **argv)
2bda0e17 255{
94826170
VZ
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
46fa338b
RR
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
f6bcfd97 276 // the first thing to do is to check if we're trying to run an Unicode
7c9955d1 277 // program under Win9x w/o MSLU emulation layer - if so, abort right now
dfc40ef3 278 // as it has no chance to work
eb5e4d9a 279#if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
c75d190a 280 if ( wxGetOsVersion() != wxWINDOWS_NT && wxGetOsVersion() != wxWINDOWS_CE && wxGetOsVersion() != wxWINDOWS_SMARTPHONE && wxGetOsVersion() != wxWINDOWS_POCKETPC )
f6bcfd97
BP
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,
f07dc2e2 288 _T("This program uses Unicode and requires Windows NT/2000/XP/CE.\nProgram aborted."),
77ffb593 289 _T("wxWidgets Fatal Error"),
f6bcfd97
BP
290 MB_ICONERROR | MB_OK
291 );
292
77c46f00 293 return false;
f6bcfd97 294 }
eb5e4d9a 295#endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
f6bcfd97 296
04ef50df 297#if defined(__WIN95__) && !defined(__WXMICROWIN__)
a5e0e655 298 InitCommonControls();
e5c0b16a 299#endif // __WIN95__
2bda0e17 300
afafd942
JS
301#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
302 SHInitExtraControls();
303#endif
304
360ae33f 305 wxOleInitialize();
2bda0e17 306
aa0b7e1e 307 RegisterWindowClasses();
2bda0e17 308
aa0b7e1e 309#if wxUSE_PENWINDOWS
a5e0e655 310 wxRegisterPenWin();
aa0b7e1e 311#endif
2bda0e17 312
1bffa913 313 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
2bda0e17 314
4676948b 315#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 316 wxSetKeyboardHook(true);
04ef50df 317#endif
2bda0e17 318
94826170
VZ
319 callBaseCleanup.Dismiss();
320
321 return true;
2bda0e17
KB
322}
323
42e69d6b
VZ
324// ---------------------------------------------------------------------------
325// RegisterWindowClasses
326// ---------------------------------------------------------------------------
589f0e3e 327
b782f2e0
VZ
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.
bb6290e3 331bool wxApp::RegisterWindowClasses()
2bda0e17 332{
42e69d6b 333 WNDCLASS wndclass;
03baf031 334 wxZeroMemory(wndclass);
e5c0b16a 335
193fe989
VZ
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
42e69d6b 341 // the fields which are common to all classes
e5c0b16a 342 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
e5c0b16a 343 wndclass.hInstance = wxhInstance;
42e69d6b 344 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
42e69d6b 345
b9691677
VZ
346 // register the class for all normal windows
347 wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
03baf031 348 wndclass.lpszClassName = wxCanvasClassName;
b782f2e0 349 wndclass.style = styleNormal;
e5c0b16a 350
42e69d6b 351 if ( !RegisterClass(&wndclass) )
e5c0b16a 352 {
f6bcfd97 353 wxLogLastError(wxT("RegisterClass(frame)"));
e5c0b16a
VZ
354 }
355
193fe989 356 // "no redraw" frame
03baf031 357 wndclass.lpszClassName = wxCanvasClassNameNR;
193fe989
VZ
358 wndclass.style = styleNoRedraw;
359
360 if ( !RegisterClass(&wndclass) )
361 {
f6bcfd97 362 wxLogLastError(wxT("RegisterClass(no redraw frame)"));
193fe989
VZ
363 }
364
e5c0b16a 365 // Register the MDI frame window class.
42e69d6b 366 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
b782f2e0
VZ
367 wndclass.lpszClassName = wxMDIFrameClassName;
368 wndclass.style = styleNormal;
42e69d6b
VZ
369
370 if ( !RegisterClass(&wndclass) )
e5c0b16a 371 {
f6bcfd97 372 wxLogLastError(wxT("RegisterClass(MDI parent)"));
e5c0b16a
VZ
373 }
374
193fe989 375 // "no redraw" MDI frame
b782f2e0 376 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
193fe989
VZ
377 wndclass.style = styleNoRedraw;
378
379 if ( !RegisterClass(&wndclass) )
380 {
f6bcfd97 381 wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)"));
193fe989
VZ
382 }
383
e5c0b16a 384 // Register the MDI child frame window class.
42e69d6b
VZ
385 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
386 wndclass.lpszClassName = wxMDIChildFrameClassName;
b782f2e0 387 wndclass.style = styleNormal;
42e69d6b
VZ
388
389 if ( !RegisterClass(&wndclass) )
e5c0b16a 390 {
f6bcfd97 391 wxLogLastError(wxT("RegisterClass(MDI child)"));
e5c0b16a
VZ
392 }
393
193fe989
VZ
394 // "no redraw" MDI child frame
395 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
396 wndclass.style = styleNoRedraw;
397
398 if ( !RegisterClass(&wndclass) )
399 {
f6bcfd97 400 wxLogLastError(wxT("RegisterClass(no redraw MDI child)"));
193fe989
VZ
401 }
402
77c46f00 403 return true;
2bda0e17
KB
404}
405
9787a4b6
VZ
406// ---------------------------------------------------------------------------
407// UnregisterWindowClasses
408// ---------------------------------------------------------------------------
409
410bool wxApp::UnregisterWindowClasses()
411{
77c46f00 412 bool retval = true;
9787a4b6 413
c67d6888 414#ifndef __WXMICROWIN__
9787a4b6 415 // MDI frame window class.
03baf031 416 if ( !::UnregisterClass(wxMDIFrameClassName, wxhInstance) )
9787a4b6
VZ
417 {
418 wxLogLastError(wxT("UnregisterClass(MDI parent)"));
419
77c46f00 420 retval = false;
9787a4b6
VZ
421 }
422
423 // "no redraw" MDI frame
03baf031 424 if ( !::UnregisterClass(wxMDIFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
425 {
426 wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)"));
427
77c46f00 428 retval = false;
9787a4b6
VZ
429 }
430
431 // MDI child frame window class.
03baf031 432 if ( !::UnregisterClass(wxMDIChildFrameClassName, wxhInstance) )
9787a4b6
VZ
433 {
434 wxLogLastError(wxT("UnregisterClass(MDI child)"));
435
77c46f00 436 retval = false;
9787a4b6
VZ
437 }
438
439 // "no redraw" MDI child frame
03baf031 440 if ( !::UnregisterClass(wxMDIChildFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
441 {
442 wxLogLastError(wxT("UnregisterClass(no redraw MDI child)"));
443
77c46f00 444 retval = false;
9787a4b6
VZ
445 }
446
03baf031
VZ
447 // canvas class name
448 if ( !::UnregisterClass(wxCanvasClassName, wxhInstance) )
9787a4b6
VZ
449 {
450 wxLogLastError(wxT("UnregisterClass(canvas)"));
451
77c46f00 452 retval = false;
9787a4b6
VZ
453 }
454
03baf031 455 if ( !::UnregisterClass(wxCanvasClassNameNR, wxhInstance) )
9787a4b6
VZ
456 {
457 wxLogLastError(wxT("UnregisterClass(no redraw canvas)"));
458
77c46f00 459 retval = false;
9787a4b6 460 }
03baf031
VZ
461#endif // __WXMICROWIN__
462
9787a4b6
VZ
463 return retval;
464}
465
bb6290e3 466void wxApp::CleanUp()
2bda0e17 467{
7a9dfa3c
VZ
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
4676948b 474#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 475 wxSetKeyboardHook(false);
04ef50df 476#endif
2bda0e17 477
47d67540 478#if wxUSE_PENWINDOWS
e5c0b16a 479 wxCleanUpPenWin();
2bda0e17
KB
480#endif
481
360ae33f 482 wxOleUninitialize();
2bda0e17 483
9787a4b6
VZ
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();
9787a4b6 489
1bffa913 490 delete wxWinHandleHash;
94826170 491 wxWinHandleHash = NULL;
46fa338b
RR
492
493#ifdef __WXWINCE__
494 free( wxCanvasClassName );
495 free( wxCanvasClassNameNR );
496#endif
2bda0e17
KB
497}
498
94826170
VZ
499// ----------------------------------------------------------------------------
500// wxApp ctor/dtor
501// ----------------------------------------------------------------------------
589f0e3e 502
bb6290e3 503wxApp::wxApp()
2bda0e17 504{
e5c0b16a 505 m_printMode = wxPRINT_WINDOWS;
2bda0e17
KB
506}
507
589f0e3e
JS
508wxApp::~wxApp()
509{
94826170
VZ
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 )
e5c0b16a 514 {
94826170
VZ
515 // m_argv elements were allocated by wxStrdup()
516 free(argv[--argc]);
e5c0b16a 517 }
94826170
VZ
518
519 // but m_argv itself -- using new[]
520 delete [] argv;
589f0e3e
JS
521}
522
6046e57a
VZ
523// ----------------------------------------------------------------------------
524// wxApp idle handling
525// ----------------------------------------------------------------------------
526
2bda0e17
KB
527void wxApp::OnIdle(wxIdleEvent& event)
528{
955a9197 529 wxAppBase::OnIdle(event);
c54f78a2 530
aef94d68
JS
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.
4624defa 535 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
aef94d68
JS
536 wxDC::ClearCache();
537#endif // wxUSE_DC_CACHEING
2bda0e17
KB
538}
539
e2478fde
VZ
540void 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
6046e57a
VZ
557// ----------------------------------------------------------------------------
558// other wxApp event hanlders
559// ----------------------------------------------------------------------------
560
57c208c5 561void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
562{
563 if (GetTopWindow())
77c46f00 564 GetTopWindow()->Close(true);
387a3b02
JS
565}
566
567// Default behaviour: close the application with prompts. The
568// user can veto the close, and therefore the end session.
569void wxApp::OnQueryEndSession(wxCloseEvent& event)
570{
571 if (GetTopWindow())
572 {
573 if (!GetTopWindow()->Close(!event.CanVeto()))
77c46f00 574 event.Veto(true);
387a3b02
JS
575 }
576}
577
6046e57a
VZ
578// ----------------------------------------------------------------------------
579// miscellaneous
580// ----------------------------------------------------------------------------
581
6d167489
VZ
582/* static */
583int wxApp::GetComCtl32Version()
584{
fd7b70bd 585#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
04ef50df
JS
586 return 0;
587#else
6d167489 588 // cache the result
9fc6c21c
VZ
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
bdc72a22
VZ
592 static int s_verComCtl32 = -1;
593
6d167489
VZ
594 if ( s_verComCtl32 == -1 )
595 {
bdc72a22 596 // initally assume no comctl32.dll at all
6d167489
VZ
597 s_verComCtl32 = 0;
598
9fc6c21c
VZ
599 // we're prepared to handle the errors
600 wxLogNull noLog;
601
bdc72a22 602 // do we have it?
9fc6c21c 603 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
6d167489
VZ
604
605 // if so, then we can check for the version
9fc6c21c 606 if ( dllComCtl32.IsLoaded() )
bb6290e3 607 {
548bf4b7 608#ifdef DLLVER_PLATFORM_WINDOWS
bdc72a22 609 // try to use DllGetVersion() if available in _headers_
9fc6c21c
VZ
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) )
6d167489 618 {
9fc6c21c
VZ
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 }
548bf4b7 630#endif
bdc72a22 631
9fc6c21c
VZ
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;
6d167489 642 }
9fc6c21c 643 else // 4.70+
bdc72a22 644 {
9fc6c21c
VZ
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 )
bdc72a22 649 {
9fc6c21c
VZ
650 // not found, must be 4.70
651 s_verComCtl32 = 470;
bdc72a22
VZ
652 }
653 else
654 {
9fc6c21c
VZ
655 // found, must be 4.71 or later
656 s_verComCtl32 = 471;
bdc72a22 657 }
6d167489 658 }
9fc6c21c 659 }
ef094fa0 660 }
bb6290e3 661 }
6d167489
VZ
662
663 return s_verComCtl32;
9fc6c21c 664#endif // Microwin/!Microwin
bb6290e3
JS
665}
666
2bda0e17 667// Yield to incoming messages
cb2713bf 668
8461e4c2 669bool wxApp::Yield(bool onlyIfNeeded)
2bda0e17 670{
8461e4c2 671 // MT-FIXME
77c46f00 672 static bool s_inYield = false;
8461e4c2 673
e30285ab 674#if wxUSE_LOG
2ed3265e
VZ
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();
e30285ab 678#endif // wxUSE_LOG
2ed3265e 679
8461e4c2
VZ
680 if ( s_inYield )
681 {
682 if ( !onlyIfNeeded )
683 {
684 wxFAIL_MSG( wxT("wxYield called recursively" ) );
685 }
33ac7e6f 686
77c46f00 687 return false;
8461e4c2
VZ
688 }
689
77c46f00 690 s_inYield = true;
cb2713bf 691
8e193f38
VZ
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
e5c0b16a 694 MSG msg;
8e193f38
VZ
695 while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
696 msg.message != WM_QUIT )
e5c0b16a 697 {
5b615ed8
VZ
698#if wxUSE_THREADS
699 wxMutexGuiLeaveOrEnter();
700#endif // wxUSE_THREADS
701
1bf77ee5 702 if ( !wxTheApp->Dispatch() )
e5c0b16a
VZ
703 break;
704 }
8e193f38 705
8461e4c2
VZ
706 // if there are pending events, we must process them.
707 ProcessPendingEvents();
e5c0b16a 708
e30285ab 709#if wxUSE_LOG
2ed3265e
VZ
710 // let the logs be flashed again
711 wxLog::Resume();
e30285ab 712#endif // wxUSE_LOG
2ed3265e 713
77c46f00 714 s_inYield = false;
cb2713bf 715
77c46f00 716 return true;
2bda0e17 717}
094637f6 718
6046e57a
VZ
719#if wxUSE_EXCEPTIONS
720
721// ----------------------------------------------------------------------------
722// exception handling
723// ----------------------------------------------------------------------------
724
725bool wxApp::OnExceptionInMainLoop()
726{
727 // ask the user about what to do: use the Win32 API function here as it
77ffb593 728 // could be dangerous to use any wxWidgets code in this state
6046e57a
VZ
729 switch (
730 ::MessageBox
731 (
732 NULL,
733 _T("An unhandled exception occurred. Press \"Abort\" to \
734terminate 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
51036b44
VZ
759
760// ----------------------------------------------------------------------------
761// deprecated event loop functions
762// ----------------------------------------------------------------------------
763
764#if WXWIN_COMPATIBILITY_2_4
765
766#include "wx/evtloop.h"
767
768void wxApp::DoMessage(WXMSG *pMsg)
769{
770 wxEventLoop *evtLoop = wxEventLoop::GetActive();
771 if ( evtLoop )
772 evtLoop->ProcessMessage(pMsg);
773}
774
775bool wxApp::DoMessage()
776{
777 wxEventLoop *evtLoop = wxEventLoop::GetActive();
778 return evtLoop ? evtLoop->Dispatch() : false;
779}
780
781bool 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