]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/app.cpp
*** empty log message ***
[wxWidgets.git] / src / os2 / app.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose: wxApp
4// Author: David Webster
5// Modified by:
6// Created: 10/13/99
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/frame.h"
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/gdicmn.h"
20 #include "wx/pen.h"
21 #include "wx/brush.h"
22 #include "wx/cursor.h"
23 #include "wx/icon.h"
24 #include "wx/palette.h"
25 #include "wx/dc.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/intl.h"
29 #include "wx/dynarray.h"
30# include "wx/wxchar.h"
31# include "wx/icon.h"
32#endif
33
34#include "wx/log.h"
35#include "wx/module.h"
36
37#include "wx/os2/private.h"
38
39#if wxUSE_THREADS
40 #include "wx/thread.h"
41
42 // define the array of QMSG strutures
43 WX_DECLARE_OBJARRAY(QMSG, wxMsgArray);
44
45 #include "wx/arrimpl.cpp"
46
47 WX_DEFINE_OBJARRAY(wxMsgArray);
48#endif // wxUSE_THREADS
49
50#if wxUSE_WX_RESOURCES
51 #include "wx/resource.h"
52#endif
53
54#include <string.h>
55#include <ctype.h>
56
57// ---------------------------------------------------------------------------
58// global variables
59// ---------------------------------------------------------------------------
60
61extern wxChar* wxBuffer;
62extern wxChar* wxOsVersion;
63extern wxList* wxWinHandleList;
64extern wxList WXDLLEXPORT wxPendingDelete;
65extern wxCursor* g_globalCursor;
66
67HINSTANCE wxhInstance = 0;
68QMSG svCurrentMsg;
69wxApp* wxTheApp = NULL;
70HAB vHabmain = NULL;
71
72// FIXME why not const? and not static?
73
74// NB: all "NoRedraw" classes must have the same names as the "normal" classes
75// with NR suffix - wxWindow::OS2Create() supposes this
76wxChar wxFrameClassName[] = wxT("wxFrameClass");
77wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
78wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
79wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
80wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
81wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
82wxChar wxPanelClassName[] = wxT("wxPanelClass");
83wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
84
85HICON wxSTD_FRAME_ICON = (HICON) NULL;
86HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
87HICON wxSTD_MDIPARENTFRAME_ICON = (HICON) NULL;
88
89HICON wxDEFAULT_FRAME_ICON = (HICON) NULL;
90HICON wxDEFAULT_MDICHILDFRAME_ICON = (HICON) NULL;
91HICON wxDEFAULT_MDIPARENTFRAME_ICON = (HICON) NULL;
92
93HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
94
95MRESULT EXPENTRY wxWndProc( HWND
96 ,ULONG
97 ,MPARAM
98 ,MPARAM
99 );
100
101// ===========================================================================
102// implementation
103// ===========================================================================
104
105// ---------------------------------------------------------------------------
106// wxApp
107// ---------------------------------------------------------------------------
108
109 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
110
111 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
112 EVT_IDLE(wxApp::OnIdle)
113 EVT_END_SESSION(wxApp::OnEndSession)
114 EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
115 END_EVENT_TABLE()
116
117//// Initialize
118bool wxApp::Initialize(
119 HAB vHab
120)
121{
122 //
123 // OS2 has to have an anchorblock
124 //
125 vHab = WinInitialize(0);
126
127 if (!vHab)
128 return FALSE;
129 else
130 vHabmain = vHab;
131
132 // Some people may wish to use this, but
133 // probably it shouldn't be here by default.
134#ifdef __WXDEBUG__
135 // wxRedirectIOToConsole();
136#endif
137
138 wxBuffer = new wxChar[1500]; // FIXME; why?
139
140 wxClassInfo::InitializeClasses();
141
142#if wxUSE_RESOURCES
143 wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
144#endif
145
146 // I'm annoyed ... I don't know where to put this and I don't want to
147 // create a module for that as it's part of the core.
148 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
149 wxTheColourDatabase->Initialize();
150
151 wxInitializeStockLists();
152 wxInitializeStockObjects();
153
154#if wxUSE_WX_RESOURCES
155 wxInitializeResourceSystem();
156#endif
157
158 wxBitmap::InitStandardHandlers();
159
160 g_globalCursor = new wxCursor;
161
162#if 0
163 wxSTD_FRAME_ICON = ::WinLoadFileIcon(wxT("wxSTD_FRAME"), TRUE);
164 wxSTD_MDIPARENTFRAME_ICON = ::WinLoadFileIcon(wxT("wxSTD_MDIPARENTFRAME"), TRUE);
165 wxSTD_MDICHILDFRAME_ICON = ::WinLoadFileIcon(wxT("wxSTD_MDICHILDFRAME"), TRUE);
166
167 wxDEFAULT_FRAME_ICON = ::WinLoadFileIcon(wxT("wxDEFAULT_FRAME"), TRUE);
168 wxDEFAULT_MDIPARENTFRAME_ICON = ::WinLoadFileIcon(wxT("wxDEFAULT_MDIPARENTFRAME"), TRUE);
169 wxDEFAULT_MDICHILDFRAME_ICON = ::WinLoadFileIcon(wxT("wxDEFAULT_MDICHILDFRAME"), TRUE);
170#endif
171 RegisterWindowClasses(vHab);
172 wxWinHandleList = new wxList(wxKEY_INTEGER);
173
174 // This is to foil optimizations in Visual C++ that throw out dummy.obj.
175 // PLEASE DO NOT ALTER THIS.
176#if !defined(WXMAKINGDLL) && defined(__VISAGECPP__)
177 extern char wxDummyChar;
178 if (wxDummyChar) wxDummyChar++;
179#endif
180
181 // wxSetKeyboardHook(TRUE);
182
183 wxModule::RegisterModules();
184 if (!wxModule::InitializeModules())
185 return FALSE;
186 return TRUE;
187}
188
189// ---------------------------------------------------------------------------
190// RegisterWindowClasses
191// ---------------------------------------------------------------------------
192
193// TODO we should only register classes really used by the app. For this it
194// would be enough to just delay the class registration until an attempt
195// to create a window of this class is made.
196bool wxApp::RegisterWindowClasses(
197 HAB vHab
198)
199{
200 APIRET rc;
201 ERRORID vError = 0L;
202 wxString sError;
203
204 if (!::WinRegisterClass( vHab
205 ,wxFrameClassName
206 ,(PFNWP)wxWndProc
207 ,CS_SIZEREDRAW | CS_SYNCPAINT
208 ,0
209 ))
210 {
211 vError = ::WinGetLastError(vHab);
212 sError = wxPMErrorToStr(vError);
213 wxLogLastError(sError);
214 return FALSE;
215 }
216
217 if (!::WinRegisterClass( vHab
218 ,wxFrameClassNameNoRedraw
219 ,(PFNWP)wxWndProc
220 ,0
221 ,0
222 ))
223 {
224 vError = ::WinGetLastError(vHab);
225 sError = wxPMErrorToStr(vError);
226 wxLogLastError(sError);
227 return FALSE;
228 }
229
230 if (!::WinRegisterClass( vHab
231 ,wxMDIFrameClassName
232 ,(PFNWP)wxWndProc
233 ,CS_SIZEREDRAW | CS_SYNCPAINT
234 ,0
235 ))
236 {
237 vError = ::WinGetLastError(vHab);
238 sError = wxPMErrorToStr(vError);
239 wxLogLastError(sError);
240 return FALSE;
241 }
242
243 if (!::WinRegisterClass( vHab
244 ,wxMDIFrameClassNameNoRedraw
245 ,(PFNWP)wxWndProc
246 ,0
247 ,0
248 ))
249 {
250 vError = ::WinGetLastError(vHab);
251 sError = wxPMErrorToStr(vError);
252 wxLogLastError(sError);
253 return FALSE;
254 }
255
256 if (!::WinRegisterClass( vHab
257 ,wxMDIChildFrameClassName
258 ,(PFNWP)wxWndProc
259 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_SYNCPAINT | CS_HITTEST
260 ,0
261 ))
262 {
263 vError = ::WinGetLastError(vHab);
264 sError = wxPMErrorToStr(vError);
265 wxLogLastError(sError);
266 return FALSE;
267 }
268
269 if (!::WinRegisterClass( vHab
270 ,wxMDIChildFrameClassNameNoRedraw
271 ,(PFNWP)wxWndProc
272 ,CS_HITTEST
273 ,0
274 ))
275 {
276 vError = ::WinGetLastError(vHab);
277 sError = wxPMErrorToStr(vError);
278 wxLogLastError(sError);
279 return FALSE;
280 }
281
282 if (!::WinRegisterClass( vHab
283 ,wxPanelClassName
284 ,(PFNWP)wxWndProc
285 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
286 ,0
287 ))
288 {
289 vError = ::WinGetLastError(vHab);
290 sError = wxPMErrorToStr(vError);
291 wxLogLastError(sError);
292 return FALSE;
293 }
294
295 if (!::WinRegisterClass( vHab
296 ,wxCanvasClassName
297 ,(PFNWP)wxWndProc
298 ,CS_MOVENOTIFY | CS_SIZEREDRAW | CS_HITTEST | CS_SAVEBITS | CS_SYNCPAINT
299 ,0
300 ))
301 {
302 vError = ::WinGetLastError(vHab);
303 sError = wxPMErrorToStr(vError);
304 wxLogLastError(sError);
305 return FALSE;
306 }
307 return TRUE;
308}
309
310//// Cleans up any wxWindows internal structures left lying around
311
312void wxApp::CleanUp()
313{
314 //// COMMON CLEANUP
315
316#if wxUSE_LOG
317 // flush the logged messages if any and install a 'safer' log target: the
318 // default one (wxLogGui) can't be used after the resources are freed just
319 // below and the user suppliedo ne might be even more unsafe (using any
320 // wxWindows GUI function is unsafe starting from now)
321 wxLog::DontCreateOnDemand();
322
323 // this will flush the old messages if any
324#if (!(defined(__VISAGECPP__) && __IBMCPP__ < 400))
325 // another VA 3.0 memory problem here
326 delete wxLog::SetActiveTarget(new wxLogStderr);
327#endif
328#endif // wxUSE_LOG
329
330 // One last chance for pending objects to be cleaned up
331 wxTheApp->DeletePendingObjects();
332
333#if (!(defined(__VISAGECPP__) && __IBMCPP__ < 400))
334 // another VA 3.0 memory problem here
335 wxModule::CleanUpModules();
336#endif
337
338#if wxUSE_WX_RESOURCES
339 wxCleanUpResourceSystem();
340
341 // wxDefaultResourceTable->ClearTable();
342#endif
343
344 // Indicate that the cursor can be freed, so that cursor won't be deleted
345 // by deleting the bitmap list before g_globalCursor goes out of scope
346 // (double deletion of the cursor).
347 wxSetCursor(wxNullCursor);
348#if (!(defined(__VISAGECPP__) && __IBMCPP__ < 400))
349 // another VA 3.0 memory problem here
350 delete g_globalCursor;
351#endif
352 g_globalCursor = NULL;
353
354 wxDeleteStockObjects();
355
356 // Destroy all GDI lists, etc.
357 wxDeleteStockLists();
358
359 delete wxTheColourDatabase;
360 wxTheColourDatabase = NULL;
361
362 wxBitmap::CleanUpHandlers();
363
364 delete[] wxBuffer;
365 wxBuffer = NULL;
366
367 //// WINDOWS-SPECIFIC CLEANUP
368
369 // wxSetKeyboardHook(FALSE);
370
371 if (wxSTD_FRAME_ICON)
372 ::WinFreeFileIcon(wxSTD_FRAME_ICON);
373 if (wxSTD_MDICHILDFRAME_ICON)
374 ::WinFreeFileIcon(wxSTD_MDICHILDFRAME_ICON);
375 if (wxSTD_MDIPARENTFRAME_ICON)
376 ::WinFreeFileIcon(wxSTD_MDIPARENTFRAME_ICON);
377
378 if (wxDEFAULT_FRAME_ICON)
379 ::WinFreeFileIcon(wxDEFAULT_FRAME_ICON);
380 if (wxDEFAULT_MDICHILDFRAME_ICON)
381 ::WinFreeFileIcon(wxDEFAULT_MDICHILDFRAME_ICON);
382 if (wxDEFAULT_MDIPARENTFRAME_ICON)
383 ::WinFreeFileIcon(wxDEFAULT_MDIPARENTFRAME_ICON);
384
385 if ( wxDisableButtonBrush )
386 {
387// TODO: ::DeleteObject( wxDisableButtonBrush );
388 }
389
390 if (wxWinHandleList)
391 delete wxWinHandleList;
392
393 // GL: I'm annoyed ... I don't know where to put this and I don't want to
394 // create a module for that as it's part of the core.
395#if wxUSE_THREADS
396 delete wxPendingEvents;
397 delete wxPendingEventsLocker;
398 // If we don't do the following, we get an apparent memory leak.
399 ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
400#endif
401
402 wxClassInfo::CleanUpClasses();
403
404 delete wxTheApp;
405 wxTheApp = NULL;
406
407#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
408 // At this point we want to check if there are any memory
409 // blocks that aren't part of the wxDebugContext itself,
410 // as a special case. Then when dumping we need to ignore
411 // wxDebugContext, too.
412 if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
413 {
414 wxLogDebug(wxT("There were memory leaks."));
415 wxDebugContext::Dump();
416 wxDebugContext::PrintStatistics();
417 }
418 // wxDebugContext::SetStream(NULL, NULL);
419#endif
420
421#if wxUSE_LOG
422 // do it as the very last thing because everything else can log messages
423 delete wxLog::SetActiveTarget(NULL);
424#endif // wxUSE_LOG
425}
426
427int wxEntry(
428 int argc
429, char* argv[]
430)
431{
432 HAB vHab = 0;
433
434 if (!wxApp::Initialize(vHab))
435 return 0;
436
437 //
438 // create the application object or ensure that one already exists
439 //
440 if (!wxTheApp)
441 {
442 // The app may have declared a global application object, but we recommend
443 // the IMPLEMENT_APP macro is used instead, which sets an initializer
444 // function for delayed, dynamic app object construction.
445 wxCHECK_MSG( wxApp::GetInitializerFunction(), 0,
446 wxT("No initializer - use IMPLEMENT_APP macro.") );
447 wxTheApp = (*wxApp::GetInitializerFunction()) ();
448 }
449 wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") );
450 wxTheApp->argc = argc;
451
452#if wxUSE_UNICODE
453 wxTheApp->argv = new wxChar*[argc+1];
454
455 int nArgc = 0;
456
457 while (nArgc < argc)
458 {
459 wxTheApp->argv[nArgc] = wxStrdup(wxConvLibc.cMB2WX(argv[nArgc]));
460 nArgc++;
461 }
462 wxTheApp->argv[nArgc] = (wxChar *)NULL;
463#else
464 wxTheApp->argv = argv;
465#endif
466
467 wxString sName(wxFileNameFromPath(argv[0]));
468
469 wxStripExtension(sName);
470 wxTheApp->SetAppName(sName);
471
472 int nRetValue = 0;
473
474 if (!wxTheApp->OnInitGui())
475 nRetValue = -1;
476
477 if (nRetValue == 0)
478 {
479 if (wxTheApp->OnInit())
480 {
481 nRetValue = wxTheApp->OnRun();
482// nRetValue = -1;
483 }
484 }
485
486 wxWindow* pTopWindow = wxTheApp->GetTopWindow();
487
488 if (pTopWindow)
489 {
490 // Forcibly delete the window.
491 if (pTopWindow->IsKindOf(CLASSINFO(wxFrame)) ||
492 pTopWindow->IsKindOf(CLASSINFO(wxDialog)) )
493 {
494 pTopWindow->Close(TRUE);
495 wxTheApp->DeletePendingObjects();
496 }
497 else
498 {
499 delete pTopWindow;
500 wxTheApp->SetTopWindow(NULL);
501 }
502 }
503 wxTheApp->OnExit();
504 wxApp::CleanUp();
505 return(nRetValue);
506}
507
508bool wxApp::OnInitGui()
509{
510 ERRORID vError;
511 wxString sError;
512
513 m_hMq = ::WinCreateMsgQueue(vHabmain, 0);
514 if (!m_hMq)
515 {
516 vError = ::WinGetLastError(vHabmain);
517 sError = wxPMErrorToStr(vError);
518 wxLogDebug(sError);
519 return FALSE;
520 }
521 return TRUE;
522}
523
524//
525// Static member initialization
526//
527wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
528
529wxApp::wxApp()
530{
531 m_topWindow = NULL;
532 wxTheApp = this;
533 m_wantDebugOutput = TRUE;
534
535 argc = 0;
536 argv = NULL;
537 m_nPrintMode = wxPRINT_WINDOWS;
538 m_exitOnFrameDelete = TRUE;
539 m_bAuto3D = TRUE;
540}
541
542wxApp::~wxApp()
543{
544#if wxUSE_UNICODE
545 // Delete command-line args
546 int i;
547 for (i = 0; i < argc; i++)
548 {
549 delete[] argv[i];
550 }
551 delete[] argv;
552#endif
553}
554
555bool wxApp::Initialized()
556{
557 if (GetTopWindow())
558 return TRUE;
559 else
560 return FALSE;
561}
562
563//
564// Get and process a message, returning FALSE if WM_QUIT
565// received (and also set the flag telling the app to exit the main loop)
566//
567bool wxApp::DoMessage()
568{
569 BOOL bRc = ::WinGetMsg(vHabmain, &m_vMsg, HWND(NULL), 0, 0);
570
571 if (bRc == 0)
572 {
573 // got WM_QUIT
574 m_bKeepGoing = FALSE;
575 return FALSE;
576 }
577 else if (bRc == -1)
578 {
579 // should never happen, but let's test for it nevertheless
580 wxLogLastError("GetMessage");
581 }
582 else
583 {
584#if wxUSE_THREADS
585 wxASSERT_MSG( wxThread::IsMain()
586 ,wxT("only the main thread can process Windows messages")
587 );
588
589 static bool sbHadGuiLock = TRUE;
590 static wxMsgArray svSavedMessages;
591
592 //
593 // if a secondary thread owns is doing GUI calls, save all messages for
594 // later processing - we can't process them right now because it will
595 // lead to recursive library calls (and we're not reentrant)
596 //
597 if (!wxGuiOwnedByMainThread())
598 {
599 sbHadGuiLock = FALSE;
600
601 // leave out WM_COMMAND messages: too dangerous, sometimes
602 // the message will be processed twice
603 if ( !wxIsWaitingForThread() ||
604 svCurrentMsg.msg != WM_COMMAND )
605 {
606 svSavedMessages.Add(svCurrentMsg);
607 }
608 return TRUE;
609 }
610 else
611 {
612 //
613 // have we just regained the GUI lock? if so, post all of the saved
614 // messages
615 //
616 // FIXME of course, it's not _exactly_ the same as processing the
617 // messages normally - expect some things to break...
618 //
619 if (!sbHadGuiLock )
620 {
621 sbHadGuiLock = TRUE;
622
623 size_t nCount = svSavedMessages.Count();
624
625 for (size_t n = 0; n < nCount; n++)
626 {
627 QMSG vMsg = svSavedMessages[n];
628
629 if ( !ProcessMessage((WXMSG *)&vMsg) )
630 {
631 ::WinDispatchMsg(vHabmain, &vMsg);
632 }
633 }
634 svSavedMessages.Empty();
635 }
636 }
637#endif // wxUSE_THREADS
638
639 // Process the message
640 if (!ProcessMessage((WXMSG *)&svCurrentMsg) )
641 {
642 ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg);
643 }
644 }
645 return TRUE;
646}
647
648//////////////////////////////////////////////////////////////////////////////
649//
650// Keep trying to process messages until WM_QUIT
651// received.
652//
653// If there are messages to be processed, they will all be
654// processed and OnIdle will not be called.
655// When there are no more messages, OnIdle is called.
656// If OnIdle requests more time,
657// it will be repeatedly called so long as there are no pending messages.
658// A 'feature' of this is that once OnIdle has decided that no more processing
659// is required, then it won't get processing time until further messages
660// are processed (it'll sit in DoMessage).
661//
662//////////////////////////////////////////////////////////////////////////////
663int wxApp::MainLoop()
664{
665 m_bKeepGoing = TRUE;
666
667 while (m_bKeepGoing)
668 {
669#if wxUSE_THREADS
670 wxMutexGuiLeaveOrEnter();
671#endif // wxUSE_THREADS
672 while (!::WinPeekMsg(vHabmain, &svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) &&
673 ProcessIdle() )
674 {
675 }
676 DoMessage();
677 }
678 return (int)svCurrentMsg.mp1;
679}
680
681//
682// Returns TRUE if more time is needed.
683//
684bool wxApp::ProcessIdle()
685{
686 wxIdleEvent vEvent;
687
688 vEvent.SetEventObject(this);
689 ProcessEvent(vEvent);
690 return vEvent.MoreRequested();
691}
692
693#if wxUSE_THREADS
694void wxApp::ProcessPendingEvents()
695{
696 wxNode* pNode = wxPendingEvents->First();
697 wxCriticalSectionLocker vLocker(*wxPendingEventsLocker);
698
699 while (pNode)
700 {
701 wxEvtHandler* pHandler = (wxEvtHandler *)pNode->Data();
702 pHandler->ProcessPendingEvents();
703
704 delete pNode;
705 pNode = wxPendingEvents->First();
706 }
707}
708#endif
709
710void wxApp::ExitMainLoop()
711{
712 m_bKeepGoing = FALSE;
713}
714
715bool wxApp::Pending()
716{
717 return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0);
718}
719
720void wxApp::Dispatch()
721{
722 DoMessage();
723}
724
725//////////////////////////////////////////////////////////////////////////////
726//
727// Give all windows a chance to preprocess
728// the message. Some may have accelerator tables, or have
729// MDI complications.
730//
731//////////////////////////////////////////////////////////////////////////////
732bool wxApp::ProcessMessage(
733 WXMSG* pWxmsg
734)
735{
736 QMSG* vMsg = (PQMSG)pWxmsg;
737 HWND hWnd = vMsg->hwnd;
738 wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
739 wxWindow* pWnd;
740
741 //
742 // for some composite controls (like a combobox), wndThis might be NULL
743 // because the subcontrol is not a wxWindow, but only the control itself
744 // is - try to catch this case
745 //
746 while (hWnd && !pWndThis)
747 {
748 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
749 pWndThis = wxFindWinFromHandle((WXHWND)hWnd);
750 }
751
752 // Anyone for a non-translation message? Try youngest descendants first.
753 for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent())
754 {
755 if (pWnd->OS2ProcessMessage(pWxmsg))
756 return TRUE;
757 }
758 return FALSE;
759}
760
761void wxApp::OnIdle(
762 wxIdleEvent& rEvent
763)
764{
765 static bool sbInOnIdle = FALSE;
766
767 //
768 // Avoid recursion (via ProcessEvent default case)
769 //
770 if (sbInOnIdle )
771 return;
772
773 sbInOnIdle = TRUE;
774
775 //
776 // 'Garbage' collection of windows deleted with Close().
777 //
778 DeletePendingObjects();
779
780#if wxUSE_LOG
781 // flush the logged messages if any
782 wxLog* pLog = wxLog::GetActiveTarget();
783
784 if (pLog != NULL && pLog->HasPendingMessages())
785 pLog->Flush();
786#endif // wxUSE_LOG
787
788 // Send OnIdle events to all windows
789 if (SendIdleEvents())
790 {
791 //
792 // SendIdleEvents() returns TRUE if at least one window requested more
793 // idle events
794 //
795 rEvent.RequestMore(TRUE);
796 }
797
798 //
799 // If they are pending events, we must process them.
800 //
801#if wxUSE_THREADS
802 ProcessPendingEvents();
803#endif
804 sbInOnIdle = FALSE;
805}
806
807void wxWakeUpIdle()
808{
809 // **** please implement me! ****
810 // Wake up the idle handler processor, even if it is in another thread...
811}
812
813// Send idle event to all top-level windows
814bool wxApp::SendIdleEvents()
815{
816 bool bNeedMore = FALSE;
817 wxWindowList::Node* pNode = wxTopLevelWindows.GetFirst();
818
819 while (pNode)
820 {
821 wxWindow* pWin = pNode->GetData();
822
823 if (SendIdleEvents(pWin))
824 bNeedMore = TRUE;
825 pNode = pNode->GetNext();
826 }
827 return bNeedMore;
828}
829
830//
831// Send idle event to window and all subwindows
832//
833bool wxApp::SendIdleEvents(
834 wxWindow* pWin
835)
836{
837 bool bNeedMore = FALSE;
838 wxIdleEvent vEvent;
839
840 vEvent.SetEventObject(pWin);
841 pWin->GetEventHandler()->ProcessEvent(vEvent);
842
843 if (vEvent.MoreRequested())
844 bNeedMore = TRUE;
845
846 wxNode* pNode = pWin->GetChildren().First();
847
848 while (pNode)
849 {
850 wxWindow* pWin = (wxWindow*) pNode->Data();
851
852 if (SendIdleEvents(pWin))
853 bNeedMore = TRUE;
854 pNode = pNode->Next();
855 }
856 return bNeedMore;
857}
858
859void wxApp::DeletePendingObjects()
860{
861 wxNode* pNode = wxPendingDelete.First();
862
863 while (pNode)
864 {
865 wxObject* pObj = (wxObject *)pNode->Data();
866
867 delete pObj;
868
869 if (wxPendingDelete.Member(pObj))
870 delete pNode;
871
872 //
873 // Deleting one object may have deleted other pending
874 // objects, so start from beginning of list again.
875 //
876 pNode = wxPendingDelete.First();
877 }
878}
879
880void wxApp::OnEndSession(
881 wxCloseEvent& WXUNUSED(rEvent))
882{
883 if (GetTopWindow())
884 GetTopWindow()->Close(TRUE);
885}
886
887//
888// Default behaviour: close the application with prompts. The
889// user can veto the close, and therefore the end session.
890//
891void wxApp::OnQueryEndSession(
892 wxCloseEvent& rEvent
893)
894{
895 if (GetTopWindow())
896 {
897 if (!GetTopWindow()->Close(!rEvent.CanVeto()))
898 rEvent.Veto(TRUE);
899 }
900}
901
902void wxExit()
903{
904 wxLogError(_("Fatal error: exiting"));
905
906 wxApp::CleanUp();
907}
908
909// Yield to incoming messages
910bool wxYield()
911{
912 HAB vHab = 0;
913 QMSG vMsg;
914 // We want to go back to the main message loop
915 // if we see a WM_QUIT. (?)
916 while (::WinPeekMsg(vHab, &vMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) && vMsg.msg != WM_QUIT)
917 {
918 if (!wxTheApp->DoMessage())
919 break;
920 }
921 // If they are pending events, we must process them.
922#if wxUSE_THREADS
923 wxTheApp->ProcessPendingEvents();
924#endif
925 return TRUE;
926}
927
928wxIcon wxApp::GetStdIcon(
929 int nWhich
930) const
931{
932 switch(nWhich)
933 {
934 case wxICON_INFORMATION:
935 return wxIcon("wxICON_INFO");
936
937 case wxICON_QUESTION:
938 return wxIcon("wxICON_QUESTION");
939
940 case wxICON_EXCLAMATION:
941 return wxIcon("wxICON_WARNING");
942
943 default:
944 wxFAIL_MSG(wxT("requested non existent standard icon"));
945 // still fall through
946
947 case wxICON_HAND:
948 return wxIcon("wxICON_ERROR");
949 }
950 return wxIcon("wxICON_ERROR");
951}
952
953HINSTANCE wxGetInstance()
954{
955 return wxhInstance;
956}
957
958void wxSetInstance(HINSTANCE hInst)
959{
960 wxhInstance = hInst;
961}
962