]> git.saurik.com Git - wxWidgets.git/blame - src/msw/app.cpp
wxUSE_RICHeDIT added
[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$
8// Copyright: (c) Julian Smart and Markus Holzem
a5e0e655 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
e5c0b16a
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
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"
2bda0e17
KB
48#endif
49
2bda0e17
KB
50#include "wx/log.h"
51#include "wx/module.h"
4bf78aae 52
4286a5b5
RR
53#include "wx/msw/private.h"
54
4bf78aae 55#if wxUSE_THREADS
bee503b0
VZ
56 #include "wx/thread.h"
57
58 // define the array of MSG strutures
59 WX_DECLARE_OBJARRAY(MSG, wxMsgArray);
60
61 #include "wx/arrimpl.cpp"
62
63 WX_DEFINE_OBJARRAY(wxMsgArray);
64#endif // wxUSE_THREADS
2bda0e17 65
47d67540 66#if wxUSE_WX_RESOURCES
e5c0b16a 67 #include "wx/resource.h"
2bda0e17
KB
68#endif
69
e5c0b16a 70// OLE is used for drag-and-drop, clipboard, OLE Automation...
7dee726c 71#ifndef wxUSE_NORLANDER_HEADERS
e5c0b16a
VZ
72#if defined(__GNUWIN32__) || defined(__SC__) || defined(__SALFORDC__)
73 #undef wxUSE_OLE
74
75 #define wxUSE_OLE 0
76#endif // broken compilers
7dee726c 77#endif
e5c0b16a
VZ
78
79#if wxUSE_OLE
6e0d9d43 80 #include <ole2.h>
d05237ea 81#endif
ce3ed50d 82
2bda0e17 83#include <string.h>
a5e0e655 84#include <ctype.h>
2bda0e17 85
65fd5cb0 86#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
e5c0b16a 87 #include <commctrl.h>
2bda0e17
KB
88#endif
89
6e0d9d43 90#include "wx/msw/msvcrt.h"
370382c7 91
e5c0b16a
VZ
92// ---------------------------------------------------------------------------
93// global variables
94// ---------------------------------------------------------------------------
95
837e5743
OK
96extern wxChar *wxBuffer;
97extern wxChar *wxOsVersion;
2bda0e17 98extern wxList *wxWinHandleList;
cde9f08e 99extern wxList WXDLLEXPORT wxPendingDelete;
2bda0e17
KB
100extern void wxSetKeyboardHook(bool doIt);
101extern wxCursor *g_globalCursor;
102
c4e7c2aa 103HINSTANCE wxhInstance = 0;
42e69d6b 104MSG s_currentMsg;
2bda0e17
KB
105wxApp *wxTheApp = NULL;
106
e5c0b16a 107// FIXME why not const? and not static?
193fe989
VZ
108
109// NB: all "NoRedraw" classes must have the same names as the "normal" classes
110// with NR suffix - wxWindow::MSWCreate() supposes this
223d09f6
KB
111wxChar wxFrameClassName[] = wxT("wxFrameClass");
112wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
113wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
114wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
115wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
116wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
117wxChar wxPanelClassName[] = wxT("wxPanelClass");
118wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
2bda0e17 119
57c208c5
JS
120HICON wxSTD_FRAME_ICON = (HICON) NULL;
121HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
122HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
2bda0e17 123
57c208c5
JS
124HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
125HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
126HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
2bda0e17 127
57c208c5 128HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
2bda0e17 129
3135f4a7 130LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
2bda0e17 131
57c208c5 132#if wxUSE_RICHEDIT
6d167489
VZ
133 // the handle to richedit DLL and the version of the DLL loaded
134 static HINSTANCE gs_hRichEdit = (HINSTANCE)NULL;
135 static int gs_verRichEdit = -1;
2bda0e17
KB
136#endif
137
e5c0b16a
VZ
138// ===========================================================================
139// implementation
140// ===========================================================================
589f0e3e 141
e5c0b16a
VZ
142// ---------------------------------------------------------------------------
143// wxApp
144// ---------------------------------------------------------------------------
145
146#if !USE_SHARED_LIBRARY
147 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
148
149 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
150 EVT_IDLE(wxApp::OnIdle)
151 EVT_END_SESSION(wxApp::OnEndSession)
152 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
153 END_EVENT_TABLE()
154#endif
155
e5c0b16a 156//// Initialize
589f0e3e 157bool wxApp::Initialize()
2bda0e17 158{
c030b70f
JS
159 // Some people may wish to use this, but
160 // probably it shouldn't be here by default.
161#ifdef __WXDEBUG__
e5c0b16a 162 // wxRedirectIOToConsole();
c030b70f
JS
163#endif
164
837e5743 165 wxBuffer = new wxChar[1500]; // FIXME
589f0e3e 166
aa0b7e1e 167 wxClassInfo::InitializeClasses();
589f0e3e 168
aa0b7e1e 169#if wxUSE_RESOURCES
223d09f6 170 wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
aa0b7e1e 171#endif
589f0e3e 172
4d3a259a 173#if wxUSE_THREADS
8e193f38 174 wxPendingEventsLocker = new wxCriticalSection;
4d3a259a
GL
175#endif
176
aa0b7e1e
JS
177 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
178 wxTheColourDatabase->Initialize();
589f0e3e 179
aa0b7e1e
JS
180 wxInitializeStockLists();
181 wxInitializeStockObjects();
589f0e3e 182
aa0b7e1e 183#if wxUSE_WX_RESOURCES
a5e0e655 184 wxInitializeResourceSystem();
aa0b7e1e 185#endif
2bda0e17 186
aa0b7e1e 187 wxBitmap::InitStandardHandlers();
2bda0e17 188
aa0b7e1e 189#if defined(__WIN95__)
a5e0e655 190 InitCommonControls();
57c208c5 191
e5c0b16a 192#endif // __WIN95__
2bda0e17 193
c49245f8
VZ
194#if wxUSE_OLE
195
196#ifdef __WIN16__
e5c0b16a 197 // for OLE, enlarge message queue to be as large as possible
aa0b7e1e 198 int iMsg = 96;
c49245f8
VZ
199 while (!SetMessageQueue(iMsg) && (iMsg -= 8))
200 ;
201#endif // Win16
a5e0e655
VZ
202 // we need to initialize OLE library
203 if ( FAILED(::OleInitialize(NULL)) )
e5c0b16a 204 wxLogError(_("Cannot initialize OLE"));
c49245f8 205#endif // wxUSE_OLE
2bda0e17 206
1f112209 207#if wxUSE_CTL3D
a5e0e655 208 if (!Ctl3dRegister(wxhInstance))
223d09f6 209 wxLogError(wxT("Cannot register CTL3D"));
2bda0e17 210
a5e0e655 211 Ctl3dAutoSubclass(wxhInstance);
aa0b7e1e 212#endif
2bda0e17 213
aa0b7e1e 214 g_globalCursor = new wxCursor;
589f0e3e 215
87a1e308
VZ
216 // VZ: these icons are not in wx.rc anyhow (but should they?)!
217#if 0
223d09f6
KB
218 wxSTD_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_FRAME"));
219 wxSTD_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_MDIPARENTFRAME"));
220 wxSTD_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_MDICHILDFRAME"));
2bda0e17 221
223d09f6
KB
222 wxDEFAULT_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_FRAME"));
223 wxDEFAULT_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_MDIPARENTFRAME"));
224 wxDEFAULT_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_MDICHILDFRAME"));
87a1e308 225#endif // 0
2bda0e17 226
aa0b7e1e 227 RegisterWindowClasses();
2bda0e17 228
aa0b7e1e 229 // Create the brush for disabling bitmap buttons
2bda0e17 230
42e69d6b 231 LOGBRUSH lb;
aa0b7e1e 232 lb.lbStyle = BS_PATTERN;
223d09f6 233 lb.lbHatch = (int)LoadBitmap( wxhInstance, wxT("wxDISABLE_BUTTON_BITMAP") );
3a5ffa81
VZ
234 if ( lb.lbHatch )
235 {
236 wxDisableButtonBrush = ::CreateBrushIndirect( & lb );
237 ::DeleteObject( (HGDIOBJ)lb.lbHatch );
238 }
239 //else: wxWindows resources are probably not linked in
2bda0e17 240
aa0b7e1e 241#if wxUSE_PENWINDOWS
a5e0e655 242 wxRegisterPenWin();
aa0b7e1e 243#endif
2bda0e17 244
aa0b7e1e 245 wxWinHandleList = new wxList(wxKEY_INTEGER);
2bda0e17 246
6e0d9d43 247 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
8cbd2bde 248 // PLEASE DO NOT ALTER THIS.
3f4a0c5b 249#if defined(__VISUALC__) && !defined(WXMAKINGDLL)
a5e0e655
VZ
250 extern char wxDummyChar;
251 if (wxDummyChar) wxDummyChar++;
aa0b7e1e 252#endif
a5e0e655 253
aa0b7e1e 254 wxSetKeyboardHook(TRUE);
2bda0e17 255
aa0b7e1e
JS
256 wxModule::RegisterModules();
257 if (!wxModule::InitializeModules())
258 return FALSE;
259 return TRUE;
2bda0e17
KB
260}
261
42e69d6b
VZ
262// ---------------------------------------------------------------------------
263// RegisterWindowClasses
264// ---------------------------------------------------------------------------
589f0e3e 265
b782f2e0
VZ
266// TODO we should only register classes really used by the app. For this it
267// would be enough to just delay the class registration until an attempt
268// to create a window of this class is made.
bb6290e3 269bool wxApp::RegisterWindowClasses()
2bda0e17 270{
42e69d6b 271 WNDCLASS wndclass;
e5c0b16a 272
193fe989
VZ
273 // for each class we register one with CS_(V|H)REDRAW style and one
274 // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
275 static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
276 static const long styleNoRedraw = CS_DBLCLKS;
277
42e69d6b 278 // the fields which are common to all classes
e5c0b16a
VZ
279 wndclass.lpfnWndProc = (WNDPROC)wxWndProc;
280 wndclass.cbClsExtra = 0;
193fe989 281 wndclass.cbWndExtra = sizeof( DWORD ); // VZ: what is this DWORD used for?
e5c0b16a 282 wndclass.hInstance = wxhInstance;
42e69d6b
VZ
283 wndclass.hIcon = (HICON) NULL;
284 wndclass.hCursor = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
e5c0b16a 285 wndclass.lpszMenuName = NULL;
42e69d6b
VZ
286
287 // Register the frame window class.
288 wndclass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
e5c0b16a 289 wndclass.lpszClassName = wxFrameClassName;
b782f2e0 290 wndclass.style = styleNormal;
e5c0b16a 291
42e69d6b 292 if ( !RegisterClass(&wndclass) )
e5c0b16a 293 {
42e69d6b
VZ
294 wxLogLastError("RegisterClass(frame)");
295
296 return FALSE;
e5c0b16a
VZ
297 }
298
193fe989
VZ
299 // "no redraw" frame
300 wndclass.lpszClassName = wxFrameClassNameNoRedraw;
301 wndclass.style = styleNoRedraw;
302
303 if ( !RegisterClass(&wndclass) )
304 {
305 wxLogLastError("RegisterClass(no redraw frame)");
306
307 return FALSE;
308 }
309
e5c0b16a 310 // Register the MDI frame window class.
42e69d6b 311 wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
b782f2e0
VZ
312 wndclass.lpszClassName = wxMDIFrameClassName;
313 wndclass.style = styleNormal;
42e69d6b
VZ
314
315 if ( !RegisterClass(&wndclass) )
e5c0b16a 316 {
42e69d6b
VZ
317 wxLogLastError("RegisterClass(MDI parent)");
318
319 return FALSE;
e5c0b16a
VZ
320 }
321
193fe989 322 // "no redraw" MDI frame
b782f2e0 323 wndclass.lpszClassName = wxMDIFrameClassNameNoRedraw;
193fe989
VZ
324 wndclass.style = styleNoRedraw;
325
326 if ( !RegisterClass(&wndclass) )
327 {
328 wxLogLastError("RegisterClass(no redraw MDI parent frame)");
329
330 return FALSE;
331 }
332
e5c0b16a 333 // Register the MDI child frame window class.
42e69d6b
VZ
334 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
335 wndclass.lpszClassName = wxMDIChildFrameClassName;
b782f2e0 336 wndclass.style = styleNormal;
42e69d6b
VZ
337
338 if ( !RegisterClass(&wndclass) )
e5c0b16a 339 {
42e69d6b
VZ
340 wxLogLastError("RegisterClass(MDI child)");
341
342 return FALSE;
e5c0b16a
VZ
343 }
344
193fe989
VZ
345 // "no redraw" MDI child frame
346 wndclass.lpszClassName = wxMDIChildFrameClassNameNoRedraw;
347 wndclass.style = styleNoRedraw;
348
349 if ( !RegisterClass(&wndclass) )
350 {
351 wxLogLastError("RegisterClass(no redraw MDI child)");
352
353 return FALSE;
354 }
355
e5c0b16a 356 // Register the panel window class.
42e69d6b
VZ
357 wndclass.hbrBackground = (HBRUSH) GetStockObject( LTGRAY_BRUSH );
358 wndclass.lpszClassName = wxPanelClassName;
b782f2e0 359 wndclass.style = styleNormal;
42e69d6b
VZ
360
361 if ( !RegisterClass(&wndclass) )
e5c0b16a 362 {
42e69d6b
VZ
363 wxLogLastError("RegisterClass(panel)");
364
365 return FALSE;
e5c0b16a
VZ
366 }
367
e5c0b16a 368 // Register the canvas and textsubwindow class name
42e69d6b
VZ
369 wndclass.hbrBackground = (HBRUSH)NULL;
370 wndclass.lpszClassName = wxCanvasClassName;
371
372 if ( !RegisterClass(&wndclass) )
e5c0b16a 373 {
42e69d6b
VZ
374 wxLogLastError("RegisterClass(canvas)");
375
376 return FALSE;
e5c0b16a
VZ
377 }
378
379 return TRUE;
2bda0e17
KB
380}
381
42e69d6b
VZ
382// ---------------------------------------------------------------------------
383// Convert Windows to argc, argv style
384// ---------------------------------------------------------------------------
589f0e3e
JS
385
386void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine)
387{
da36f544 388 wxStringList args;
589f0e3e 389
da36f544
JS
390 wxString cmdLine(lpCmdLine);
391 int count = 0;
589f0e3e 392
da36f544 393 // Get application name
837e5743 394 wxChar name[260]; // 260 is MAX_PATH value from windef.h
da36f544
JS
395 ::GetModuleFileName(wxhInstance, name, WXSIZEOF(name));
396
da36f544 397 args.Add(name);
50ef256e 398 count++;
589f0e3e 399
837e5743 400 wxStrcpy(name, wxFileNameFromPath(name));
da36f544
JS
401 wxStripExtension(name);
402 wxTheApp->SetAppName(name);
589f0e3e 403
da36f544
JS
404 // Break up string
405 // Treat strings enclosed in double-quotes as single arguments
406 int i = 0;
407 int len = cmdLine.Length();
408 while (i < len)
a5e0e655 409 {
da36f544 410 // Skip whitespace
837e5743 411 while ((i < len) && wxIsspace(cmdLine.GetChar(i)))
da36f544
JS
412 i ++;
413
414 if (i < len)
415 {
223d09f6 416 if (cmdLine.GetChar(i) == wxT('"')) // We found the start of a string
da36f544
JS
417 {
418 i ++;
419 int first = i;
223d09f6 420 while ((i < len) && (cmdLine.GetChar(i) != wxT('"')))
da36f544
JS
421 i ++;
422
423 wxString arg(cmdLine.Mid(first, (i - first)));
424
425 args.Add(arg);
426 count ++;
427
428 if (i < len)
429 i ++; // Skip past 2nd quote
430 }
431 else // Unquoted argument
432 {
433 int first = i;
837e5743 434 while ((i < len) && !wxIsspace(cmdLine.GetChar(i)))
da36f544
JS
435 i ++;
436
437 wxString arg(cmdLine.Mid(first, (i - first)));
438
439 args.Add(arg);
440 count ++;
441 }
442 }
a5e0e655 443 }
a5e0e655 444
837e5743 445 wxTheApp->argv = new wxChar*[count + 1];
da36f544 446 for (i = 0; i < count; i++)
a5e0e655 447 {
da36f544 448 wxString arg(args[i]);
837e5743 449 wxTheApp->argv[i] = copystring((const wxChar*)arg);
a5e0e655 450 }
da36f544
JS
451 wxTheApp->argv[count] = NULL; // argv[] is a NULL-terminated list
452 wxTheApp->argc = count;
589f0e3e
JS
453}
454
455//// Cleans up any wxWindows internal structures left lying around
456
bb6290e3 457void wxApp::CleanUp()
2bda0e17 458{
e5c0b16a
VZ
459 //// COMMON CLEANUP
460
546db2a8 461#if wxUSE_LOG
e5c0b16a
VZ
462 // flush the logged messages if any and install a 'safer' log target: the
463 // default one (wxLogGui) can't be used after the resources are freed just
464 // below and the user suppliedo ne might be even more unsafe (using any
465 // wxWindows GUI function is unsafe starting from now)
466 wxLog::DontCreateOnDemand();
f5e5bd66 467
e5c0b16a
VZ
468 // this will flush the old messages if any
469 delete wxLog::SetActiveTarget(new wxLogStderr);
546db2a8 470#endif // wxUSE_LOG
f5e5bd66 471
e5c0b16a
VZ
472 // One last chance for pending objects to be cleaned up
473 wxTheApp->DeletePendingObjects();
f5e5bd66 474
e5c0b16a 475 wxModule::CleanUpModules();
2bda0e17 476
47d67540 477#if wxUSE_WX_RESOURCES
e5c0b16a 478 wxCleanUpResourceSystem();
589f0e3e 479
e5c0b16a 480 // wxDefaultResourceTable->ClearTable();
589f0e3e
JS
481#endif
482
e5c0b16a
VZ
483 // Indicate that the cursor can be freed, so that cursor won't be deleted
484 // by deleting the bitmap list before g_globalCursor goes out of scope
485 // (double deletion of the cursor).
486 wxSetCursor(wxNullCursor);
487 delete g_globalCursor;
2a47d3c1 488 g_globalCursor = NULL;
589f0e3e 489
42e69d6b 490 wxDeleteStockObjects();
589f0e3e 491
e5c0b16a
VZ
492 // Destroy all GDI lists, etc.
493 wxDeleteStockLists();
589f0e3e 494
e5c0b16a
VZ
495 delete wxTheColourDatabase;
496 wxTheColourDatabase = NULL;
589f0e3e 497
e5c0b16a 498 wxBitmap::CleanUpHandlers();
589f0e3e 499
e5c0b16a
VZ
500 delete[] wxBuffer;
501 wxBuffer = NULL;
589f0e3e 502
e5c0b16a 503 //// WINDOWS-SPECIFIC CLEANUP
2bda0e17 504
e5c0b16a 505 wxSetKeyboardHook(FALSE);
2bda0e17 506
57c208c5 507#if wxUSE_RICHEDIT
e5c0b16a
VZ
508 if (gs_hRichEdit != (HINSTANCE) NULL)
509 FreeLibrary(gs_hRichEdit);
2bda0e17
KB
510#endif
511
47d67540 512#if wxUSE_PENWINDOWS
e5c0b16a 513 wxCleanUpPenWin();
2bda0e17
KB
514#endif
515
e5c0b16a
VZ
516 if (wxSTD_FRAME_ICON)
517 DestroyIcon(wxSTD_FRAME_ICON);
518 if (wxSTD_MDICHILDFRAME_ICON)
519 DestroyIcon(wxSTD_MDICHILDFRAME_ICON);
520 if (wxSTD_MDIPARENTFRAME_ICON)
521 DestroyIcon(wxSTD_MDIPARENTFRAME_ICON);
522
523 if (wxDEFAULT_FRAME_ICON)
524 DestroyIcon(wxDEFAULT_FRAME_ICON);
525 if (wxDEFAULT_MDICHILDFRAME_ICON)
526 DestroyIcon(wxDEFAULT_MDICHILDFRAME_ICON);
527 if (wxDEFAULT_MDIPARENTFRAME_ICON)
528 DestroyIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
529
530 if ( wxDisableButtonBrush )
42e69d6b 531 ::DeleteObject( wxDisableButtonBrush );
e5c0b16a
VZ
532
533#if wxUSE_OLE
534 ::OleUninitialize();
5de5db0e 535#endif
2bda0e17 536
1f112209 537#if wxUSE_CTL3D
e5c0b16a 538 Ctl3dUnregister(wxhInstance);
2bda0e17
KB
539#endif
540
e5c0b16a 541 if (wxWinHandleList)
42e69d6b 542 delete wxWinHandleList;
d50b2a58 543
3135f4a7 544 // GL: I'm annoyed ... I don't know where to put this and I don't want to
4d3a259a 545 // create a module for that as it's part of the core.
4d3a259a 546 delete wxPendingEvents;
8e193f38 547#if wxUSE_THREADS
4d3a259a 548 delete wxPendingEventsLocker;
63863e09
JS
549 // If we don't do the following, we get an apparent memory leak.
550 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
4d3a259a
GL
551#endif
552
e5c0b16a 553 wxClassInfo::CleanUpClasses();
0c32066b 554
e5c0b16a
VZ
555 delete wxTheApp;
556 wxTheApp = NULL;
184b5d99
JS
557
558#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
e5c0b16a
VZ
559 // At this point we want to check if there are any memory
560 // blocks that aren't part of the wxDebugContext itself,
561 // as a special case. Then when dumping we need to ignore
562 // wxDebugContext, too.
d13c32e9 563 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
e5c0b16a 564 {
223d09f6 565 wxLogDebug(wxT("There were memory leaks."));
e5c0b16a
VZ
566 wxDebugContext::Dump();
567 wxDebugContext::PrintStatistics();
568 }
569 // wxDebugContext::SetStream(NULL, NULL);
184b5d99
JS
570#endif
571
546db2a8 572#if wxUSE_LOG
e5c0b16a
VZ
573 // do it as the very last thing because everything else can log messages
574 delete wxLog::SetActiveTarget(NULL);
546db2a8 575#endif // wxUSE_LOG
2bda0e17
KB
576}
577
2bda0e17
KB
578#if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
579
e5c0b16a
VZ
580// temporarily disable this warning which would be generated in release builds
581// because of __try
3f4a0c5b 582#ifdef __VISUALC__
f8a3e080
VZ
583 #pragma warning(disable: 4715) // not all control paths return a value
584#endif // Visual C++
585
589f0e3e 586//// Main wxWindows entry point
a5e0e655
VZ
587int wxEntry(WXHINSTANCE hInstance,
588 WXHINSTANCE WXUNUSED(hPrevInstance),
589 char *lpCmdLine,
590 int nCmdShow,
591 bool enterLoop)
2bda0e17 592{
6e0d9d43
VZ
593 // do check for memory leaks on program exit
594 // (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free
595 // deallocated memory which may be used to simulate low-memory condition)
596 wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
597
e5c0b16a
VZ
598 // take everything into a try-except block in release build
599 // FIXME other compilers must support Win32 SEH (structured exception
600 // handling) too, just find the appropriate keyword in their docs!
601 // Please note that it's _not_ the same as C++ exceptions!
3f4a0c5b 602#if !defined(__WXDEBUG__) && defined(__VISUALC__)
f8a3e080
VZ
603 #define CATCH_PROGRAM_EXCEPTIONS
604
3f4a0c5b 605 __try {
f8a3e080
VZ
606#else
607 #undef CATCH_PROGRAM_EXCEPTIONS
a5e0e655 608#endif
e5c0b16a 609 wxhInstance = (HINSTANCE) hInstance;
2bda0e17 610
e5c0b16a
VZ
611 if (!wxApp::Initialize())
612 return 0;
2bda0e17 613
e5c0b16a
VZ
614 // create the application object or ensure that one already exists
615 if (!wxTheApp)
616 {
617 // The app may have declared a global application object, but we recommend
618 // the IMPLEMENT_APP macro is used instead, which sets an initializer
619 // function for delayed, dynamic app object construction.
620 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
223d09f6 621 wxT("No initializer - use IMPLEMENT_APP macro.") );
f8a3e080 622
e5c0b16a
VZ
623 wxTheApp = (*wxApp::GetInitializerFunction()) ();
624 }
625
223d09f6 626 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
e5c0b16a
VZ
627
628 // save the WinMain() parameters
629 wxTheApp->ConvertToStandardCommandArgs(lpCmdLine);
630 wxTheApp->m_nCmdShow = nCmdShow;
a5e0e655 631
e5c0b16a
VZ
632 // GUI-specific initialisation. In fact on Windows we don't have any,
633 // but this call is provided for compatibility across platforms.
42e69d6b 634 wxTheApp->OnInitGui();
f8a3e080 635
36edded9
JS
636 // We really don't want timestamps by default, because it means
637 // we can't simply double-click on the error message and get to that
638 // line in the source. So VC++ at least, let's have a sensible default.
639#ifdef __VISUALC__
640 wxLog::SetTimestamp(NULL);
641#endif
642
e5c0b16a
VZ
643 int retValue = 0;
644
645 if ( wxTheApp->OnInit() )
646 {
647 if ( enterLoop )
648 {
649 retValue = wxTheApp->OnRun();
650 }
651 else
652 // We want to initialize, but not run or exit immediately.
653 return 1;
654 }
655 //else: app initialization failed, so we skipped OnRun()
656
657 wxWindow *topWindow = wxTheApp->GetTopWindow();
658 if ( topWindow )
659 {
660 // Forcibly delete the window.
661 if ( topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
662 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
663 {
664 topWindow->Close(TRUE);
665 wxTheApp->DeletePendingObjects();
666 }
667 else
668 {
669 delete topWindow;
670 wxTheApp->SetTopWindow(NULL);
671 }
672 }
673
674 wxTheApp->OnExit();
675
676 wxApp::CleanUp();
677
678 return retValue;
679
680#ifdef CATCH_PROGRAM_EXCEPTIONS
681 }
682 __except ( EXCEPTION_EXECUTE_HANDLER ) {
683 /*
684 if ( wxTheApp )
685 wxTheApp->OnFatalException();
686 */
687
688 // using wxLog would be unsafe here
689 ::MessageBox(NULL,
690 _("Unrecoverable program error detected: "
691 " the application will terminate."),
692 _("Fatal Error"),
693 MB_APPLMODAL | MB_ICONSTOP | MB_OK);
694
695 ::ExitProcess(3); // the same exit code as abort()
696
697 // NOTREACHED
698 }
f8a3e080 699#endif // CATCH_PROGRAM_EXCEPTIONS
2bda0e17
KB
700}
701
f8a3e080 702// restore warning state
3f4a0c5b 703#ifdef __VISUALC__
f8a3e080
VZ
704 #pragma warning(default: 4715) // not all control paths return a value
705#endif // Visual C++
706
2bda0e17
KB
707#else /* _WINDLL */
708
589f0e3e
JS
709//// Entry point for DLLs
710
2bda0e17
KB
711int wxEntry(WXHINSTANCE hInstance)
712{
e5c0b16a
VZ
713 wxhInstance = (HINSTANCE) hInstance;
714 wxApp::Initialize();
2bda0e17 715
e5c0b16a
VZ
716 // The app may have declared a global application object, but we recommend
717 // the IMPLEMENT_APP macro is used instead, which sets an initializer function
718 // for delayed, dynamic app object construction.
719 if (!wxTheApp)
a5e0e655 720 {
e5c0b16a
VZ
721 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
722 "No initializer - use IMPLEMENT_APP macro." );
2bda0e17 723
e5c0b16a
VZ
724 wxTheApp = (* wxApp::GetInitializerFunction()) ();
725 }
2bda0e17 726
e5c0b16a 727 wxCHECK_MSG( wxTheApp, 0, "You have to define an instance of wxApp!" );
2bda0e17 728
e5c0b16a
VZ
729 wxTheApp->argc = 0;
730 wxTheApp->argv = NULL;
2bda0e17 731
e5c0b16a 732 wxTheApp->OnInitGui();
2bda0e17 733
e5c0b16a 734 wxTheApp->OnInit();
2bda0e17 735
e5c0b16a
VZ
736 wxWindow *topWindow = wxTheApp->GetTopWindow();
737 if ( topWindow && topWindow->GetHWND())
738 {
739 topWindow->Show(TRUE);
740 }
2bda0e17 741
e5c0b16a 742 return 1;
2bda0e17
KB
743}
744#endif // _WINDLL
745
589f0e3e
JS
746//// Static member initialization
747
c94ad3c3 748wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
2bda0e17 749
bb6290e3 750wxApp::wxApp()
2bda0e17 751{
e5c0b16a
VZ
752 m_topWindow = NULL;
753 wxTheApp = this;
42e69d6b
VZ
754 m_wantDebugOutput = TRUE;
755
e5c0b16a
VZ
756 argc = 0;
757 argv = NULL;
e5c0b16a 758 m_printMode = wxPRINT_WINDOWS;
e5c0b16a
VZ
759 m_exitOnFrameDelete = TRUE;
760 m_auto3D = TRUE;
2bda0e17
KB
761}
762
589f0e3e
JS
763wxApp::~wxApp()
764{
e5c0b16a
VZ
765 // Delete command-line args
766 int i;
767 for (i = 0; i < argc; i++)
768 {
769 delete[] argv[i];
770 }
771 delete[] argv;
589f0e3e
JS
772}
773
bb6290e3 774bool wxApp::Initialized()
2bda0e17
KB
775{
776#ifndef _WINDLL
e5c0b16a
VZ
777 if (GetTopWindow())
778 return TRUE;
779 else
780 return FALSE;
2bda0e17
KB
781#endif
782#ifdef _WINDLL // Assume initialized if DLL (no way of telling)
e5c0b16a 783 return TRUE;
2bda0e17
KB
784#endif
785}
786
787/*
788 * Get and process a message, returning FALSE if WM_QUIT
bee503b0 789 * received (and also set the flag telling the app to exit the main loop)
2bda0e17
KB
790 *
791 */
bb6290e3 792bool wxApp::DoMessage()
2bda0e17 793{
bee503b0
VZ
794 BOOL rc = ::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0);
795 if ( rc == 0 )
796 {
797 // got WM_QUIT
798 m_keepGoing = FALSE;
4a9968f9 799
bee503b0
VZ
800 return FALSE;
801 }
802 else if ( rc == -1 )
803 {
804 // should never happen, but let's test for it nevertheless
805 wxLogLastError("GetMessage");
806 }
807 else
808 {
809#if wxUSE_THREADS
810 wxASSERT_MSG( wxThread::IsMain(),
223d09f6 811 wxT("only the main thread can process Windows messages") );
d50b2a58 812
bee503b0
VZ
813 static bool s_hadGuiLock = TRUE;
814 static wxMsgArray s_aSavedMessages;
815
816 // if a secondary thread owns is doing GUI calls, save all messages for
817 // later processing - we can't process them right now because it will
818 // lead to recursive library calls (and we're not reentrant)
819 if ( !wxGuiOwnedByMainThread() )
820 {
821 s_hadGuiLock = FALSE;
822
4a9968f9
VZ
823 // leave out WM_COMMAND messages: too dangerous, sometimes
824 // the message will be processed twice
825 if ( !wxIsWaitingForThread() ||
e5c0b16a 826 s_currentMsg.message != WM_COMMAND )
4a9968f9
VZ
827 {
828 s_aSavedMessages.Add(s_currentMsg);
829 }
bee503b0
VZ
830
831 return TRUE;
832 }
833 else
834 {
835 // have we just regained the GUI lock? if so, post all of the saved
836 // messages
837 //
838 // FIXME of course, it's not _exactly_ the same as processing the
839 // messages normally - expect some things to break...
840 if ( !s_hadGuiLock )
841 {
842 s_hadGuiLock = TRUE;
843
844 size_t count = s_aSavedMessages.Count();
845 for ( size_t n = 0; n < count; n++ )
846 {
847 MSG& msg = s_aSavedMessages[n];
848
849 if ( !ProcessMessage((WXMSG *)&msg) )
850 {
851 ::TranslateMessage(&msg);
852 ::DispatchMessage(&msg);
853 }
854 }
855
856 s_aSavedMessages.Empty();
857 }
858 }
859#endif // wxUSE_THREADS
860
861 // Process the message
862 if ( !ProcessMessage((WXMSG *)&s_currentMsg) )
863 {
864 ::TranslateMessage(&s_currentMsg);
bee503b0
VZ
865 ::DispatchMessage(&s_currentMsg);
866 }
867 }
868
869 return TRUE;
2bda0e17
KB
870}
871
872/*
873 * Keep trying to process messages until WM_QUIT
874 * received.
875 *
876 * If there are messages to be processed, they will all be
877 * processed and OnIdle will not be called.
878 * When there are no more messages, OnIdle is called.
879 * If OnIdle requests more time,
880 * it will be repeatedly called so long as there are no pending messages.
881 * A 'feature' of this is that once OnIdle has decided that no more processing
882 * is required, then it won't get processing time until further messages
883 * are processed (it'll sit in DoMessage).
884 */
885
bb6290e3 886int wxApp::MainLoop()
2bda0e17 887{
e5c0b16a 888 m_keepGoing = TRUE;
bee503b0 889
e5c0b16a
VZ
890 while ( m_keepGoing )
891 {
892#if wxUSE_THREADS
bee503b0 893 wxMutexGuiLeaveOrEnter();
e5c0b16a 894#endif // wxUSE_THREADS
bee503b0 895
e5c0b16a
VZ
896 while ( !::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) &&
897 ProcessIdle() )
898 {
899 }
bee503b0 900
7214297d 901
e5c0b16a
VZ
902 DoMessage();
903 }
2bda0e17 904
e5c0b16a 905 return s_currentMsg.wParam;
2bda0e17
KB
906}
907
908// Returns TRUE if more time is needed.
bb6290e3 909bool wxApp::ProcessIdle()
2bda0e17
KB
910{
911 wxIdleEvent event;
912 event.SetEventObject(this);
913 ProcessEvent(event);
914
915 return event.MoreRequested();
916}
917
bb6290e3 918void wxApp::ExitMainLoop()
2bda0e17 919{
e5c0b16a 920 m_keepGoing = FALSE;
2bda0e17
KB
921}
922
bb6290e3 923bool wxApp::Pending()
2bda0e17 924{
42e69d6b 925 return (::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) != 0);
2bda0e17
KB
926}
927
bb6290e3 928void wxApp::Dispatch()
2bda0e17 929{
bee503b0 930 DoMessage();
2bda0e17
KB
931}
932
933/*
934 * Give all windows a chance to preprocess
935 * the message. Some may have accelerator tables, or have
936 * MDI complications.
937 */
2a47d3c1 938
d3f0a137 939bool wxApp::ProcessMessage(WXMSG *wxmsg)
2bda0e17 940{
d3f0a137
VZ
941 MSG *msg = (MSG *)wxmsg;
942 HWND hWnd = msg->hwnd;
943 wxWindow *wndThis = wxFindWinFromHandle((WXHWND)hWnd), *wnd;
2bda0e17 944
834362a2
VZ
945 // for some composite controls (like a combobox), wndThis might be NULL
946 // because the subcontrol is not a wxWindow, but only the control itself
947 // is - try to catch this case
948 while ( hWnd && !wndThis )
949 {
950 hWnd = ::GetParent(hWnd);
3135f4a7 951 wndThis = wxFindWinFromHandle((WXHWND)hWnd);
834362a2
VZ
952 }
953
e5c0b16a
VZ
954 // Try translations first; find the youngest window with
955 // a translation table.
d3f0a137 956 for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
2bda0e17 957 {
d3f0a137
VZ
958 if ( wnd->MSWTranslateMessage(wxmsg) )
959 return TRUE;
2bda0e17 960 }
2bda0e17 961
e5c0b16a 962 // Anyone for a non-translation message? Try youngest descendants first.
d3f0a137 963 for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
57a7b7c1 964 {
d3f0a137
VZ
965 if ( wnd->MSWProcessMessage(wxmsg) )
966 return TRUE;
57a7b7c1 967 }
d3f0a137 968
e5c0b16a 969 return FALSE;
2bda0e17
KB
970}
971
972void wxApp::OnIdle(wxIdleEvent& event)
973{
3222fde2 974 static bool s_inOnIdle = FALSE;
2bda0e17 975
3222fde2
VZ
976 // Avoid recursion (via ProcessEvent default case)
977 if ( s_inOnIdle )
978 return;
2bda0e17 979
3222fde2 980 s_inOnIdle = TRUE;
2bda0e17 981
3222fde2
VZ
982 // 'Garbage' collection of windows deleted with Close().
983 DeletePendingObjects();
2bda0e17 984
546db2a8 985#if wxUSE_LOG
3222fde2
VZ
986 // flush the logged messages if any
987 wxLog *pLog = wxLog::GetActiveTarget();
988 if ( pLog != NULL && pLog->HasPendingMessages() )
989 pLog->Flush();
546db2a8 990#endif // wxUSE_LOG
c54f78a2 991
3222fde2
VZ
992 // Send OnIdle events to all windows
993 if ( SendIdleEvents() )
994 {
995 // SendIdleEvents() returns TRUE if at least one window requested more
996 // idle events
997 event.RequestMore(TRUE);
998 }
2bda0e17 999
8e193f38
VZ
1000 // If they are pending events, we must process them: pending events are
1001 // either events to the threads other than main or events posted with
1002 // wxPostEvent() functions
aadbdf11 1003 ProcessPendingEvents();
8e193f38 1004
3222fde2 1005 s_inOnIdle = FALSE;
2bda0e17
KB
1006}
1007
1008// Send idle event to all top-level windows
bb6290e3 1009bool wxApp::SendIdleEvents()
2bda0e17
KB
1010{
1011 bool needMore = FALSE;
e146b8c8 1012
f1d534df 1013 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
3222fde2
VZ
1014 while (node)
1015 {
e146b8c8 1016 wxWindow* win = node->GetData();
3222fde2 1017 if (SendIdleEvents(win))
2bda0e17 1018 needMore = TRUE;
e146b8c8 1019 node = node->GetNext();
3222fde2
VZ
1020 }
1021
2bda0e17
KB
1022 return needMore;
1023}
1024
1025// Send idle event to window and all subwindows
1026bool wxApp::SendIdleEvents(wxWindow* win)
1027{
e5c0b16a 1028 bool needMore = FALSE;
2bda0e17 1029
e5c0b16a
VZ
1030 wxIdleEvent event;
1031 event.SetEventObject(win);
1032 win->GetEventHandler()->ProcessEvent(event);
2bda0e17 1033
e5c0b16a
VZ
1034 if (event.MoreRequested())
1035 needMore = TRUE;
2bda0e17 1036
e5c0b16a
VZ
1037 wxNode* node = win->GetChildren().First();
1038 while (node)
1039 {
1040 wxWindow* win = (wxWindow*) node->Data();
1041 if (SendIdleEvents(win))
1042 needMore = TRUE;
2bda0e17 1043
e5c0b16a
VZ
1044 node = node->Next();
1045 }
42e69d6b 1046 return needMore;
2bda0e17
KB
1047}
1048
bb6290e3 1049void wxApp::DeletePendingObjects()
2bda0e17 1050{
e5c0b16a
VZ
1051 wxNode *node = wxPendingDelete.First();
1052 while (node)
1053 {
1054 wxObject *obj = (wxObject *)node->Data();
d50b2a58 1055
e5c0b16a 1056 delete obj;
2bda0e17 1057
e5c0b16a
VZ
1058 if (wxPendingDelete.Member(obj))
1059 delete node;
2bda0e17 1060
e5c0b16a
VZ
1061 // Deleting one object may have deleted other pending
1062 // objects, so start from beginning of list again.
1063 node = wxPendingDelete.First();
1064 }
2bda0e17
KB
1065}
1066
57c208c5 1067void wxApp::OnEndSession(wxCloseEvent& WXUNUSED(event))
387a3b02
JS
1068{
1069 if (GetTopWindow())
1070 GetTopWindow()->Close(TRUE);
1071}
1072
1073// Default behaviour: close the application with prompts. The
1074// user can veto the close, and therefore the end session.
1075void wxApp::OnQueryEndSession(wxCloseEvent& event)
1076{
1077 if (GetTopWindow())
1078 {
1079 if (!GetTopWindow()->Close(!event.CanVeto()))
1080 event.Veto(TRUE);
1081 }
1082}
1083
6d167489
VZ
1084#if wxUSE_RICHEDIT
1085
1086/* static */
1087bool wxApp::InitRichEdit(int version)
bb6290e3 1088{
6d167489
VZ
1089 wxCHECK_MSG( version >= 1 && version <= 3, FALSE,
1090 _T("incorrect richedit control version requested") );
d50b2a58 1091
6d167489 1092 if ( version <= gs_verRichEdit )
bb6290e3 1093 {
6d167489
VZ
1094 // we've already got this or better
1095 return TRUE;
1096 }
d50b2a58 1097
6d167489
VZ
1098 if ( gs_hRichEdit )
1099 {
1100 ::FreeLibrary(gs_hRichEdit);
1101 }
1102
1103 // always try load riched20.dll first - like this we won't have to reload
1104 // it later if we're first asked for RE 1 and then for RE 2 or 3
1105 wxString dllname = _T("riched20.dll");
1106 gs_hRichEdit = ::LoadLibrary(dllname);
1107 if ( !gs_hRichEdit && (version == 1) )
1108 {
1109 // fall back to RE 1
1110 dllname = _T("riched32.dll");
1111 gs_hRichEdit = ::LoadLibrary(dllname);
1112 }
1113
1114 if ( !gs_hRichEdit )
1115 {
1116 wxLogSysError(_("Could not load Rich Edit DLL '%s'"), dllname.c_str());
1117
1118 gs_verRichEdit = -1;
1119
1120 return FALSE;
1121 }
1122
1123 gs_verRichEdit = version;
1124
1125 return TRUE;
1126}
1127
1128#endif // wxUSE_RICHEDIT
1129
1130/* static */
1131int wxApp::GetComCtl32Version()
1132{
1133 // TODO should use DllGetVersion() instead of this hack
1134
1135 // cache the result
1136 static int s_verComCtl32 = -1; // MT-FIXME
1137
1138 if ( s_verComCtl32 == -1 )
1139 {
1140 s_verComCtl32 = 0;
1141
1142 // have we loaded COMCTL32 yet?
1143 HMODULE theModule = ::GetModuleHandle(wxT("COMCTL32"));
1144
1145 // if so, then we can check for the version
1146 if (theModule)
bb6290e3 1147 {
6d167489
VZ
1148 // InitCommonControlsEx is unique to 4.7 and later
1149 FARPROC theProc = ::GetProcAddress(theModule,
1150 _T("InitCommonControlsEx"));
1151
1152 if ( !theProc )
1153 { // not found, must be 4.00
1154 s_verComCtl32 = 400;
e5c0b16a
VZ
1155 }
1156 else
6d167489
VZ
1157 {
1158 // The following symbol are unique to 4.71
1159 // DllInstall
1160 // FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos
1161 // FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo
1162 // FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange
1163 // FlatSB_ShowScrollBar
1164 // _DrawIndirectImageList _DuplicateImageList
1165 // InitializeFlatSB
1166 // UninitializeFlatSB
1167 // we could check for any of these - I chose DllInstall
1168 FARPROC theProc = ::GetProcAddress(theModule, _T("DllInstall"));
1169 if ( !theProc )
1170 {
1171 // not found, must be 4.70
1172 s_verComCtl32 = 470;
1173 }
1174 else
1175 { // found, must be 4.71
1176 s_verComCtl32 = 471;
1177 }
e5c0b16a 1178 }
bb6290e3
JS
1179 }
1180 }
6d167489
VZ
1181
1182 return s_verComCtl32;
bb6290e3
JS
1183}
1184
1185void wxExit()
2bda0e17 1186{
e5c0b16a
VZ
1187 wxLogError(_("Fatal error: exiting"));
1188
1189 wxApp::CleanUp();
2bda0e17
KB
1190}
1191
1192// Yield to incoming messages
bb6290e3 1193bool wxYield()
2bda0e17 1194{
8e193f38
VZ
1195 // we don't want to process WM_QUIT from here - it should be processed in
1196 // the main event loop in order to stop it
1197
e5c0b16a 1198 MSG msg;
8e193f38
VZ
1199 while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
1200 msg.message != WM_QUIT )
e5c0b16a
VZ
1201 {
1202 if ( !wxTheApp->DoMessage() )
1203 break;
1204 }
8e193f38 1205
aadbdf11 1206 // If they are pending events, we must process them.
6a2f3103 1207 wxTheApp->ProcessPendingEvents();
e5c0b16a
VZ
1208
1209 return TRUE;
2bda0e17 1210}
094637f6 1211
9779893b
RD
1212//-----------------------------------------------------------------------------
1213// wxWakeUpIdle
1214//-----------------------------------------------------------------------------
1215
1216void wxWakeUpIdle()
1217{
1218 // Send the top window a dummy message so idle handler processing will
1219 // start up again. Doing it this way ensures that the idle handler
1220 // wakes up in the right thread.
1221 wxWindow *topWindow = wxTheApp->GetTopWindow();
1222 if ( topWindow ) {
1223 HWND hWnd = (HWND)topWindow->GetHWND();
1224 ::PostMessage(hWnd, WM_NULL, 0, 0);
1225 }
1226}
1227
1228//-----------------------------------------------------------------------------
1229
ebea0891
KB
1230wxIcon
1231wxApp::GetStdIcon(int which) const
1232{
094637f6
VZ
1233 switch(which)
1234 {
1235 case wxICON_INFORMATION:
1236 return wxIcon("wxICON_INFO");
1237
1238 case wxICON_QUESTION:
1239 return wxIcon("wxICON_QUESTION");
1240
1241 case wxICON_EXCLAMATION:
1242 return wxIcon("wxICON_WARNING");
1243
1244 default:
223d09f6 1245 wxFAIL_MSG(wxT("requested non existent standard icon"));
094637f6
VZ
1246 // still fall through
1247
1248 case wxICON_HAND:
1249 return wxIcon("wxICON_ERROR");
1250 }
ebea0891
KB
1251}
1252
2bda0e17
KB
1253
1254HINSTANCE wxGetInstance()
1255{
e5c0b16a 1256 return wxhInstance;
2bda0e17
KB
1257}
1258
b97b1af8
RD
1259void wxSetInstance(HINSTANCE hInst)
1260{
1261 wxhInstance = hInst;
1262}
1263
2bda0e17
KB
1264// For some reason, with MSVC++ 1.5, WinMain isn't linked in properly
1265// if in a separate file. So include it here to ensure it's linked.
3f4a0c5b 1266#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__))
e5c0b16a 1267#include "main.cpp"
2bda0e17 1268#endif