]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
Added wxMGL switch
[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
JS
8// Copyright: (c) Julian Smart
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
RR
56#include "wx/msw/private.h"
57
8614c467
VZ
58#if wxUSE_TOOLTIPS
59 #include "wx/tooltip.h"
60#endif // wxUSE_TOOLTIPS
61
c42404a5
VZ
62// OLE is used for drag-and-drop, clipboard, OLE Automation..., but some
63// compilers don't support it (missing headers, libs, ...)
2bdf7154 64#if defined(__GNUWIN32_OLD__) || defined(__SYMANTEC__) || defined(__SALFORDC__)
e5c0b16a
VZ
65 #undef wxUSE_OLE
66
67 #define wxUSE_OLE 0
68#endif // broken compilers
69
70#if wxUSE_OLE
6e0d9d43 71 #include <ole2.h>
d05237ea 72#endif
ce3ed50d 73
2bda0e17 74#include <string.h>
a5e0e655 75#include <ctype.h>
2bda0e17 76
0d236fd0 77#include "wx/msw/wrapcctl.h"
bdc72a22 78
9fc6c21c 79#if (!defined(__MINGW32__) || wxCHECK_W32API_VERSION( 2, 0 )) && \
50165591 80 !defined(__CYGWIN__) && !defined(__DIGITALMARS__) && !defined(__WXWINCE__) && \
1bf77ee5 81 (!defined(_MSC_VER) || (_MSC_VER > 1100))
036bc7d9
VZ
82 #include <shlwapi.h>
83#endif
84
e5c0b16a
VZ
85// ---------------------------------------------------------------------------
86// global variables
87// ---------------------------------------------------------------------------
88
cde9f08e 89extern wxList WXDLLEXPORT wxPendingDelete;
4676948b
JS
90
91#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2bda0e17 92extern void wxSetKeyboardHook(bool doIt);
04ef50df 93#endif
2bda0e17 94
193fe989
VZ
95// NB: all "NoRedraw" classes must have the same names as the "normal" classes
96// with NR suffix - wxWindow::MSWCreate() supposes this
03baf031
VZ
97const wxChar *wxCanvasClassName = wxT("wxWindowClass");
98const wxChar *wxCanvasClassNameNR = wxT("wxWindowClassNR");
2ffa221c
VZ
99const wxChar *wxMDIFrameClassName = wxT("wxMDIFrameClass");
100const wxChar *wxMDIFrameClassNameNoRedraw = wxT("wxMDIFrameClassNR");
101const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
102const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
2bda0e17 103
57c208c5 104HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
2bda0e17 105
94826170
VZ
106// ----------------------------------------------------------------------------
107// private functions
108// ----------------------------------------------------------------------------
2bda0e17 109
94826170 110LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
3b415ba4 111
e5c0b16a 112// ===========================================================================
e2478fde
VZ
113// wxGUIAppTraits implementation
114// ===========================================================================
115
116// private class which we use to pass parameters from BeforeChildWaitLoop() to
117// AfterChildWaitLoop()
118struct ChildWaitLoopData
119{
120 ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *winActive_)
121 {
122 wd = wd_;
123 winActive = winActive_;
124 }
125
126 wxWindowDisabler *wd;
127 wxWindow *winActive;
128};
129
130void *wxGUIAppTraits::BeforeChildWaitLoop()
131{
132 /*
133 We use a dirty hack here to disable all application windows (which we
134 must do because otherwise the calls to wxYield() could lead to some very
135 unexpected reentrancies in the users code) but to avoid losing
136 focus/activation entirely when the child process terminates which would
137 happen if we simply disabled everything using wxWindowDisabler. Indeed,
138 remember that Windows will never activate a disabled window and when the
139 last childs window is closed and Windows looks for a window to activate
140 all our windows are still disabled. There is no way to enable them in
141 time because we don't know when the childs windows are going to be
142 closed, so the solution we use here is to keep one special tiny frame
143 enabled all the time. Then when the child terminates it will get
144 activated and when we close it below -- after reenabling all the other
145 windows! -- the previously active window becomes activated again and
146 everything is ok.
147 */
148 wxBeginBusyCursor();
149
150 // first disable all existing windows
151 wxWindowDisabler *wd = new wxWindowDisabler;
152
153 // then create an "invisible" frame: it has minimal size, is positioned
154 // (hopefully) outside the screen and doesn't appear on the taskbar
155 wxWindow *winActive = new wxFrame
156 (
157 wxTheApp->GetTopWindow(),
fda7962d
JS
158 wxID_ANY,
159 wxEmptyString,
e2478fde
VZ
160 wxPoint(32600, 32600),
161 wxSize(1, 1),
162 wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR
163 );
164 winActive->Show();
165
166 return new ChildWaitLoopData(wd, winActive);
167}
168
169void wxGUIAppTraits::AlwaysYield()
170{
171 wxYield();
172}
173
174void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig)
175{
176 wxEndBusyCursor();
177
178 const ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig;
179
180 delete data->wd;
181
182 // finally delete the dummy frame and, as wd has been already destroyed and
183 // the other windows reenabled, the activation is going to return to the
184 // window which had had it before
185 data->winActive->Destroy();
186}
187
188bool wxGUIAppTraits::DoMessageFromThreadWait()
189{
1bf77ee5
VZ
190 // we should return false only if the app should exit, i.e. only if
191 // Dispatch() determines that the main event loop should terminate
192 return !wxTheApp || wxTheApp->Dispatch();
e2478fde
VZ
193}
194
324899f6 195wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
a8eaaeb2 196{
1bf77ee5 197 static wxToolkitInfo info;
324899f6
VS
198 wxToolkitInfo& baseInfo = wxAppTraits::GetToolkitInfo();
199 info.versionMajor = baseInfo.versionMajor;
200 info.versionMinor = baseInfo.versionMinor;
201 info.os = baseInfo.os;
a8eaaeb2
VS
202 info.shortName = _T("msw");
203 info.name = _T("wxMSW");
204#ifdef __WXUNIVERSAL__
205 info.shortName << _T("univ");
206 info.name << _T("/wxUniversal");
207#endif
324899f6 208 return info;
a8eaaeb2
VS
209}
210
e2478fde
VZ
211// ===========================================================================
212// wxApp implementation
e5c0b16a 213// ===========================================================================
589f0e3e 214
94826170
VZ
215int wxApp::m_nCmdShow = SW_SHOWNORMAL;
216
e5c0b16a 217// ---------------------------------------------------------------------------
e2478fde 218// wxWin macros
e5c0b16a
VZ
219// ---------------------------------------------------------------------------
220
f6bcfd97 221IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
e5c0b16a 222
f6bcfd97
BP
223BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
224 EVT_IDLE(wxApp::OnIdle)
225 EVT_END_SESSION(wxApp::OnEndSession)
226 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
227END_EVENT_TABLE()
e5c0b16a 228
94826170
VZ
229// class to ensure that wxAppBase::CleanUp() is called if our Initialize()
230// fails
231class wxCallBaseCleanup
232{
233public:
234 wxCallBaseCleanup(wxApp *app) : m_app(app) { }
235 ~wxCallBaseCleanup() { if ( m_app ) m_app->wxAppBase::CleanUp(); }
236
237 void Dismiss() { m_app = NULL; }
238
239private:
240 wxApp *m_app;
241};
242
e5c0b16a 243//// Initialize
05e2b077 244bool wxApp::Initialize(int& argc, wxChar **argv)
2bda0e17 245{
94826170
VZ
246 if ( !wxAppBase::Initialize(argc, argv) )
247 return false;
248
249 // ensure that base cleanup is done if we return too early
250 wxCallBaseCleanup callBaseCleanup(this);
251
f6bcfd97 252 // the first thing to do is to check if we're trying to run an Unicode
7c9955d1 253 // program under Win9x w/o MSLU emulation layer - if so, abort right now
dfc40ef3 254 // as it has no chance to work
eb5e4d9a 255#if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
f07dc2e2 256 if ( wxGetOsVersion() != wxWINDOWS_NT && wxGetOsVersion() != wxWINDOWS_CE )
f6bcfd97
BP
257 {
258 // note that we can use MessageBoxW() as it's implemented even under
259 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
260 // used by wxLocale are not
261 ::MessageBox
262 (
263 NULL,
f07dc2e2 264 _T("This program uses Unicode and requires Windows NT/2000/XP/CE.\nProgram aborted."),
f6bcfd97
BP
265 _T("wxWindows Fatal Error"),
266 MB_ICONERROR | MB_OK
267 );
268
269 return FALSE;
270 }
eb5e4d9a 271#endif // wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
f6bcfd97 272
04ef50df 273#if defined(__WIN95__) && !defined(__WXMICROWIN__)
a5e0e655 274 InitCommonControls();
e5c0b16a 275#endif // __WIN95__
2bda0e17 276
8cb172b4 277#if wxUSE_OLE || wxUSE_DRAG_AND_DROP
c49245f8
VZ
278
279#ifdef __WIN16__
e5c0b16a 280 // for OLE, enlarge message queue to be as large as possible
aa0b7e1e 281 int iMsg = 96;
c49245f8
VZ
282 while (!SetMessageQueue(iMsg) && (iMsg -= 8))
283 ;
284#endif // Win16
8cb172b4 285
abad5367 286#if wxUSE_OLE
a5e0e655 287 // we need to initialize OLE library
f07dc2e2
JS
288#ifdef __WXWINCE__
289 if ( FAILED(::CoInitializeEx(NULL, COINIT_MULTITHREADED)) )
290 wxLogError(_("Cannot initialize OLE"));
291#else
a5e0e655 292 if ( FAILED(::OleInitialize(NULL)) )
e5c0b16a 293 wxLogError(_("Cannot initialize OLE"));
abad5367 294#endif
f07dc2e2 295#endif
1e6feb95 296
c49245f8 297#endif // wxUSE_OLE
2bda0e17 298
1f112209 299#if wxUSE_CTL3D
a5e0e655 300 if (!Ctl3dRegister(wxhInstance))
223d09f6 301 wxLogError(wxT("Cannot register CTL3D"));
2bda0e17 302
a5e0e655 303 Ctl3dAutoSubclass(wxhInstance);
1e6feb95 304#endif // wxUSE_CTL3D
2bda0e17 305
aa0b7e1e 306 RegisterWindowClasses();
2bda0e17 307
4676948b 308#if defined(__WXMICROWIN__) && !defined(__WXWINCE__)
aa0b7e1e 309 // Create the brush for disabling bitmap buttons
2bda0e17 310
42e69d6b 311 LOGBRUSH lb;
aa0b7e1e 312 lb.lbStyle = BS_PATTERN;
097f29c2 313 lb.lbColor = 0;
223d09f6 314 lb.lbHatch = (int)LoadBitmap( wxhInstance, wxT("wxDISABLE_BUTTON_BITMAP") );
3a5ffa81
VZ
315 if ( lb.lbHatch )
316 {
317 wxDisableButtonBrush = ::CreateBrushIndirect( & lb );
318 ::DeleteObject( (HGDIOBJ)lb.lbHatch );
319 }
320 //else: wxWindows resources are probably not linked in
04ef50df 321#endif
2bda0e17 322
aa0b7e1e 323#if wxUSE_PENWINDOWS
a5e0e655 324 wxRegisterPenWin();
aa0b7e1e 325#endif
2bda0e17 326
1bffa913 327 wxWinHandleHash = new wxWinHashTable(wxKEY_INTEGER, 100);
2bda0e17 328
6e0d9d43 329 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
8cbd2bde 330 // PLEASE DO NOT ALTER THIS.
7fee680b 331#if defined(__VISUALC__) && defined(__WIN16__) && !defined(WXMAKINGDLL)
a5e0e655
VZ
332 extern char wxDummyChar;
333 if (wxDummyChar) wxDummyChar++;
aa0b7e1e 334#endif
a5e0e655 335
4676948b 336#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
aa0b7e1e 337 wxSetKeyboardHook(TRUE);
04ef50df 338#endif
2bda0e17 339
94826170
VZ
340 callBaseCleanup.Dismiss();
341
342 return true;
2bda0e17
KB
343}
344
42e69d6b
VZ
345// ---------------------------------------------------------------------------
346// RegisterWindowClasses
347// ---------------------------------------------------------------------------
589f0e3e 348
b782f2e0
VZ
349// TODO we should only register classes really used by the app. For this it
350// would be enough to just delay the class registration until an attempt
351// to create a window of this class is made.
bb6290e3 352bool wxApp::RegisterWindowClasses()
2bda0e17 353{
42e69d6b 354 WNDCLASS wndclass;
03baf031 355 wxZeroMemory(wndclass);
e5c0b16a 356
193fe989
VZ
357 // for each class we register one with CS_(V|H)REDRAW style and one
358 // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
359 static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
360 static const long styleNoRedraw = CS_DBLCLKS;
361
42e69d6b 362 // the fields which are common to all classes
e5c0b16a 363 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
e5c0b16a 364 wndclass.hInstance = wxhInstance;
42e69d6b 365 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
42e69d6b
VZ
366
367 // Register the frame window class.
368 wndclass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
03baf031 369 wndclass.lpszClassName = wxCanvasClassName;
b782f2e0 370 wndclass.style = styleNormal;
e5c0b16a 371
42e69d6b 372 if ( !RegisterClass(&wndclass) )
e5c0b16a 373 {
f6bcfd97 374 wxLogLastError(wxT("RegisterClass(frame)"));
e5c0b16a
VZ
375 }
376
193fe989 377 // "no redraw" frame
03baf031 378 wndclass.lpszClassName = wxCanvasClassNameNR;
193fe989
VZ
379 wndclass.style = styleNoRedraw;
380
381 if ( !RegisterClass(&wndclass) )
382 {
f6bcfd97 383 wxLogLastError(wxT("RegisterClass(no redraw frame)"));
193fe989
VZ
384 }
385
e5c0b16a 386 // Register the MDI frame window class.
42e69d6b 387 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
b782f2e0
VZ
388 wndclass.lpszClassName = wxMDIFrameClassName;
389 wndclass.style = styleNormal;
42e69d6b
VZ
390
391 if ( !RegisterClass(&wndclass) )
e5c0b16a 392 {
f6bcfd97 393 wxLogLastError(wxT("RegisterClass(MDI parent)"));
e5c0b16a
VZ
394 }
395
193fe989 396 // "no redraw" MDI frame
b782f2e0 397 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
193fe989
VZ
398 wndclass.style = styleNoRedraw;
399
400 if ( !RegisterClass(&wndclass) )
401 {
f6bcfd97 402 wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)"));
193fe989
VZ
403 }
404
e5c0b16a 405 // Register the MDI child frame window class.
42e69d6b
VZ
406 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
407 wndclass.lpszClassName = wxMDIChildFrameClassName;
b782f2e0 408 wndclass.style = styleNormal;
42e69d6b
VZ
409
410 if ( !RegisterClass(&wndclass) )
e5c0b16a 411 {
f6bcfd97 412 wxLogLastError(wxT("RegisterClass(MDI child)"));
e5c0b16a
VZ
413 }
414
193fe989
VZ
415 // "no redraw" MDI child frame
416 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
417 wndclass.style = styleNoRedraw;
418
419 if ( !RegisterClass(&wndclass) )
420 {
f6bcfd97 421 wxLogLastError(wxT("RegisterClass(no redraw MDI child)"));
193fe989
VZ
422 }
423
e5c0b16a 424 return TRUE;
2bda0e17
KB
425}
426
9787a4b6
VZ
427// ---------------------------------------------------------------------------
428// UnregisterWindowClasses
429// ---------------------------------------------------------------------------
430
431bool wxApp::UnregisterWindowClasses()
432{
433 bool retval = TRUE;
434
c67d6888 435#ifndef __WXMICROWIN__
9787a4b6 436 // MDI frame window class.
03baf031 437 if ( !::UnregisterClass(wxMDIFrameClassName, wxhInstance) )
9787a4b6
VZ
438 {
439 wxLogLastError(wxT("UnregisterClass(MDI parent)"));
440
441 retval = FALSE;
442 }
443
444 // "no redraw" MDI frame
03baf031 445 if ( !::UnregisterClass(wxMDIFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
446 {
447 wxLogLastError(wxT("UnregisterClass(no redraw MDI parent frame)"));
448
449 retval = FALSE;
450 }
451
452 // MDI child frame window class.
03baf031 453 if ( !::UnregisterClass(wxMDIChildFrameClassName, wxhInstance) )
9787a4b6
VZ
454 {
455 wxLogLastError(wxT("UnregisterClass(MDI child)"));
456
457 retval = FALSE;
458 }
459
460 // "no redraw" MDI child frame
03baf031 461 if ( !::UnregisterClass(wxMDIChildFrameClassNameNoRedraw, wxhInstance) )
9787a4b6
VZ
462 {
463 wxLogLastError(wxT("UnregisterClass(no redraw MDI child)"));
464
465 retval = FALSE;
466 }
467
03baf031
VZ
468 // canvas class name
469 if ( !::UnregisterClass(wxCanvasClassName, wxhInstance) )
9787a4b6
VZ
470 {
471 wxLogLastError(wxT("UnregisterClass(canvas)"));
472
473 retval = FALSE;
474 }
475
03baf031 476 if ( !::UnregisterClass(wxCanvasClassNameNR, wxhInstance) )
9787a4b6
VZ
477 {
478 wxLogLastError(wxT("UnregisterClass(no redraw canvas)"));
479
480 retval = FALSE;
481 }
03baf031
VZ
482#endif // __WXMICROWIN__
483
9787a4b6
VZ
484 return retval;
485}
486
bb6290e3 487void wxApp::CleanUp()
2bda0e17 488{
7a9dfa3c
VZ
489 // all objects pending for deletion must be deleted first, otherwise we
490 // would crash when they use wxWinHandleHash (and UnregisterWindowClasses()
491 // call wouldn't succeed as long as any windows still exist), so call the
492 // base class method first and only then do our clean up
493 wxAppBase::CleanUp();
494
4676948b 495#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
e5c0b16a 496 wxSetKeyboardHook(FALSE);
04ef50df 497#endif
2bda0e17 498
47d67540 499#if wxUSE_PENWINDOWS
e5c0b16a 500 wxCleanUpPenWin();
2bda0e17
KB
501#endif
502
e5c0b16a 503 if ( wxDisableButtonBrush )
42e69d6b 504 ::DeleteObject( wxDisableButtonBrush );
e5c0b16a
VZ
505
506#if wxUSE_OLE
f07dc2e2
JS
507#ifdef __WXWINCE__
508 ::CoUninitialize();
509#else
e5c0b16a 510 ::OleUninitialize();
f07dc2e2 511#endif
5de5db0e 512#endif
2bda0e17 513
9787a4b6
VZ
514 // for an EXE the classes are unregistered when it terminates but DLL may
515 // be loaded several times (load/unload/load) into the same process in
516 // which case the registration will fail after the first time if we don't
517 // unregister the classes now
518 UnregisterWindowClasses();
9787a4b6 519
1f112209 520#if wxUSE_CTL3D
e5c0b16a 521 Ctl3dUnregister(wxhInstance);
2bda0e17
KB
522#endif
523
1bffa913 524 delete wxWinHandleHash;
94826170 525 wxWinHandleHash = NULL;
2bda0e17
KB
526}
527
94826170
VZ
528// ----------------------------------------------------------------------------
529// wxApp ctor/dtor
530// ----------------------------------------------------------------------------
589f0e3e 531
bb6290e3 532wxApp::wxApp()
2bda0e17 533{
e5c0b16a 534 m_printMode = wxPRINT_WINDOWS;
2bda0e17
KB
535}
536
589f0e3e
JS
537wxApp::~wxApp()
538{
94826170
VZ
539 // our cmd line arguments are allocated inside wxEntry(HINSTANCE), they
540 // don't come from main(), so we have to free them
541
542 while ( argc )
e5c0b16a 543 {
94826170
VZ
544 // m_argv elements were allocated by wxStrdup()
545 free(argv[--argc]);
e5c0b16a 546 }
94826170
VZ
547
548 // but m_argv itself -- using new[]
549 delete [] argv;
589f0e3e
JS
550}
551
bb6290e3 552bool wxApp::Initialized()
2bda0e17
KB
553{
554#ifndef _WINDLL
e5c0b16a
VZ
555 if (GetTopWindow())
556 return TRUE;
557 else
558 return FALSE;
3b415ba4 559#else // Assume initialized if DLL (no way of telling)
e5c0b16a 560 return TRUE;
2bda0e17
KB
561#endif
562}
563
2bda0e17
KB
564void wxApp::OnIdle(wxIdleEvent& event)
565{
955a9197 566 wxAppBase::OnIdle(event);
c54f78a2 567
aef94d68
JS
568#if wxUSE_DC_CACHEING
569 // automated DC cache management: clear the cached DCs and bitmap
570 // if it's likely that the app has finished with them, that is, we
571 // get an idle event and we're not dragging anything.
4624defa 572 if (!::GetKeyState(MK_LBUTTON) && !::GetKeyState(MK_MBUTTON) && !::GetKeyState(MK_RBUTTON))
aef94d68
JS
573 wxDC::ClearCache();
574#endif // wxUSE_DC_CACHEING
2bda0e17
KB
575}
576
e2478fde
VZ
577void wxApp::WakeUpIdle()
578{
579 // Send the top window a dummy message so idle handler processing will
580 // start up again. Doing it this way ensures that the idle handler
581 // wakes up in the right thread (see also wxWakeUpMainThread() which does
582 // the same for the main app thread only)
583 wxWindow *topWindow = wxTheApp->GetTopWindow();
584 if ( topWindow )
585 {
586 if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
587 {
588 // should never happen
589 wxLogLastError(wxT("PostMessage(WM_NULL)"));
590 }
591 }
592}
593
57c208c5 594void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
595{
596 if (GetTopWindow())
597 GetTopWindow()->Close(TRUE);
598}
599
600// Default behaviour: close the application with prompts. The
601// user can veto the close, and therefore the end session.
602void wxApp::OnQueryEndSession(wxCloseEvent& event)
603{
604 if (GetTopWindow())
605 {
606 if (!GetTopWindow()->Close(!event.CanVeto()))
607 event.Veto(TRUE);
608 }
609}
610
6d167489
VZ
611/* static */
612int wxApp::GetComCtl32Version()
613{
50165591
CE
614//FIX ME FOR DIGITALMARS!!
615#if defined(__WXMICROWIN__) || defined(__WXWINCE__) || defined(__DIGITALMARS__)
04ef50df
JS
616 return 0;
617#else
6d167489 618 // cache the result
9fc6c21c
VZ
619 //
620 // NB: this is MT-ok as in the worst case we'd compute s_verComCtl32 twice,
621 // but as its value should be the same both times it doesn't matter
bdc72a22
VZ
622 static int s_verComCtl32 = -1;
623
6d167489
VZ
624 if ( s_verComCtl32 == -1 )
625 {
bdc72a22 626 // initally assume no comctl32.dll at all
6d167489
VZ
627 s_verComCtl32 = 0;
628
9fc6c21c
VZ
629 // we're prepared to handle the errors
630 wxLogNull noLog;
631
bdc72a22 632 // do we have it?
9fc6c21c 633 wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
6d167489
VZ
634
635 // if so, then we can check for the version
9fc6c21c 636 if ( dllComCtl32.IsLoaded() )
bb6290e3 637 {
548bf4b7 638#ifdef DLLVER_PLATFORM_WINDOWS
bdc72a22 639 // try to use DllGetVersion() if available in _headers_
9fc6c21c
VZ
640 wxDYNLIB_FUNCTION( DLLGETVERSIONPROC, DllGetVersion, dllComCtl32 );
641 if ( pfnDllGetVersion )
642 {
643 DLLVERSIONINFO dvi;
644 dvi.cbSize = sizeof(dvi);
645
646 HRESULT hr = (*pfnDllGetVersion)(&dvi);
647 if ( FAILED(hr) )
6d167489 648 {
9fc6c21c
VZ
649 wxLogApiError(_T("DllGetVersion"), hr);
650 }
651 else
652 {
653 // this is incompatible with _WIN32_IE values, but
654 // compatible with the other values returned by
655 // GetComCtl32Version()
656 s_verComCtl32 = 100*dvi.dwMajorVersion +
657 dvi.dwMinorVersion;
658 }
659 }
548bf4b7 660#endif
bdc72a22 661
9fc6c21c
VZ
662 // if DllGetVersion() is unavailable either during compile or
663 // run-time, try to guess the version otherwise
664 if ( !s_verComCtl32 )
665 {
666 // InitCommonControlsEx is unique to 4.70 and later
667 void *pfn = dllComCtl32.GetSymbol(_T("InitCommonControlsEx"));
668 if ( !pfn )
669 {
670 // not found, must be 4.00
671 s_verComCtl32 = 400;
6d167489 672 }
9fc6c21c 673 else // 4.70+
bdc72a22 674 {
9fc6c21c
VZ
675 // many symbols appeared in comctl32 4.71, could use any of
676 // them except may be DllInstall()
677 pfn = dllComCtl32.GetSymbol(_T("InitializeFlatSB"));
678 if ( !pfn )
bdc72a22 679 {
9fc6c21c
VZ
680 // not found, must be 4.70
681 s_verComCtl32 = 470;
bdc72a22
VZ
682 }
683 else
684 {
9fc6c21c
VZ
685 // found, must be 4.71 or later
686 s_verComCtl32 = 471;
bdc72a22 687 }
6d167489 688 }
9fc6c21c 689 }
ef094fa0 690 }
bb6290e3 691 }
6d167489
VZ
692
693 return s_verComCtl32;
9fc6c21c 694#endif // Microwin/!Microwin
bb6290e3
JS
695}
696
2bda0e17 697// Yield to incoming messages
cb2713bf 698
8461e4c2 699bool wxApp::Yield(bool onlyIfNeeded)
2bda0e17 700{
8461e4c2
VZ
701 // MT-FIXME
702 static bool s_inYield = FALSE;
703
e30285ab 704#if wxUSE_LOG
2ed3265e
VZ
705 // disable log flushing from here because a call to wxYield() shouldn't
706 // normally result in message boxes popping up &c
707 wxLog::Suspend();
e30285ab 708#endif // wxUSE_LOG
2ed3265e 709
8461e4c2
VZ
710 if ( s_inYield )
711 {
712 if ( !onlyIfNeeded )
713 {
714 wxFAIL_MSG( wxT("wxYield called recursively" ) );
715 }
33ac7e6f 716
8461e4c2
VZ
717 return FALSE;
718 }
719
720 s_inYield = TRUE;
cb2713bf 721
8e193f38
VZ
722 // we don't want to process WM_QUIT from here - it should be processed in
723 // the main event loop in order to stop it
e5c0b16a 724 MSG msg;
8e193f38
VZ
725 while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
726 msg.message != WM_QUIT )
e5c0b16a 727 {
5b615ed8
VZ
728#if wxUSE_THREADS
729 wxMutexGuiLeaveOrEnter();
730#endif // wxUSE_THREADS
731
1bf77ee5 732 if ( !wxTheApp->Dispatch() )
e5c0b16a
VZ
733 break;
734 }
8e193f38 735
8461e4c2
VZ
736 // if there are pending events, we must process them.
737 ProcessPendingEvents();
e5c0b16a 738
e30285ab 739#if wxUSE_LOG
2ed3265e
VZ
740 // let the logs be flashed again
741 wxLog::Resume();
e30285ab 742#endif // wxUSE_LOG
2ed3265e 743
8461e4c2 744 s_inYield = FALSE;
cb2713bf 745
e5c0b16a 746 return TRUE;
2bda0e17 747}
094637f6 748