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