]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
fix to last custom draw fix: only leave space for the image in the first column
[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
e5c0b16a
VZ
28 #include "wx/frame.h"
29 #include "wx/app.h"
30 #include "wx/utils.h"
31 #include "wx/gdicmn.h"
32 #include "wx/pen.h"
33 #include "wx/brush.h"
34 #include "wx/cursor.h"
35 #include "wx/icon.h"
36 #include "wx/palette.h"
37 #include "wx/dc.h"
38 #include "wx/dialog.h"
39 #include "wx/msgdlg.h"
40 #include "wx/intl.h"
41 #include "wx/dynarray.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"
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
221 return !wxTheApp || wxTheApp->Dispatch();
e2478fde
VZ
222}
223
324899f6 224wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
a8eaaeb2 225{
1bf77ee5 226 static wxToolkitInfo info;
324899f6
VS
227 wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo();
228 info.versionMajor = baseInfo.versionMajor;
229 info.versionMinor = baseInfo.versionMinor;
230 info.os = baseInfo.os;
a8eaaeb2
VS
231 info.shortName = _T("msw");
232 info.name = _T("wxMSW");
233#ifdef __WXUNIVERSAL__
234 info.shortName << _T("univ");
235 info.name << _T("/wxUniversal");
236#endif
324899f6 237 return info;
a8eaaeb2
VS
238}
239
e2478fde
VZ
240// ===========================================================================
241// wxApp implementation
e5c0b16a 242// ===========================================================================
589f0e3e 243
94826170
VZ
244int wxApp::m_nCmdShow = SW_SHOWNORMAL;
245
e5c0b16a 246// ---------------------------------------------------------------------------
e2478fde 247// wxWin macros
e5c0b16a
VZ
248// ---------------------------------------------------------------------------
249
f6bcfd97 250IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
e5c0b16a 251
f6bcfd97
BP
252BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
253 EVT_IDLE(wxApp::OnIdle)
254 EVT_END_SESSION(wxApp::OnEndSession)
255 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
256END_EVENT_TABLE()
e5c0b16a 257
94826170
VZ
258// class to ensure that wxAppBase::CleanUp() is called if our Initialize()
259// fails
260class wxCallBaseCleanup
261{
262public:
263 wxCallBaseCleanup(wxApp *app) : m_app(app) { }
264 ~wxCallBaseCleanup() { if ( m_app ) m_app->wxAppBase::CleanUp(); }
265
266 void Dismiss() { m_app = NULL; }
267
268private:
269 wxApp *m_app;
270};
271
e5c0b16a 272//// Initialize
05e2b077 273bool wxApp::Initialize(int& argc, wxChar **argv)
2bda0e17 274{
94826170
VZ
275 if ( !wxAppBase::Initialize(argc, argv) )
276 return false;
277
278 // ensure that base cleanup is done if we return too early
279 wxCallBaseCleanup callBaseCleanup(this);
280
46fa338b
RR
281#ifdef __WXWINCE__
282 wxString tmp = GetAppName();
283 tmp += wxT("ClassName");
284 wxCanvasClassName = wxStrdup( tmp.c_str() );
285 tmp += wxT("NR");
286 wxCanvasClassNameNR = wxStrdup( tmp.c_str() );
287 HWND hWnd = FindWindow( wxCanvasClassNameNR, NULL );
288 if (hWnd)
289 {
290 SetForegroundWindow( (HWND)(((DWORD)hWnd)|0x01) );
291 return false;
292 }
293#endif
294
a71d815b 295#if !defined(__WXMICROWIN__)
a5e0e655 296 InitCommonControls();
a71d815b 297#endif // !defined(__WXMICROWIN__)
2bda0e17 298
afafd942
JS
299#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
300 SHInitExtraControls();
301#endif
302
d5ea3919
JS
303#ifndef __WXWINCE__
304 // Don't show a message box if a function such as SHGetFileInfo
305 // fails to find a device.
306 SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
307#endif
308
360ae33f 309 wxOleInitialize();
2bda0e17 310
aa0b7e1e 311 RegisterWindowClasses();
2bda0e17 312
1bffa913 313 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
2bda0e17 314
4676948b 315#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 316 wxSetKeyboardHook(true);
04ef50df 317#endif
2bda0e17 318
94826170
VZ
319 callBaseCleanup.Dismiss();
320
321 return true;
2bda0e17
KB
322}
323
42e69d6b
VZ
324// ---------------------------------------------------------------------------
325// RegisterWindowClasses
326// ---------------------------------------------------------------------------
589f0e3e 327
b782f2e0
VZ
328// TODO we should only register classes really used by the app. For this it
329// would be enough to just delay the class registration until an attempt
330// to create a window of this class is made.
bb6290e3 331bool wxApp::RegisterWindowClasses()
2bda0e17 332{
42e69d6b 333 WNDCLASS wndclass;
03baf031 334 wxZeroMemory(wndclass);
e5c0b16a 335
193fe989
VZ
336 // for each class we register one with CS_(V|H)REDRAW style and one
337 // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
338 static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
339 static const long styleNoRedraw = CS_DBLCLKS;
340
42e69d6b 341 // the fields which are common to all classes
e5c0b16a 342 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
e5c0b16a 343 wndclass.hInstance = wxhInstance;
42e69d6b 344 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
42e69d6b 345
b9691677
VZ
346 // register the class for all normal windows
347 wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
03baf031 348 wndclass.lpszClassName = wxCanvasClassName;
b782f2e0 349 wndclass.style = styleNormal;
e5c0b16a 350
42e69d6b 351 if ( !RegisterClass(&wndclass) )
e5c0b16a 352 {
f6bcfd97 353 wxLogLastError(wxT("RegisterClass(frame)"));
e5c0b16a
VZ
354 }
355
193fe989 356 // "no redraw" frame
03baf031 357 wndclass.lpszClassName = wxCanvasClassNameNR;
193fe989
VZ
358 wndclass.style = styleNoRedraw;
359
360 if ( !RegisterClass(&wndclass) )
361 {
f6bcfd97 362 wxLogLastError(wxT("RegisterClass(no redraw frame)"));
193fe989
VZ
363 }
364
e5c0b16a 365 // Register the MDI frame window class.
42e69d6b 366 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
b782f2e0
VZ
367 wndclass.lpszClassName = wxMDIFrameClassName;
368 wndclass.style = styleNormal;
42e69d6b
VZ
369
370 if ( !RegisterClass(&wndclass) )
e5c0b16a 371 {
f6bcfd97 372 wxLogLastError(wxT("RegisterClass(MDI parent)"));
e5c0b16a
VZ
373 }
374
193fe989 375 // "no redraw" MDI frame
b782f2e0 376 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
193fe989
VZ
377 wndclass.style = styleNoRedraw;
378
379 if ( !RegisterClass(&wndclass) )
380 {
f6bcfd97 381 wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)"));
193fe989
VZ
382 }
383
e5c0b16a 384 // Register the MDI child frame window class.
42e69d6b
VZ
385 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
386 wndclass.lpszClassName = wxMDIChildFrameClassName;
b782f2e0 387 wndclass.style = styleNormal;
42e69d6b
VZ
388
389 if ( !RegisterClass(&wndclass) )
e5c0b16a 390 {
f6bcfd97 391 wxLogLastError(wxT("RegisterClass(MDI child)"));
e5c0b16a
VZ
392 }
393
193fe989
VZ
394 // "no redraw" MDI child frame
395 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
396 wndclass.style = styleNoRedraw;
397
398 if ( !RegisterClass(&wndclass) )
399 {
f6bcfd97 400 wxLogLastError(wxT("RegisterClass(no redraw MDI child)"));
193fe989
VZ
401 }
402
77c46f00 403 return true;
2bda0e17
KB
404}
405
9787a4b6
VZ
406// ---------------------------------------------------------------------------
407// UnregisterWindowClasses
408// ---------------------------------------------------------------------------
409
410bool wxApp::UnregisterWindowClasses()
411{
77c46f00 412 bool retval = true;
9787a4b6 413
c67d6888 414#ifndef __WXMICROWIN__
9787a4b6 415 // MDI frame window class.
03baf031 416 if ( !::UnregisterClass(wxMDIFrameClassName, wxhInstance) )
9787a4b6
VZ
417 {
418 wxLogLastError(wxT("UnregisterClass(MDI parent)"));
419
77c46f00 420 retval = false;
9787a4b6
VZ
421 }
422
423 // "no redraw" MDI frame
03baf031 424 if ( !::UnregisterClass(wxMDIFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
425 {
426 wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)"));
427
77c46f00 428 retval = false;
9787a4b6
VZ
429 }
430
431 // MDI child frame window class.
03baf031 432 if ( !::UnregisterClass(wxMDIChildFrameClassName, wxhInstance) )
9787a4b6
VZ
433 {
434 wxLogLastError(wxT("UnregisterClass(MDI child)"));
435
77c46f00 436 retval = false;
9787a4b6
VZ
437 }
438
439 // "no redraw" MDI child frame
03baf031 440 if ( !::UnregisterClass(wxMDIChildFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
441 {
442 wxLogLastError(wxT("UnregisterClass(no redraw MDI child)"));
443
77c46f00 444 retval = false;
9787a4b6
VZ
445 }
446
03baf031
VZ
447 // canvas class name
448 if ( !::UnregisterClass(wxCanvasClassName, wxhInstance) )
9787a4b6
VZ
449 {
450 wxLogLastError(wxT("UnregisterClass(canvas)"));
451
77c46f00 452 retval = false;
9787a4b6
VZ
453 }
454
03baf031 455 if ( !::UnregisterClass(wxCanvasClassNameNR, wxhInstance) )
9787a4b6
VZ
456 {
457 wxLogLastError(wxT("UnregisterClass(no redraw canvas)"));
458
77c46f00 459 retval = false;
9787a4b6 460 }
03baf031
VZ
461#endif // __WXMICROWIN__
462
9787a4b6
VZ
463 return retval;
464}
465
bb6290e3 466void wxApp::CleanUp()
2bda0e17 467{
7a9dfa3c
VZ
468 // all objects pending for deletion must be deleted first, otherwise we
469 // would crash when they use wxWinHandleHash (and UnregisterWindowClasses()
470 // call wouldn't succeed as long as any windows still exist), so call the
471 // base class method first and only then do our clean up
472 wxAppBase::CleanUp();
473
4676948b 474#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
77c46f00 475 wxSetKeyboardHook(false);
04ef50df 476#endif
2bda0e17 477
360ae33f 478 wxOleUninitialize();
2bda0e17 479
9787a4b6
VZ
480 // for an EXE the classes are unregistered when it terminates but DLL may
481 // be loaded several times (load/unload/load) into the same process in
482 // which case the registration will fail after the first time if we don't
483 // unregister the classes now
484 UnregisterWindowClasses();
9787a4b6 485
1bffa913 486 delete wxWinHandleHash;
94826170 487 wxWinHandleHash = NULL;
a71d815b 488
46fa338b
RR
489#ifdef __WXWINCE__
490 free( wxCanvasClassName );
491 free( wxCanvasClassNameNR );
492#endif
2bda0e17
KB
493}
494
94826170
VZ
495// ----------------------------------------------------------------------------
496// wxApp ctor/dtor
497// ----------------------------------------------------------------------------
589f0e3e 498
bb6290e3 499wxApp::wxApp()
2bda0e17 500{
e5c0b16a 501 m_printMode = wxPRINT_WINDOWS;
2bda0e17
KB
502}
503
589f0e3e
JS
504wxApp::~wxApp()
505{
589f0e3e
JS
506}
507
6046e57a
VZ
508// ----------------------------------------------------------------------------
509// wxApp idle handling
510// ----------------------------------------------------------------------------
511
2bda0e17
KB
512void wxApp::OnIdle(wxIdleEvent& event)
513{
955a9197 514 wxAppBase::OnIdle(event);
c54f78a2 515
aef94d68
JS
516#if wxUSE_DC_CACHEING
517 // automated DC cache management: clear the cached DCs and bitmap
518 // if it's likely that the app has finished with them, that is, we
519 // get an idle event and we're not dragging anything.
4624defa 520 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
aef94d68
JS
521 wxDC::ClearCache();
522#endif // wxUSE_DC_CACHEING
2bda0e17
KB
523}
524
e2478fde
VZ
525void wxApp::WakeUpIdle()
526{
527 // Send the top window a dummy message so idle handler processing will
528 // start up again. Doing it this way ensures that the idle handler
529 // wakes up in the right thread (see also wxWakeUpMainThread() which does
530 // the same for the main app thread only)
531 wxWindow *topWindow = wxTheApp->GetTopWindow();
532 if ( topWindow )
533 {
534 if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
535 {
536 // should never happen
537 wxLogLastError(wxT("PostMessage(WM_NULL)"));
538 }
539 }
540}
541
6046e57a
VZ
542// ----------------------------------------------------------------------------
543// other wxApp event hanlders
544// ----------------------------------------------------------------------------
545
57c208c5 546void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
547{
548 if (GetTopWindow())
77c46f00 549 GetTopWindow()->Close(true);
387a3b02
JS
550}
551
552// Default behaviour: close the application with prompts. The
553// user can veto the close, and therefore the end session.
554void wxApp::OnQueryEndSession(wxCloseEvent& event)
555{
556 if (GetTopWindow())
557 {
558 if (!GetTopWindow()->Close(!event.CanVeto()))
77c46f00 559 event.Veto(true);
387a3b02
JS
560 }
561}
562
6046e57a
VZ
563// ----------------------------------------------------------------------------
564// miscellaneous
565// ----------------------------------------------------------------------------
566
6d167489
VZ
567/* static */
568int wxApp::GetComCtl32Version()
569{
fd7b70bd 570#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
04ef50df
JS
571 return 0;
572#else
6d167489 573 // cache the result
9fc6c21c
VZ
574 //
575 // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice,
576 // but as its value should be the same both times it doesn't matter
bdc72a22
VZ
577 static int s_verComCtl32 = -1;
578
6d167489
VZ
579 if ( s_verComCtl32 == -1 )
580 {
bdc72a22 581 // initally assume no comctl32.dll at all
6d167489
VZ
582 s_verComCtl32 = 0;
583
9fc6c21c
VZ
584 // we're prepared to handle the errors
585 wxLogNull noLog;
64c288fa
JS
586
587#if wxUSE_DYNLIB_CLASS
bdc72a22 588 // do we have it?
9fc6c21c 589 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
6d167489
VZ
590
591 // if so, then we can check for the version
9fc6c21c 592 if ( dllComCtl32.IsLoaded() )
bb6290e3 593 {
25a11614 594 // now check if the function is available during run-time
9fc6c21c
VZ
595 wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 );
596 if ( pfnDllGetVersion )
597 {
598 DLLVERSIONINFO dvi;
599 dvi.cbSize = sizeof(dvi);
600
601 HRESULT hr = (*pfnDllGetVersion)(&dvi);
602 if ( FAILED(hr) )
6d167489 603 {
9fc6c21c
VZ
604 wxLogApiError(_T("DllGetVersion"), hr);
605 }
606 else
607 {
608 // this is incompatible with _WIN32_IE values, but
609 // compatible with the other values returned by
610 // GetComCtl32Version()
611 s_verComCtl32 = 100*dvi.dwMajorVersion +
612 dvi.dwMinorVersion;
613 }
614 }
bdc72a22 615
9fc6c21c
VZ
616 // if DllGetVersion() is unavailable either during compile or
617 // run-time, try to guess the version otherwise
618 if ( !s_verComCtl32 )
619 {
620 // InitCommonControlsEx is unique to 4.70 and later
621 void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx"));
622 if ( !pfn )
623 {
624 // not found, must be 4.00
625 s_verComCtl32 = 400;
6d167489 626 }
9fc6c21c 627 else // 4.70+
bdc72a22 628 {
9fc6c21c
VZ
629 // many symbols appeared in comctl32 4.71, could use any of
630 // them except may be DllInstall()
631 pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB"));
632 if ( !pfn )
bdc72a22 633 {
9fc6c21c
VZ
634 // not found, must be 4.70
635 s_verComCtl32 = 470;
bdc72a22
VZ
636 }
637 else
638 {
9fc6c21c
VZ
639 // found, must be 4.71 or later
640 s_verComCtl32 = 471;
bdc72a22 641 }
6d167489 642 }
9fc6c21c 643 }
ef094fa0 644 }
64c288fa 645#endif
bb6290e3 646 }
6d167489
VZ
647
648 return s_verComCtl32;
9fc6c21c 649#endif // Microwin/!Microwin
bb6290e3
JS
650}
651
2bda0e17 652// Yield to incoming messages
cb2713bf 653
8461e4c2 654bool wxApp::Yield(bool onlyIfNeeded)
2bda0e17 655{
8461e4c2 656 // MT-FIXME
77c46f00 657 static bool s_inYield = false;
8461e4c2 658
e30285ab 659#if wxUSE_LOG
2ed3265e
VZ
660 // disable log flushing from here because a call to wxYield() shouldn't
661 // normally result in message boxes popping up &c
662 wxLog::Suspend();
e30285ab 663#endif // wxUSE_LOG
2ed3265e 664
8461e4c2
VZ
665 if ( s_inYield )
666 {
667 if ( !onlyIfNeeded )
668 {
669 wxFAIL_MSG( wxT("wxYield called recursively" ) );
670 }
33ac7e6f 671
77c46f00 672 return false;
8461e4c2
VZ
673 }
674
77c46f00 675 s_inYield = true;
cb2713bf 676
8e193f38
VZ
677 // we don't want to process WM_QUIT from here - it should be processed in
678 // the main event loop in order to stop it
e5c0b16a 679 MSG msg;
8e193f38
VZ
680 while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
681 msg.message != WM_QUIT )
e5c0b16a 682 {
5b615ed8
VZ
683#if wxUSE_THREADS
684 wxMutexGuiLeaveOrEnter();
685#endif // wxUSE_THREADS
686
1bf77ee5 687 if ( !wxTheApp->Dispatch() )
e5c0b16a
VZ
688 break;
689 }
8e193f38 690
8461e4c2
VZ
691 // if there are pending events, we must process them.
692 ProcessPendingEvents();
e5c0b16a 693
e30285ab 694#if wxUSE_LOG
2ed3265e
VZ
695 // let the logs be flashed again
696 wxLog::Resume();
e30285ab 697#endif // wxUSE_LOG
2ed3265e 698
77c46f00 699 s_inYield = false;
cb2713bf 700
77c46f00 701 return true;
2bda0e17 702}
094637f6 703
6046e57a
VZ
704#if wxUSE_EXCEPTIONS
705
706// ----------------------------------------------------------------------------
707// exception handling
708// ----------------------------------------------------------------------------
709
710bool wxApp::OnExceptionInMainLoop()
711{
712 // ask the user about what to do: use the Win32 API function here as it
77ffb593 713 // could be dangerous to use any wxWidgets code in this state
6046e57a
VZ
714 switch (
715 ::MessageBox
716 (
717 NULL,
718 _T("An unhandled exception occurred. Press \"Abort\" to \
719terminate the program,\r\n\
720\"Retry\" to exit the program normally and \"Ignore\" to try to continue."),
721 _T("Unhandled exception"),
722 MB_ABORTRETRYIGNORE |
a71d815b 723 MB_ICONERROR|
6046e57a
VZ
724 MB_TASKMODAL
725 )
726 )
727 {
728 case IDABORT:
729 throw;
730
731 default:
732 wxFAIL_MSG( _T("unexpected MessageBox() return code") );
733 // fall through
734
735 case IDRETRY:
736 return false;
737
738 case IDIGNORE:
739 return true;
740 }
741}
742
743#endif // wxUSE_EXCEPTIONS
51036b44
VZ
744
745// ----------------------------------------------------------------------------
746// deprecated event loop functions
747// ----------------------------------------------------------------------------
748
749#if WXWIN_COMPATIBILITY_2_4
750
751#include "wx/evtloop.h"
752
753void wxApp::DoMessage(WXMSG *pMsg)
754{
755 wxEventLoop *evtLoop = wxEventLoop::GetActive();
756 if ( evtLoop )
757 evtLoop->ProcessMessage(pMsg);
758}
759
760bool wxApp::DoMessage()
761{
762 wxEventLoop *evtLoop = wxEventLoop::GetActive();
763 return evtLoop ? evtLoop->Dispatch() : false;
764}
765
766bool wxApp::ProcessMessage(WXMSG* pMsg)
767{
768 wxEventLoop *evtLoop = wxEventLoop::GetActive();
769 return evtLoop && evtLoop->PreProcessMessage(pMsg);
770}
771
772#endif // WXWIN_COMPATIBILITY_2_4