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