From 598dc9b7779271df770ccbe0377a0f9e15816583 Mon Sep 17 00:00:00 2001 From: Stefan Neis Date: Sun, 21 Sep 2003 21:54:03 +0000 Subject: [PATCH] Switched over to using wxEventLoop. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23785 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/os2/app.h | 21 +--- include/wx/os2/dialog.h | 5 + src/os2/app.cpp | 254 +--------------------------------------- src/os2/dialog.cpp | 56 ++++++--- src/os2/evtloop.cpp | 233 ++++++++++++++++++++++++++---------- src/os2/window.cpp | 5 +- 6 files changed, 227 insertions(+), 347 deletions(-) diff --git a/include/wx/os2/app.h b/include/wx/os2/app.h index c7cc54efbc..8095ec921c 100644 --- a/include/wx/os2/app.h +++ b/include/wx/os2/app.h @@ -68,16 +68,12 @@ public: wxApp(); virtual ~wxApp(); - virtual bool OnInitGui(void); - // override base class (pure) virtuals - virtual int MainLoop(void); - virtual void ExitMainLoop(void); - virtual bool Initialized(void); - virtual bool Pending(void) ; - virtual bool Dispatch(void); + virtual bool Initialize(int& argc, wxChar **argv); + virtual void CleanUp(void); - virtual void Exit(); + virtual bool Initialized(void); + virtual bool OnInitGui(void); virtual bool Yield(bool onlyIfNeeded = FALSE); virtual void WakeUpIdle(void); @@ -113,22 +109,15 @@ private: public: // Implementation - virtual bool Initialize(int& argc, wxChar **argv); - virtual void CleanUp(void); - static bool RegisterWindowClasses(HAB vHab); - virtual void DoMessage(WXMSG *pMsg); - virtual bool DoMessage(void); - virtual bool ProcessMessage(WXMSG* pMsg); public: int m_nCmdShow; HMQ m_hMq; protected: - bool m_bKeepGoing ; - DECLARE_EVENT_TABLE() + DECLARE_NO_COPY_CLASS(wxApp) }; #endif // _WX_APP_H_ diff --git a/include/wx/os2/dialog.h b/include/wx/os2/dialog.h index bd96a0497a..89671430e9 100644 --- a/include/wx/os2/dialog.h +++ b/include/wx/os2/dialog.h @@ -16,6 +16,8 @@ WXDLLEXPORT_DATA(extern const char*) wxDialogNameStr; +class WXDLLEXPORT wxDialogModalData; + // // Dialog boxes // @@ -147,6 +149,9 @@ protected: private: wxWindow* m_pOldFocus; + // this pointer is non-NULL only while the modal event loop is running + wxDialogModalData *m_modalData; + // // While we are showing a modal dialog we disable the other windows using // this object diff --git a/src/os2/app.cpp b/src/os2/app.cpp index 50a810d166..cfcccb9c6b 100644 --- a/src/os2/app.cpp +++ b/src/os2/app.cpp @@ -33,7 +33,6 @@ #include "wx/dynarray.h" #include "wx/wxchar.h" #include "wx/icon.h" - #include "wx/timer.h" #endif #include "wx/log.h" @@ -67,13 +66,6 @@ extern "C" int _System bsdselect(int, #if wxUSE_THREADS #include "wx/thread.h" - - // define the array of QMSG strutures - WX_DECLARE_OBJARRAY(QMSG, wxMsgArray); - - #include "wx/arrimpl.cpp" - - WX_DEFINE_OBJARRAY(wxMsgArray); #endif // wxUSE_THREADS #if wxUSE_TOOLTIPS @@ -93,7 +85,6 @@ extern wxList WXDLLEXPORT wxPendingDelete; extern wxCursor* g_globalCursor; HAB vHabmain = NULLHANDLE; -QMSG svCurrentMsg; HICON wxSTD_FRAME_ICON = (HICON) NULL; @@ -514,241 +505,6 @@ bool wxApp::Initialized() return FALSE; } // end of wxApp::Initialized -// -// Get and process a message, returning FALSE if WM_QUIT -// received (and also set the flag telling the app to exit the main loop) -// - -bool wxApp::DoMessage() -{ - BOOL bRc = ::WinGetMsg(vHabmain, &svCurrentMsg, HWND(NULL), 0, 0); - - if (bRc == 0) - { - // got WM_QUIT - m_bKeepGoing = FALSE; - return FALSE; - } - else if (bRc == -1) - { - // should never happen, but let's test for it nevertheless - wxLogLastError("GetMessage"); - } - else - { -#if wxUSE_THREADS - wxASSERT_MSG( wxThread::IsMain() - ,wxT("only the main thread can process Windows messages") - ); - - static bool sbHadGuiLock = TRUE; - static wxMsgArray svSavedMessages; - - // - // If a secondary thread owns is doing GUI calls, save all messages for - // later processing - we can't process them right now because it will - // lead to recursive library calls (and we're not reentrant) - // - if (!wxGuiOwnedByMainThread()) - { - sbHadGuiLock = FALSE; - - // - // Leave out WM_COMMAND messages: too dangerous, sometimes - // the message will be processed twice - // - if ( !wxIsWaitingForThread() || - svCurrentMsg.msg != WM_COMMAND ) - { - svSavedMessages.Add(svCurrentMsg); - } - return TRUE; - } - else - { - // - // Have we just regained the GUI lock? if so, post all of the saved - // messages - // - if (!sbHadGuiLock ) - { - sbHadGuiLock = TRUE; - - size_t nCount = svSavedMessages.Count(); - - for (size_t n = 0; n < nCount; n++) - { - QMSG vMsg = svSavedMessages[n]; - - DoMessage((WXMSG*)&vMsg); - } - svSavedMessages.Empty(); - } - } -#endif // wxUSE_THREADS - - // - // Process the message - // - DoMessage((WXMSG *)&svCurrentMsg); - } - return TRUE; -} // end of wxApp::DoMessage - -void wxApp::DoMessage( - WXMSG* pMsg -) -{ - if (!ProcessMessage((WXMSG *)&svCurrentMsg)) - { - ::WinDispatchMsg(vHabmain, (PQMSG)&svCurrentMsg); - } -} // end of wxApp::DoMessage - -////////////////////////////////////////////////////////////////////////////// -// -// Keep trying to process messages until WM_QUIT -// received. -// -// If there are messages to be processed, they will all be -// processed and OnIdle will not be called. -// When there are no more messages, OnIdle is called. -// If OnIdle requests more time, -// it will be repeatedly called so long as there are no pending messages. -// A 'feature' of this is that once OnIdle has decided that no more processing -// is required, then it won't get processing time until further messages -// are processed (it'll sit in DoMessage). -// -////////////////////////////////////////////////////////////////////////////// -int wxApp::MainLoop() -{ - m_bKeepGoing = TRUE; - - while (m_bKeepGoing) - { -#if wxUSE_THREADS - wxMutexGuiLeaveOrEnter(); -#endif // wxUSE_THREADS - while (!Pending() && ProcessIdle()) - { - HandleSockets(); - wxUsleep(10); - } - HandleSockets(); - if (Pending()) - DoMessage(); - else - wxUsleep(10); - - } - return (int)svCurrentMsg.mp1; -} // end of wxApp::MainLoop - -void wxApp::ExitMainLoop() -{ - ::WinPostMsg(NULL, WM_QUIT, 0, 0); -} // end of wxApp::ExitMainLoop - -bool wxApp::Pending() -{ - return (::WinPeekMsg(vHabmain, (PQMSG)&svCurrentMsg, (HWND)NULL, 0, 0, PM_NOREMOVE) != 0); -} // end of wxApp::Pending - -bool wxApp::Dispatch() -{ - return DoMessage(); -} - -////////////////////////////////////////////////////////////////////////////// -// -// Give all windows a chance to preprocess -// the message. Some may have accelerator tables, or have -// MDI complications. -// -////////////////////////////////////////////////////////////////////////////// -bool wxApp::ProcessMessage( - WXMSG* pWxmsg -) -{ - QMSG* pMsg = (PQMSG)pWxmsg; - HWND hWnd = pMsg->hwnd; - wxWindow* pWndThis = wxFindWinFromHandle((WXHWND)hWnd); - wxWindow* pWnd; - - // - // Pass non-system timer messages to the wxTimerProc - // - if (pMsg->msg == WM_TIMER && - (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR && - SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW && - SHORT1FROMMP(pMsg->mp1) != TID_SCROLL && - SHORT1FROMMP(pMsg->mp1) != 0x0000 - )) - wxTimerProc(NULL, 0, (int)pMsg->mp1, 0); - - // - // Allow the window to prevent certain messages from being - // translated/processed (this is currently used by wxTextCtrl to always - // grab Ctrl-C/V/X, even if they are also accelerators in some parent) - // - if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage(pWxmsg)) - { - return FALSE; - } - - // - // For some composite controls (like a combobox), wndThis might be NULL - // because the subcontrol is not a wxWindow, but only the control itself - // is - try to catch this case - // - while (hWnd && !pWndThis) - { - hWnd = ::WinQueryWindow(hWnd, QW_PARENT); - pWndThis = wxFindWinFromHandle((WXHWND)hWnd); - } - - // - // Try translations first; find the youngest window with - // a translation table. OS/2 has case sensative accels, so - // this block, coded by BK, removes that and helps make them - // case insensative. - // - if(pMsg->msg == WM_CHAR) - { - PBYTE pChmsg = (PBYTE)&(pMsg->msg); - USHORT uSch = CHARMSG(pChmsg)->chr; - bool bRc; - - // - // Do not process keyup events - // - if(!(CHARMSG(pChmsg)->fs & KC_KEYUP)) - { - if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0) - CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch); - - - for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() ) - { - if((bRc = pWnd->OS2TranslateMessage(pWxmsg)) == TRUE) - break; - } - - if(!bRc) // untranslated, should restore original value - CHARMSG(pChmsg)->chr = uSch; - } - } - // - // Anyone for a non-translation message? Try youngest descendants first. - // -// for (pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent()) -// { -// if (pWnd->OS2ProcessMessage(pWxmsg)) -// return TRUE; -// } - return FALSE; -} // end of wxApp::ProcessMessage - bool gbInOnIdle = FALSE; void wxApp::OnIdle( @@ -801,14 +557,6 @@ void wxApp::OnQueryEndSession( } } // end of wxApp::OnQueryEndSession -void wxApp::Exit() -{ - wxApp::CleanUp(); - - // VZ: must really exit somehow, insert appropriate OS/2 syscall (FIXME) - wxAppConsole::Exit(); -} // end of wxExit - // // Yield to incoming messages // @@ -846,7 +594,7 @@ bool wxApp::Yield(bool onlyIfNeeded) #if wxUSE_THREADS wxMutexGuiLeaveOrEnter(); #endif // wxUSE_THREADS - if (!wxTheApp->DoMessage()) + if (!wxTheApp->Dispatch()) break; } // diff --git a/src/os2/dialog.cpp b/src/os2/dialog.cpp index 1ab046a28e..ff6cf0344b 100644 --- a/src/os2/dialog.cpp +++ b/src/os2/dialog.cpp @@ -24,6 +24,8 @@ #include "wx/os2/private.h" #include "wx/log.h" +#include "wx/evtloop.h" +#include "wx/ptr_scpd.h" #define wxDIALOG_DEFAULT_X 300 #define wxDIALOG_DEFAULT_Y 300 @@ -44,6 +46,41 @@ BEGIN_EVENT_TABLE(wxDialog, wxDialogBase) EVT_CLOSE(wxDialog::OnCloseWindow) END_EVENT_TABLE() +// ---------------------------------------------------------------------------- +// wxDialogModalData +// ---------------------------------------------------------------------------- + +// this is simply a container for any data we need to implement modality which +// allows us to avoid changing wxDialog each time the implementation changes +class wxDialogModalData +{ +public: + wxDialogModalData(wxDialog *dialog) : m_evtLoop(dialog) { } + + void RunLoop() + { + m_evtLoop.Run(); + } + + void ExitLoop() + { + m_evtLoop.Exit(); + } + +private: + wxModalEventLoop m_evtLoop; +}; + +wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData); + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxDialog construction +// ---------------------------------------------------------------------------- + void wxDialog::Init() { m_pOldFocus = (wxWindow *)NULL; @@ -215,25 +252,16 @@ void wxDialog::DoShowModal() gbInOnIdle = FALSE; - // - // Enter the modal loop - // - while ( IsModalShowing() ) + // enter the modal loop { -#if wxUSE_THREADS - wxMutexGuiLeaveOrEnter(); -#endif // wxUSE_THREADS - - while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() ) - ; - - // a message came or no more idle processing to do - wxTheApp->DoMessage(); + wxDialogModalDataTiedPtr modalData(&m_modalData, + new wxDialogModalData(this)); + modalData->RunLoop(); } gbInOnIdle = bWasInOnIdle; // - // Snd restore focus + // and restore focus // Note that this code MUST NOT access the dialog object's data // in case the object has been deleted (which will be the case // for a modal dialog that has been destroyed before calling EndModal). diff --git a/src/os2/evtloop.cpp b/src/os2/evtloop.cpp index 2b72b4088d..8ca8d5c0c0 100644 --- a/src/os2/evtloop.cpp +++ b/src/os2/evtloop.cpp @@ -31,22 +31,26 @@ #ifndef WX_PRECOMP #include "wx/window.h" #include "wx/app.h" + #include "wx/timer.h" #endif //WX_PRECOMP #include "wx/evtloop.h" +#include "wx/log.h" #include "wx/tooltip.h" +#include "wx/ptr_scpd.h" #include "wx/os2/private.h" #if wxUSE_THREADS // define the array of QMSG strutures WX_DECLARE_OBJARRAY(QMSG, wxMsgArray); - // VS: this is a bit dirty - it duplicates same declaration in app.cpp - // (and there's no WX_DEFINE_OBJARRAY for that reason - it is already - // defined in app.cpp). + + #include "wx/arrimpl.cpp" + + WX_DEFINE_OBJARRAY(wxMsgArray); #endif -extern HAB vHabMain; +extern HAB vHabmain; // ---------------------------------------------------------------------------- // wxEventLoopImpl @@ -77,6 +81,36 @@ private: int m_exitcode; }; +// ---------------------------------------------------------------------------- +// helper class +// ---------------------------------------------------------------------------- + +wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoopImpl); + +// this object sets the wxEventLoop given to the ctor as the currently active +// one and unsets it in its dtor +class wxEventLoopActivator +{ +public: + wxEventLoopActivator(wxEventLoop **pActive, + wxEventLoop *evtLoop) + { + m_pActive = pActive; + m_evtLoopOld = *pActive; + *pActive = evtLoop; + } + + ~wxEventLoopActivator() + { + // restore the previously active event loop + *m_pActive = m_evtLoopOld; + } + +private: + wxEventLoop *m_evtLoopOld; + wxEventLoop **m_pActive; +}; + // ============================================================================ // wxEventLoopImpl implementation // ============================================================================ @@ -91,44 +125,93 @@ void wxEventLoopImpl::ProcessMessage(QMSG *msg) if ( !PreProcessMessage(msg) ) { // if it wasn't done, dispatch it to the corresponding window - ::WinDispatchMsg(vHabMain, msg); + ::WinDispatchMsg(vHabmain, msg); } } -bool wxEventLoopImpl::PreProcessMessage(QMSG *msg) +bool wxEventLoopImpl::PreProcessMessage(QMSG *pMsg) { - HWND hWnd = msg->hwnd; - wxWindow *wndThis = wxFindWinFromHandle((WXHWND)hWnd); - -#if wxUSE_TOOLTIPS - // we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to - // popup the tooltip bubbles - if ( wndThis && (msg->message == WM_MOUSEMOVE) ) + HWND hWnd = pMsg->hwnd; + wxWindow *pWndThis = wxFindWinFromHandle((WXHWND)hWnd); + wxWindow *pWnd; + + // + // Pass non-system timer messages to the wxTimerProc + // + if (pMsg->msg == WM_TIMER && + (SHORT1FROMMP(pMsg->mp1) != TID_CURSOR && + SHORT1FROMMP(pMsg->mp1) != TID_FLASHWINDOW && + SHORT1FROMMP(pMsg->mp1) != TID_SCROLL && + SHORT1FROMMP(pMsg->mp1) != 0x0000 + )) + wxTimerProc(NULL, 0, (int)pMsg->mp1, 0); + + // Allow the window to prevent certain messages from being + // translated/processed (this is currently used by wxTextCtrl to always + // grab Ctrl-C/V/X, even if they are also accelerators in some parent) + // + if (pWndThis && !pWndThis->OS2ShouldPreProcessMessage((WXMSG*)pMsg)) { - wxToolTip *tt = wndThis->GetToolTip(); - if ( tt ) - { - tt->RelayEvent((WXMSG *)msg); - } + return FALSE; } -#endif // wxUSE_TOOLTIPS - // try translations first; find the youngest window with a translation - // table. - wxWindow *wnd; - for ( wnd = wndThis; wnd; wnd = wnd->GetParent() ) + // + // For some composite controls (like a combobox), wndThis might be NULL + // because the subcontrol is not a wxWindow, but only the control itself + // is - try to catch this case + // + while (hWnd && !pWndThis) { - if ( wnd->OS2TranslateMessage((WXMSG *)msg) ) - return TRUE; + hWnd = ::WinQueryWindow(hWnd, QW_PARENT); + pWndThis = wxFindWinFromHandle((WXHWND)hWnd); } - // Anyone for a non-translation message? Try youngest descendants first. - for ( wnd = wndThis; wnd; wnd = wnd->GetParent() ) + + // + // Try translations first; find the youngest window with + // a translation table. OS/2 has case sensiive accels, so + // this block, coded by BK, removes that and helps make them + // case insensitive. + // + if(pMsg->msg == WM_CHAR) { - if ( wnd->OS2ProcessMessage((WXMSG *)msg) ) - return TRUE; + PBYTE pChmsg = (PBYTE)&(pMsg->msg); + USHORT uSch = CHARMSG(pChmsg)->chr; + bool bRc = FALSE; + + // + // Do not process keyup events + // + if(!(CHARMSG(pChmsg)->fs & KC_KEYUP)) + { + if((CHARMSG(pChmsg)->fs & (KC_ALT | KC_CTRL)) && CHARMSG(pChmsg)->chr != 0) + CHARMSG(pChmsg)->chr = (USHORT)wxToupper((UCHAR)uSch); + + + for(pWnd = pWndThis; pWnd; pWnd = pWnd->GetParent() ) + { + if((bRc = pWnd->OS2TranslateMessage((WXMSG*)pMsg)) == TRUE) + return TRUE; + // break; + // stop at first top level window, i.e. don't try to process the + // key strokes originating in a dialog using the accelerators of + // the parent frame - this doesn't make much sense + if ( pWnd->IsTopLevel() ) + break; + } + + if(!bRc) // untranslated, should restore original value + CHARMSG(pChmsg)->chr = uSch; + } } - + // + // Anyone for a non-translation message? Try youngest descendants first. + // +// for (pWnd = pWndThis->GetParent(); pWnd; pWnd = pWnd->GetParent()) +// { +// if (pWnd->OS2ProcessMessage(pWxmsg)) +// return TRUE; +// } return FALSE; } @@ -161,15 +244,47 @@ bool wxEventLoop::IsRunning() const return m_impl != NULL; } +////////////////////////////////////////////////////////////////////////////// +// +// Keep trying to process messages until WM_QUIT +// received. +// +// If there are messages to be processed, they will all be +// processed and OnIdle will not be called. +// When there are no more messages, OnIdle is called. +// If OnIdle requests more time, +// it will be repeatedly called so long as there are no pending messages. +// A 'feature' of this is that once OnIdle has decided that no more processing +// is required, then it won't get processing time until further messages +// are processed (it'll sit in Dispatch). +// +////////////////////////////////////////////////////////////////////////////// +class CallEventLoopMethod +{ +public: + typedef void (wxEventLoop::*FuncType)(); + + CallEventLoopMethod(wxEventLoop *evtLoop, FuncType fn) + : m_evtLoop(evtLoop), m_fn(fn) { } + ~CallEventLoopMethod() { (m_evtLoop->*m_fn)(); } + +private: + wxEventLoop *m_evtLoop; + FuncType m_fn; +}; + int wxEventLoop::Run() { // event loops are not recursive, you need to create another loop! wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") ); - m_impl = new wxEventLoopImpl; + // SendIdleMessage() and Dispatch() below may throw so the code here should + // be exception-safe, hence we must use local objects for all actions we + // should undo + wxEventLoopActivator activate(&ms_activeLoop, this); + wxEventLoopImplTiedPtr impl(&m_impl, new wxEventLoopImpl); - wxEventLoop *oldLoop = ms_activeLoop; - ms_activeLoop = this; + CallEventLoopMethod callOnExit(this, &wxEventLoop::OnExit); for ( ;; ) { @@ -180,24 +295,25 @@ int wxEventLoop::Run() // generate and process idle events for as long as we don't have // anything else to do while ( !Pending() && m_impl->SendIdleMessage() ) - ; - - // a message came or no more idle processing to do, sit in Dispatch() - // waiting for the next message - if ( !Dispatch() ) - { - // we got WM_QUIT - break; - } + { + wxTheApp->HandleSockets(); + wxUsleep(10); + } + + wxTheApp->HandleSockets(); + if (Pending()) + { + if ( !Dispatch() ) + { + // we got WM_QUIT + break; + } + } + else + wxUsleep(10); } - int exitcode = m_impl->GetExitCode(); - delete m_impl; - m_impl = NULL; - - ms_activeLoop = oldLoop; - - return exitcode; + return m_impl->GetExitCode(); } void wxEventLoop::Exit(int rc) @@ -216,7 +332,7 @@ void wxEventLoop::Exit(int rc) bool wxEventLoop::Pending() const { QMSG msg; - return ::WinPeekMsg(vHabMain, &msg, 0, 0, 0, PM_NOREMOVE) != 0; + return ::WinPeekMsg(vHabmain, &msg, 0, 0, 0, PM_NOREMOVE) != 0; } bool wxEventLoop::Dispatch() @@ -224,23 +340,14 @@ bool wxEventLoop::Dispatch() wxCHECK_MSG( IsRunning(), FALSE, _T("can't call Dispatch() if not running") ); QMSG msg; - BOOL rc = ::WinGetMsg(vHabMain, &msg, (HWND) NULL, 0, 0); + BOOL bRc = ::WinGetMsg(vHabmain, &msg, (HWND) NULL, 0, 0); - if ( rc == 0 ) + if ( bRc == 0 ) { // got WM_QUIT return FALSE; } - if ( rc == -1 ) - { - // should never happen, but let's test for it nevertheless - wxLogLastError(wxT("GetMessage")); - - // still break from the loop - return FALSE; - } - #if wxUSE_THREADS wxASSERT_MSG( wxThread::IsMain(), wxT("only the main thread can process Windows messages") ); @@ -257,7 +364,7 @@ bool wxEventLoop::Dispatch() // leave out WM_COMMAND messages: too dangerous, sometimes // the message will be processed twice - if ( !wxIsWaitingForThread() || msg.message != WM_COMMAND ) + if ( !wxIsWaitingForThread() || msg.msg != WM_COMMAND ) { s_aSavedMessages.Add(msg); } @@ -278,7 +385,7 @@ bool wxEventLoop::Dispatch() size_t count = s_aSavedMessages.Count(); for ( size_t n = 0; n < count; n++ ) { - MSG& msg = s_aSavedMessages[n]; + QMSG& msg = s_aSavedMessages[n]; m_impl->ProcessMessage(&msg); } diff --git a/src/os2/window.cpp b/src/os2/window.cpp index daea0da4e1..a58a694e85 100644 --- a/src/os2/window.cpp +++ b/src/os2/window.cpp @@ -1969,7 +1969,10 @@ static void wxYieldForCommandsOnly() while (::WinPeekMsg(vHabmain, &vMsg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE) && vMsg.msg != WM_QUIT) { - wxTheApp->DoMessage((WXMSG*)&vMsg); + // luckily (as we don't have access to wxEventLoopImpl method from here + // anyhow...) we don't need to pre process WM_COMMANDs so dispatch it + // immediately + ::WinDispatchMsg(vHabmain, &vMsg); } if (vMsg.msg == WM_QUIT) ::WinPostMsg(NULL, WM_QUIT, 0, 0); -- 2.45.2