]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
use wxDiskspaceSize_t which is long and not wxLongLong if wxUSE_LONGLONG==0 (part...
[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{
94826170
VZ
506 // our cmd line arguments are allocated inside wxEntry(HINSTANCE), they
507 // don't come from main(), so we have to free them
508
509 while ( argc )
e5c0b16a 510 {
94826170
VZ
511 // m_argv elements were allocated by wxStrdup()
512 free(argv[--argc]);
e5c0b16a 513 }
94826170
VZ
514
515 // but m_argv itself -- using new[]
516 delete [] argv;
589f0e3e
JS
517}
518
6046e57a
VZ
519// ----------------------------------------------------------------------------
520// wxApp idle handling
521// ----------------------------------------------------------------------------
522
2bda0e17
KB
523void wxApp::OnIdle(wxIdleEvent& event)
524{
955a9197 525 wxAppBase::OnIdle(event);
c54f78a2 526
aef94d68
JS
527#if wxUSE_DC_CACHEING
528 // automated DC cache management: clear the cached DCs and bitmap
529 // if it's likely that the app has finished with them, that is, we
530 // get an idle event and we're not dragging anything.
4624defa 531 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
aef94d68
JS
532 wxDC::ClearCache();
533#endif // wxUSE_DC_CACHEING
2bda0e17
KB
534}
535
e2478fde
VZ
536void wxApp::WakeUpIdle()
537{
538 // Send the top window a dummy message so idle handler processing will
539 // start up again. Doing it this way ensures that the idle handler
540 // wakes up in the right thread (see also wxWakeUpMainThread() which does
541 // the same for the main app thread only)
542 wxWindow *topWindow = wxTheApp->GetTopWindow();
543 if ( topWindow )
544 {
545 if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
546 {
547 // should never happen
548 wxLogLastError(wxT("PostMessage(WM_NULL)"));
549 }
550 }
551}
552
6046e57a
VZ
553// ----------------------------------------------------------------------------
554// other wxApp event hanlders
555// ----------------------------------------------------------------------------
556
57c208c5 557void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
558{
559 if (GetTopWindow())
77c46f00 560 GetTopWindow()->Close(true);
387a3b02
JS
561}
562
563// Default behaviour: close the application with prompts. The
564// user can veto the close, and therefore the end session.
565void wxApp::OnQueryEndSession(wxCloseEvent& event)
566{
567 if (GetTopWindow())
568 {
569 if (!GetTopWindow()->Close(!event.CanVeto()))
77c46f00 570 event.Veto(true);
387a3b02
JS
571 }
572}
573
6046e57a
VZ
574// ----------------------------------------------------------------------------
575// miscellaneous
576// ----------------------------------------------------------------------------
577
6d167489
VZ
578/* static */
579int wxApp::GetComCtl32Version()
580{
fd7b70bd 581#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
04ef50df
JS
582 return 0;
583#else
6d167489 584 // cache the result
9fc6c21c
VZ
585 //
586 // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice,
587 // but as its value should be the same both times it doesn't matter
bdc72a22
VZ
588 static int s_verComCtl32 = -1;
589
6d167489
VZ
590 if ( s_verComCtl32 == -1 )
591 {
bdc72a22 592 // initally assume no comctl32.dll at all
6d167489
VZ
593 s_verComCtl32 = 0;
594
9fc6c21c
VZ
595 // we're prepared to handle the errors
596 wxLogNull noLog;
64c288fa
JS
597
598#if wxUSE_DYNLIB_CLASS
bdc72a22 599 // do we have it?
9fc6c21c 600 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
6d167489
VZ
601
602 // if so, then we can check for the version
9fc6c21c 603 if ( dllComCtl32.IsLoaded() )
bb6290e3 604 {
25a11614 605 // now check if the function is available during run-time
9fc6c21c
VZ
606 wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 );
607 if ( pfnDllGetVersion )
608 {
609 DLLVERSIONINFO dvi;
610 dvi.cbSize = sizeof(dvi);
611
612 HRESULT hr = (*pfnDllGetVersion)(&dvi);
613 if ( FAILED(hr) )
6d167489 614 {
9fc6c21c
VZ
615 wxLogApiError(_T("DllGetVersion"), hr);
616 }
617 else
618 {
619 // this is incompatible with _WIN32_IE values, but
620 // compatible with the other values returned by
621 // GetComCtl32Version()
622 s_verComCtl32 = 100*dvi.dwMajorVersion +
623 dvi.dwMinorVersion;
624 }
625 }
bdc72a22 626
9fc6c21c
VZ
627 // if DllGetVersion() is unavailable either during compile or
628 // run-time, try to guess the version otherwise
629 if ( !s_verComCtl32 )
630 {
631 // InitCommonControlsEx is unique to 4.70 and later
632 void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx"));
633 if ( !pfn )
634 {
635 // not found, must be 4.00
636 s_verComCtl32 = 400;
6d167489 637 }
9fc6c21c 638 else // 4.70+
bdc72a22 639 {
9fc6c21c
VZ
640 // many symbols appeared in comctl32 4.71, could use any of
641 // them except may be DllInstall()
642 pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB"));
643 if ( !pfn )
bdc72a22 644 {
9fc6c21c
VZ
645 // not found, must be 4.70
646 s_verComCtl32 = 470;
bdc72a22
VZ
647 }
648 else
649 {
9fc6c21c
VZ
650 // found, must be 4.71 or later
651 s_verComCtl32 = 471;
bdc72a22 652 }
6d167489 653 }
9fc6c21c 654 }
ef094fa0 655 }
64c288fa 656#endif
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 |
a71d815b 734 MB_ICONERROR|
6046e57a
VZ
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