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