]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
unused win_gtk stuff
[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
cde9f08e 112extern wxList WXDLLEXPORT wxPendingDelete;
4676948b
JS
113
114#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2bda0e17 115extern void wxSetKeyboardHook(bool doIt);
04ef50df 116#endif
2bda0e17 117
193fe989
VZ
118// NB: all "NoRedraw" classes must have the same names as the "normal" classes
119// with NR suffix - wxWindow::MSWCreate() supposes this
46fa338b 120#ifdef __WXWINCE__
7a4d2469
RN
121WXDLLIMPEXP_CORE wxChar *wxCanvasClassName;
122WXDLLIMPEXP_CORE wxChar *wxCanvasClassNameNR;
46fa338b 123#else
7a4d2469
RN
124WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName = wxT("wxWindowClass");
125WXDLLIMPEXP_CORE const wxChar *wxCanvasClassNameNR = wxT("wxWindowClassNR");
46fa338b 126#endif
7a4d2469
RN
127WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassName = wxT("wxMDIFrameClass");
128WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassNameNoRedraw = wxT("wxMDIFrameClassNR");
129WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
130WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
2bda0e17 131
94826170
VZ
132// ----------------------------------------------------------------------------
133// private functions
134// ----------------------------------------------------------------------------
2bda0e17 135
94826170 136LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
3b415ba4 137
e5c0b16a 138// ===========================================================================
e2478fde
VZ
139// wxGUIAppTraits implementation
140// ===========================================================================
141
142// private class which we use to pass parameters from BeforeChildWaitLoop() to
143// AfterChildWaitLoop()
144struct ChildWaitLoopData
145{
146 ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *winActive_)
147 {
148 wd = wd_;
149 winActive = winActive_;
150 }
151
152 wxWindowDisabler *wd;
153 wxWindow *winActive;
154};
155
156void *wxGUIAppTraits::BeforeChildWaitLoop()
157{
158 /*
159 We use a dirty hack here to disable all application windows (which we
160 must do because otherwise the calls to wxYield() could lead to some very
161 unexpected reentrancies in the users code) but to avoid losing
162 focus/activation entirely when the child process terminates which would
163 happen if we simply disabled everything using wxWindowDisabler. Indeed,
164 remember that Windows will never activate a disabled window and when the
165 last childs window is closed and Windows looks for a window to activate
166 all our windows are still disabled. There is no way to enable them in
167 time because we don't know when the childs windows are going to be
168 closed, so the solution we use here is to keep one special tiny frame
169 enabled all the time. Then when the child terminates it will get
170 activated and when we close it below -- after reenabling all the other
171 windows! -- the previously active window becomes activated again and
172 everything is ok.
173 */
174 wxBeginBusyCursor();
175
176 // first disable all existing windows
177 wxWindowDisabler *wd = new wxWindowDisabler;
178
179 // then create an "invisible" frame: it has minimal size, is positioned
180 // (hopefully) outside the screen and doesn't appear on the taskbar
181 wxWindow *winActive = new wxFrame
182 (
183 wxTheApp->GetTopWindow(),
fda7962d
JS
184 wxID_ANY,
185 wxEmptyString,
e2478fde
VZ
186 wxPoint(32600, 32600),
187 wxSize(1, 1),
188 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR
189 );
190 winActive->Show();
191
192 return new ChildWaitLoopData(wd, winActive);
193}
194
195void wxGUIAppTraits::AlwaysYield()
196{
197 wxYield();
198}
199
200void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig)
201{
202 wxEndBusyCursor();
203
0588f8d7 204 ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig;
e2478fde
VZ
205
206 delete data->wd;
207
208 // finally delete the dummy frame and, as wd has been already destroyed and
209 // the other windows reenabled, the activation is going to return to the
210 // window which had had it before
211 data->winActive->Destroy();
51036b44
VZ
212
213 // also delete the temporary data object itself
214 delete data;
e2478fde
VZ
215}
216
217bool wxGUIAppTraits::DoMessageFromThreadWait()
218{
1bf77ee5
VZ
219 // we should return false only if the app should exit, i.e. only if
220 // Dispatch() determines that the main event loop should terminate
031943ac
VZ
221 wxEventLoop *evtLoop = wxEventLoop::GetActive();
222 if ( !evtLoop || !evtLoop->Pending() )
223 {
224 // no events means no quit event
225 return true;
226 }
227
228 return evtLoop->Dispatch();
e2478fde
VZ
229}
230
324899f6 231wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
a8eaaeb2 232{
1bf77ee5 233 static wxToolkitInfo info;
324899f6
VS
234 wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo();
235 info.versionMajor = baseInfo.versionMajor;
236 info.versionMinor = baseInfo.versionMinor;
237 info.os = baseInfo.os;
a8eaaeb2
VS
238 info.shortName = _T("msw");
239 info.name = _T("wxMSW");
240#ifdef __WXUNIVERSAL__
241 info.shortName << _T("univ");
242 info.name << _T("/wxUniversal");
243#endif
324899f6 244 return info;
a8eaaeb2
VS
245}
246
e2478fde
VZ
247// ===========================================================================
248// wxApp implementation
e5c0b16a 249// ===========================================================================
589f0e3e 250
94826170
VZ
251int wxApp::m_nCmdShow = SW_SHOWNORMAL;
252
e5c0b16a 253// ---------------------------------------------------------------------------
e2478fde 254// wxWin macros
e5c0b16a
VZ
255// ---------------------------------------------------------------------------
256
f6bcfd97 257IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
e5c0b16a 258
f6bcfd97
BP
259BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
260 EVT_IDLE(wxApp::OnIdle)
261 EVT_END_SESSION(wxApp::OnEndSession)
262 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
263END_EVENT_TABLE()
e5c0b16a 264
94826170
VZ
265// class to ensure that wxAppBase::CleanUp() is called if our Initialize()
266// fails
267class wxCallBaseCleanup
268{
269public:
270 wxCallBaseCleanup(wxApp *app) : m_app(app) { }
271 ~wxCallBaseCleanup() { if ( m_app ) m_app->wxAppBase::CleanUp(); }
272
273 void Dismiss() { m_app = NULL; }
274
275private:
276 wxApp *m_app;
277};
278
e5c0b16a 279//// Initialize
05e2b077 280bool wxApp::Initialize(int& argc, wxChar **argv)
2bda0e17 281{
94826170
VZ
282 if ( !wxAppBase::Initialize(argc, argv) )
283 return false;
284
285 // ensure that base cleanup is done if we return too early
286 wxCallBaseCleanup callBaseCleanup(this);
287
46fa338b
RR
288#ifdef __WXWINCE__
289 wxString tmp = GetAppName();
290 tmp += wxT("ClassName");
291 wxCanvasClassName = wxStrdup( tmp.c_str() );
292 tmp += wxT("NR");
293 wxCanvasClassNameNR = wxStrdup( tmp.c_str() );
294 HWND hWnd = FindWindow( wxCanvasClassNameNR, NULL );
295 if (hWnd)
296 {
297 SetForegroundWindow( (HWND)(((DWORD)hWnd)|0x01) );
298 return false;
299 }
300#endif
301
a71d815b 302#if !defined(__WXMICROWIN__)
a5e0e655 303 InitCommonControls();
a71d815b 304#endif // !defined(__WXMICROWIN__)
2bda0e17 305
afafd942
JS
306#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
307 SHInitExtraControls();
308#endif
309
d5ea3919
JS
310#ifndef __WXWINCE__
311 // Don't show a message box if a function such as SHGetFileInfo
312 // fails to find a device.
313 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
314#endif
ad9835c9 315
360ae33f 316 wxOleInitialize();
2bda0e17 317
aa0b7e1e 318 RegisterWindowClasses();
2bda0e17 319
1bffa913 320 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
2bda0e17 321
4676948b 322#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 323 wxSetKeyboardHook(true);
04ef50df 324#endif
2bda0e17 325
94826170
VZ
326 callBaseCleanup.Dismiss();
327
328 return true;
2bda0e17
KB
329}
330
42e69d6b
VZ
331// ---------------------------------------------------------------------------
332// RegisterWindowClasses
333// ---------------------------------------------------------------------------
589f0e3e 334
b782f2e0
VZ
335// TODO we should only register classes really used by the app. For this it
336// would be enough to just delay the class registration until an attempt
337// to create a window of this class is made.
bb6290e3 338bool wxApp::RegisterWindowClasses()
2bda0e17 339{
42e69d6b 340 WNDCLASS wndclass;
03baf031 341 wxZeroMemory(wndclass);
e5c0b16a 342
193fe989
VZ
343 // for each class we register one with CS_(V|H)REDRAW style and one
344 // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
345 static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
346 static const long styleNoRedraw = CS_DBLCLKS;
347
42e69d6b 348 // the fields which are common to all classes
e5c0b16a 349 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
e5c0b16a 350 wndclass.hInstance = wxhInstance;
42e69d6b 351 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
42e69d6b 352
b9691677
VZ
353 // register the class for all normal windows
354 wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
03baf031 355 wndclass.lpszClassName = wxCanvasClassName;
b782f2e0 356 wndclass.style = styleNormal;
e5c0b16a 357
42e69d6b 358 if ( !RegisterClass(&wndclass) )
e5c0b16a 359 {
f6bcfd97 360 wxLogLastError(wxT("RegisterClass(frame)"));
e5c0b16a
VZ
361 }
362
193fe989 363 // "no redraw" frame
03baf031 364 wndclass.lpszClassName = wxCanvasClassNameNR;
193fe989
VZ
365 wndclass.style = styleNoRedraw;
366
367 if ( !RegisterClass(&wndclass) )
368 {
f6bcfd97 369 wxLogLastError(wxT("RegisterClass(no redraw frame)"));
193fe989
VZ
370 }
371
e5c0b16a 372 // Register the MDI frame window class.
42e69d6b 373 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
b782f2e0
VZ
374 wndclass.lpszClassName = wxMDIFrameClassName;
375 wndclass.style = styleNormal;
42e69d6b
VZ
376
377 if ( !RegisterClass(&wndclass) )
e5c0b16a 378 {
f6bcfd97 379 wxLogLastError(wxT("RegisterClass(MDI parent)"));
e5c0b16a
VZ
380 }
381
193fe989 382 // "no redraw" MDI frame
b782f2e0 383 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
193fe989
VZ
384 wndclass.style = styleNoRedraw;
385
386 if ( !RegisterClass(&wndclass) )
387 {
f6bcfd97 388 wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)"));
193fe989
VZ
389 }
390
e5c0b16a 391 // Register the MDI child frame window class.
42e69d6b
VZ
392 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
393 wndclass.lpszClassName = wxMDIChildFrameClassName;
b782f2e0 394 wndclass.style = styleNormal;
42e69d6b
VZ
395
396 if ( !RegisterClass(&wndclass) )
e5c0b16a 397 {
f6bcfd97 398 wxLogLastError(wxT("RegisterClass(MDI child)"));
e5c0b16a
VZ
399 }
400
193fe989
VZ
401 // "no redraw" MDI child frame
402 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
403 wndclass.style = styleNoRedraw;
404
405 if ( !RegisterClass(&wndclass) )
406 {
f6bcfd97 407 wxLogLastError(wxT("RegisterClass(no redraw MDI child)"));
193fe989
VZ
408 }
409
77c46f00 410 return true;
2bda0e17
KB
411}
412
9787a4b6
VZ
413// ---------------------------------------------------------------------------
414// UnregisterWindowClasses
415// ---------------------------------------------------------------------------
416
417bool wxApp::UnregisterWindowClasses()
418{
77c46f00 419 bool retval = true;
9787a4b6 420
c67d6888 421#ifndef __WXMICROWIN__
9787a4b6 422 // MDI frame window class.
03baf031 423 if ( !::UnregisterClass(wxMDIFrameClassName, wxhInstance) )
9787a4b6
VZ
424 {
425 wxLogLastError(wxT("UnregisterClass(MDI parent)"));
426
77c46f00 427 retval = false;
9787a4b6
VZ
428 }
429
430 // "no redraw" MDI frame
03baf031 431 if ( !::UnregisterClass(wxMDIFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
432 {
433 wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)"));
434
77c46f00 435 retval = false;
9787a4b6
VZ
436 }
437
438 // MDI child frame window class.
03baf031 439 if ( !::UnregisterClass(wxMDIChildFrameClassName, wxhInstance) )
9787a4b6
VZ
440 {
441 wxLogLastError(wxT("UnregisterClass(MDI child)"));
442
77c46f00 443 retval = false;
9787a4b6
VZ
444 }
445
446 // "no redraw" MDI child frame
03baf031 447 if ( !::UnregisterClass(wxMDIChildFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
448 {
449 wxLogLastError(wxT("UnregisterClass(no redraw MDI child)"));
450
77c46f00 451 retval = false;
9787a4b6
VZ
452 }
453
03baf031
VZ
454 // canvas class name
455 if ( !::UnregisterClass(wxCanvasClassName, wxhInstance) )
9787a4b6
VZ
456 {
457 wxLogLastError(wxT("UnregisterClass(canvas)"));
458
77c46f00 459 retval = false;
9787a4b6
VZ
460 }
461
03baf031 462 if ( !::UnregisterClass(wxCanvasClassNameNR, wxhInstance) )
9787a4b6
VZ
463 {
464 wxLogLastError(wxT("UnregisterClass(no redraw canvas)"));
465
77c46f00 466 retval = false;
9787a4b6 467 }
03baf031
VZ
468#endif // __WXMICROWIN__
469
9787a4b6
VZ
470 return retval;
471}
472
bb6290e3 473void wxApp::CleanUp()
2bda0e17 474{
7a9dfa3c
VZ
475 // all objects pending for deletion must be deleted first, otherwise we
476 // would crash when they use wxWinHandleHash (and UnregisterWindowClasses()
477 // call wouldn't succeed as long as any windows still exist), so call the
478 // base class method first and only then do our clean up
479 wxAppBase::CleanUp();
480
4676948b 481#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 482 wxSetKeyboardHook(false);
04ef50df 483#endif
2bda0e17 484
360ae33f 485 wxOleUninitialize();
2bda0e17 486
9787a4b6
VZ
487 // for an EXE the classes are unregistered when it terminates but DLL may
488 // be loaded several times (load/unload/load) into the same process in
489 // which case the registration will fail after the first time if we don't
490 // unregister the classes now
491 UnregisterWindowClasses();
9787a4b6 492
1bffa913 493 delete wxWinHandleHash;
94826170 494 wxWinHandleHash = NULL;
a71d815b 495
46fa338b
RR
496#ifdef __WXWINCE__
497 free( wxCanvasClassName );
498 free( wxCanvasClassNameNR );
499#endif
2bda0e17
KB
500}
501
94826170
VZ
502// ----------------------------------------------------------------------------
503// wxApp ctor/dtor
504// ----------------------------------------------------------------------------
589f0e3e 505
bb6290e3 506wxApp::wxApp()
2bda0e17 507{
e5c0b16a 508 m_printMode = wxPRINT_WINDOWS;
2bda0e17
KB
509}
510
589f0e3e
JS
511wxApp::~wxApp()
512{
589f0e3e
JS
513}
514
6046e57a
VZ
515// ----------------------------------------------------------------------------
516// wxApp idle handling
517// ----------------------------------------------------------------------------
518
2bda0e17
KB
519void wxApp::OnIdle(wxIdleEvent& event)
520{
955a9197 521 wxAppBase::OnIdle(event);
c54f78a2 522
aef94d68
JS
523#if wxUSE_DC_CACHEING
524 // automated DC cache management: clear the cached DCs and bitmap
525 // if it's likely that the app has finished with them, that is, we
526 // get an idle event and we're not dragging anything.
4624defa 527 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
aef94d68
JS
528 wxDC::ClearCache();
529#endif // wxUSE_DC_CACHEING
2bda0e17
KB
530}
531
e2478fde
VZ
532void wxApp::WakeUpIdle()
533{
534 // Send the top window a dummy message so idle handler processing will
535 // start up again. Doing it this way ensures that the idle handler
536 // wakes up in the right thread (see also wxWakeUpMainThread() which does
537 // the same for the main app thread only)
538 wxWindow *topWindow = wxTheApp->GetTopWindow();
539 if ( topWindow )
540 {
541 if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
542 {
543 // should never happen
544 wxLogLastError(wxT("PostMessage(WM_NULL)"));
545 }
546 }
547}
548
6046e57a
VZ
549// ----------------------------------------------------------------------------
550// other wxApp event hanlders
551// ----------------------------------------------------------------------------
552
57c208c5 553void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
554{
555 if (GetTopWindow())
77c46f00 556 GetTopWindow()->Close(true);
387a3b02
JS
557}
558
559// Default behaviour: close the application with prompts. The
560// user can veto the close, and therefore the end session.
561void wxApp::OnQueryEndSession(wxCloseEvent& event)
562{
563 if (GetTopWindow())
564 {
565 if (!GetTopWindow()->Close(!event.CanVeto()))
77c46f00 566 event.Veto(true);
387a3b02
JS
567 }
568}
569
6046e57a
VZ
570// ----------------------------------------------------------------------------
571// miscellaneous
572// ----------------------------------------------------------------------------
573
6d167489
VZ
574/* static */
575int wxApp::GetComCtl32Version()
576{
fd7b70bd 577#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
04ef50df
JS
578 return 0;
579#else
6d167489 580 // cache the result
9fc6c21c
VZ
581 //
582 // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice,
583 // but as its value should be the same both times it doesn't matter
bdc72a22
VZ
584 static int s_verComCtl32 = -1;
585
6d167489
VZ
586 if ( s_verComCtl32 == -1 )
587 {
bdc72a22 588 // initally assume no comctl32.dll at all
6d167489
VZ
589 s_verComCtl32 = 0;
590
9fc6c21c
VZ
591 // we're prepared to handle the errors
592 wxLogNull noLog;
ad9835c9 593
64c288fa 594#if wxUSE_DYNLIB_CLASS
bdc72a22 595 // do we have it?
9fc6c21c 596 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
6d167489
VZ
597
598 // if so, then we can check for the version
9fc6c21c 599 if ( dllComCtl32.IsLoaded() )
bb6290e3 600 {
25a11614 601 // now check if the function is available during run-time
9fc6c21c
VZ
602 wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 );
603 if ( pfnDllGetVersion )
604 {
605 DLLVERSIONINFO dvi;
606 dvi.cbSize = sizeof(dvi);
607
608 HRESULT hr = (*pfnDllGetVersion)(&dvi);
609 if ( FAILED(hr) )
6d167489 610 {
9fc6c21c
VZ
611 wxLogApiError(_T("DllGetVersion"), hr);
612 }
613 else
614 {
615 // this is incompatible with _WIN32_IE values, but
616 // compatible with the other values returned by
617 // GetComCtl32Version()
618 s_verComCtl32 = 100*dvi.dwMajorVersion +
619 dvi.dwMinorVersion;
620 }
621 }
bdc72a22 622
9fc6c21c
VZ
623 // if DllGetVersion() is unavailable either during compile or
624 // run-time, try to guess the version otherwise
625 if ( !s_verComCtl32 )
626 {
627 // InitCommonControlsEx is unique to 4.70 and later
628 void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx"));
629 if ( !pfn )
630 {
631 // not found, must be 4.00
632 s_verComCtl32 = 400;
6d167489 633 }
9fc6c21c 634 else // 4.70+
bdc72a22 635 {
9fc6c21c
VZ
636 // many symbols appeared in comctl32 4.71, could use any of
637 // them except may be DllInstall()
638 pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB"));
639 if ( !pfn )
bdc72a22 640 {
9fc6c21c
VZ
641 // not found, must be 4.70
642 s_verComCtl32 = 470;
bdc72a22
VZ
643 }
644 else
645 {
9fc6c21c
VZ
646 // found, must be 4.71 or later
647 s_verComCtl32 = 471;
bdc72a22 648 }
6d167489 649 }
9fc6c21c 650 }
ef094fa0 651 }
ad9835c9 652#endif
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 |
a71d815b 730 MB_ICONERROR|
6046e57a
VZ
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
51036b44
VZ
758void wxApp::DoMessage(WXMSG *pMsg)
759{
760 wxEventLoop *evtLoop = wxEventLoop::GetActive();
761 if ( evtLoop )
762 evtLoop->ProcessMessage(pMsg);
763}
764
765bool wxApp::DoMessage()
766{
767 wxEventLoop *evtLoop = wxEventLoop::GetActive();
768 return evtLoop ? evtLoop->Dispatch() : false;
769}
770
771bool wxApp::ProcessMessage(WXMSG* pMsg)
772{
773 wxEventLoop *evtLoop = wxEventLoop::GetActive();
774 return evtLoop && evtLoop->PreProcessMessage(pMsg);
775}
776
777#endif // WXWIN_COMPATIBILITY_2_4