]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
Don't skip after writing tab or we could get another one in some circumstances
[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 71#if defined(__POCKETPC__) || defined(__SMARTPHONE__)
58b76be1
VZ
72 #include <ole2.h>
73 #include <aygshell.h>
afafd942
JS
74#endif
75
e5c0b16a 76#if wxUSE_OLE
6e0d9d43 77 #include <ole2.h>
d05237ea 78#endif
ce3ed50d 79
2bda0e17 80#include <string.h>
a5e0e655 81#include <ctype.h>
2bda0e17 82
0d236fd0 83#include "wx/msw/wrapcctl.h"
bdc72a22 84
6046e57a
VZ
85// For MB_TASKMODAL
86#ifdef __WXWINCE__
87#include "wx/msw/wince/missing.h"
88#endif
89
25a11614
VZ
90// instead of including <shlwapi.h> which is not part of the core SDK and not
91// shipped at all with other compilers, we always define the parts of it we
92// need here ourselves
93//
94// NB: DLLVER_PLATFORM_WINDOWS will be defined if shlwapi.h had been somehow
95// included already
96#ifndef DLLVER_PLATFORM_WINDOWS
97 // hopefully we don't need to change packing as DWORDs should be already
98 // correctly aligned
99 struct DLLVERSIONINFO
100 {
101 DWORD cbSize;
102 DWORD dwMajorVersion; // Major version
103 DWORD dwMinorVersion; // Minor version
104 DWORD dwBuildNumber; // Build number
105 DWORD dwPlatformID; // DLLVER_PLATFORM_*
106 };
107
108 typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
109#endif // defined(DLLVERSIONINFO)
110
238a6044 111
e5c0b16a
VZ
112// ---------------------------------------------------------------------------
113// global variables
114// ---------------------------------------------------------------------------
115
cde9f08e 116extern wxList WXDLLEXPORT wxPendingDelete;
4676948b
JS
117
118#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2bda0e17 119extern void wxSetKeyboardHook(bool doIt);
04ef50df 120#endif
2bda0e17 121
193fe989
VZ
122// NB: all "NoRedraw" classes must have the same names as the "normal" classes
123// with NR suffix - wxWindow::MSWCreate() supposes this
46fa338b 124#ifdef __WXWINCE__
7a4d2469
RN
125WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
126WXDLLIMPEXP_CORE wxChar *wxCanvasClassNameNR;
46fa338b 127#else
7a4d2469
RN
128WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName = wxT("wxWindowClass");
129WXDLLIMPEXP_CORE const wxChar *wxCanvasClassNameNR = wxT("wxWindowClassNR");
46fa338b 130#endif
7a4d2469
RN
131WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassName = wxT("wxMDIFrameClass");
132WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassNameNoRedraw = wxT("wxMDIFrameClassNR");
133WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
134WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
2bda0e17 135
94826170
VZ
136// ----------------------------------------------------------------------------
137// private functions
138// ----------------------------------------------------------------------------
2bda0e17 139
94826170 140LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
3b415ba4 141
e5c0b16a 142// ===========================================================================
e2478fde
VZ
143// wxGUIAppTraits implementation
144// ===========================================================================
145
146// private class which we use to pass parameters from BeforeChildWaitLoop() to
147// AfterChildWaitLoop()
148struct ChildWaitLoopData
149{
150 ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *winActive_)
151 {
152 wd = wd_;
153 winActive = winActive_;
154 }
155
156 wxWindowDisabler *wd;
157 wxWindow *winActive;
158};
159
160void *wxGUIAppTraits::BeforeChildWaitLoop()
161{
162 /*
163 We use a dirty hack here to disable all application windows (which we
164 must do because otherwise the calls to wxYield() could lead to some very
165 unexpected reentrancies in the users code) but to avoid losing
166 focus/activation entirely when the child process terminates which would
167 happen if we simply disabled everything using wxWindowDisabler. Indeed,
168 remember that Windows will never activate a disabled window and when the
169 last childs window is closed and Windows looks for a window to activate
170 all our windows are still disabled. There is no way to enable them in
171 time because we don't know when the childs windows are going to be
172 closed, so the solution we use here is to keep one special tiny frame
173 enabled all the time. Then when the child terminates it will get
174 activated and when we close it below -- after reenabling all the other
175 windows! -- the previously active window becomes activated again and
176 everything is ok.
177 */
178 wxBeginBusyCursor();
179
180 // first disable all existing windows
181 wxWindowDisabler *wd = new wxWindowDisabler;
182
183 // then create an "invisible" frame: it has minimal size, is positioned
184 // (hopefully) outside the screen and doesn't appear on the taskbar
185 wxWindow *winActive = new wxFrame
186 (
187 wxTheApp->GetTopWindow(),
fda7962d
JS
188 wxID_ANY,
189 wxEmptyString,
e2478fde
VZ
190 wxPoint(32600, 32600),
191 wxSize(1, 1),
192 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR
193 );
194 winActive->Show();
195
196 return new ChildWaitLoopData(wd, winActive);
197}
198
199void wxGUIAppTraits::AlwaysYield()
200{
201 wxYield();
202}
203
204void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig)
205{
206 wxEndBusyCursor();
207
0588f8d7 208 ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig;
e2478fde
VZ
209
210 delete data->wd;
211
212 // finally delete the dummy frame and, as wd has been already destroyed and
213 // the other windows reenabled, the activation is going to return to the
214 // window which had had it before
215 data->winActive->Destroy();
51036b44
VZ
216
217 // also delete the temporary data object itself
218 delete data;
e2478fde
VZ
219}
220
221bool wxGUIAppTraits::DoMessageFromThreadWait()
222{
1bf77ee5
VZ
223 // we should return false only if the app should exit, i.e. only if
224 // Dispatch() determines that the main event loop should terminate
225 return !wxTheApp || wxTheApp->Dispatch();
e2478fde
VZ
226}
227
324899f6 228wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
a8eaaeb2 229{
1bf77ee5 230 static wxToolkitInfo info;
324899f6
VS
231 wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo();
232 info.versionMajor = baseInfo.versionMajor;
233 info.versionMinor = baseInfo.versionMinor;
234 info.os = baseInfo.os;
a8eaaeb2
VS
235 info.shortName = _T("msw");
236 info.name = _T("wxMSW");
237#ifdef __WXUNIVERSAL__
238 info.shortName << _T("univ");
239 info.name << _T("/wxUniversal");
240#endif
324899f6 241 return info;
a8eaaeb2
VS
242}
243
e2478fde
VZ
244// ===========================================================================
245// wxApp implementation
e5c0b16a 246// ===========================================================================
589f0e3e 247
94826170
VZ
248int wxApp::m_nCmdShow = SW_SHOWNORMAL;
249
e5c0b16a 250// ---------------------------------------------------------------------------
e2478fde 251// wxWin macros
e5c0b16a
VZ
252// ---------------------------------------------------------------------------
253
f6bcfd97 254IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
e5c0b16a 255
f6bcfd97
BP
256BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
257 EVT_IDLE(wxApp::OnIdle)
258 EVT_END_SESSION(wxApp::OnEndSession)
259 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
260END_EVENT_TABLE()
e5c0b16a 261
94826170
VZ
262// class to ensure that wxAppBase::CleanUp() is called if our Initialize()
263// fails
264class wxCallBaseCleanup
265{
266public:
267 wxCallBaseCleanup(wxApp *app) : m_app(app) { }
268 ~wxCallBaseCleanup() { if ( m_app ) m_app->wxAppBase::CleanUp(); }
269
270 void Dismiss() { m_app = NULL; }
271
272private:
273 wxApp *m_app;
274};
275
e5c0b16a 276//// Initialize
05e2b077 277bool wxApp::Initialize(int& argc, wxChar **argv)
2bda0e17 278{
94826170
VZ
279 if ( !wxAppBase::Initialize(argc, argv) )
280 return false;
281
282 // ensure that base cleanup is done if we return too early
283 wxCallBaseCleanup callBaseCleanup(this);
284
46fa338b
RR
285#ifdef __WXWINCE__
286 wxString tmp = GetAppName();
287 tmp += wxT("ClassName");
288 wxCanvasClassName = wxStrdup( tmp.c_str() );
289 tmp += wxT("NR");
290 wxCanvasClassNameNR = wxStrdup( tmp.c_str() );
291 HWND hWnd = FindWindow( wxCanvasClassNameNR, NULL );
292 if (hWnd)
293 {
294 SetForegroundWindow( (HWND)(((DWORD)hWnd)|0x01) );
295 return false;
296 }
297#endif
298
04ef50df 299#if defined(__WIN95__) && !defined(__WXMICROWIN__)
a5e0e655 300 InitCommonControls();
e5c0b16a 301#endif // __WIN95__
2bda0e17 302
afafd942
JS
303#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
304 SHInitExtraControls();
305#endif
306
360ae33f 307 wxOleInitialize();
2bda0e17 308
aa0b7e1e 309 RegisterWindowClasses();
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
360ae33f 476 wxOleUninitialize();
2bda0e17 477
9787a4b6
VZ
478 // for an EXE the classes are unregistered when it terminates but DLL may
479 // be loaded several times (load/unload/load) into the same process in
480 // which case the registration will fail after the first time if we don't
481 // unregister the classes now
482 UnregisterWindowClasses();
9787a4b6 483
1bffa913 484 delete wxWinHandleHash;
94826170 485 wxWinHandleHash = NULL;
46fa338b
RR
486
487#ifdef __WXWINCE__
488 free( wxCanvasClassName );
489 free( wxCanvasClassNameNR );
490#endif
2bda0e17
KB
491}
492
94826170
VZ
493// ----------------------------------------------------------------------------
494// wxApp ctor/dtor
495// ----------------------------------------------------------------------------
589f0e3e 496
bb6290e3 497wxApp::wxApp()
2bda0e17 498{
e5c0b16a 499 m_printMode = wxPRINT_WINDOWS;
2bda0e17
KB
500}
501
589f0e3e
JS
502wxApp::~wxApp()
503{
94826170
VZ
504 // our cmd line arguments are allocated inside wxEntry(HINSTANCE), they
505 // don't come from main(), so we have to free them
506
507 while ( argc )
e5c0b16a 508 {
94826170
VZ
509 // m_argv elements were allocated by wxStrdup()
510 free(argv[--argc]);
e5c0b16a 511 }
94826170
VZ
512
513 // but m_argv itself -- using new[]
514 delete [] argv;
589f0e3e
JS
515}
516
6046e57a
VZ
517// ----------------------------------------------------------------------------
518// wxApp idle handling
519// ----------------------------------------------------------------------------
520
2bda0e17
KB
521void wxApp::OnIdle(wxIdleEvent& event)
522{
955a9197 523 wxAppBase::OnIdle(event);
c54f78a2 524
aef94d68
JS
525#if wxUSE_DC_CACHEING
526 // automated DC cache management: clear the cached DCs and bitmap
527 // if it's likely that the app has finished with them, that is, we
528 // get an idle event and we're not dragging anything.
4624defa 529 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
aef94d68
JS
530 wxDC::ClearCache();
531#endif // wxUSE_DC_CACHEING
2bda0e17
KB
532}
533
e2478fde
VZ
534void wxApp::WakeUpIdle()
535{
536 // Send the top window a dummy message so idle handler processing will
537 // start up again. Doing it this way ensures that the idle handler
538 // wakes up in the right thread (see also wxWakeUpMainThread() which does
539 // the same for the main app thread only)
540 wxWindow *topWindow = wxTheApp->GetTopWindow();
541 if ( topWindow )
542 {
543 if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
544 {
545 // should never happen
546 wxLogLastError(wxT("PostMessage(WM_NULL)"));
547 }
548 }
549}
550
6046e57a
VZ
551// ----------------------------------------------------------------------------
552// other wxApp event hanlders
553// ----------------------------------------------------------------------------
554
57c208c5 555void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
556{
557 if (GetTopWindow())
77c46f00 558 GetTopWindow()->Close(true);
387a3b02
JS
559}
560
561// Default behaviour: close the application with prompts. The
562// user can veto the close, and therefore the end session.
563void wxApp::OnQueryEndSession(wxCloseEvent& event)
564{
565 if (GetTopWindow())
566 {
567 if (!GetTopWindow()->Close(!event.CanVeto()))
77c46f00 568 event.Veto(true);
387a3b02
JS
569 }
570}
571
6046e57a
VZ
572// ----------------------------------------------------------------------------
573// miscellaneous
574// ----------------------------------------------------------------------------
575
6d167489
VZ
576/* static */
577int wxApp::GetComCtl32Version()
578{
fd7b70bd 579#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
04ef50df
JS
580 return 0;
581#else
6d167489 582 // cache the result
9fc6c21c
VZ
583 //
584 // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice,
585 // but as its value should be the same both times it doesn't matter
bdc72a22
VZ
586 static int s_verComCtl32 = -1;
587
6d167489
VZ
588 if ( s_verComCtl32 == -1 )
589 {
bdc72a22 590 // initally assume no comctl32.dll at all
6d167489
VZ
591 s_verComCtl32 = 0;
592
9fc6c21c
VZ
593 // we're prepared to handle the errors
594 wxLogNull noLog;
595
bdc72a22 596 // do we have it?
9fc6c21c 597 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
6d167489
VZ
598
599 // if so, then we can check for the version
9fc6c21c 600 if ( dllComCtl32.IsLoaded() )
bb6290e3 601 {
25a11614 602 // now check if the function is available during run-time
9fc6c21c
VZ
603 wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 );
604 if ( pfnDllGetVersion )
605 {
606 DLLVERSIONINFO dvi;
607 dvi.cbSize = sizeof(dvi);
608
609 HRESULT hr = (*pfnDllGetVersion)(&dvi);
610 if ( FAILED(hr) )
6d167489 611 {
9fc6c21c
VZ
612 wxLogApiError(_T("DllGetVersion"), hr);
613 }
614 else
615 {
616 // this is incompatible with _WIN32_IE values, but
617 // compatible with the other values returned by
618 // GetComCtl32Version()
619 s_verComCtl32 = 100*dvi.dwMajorVersion +
620 dvi.dwMinorVersion;
621 }
622 }
bdc72a22 623
9fc6c21c
VZ
624 // if DllGetVersion() is unavailable either during compile or
625 // run-time, try to guess the version otherwise
626 if ( !s_verComCtl32 )
627 {
628 // InitCommonControlsEx is unique to 4.70 and later
629 void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx"));
630 if ( !pfn )
631 {
632 // not found, must be 4.00
633 s_verComCtl32 = 400;
6d167489 634 }
9fc6c21c 635 else // 4.70+
bdc72a22 636 {
9fc6c21c
VZ
637 // many symbols appeared in comctl32 4.71, could use any of
638 // them except may be DllInstall()
639 pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB"));
640 if ( !pfn )
bdc72a22 641 {
9fc6c21c
VZ
642 // not found, must be 4.70
643 s_verComCtl32 = 470;
bdc72a22
VZ
644 }
645 else
646 {
9fc6c21c
VZ
647 // found, must be 4.71 or later
648 s_verComCtl32 = 471;
bdc72a22 649 }
6d167489 650 }
9fc6c21c 651 }
ef094fa0 652 }
bb6290e3 653 }
6d167489
VZ
654
655 return s_verComCtl32;
9fc6c21c 656#endif // Microwin/!Microwin
bb6290e3
JS
657}
658
2bda0e17 659// Yield to incoming messages
cb2713bf 660
8461e4c2 661bool wxApp::Yield(bool onlyIfNeeded)
2bda0e17 662{
8461e4c2 663 // MT-FIXME
77c46f00 664 static bool s_inYield = false;
8461e4c2 665
e30285ab 666#if wxUSE_LOG
2ed3265e
VZ
667 // disable log flushing from here because a call to wxYield() shouldn't
668 // normally result in message boxes popping up &c
669 wxLog::Suspend();
e30285ab 670#endif // wxUSE_LOG
2ed3265e 671
8461e4c2
VZ
672 if ( s_inYield )
673 {
674 if ( !onlyIfNeeded )
675 {
676 wxFAIL_MSG( wxT("wxYield called recursively" ) );
677 }
33ac7e6f 678
77c46f00 679 return false;
8461e4c2
VZ
680 }
681
77c46f00 682 s_inYield = true;
cb2713bf 683
8e193f38
VZ
684 // we don't want to process WM_QUIT from here - it should be processed in
685 // the main event loop in order to stop it
e5c0b16a 686 MSG msg;
8e193f38
VZ
687 while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
688 msg.message != WM_QUIT )
e5c0b16a 689 {
5b615ed8
VZ
690#if wxUSE_THREADS
691 wxMutexGuiLeaveOrEnter();
692#endif // wxUSE_THREADS
693
1bf77ee5 694 if ( !wxTheApp->Dispatch() )
e5c0b16a
VZ
695 break;
696 }
8e193f38 697
8461e4c2
VZ
698 // if there are pending events, we must process them.
699 ProcessPendingEvents();
e5c0b16a 700
e30285ab 701#if wxUSE_LOG
2ed3265e
VZ
702 // let the logs be flashed again
703 wxLog::Resume();
e30285ab 704#endif // wxUSE_LOG
2ed3265e 705
77c46f00 706 s_inYield = false;
cb2713bf 707
77c46f00 708 return true;
2bda0e17 709}
094637f6 710
6046e57a
VZ
711#if wxUSE_EXCEPTIONS
712
713// ----------------------------------------------------------------------------
714// exception handling
715// ----------------------------------------------------------------------------
716
717bool wxApp::OnExceptionInMainLoop()
718{
719 // ask the user about what to do: use the Win32 API function here as it
77ffb593 720 // could be dangerous to use any wxWidgets code in this state
6046e57a
VZ
721 switch (
722 ::MessageBox
723 (
724 NULL,
725 _T("An unhandled exception occurred. Press \"Abort\" to \
726terminate the program,\r\n\
727\"Retry\" to exit the program normally and \"Ignore\" to try to continue."),
728 _T("Unhandled exception"),
729 MB_ABORTRETRYIGNORE |
730 MB_ICONERROR|
731 MB_TASKMODAL
732 )
733 )
734 {
735 case IDABORT:
736 throw;
737
738 default:
739 wxFAIL_MSG( _T("unexpected MessageBox() return code") );
740 // fall through
741
742 case IDRETRY:
743 return false;
744
745 case IDIGNORE:
746 return true;
747 }
748}
749
750#endif // wxUSE_EXCEPTIONS
51036b44
VZ
751
752// ----------------------------------------------------------------------------
753// deprecated event loop functions
754// ----------------------------------------------------------------------------
755
756#if WXWIN_COMPATIBILITY_2_4
757
758#include "wx/evtloop.h"
759
760void wxApp::DoMessage(WXMSG *pMsg)
761{
762 wxEventLoop *evtLoop = wxEventLoop::GetActive();
763 if ( evtLoop )
764 evtLoop->ProcessMessage(pMsg);
765}
766
767bool wxApp::DoMessage()
768{
769 wxEventLoop *evtLoop = wxEventLoop::GetActive();
770 return evtLoop ? evtLoop->Dispatch() : false;
771}
772
773bool wxApp::ProcessMessage(WXMSG* pMsg)
774{
775 wxEventLoop *evtLoop = wxEventLoop::GetActive();
776 return evtLoop && evtLoop->PreProcessMessage(pMsg);
777}
778
779#endif // WXWIN_COMPATIBILITY_2_4
780