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