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