From 414f2513fc42e1ec60954c7c000d7ae78ba6af8c Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 15 Apr 2005 03:04:30 +0000 Subject: [PATCH] For wxMSW capture and release the mouse as the cursor moves out or back in to the transient popup window to enable the transient to be automatically dismissed when a click happens outside of it. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33618 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/popupwin.h | 6 +++++ samples/popup/popup.cpp | 56 +++++++++++++++++++++++++++----------- src/common/popupcmn.cpp | 60 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 102 insertions(+), 20 deletions(-) diff --git a/include/wx/popupwin.h b/include/wx/popupwin.h index b02debc98f..a347db9dc6 100644 --- a/include/wx/popupwin.h +++ b/include/wx/popupwin.h @@ -127,6 +127,11 @@ protected: // get alerted when child gets deleted from under us void OnDestroy(wxWindowDestroyEvent& event); +#ifdef __WXMSW__ + // check if the mouse needs captured or released + void OnIdle(wxIdleEvent& event); +#endif + // the child of this popup if any wxWindow *m_child; @@ -141,6 +146,7 @@ protected: wxPopupWindowHandler *m_handlerPopup; wxPopupFocusHandler *m_handlerFocus; + DECLARE_EVENT_TABLE() DECLARE_DYNAMIC_CLASS(wxPopupTransientWindow) DECLARE_NO_COPY_CLASS(wxPopupTransientWindow) }; diff --git a/samples/popup/popup.cpp b/samples/popup/popup.cpp index 4741bfe738..0306e91ccf 100644 --- a/samples/popup/popup.cpp +++ b/samples/popup/popup.cpp @@ -81,6 +81,7 @@ private: wxScrolledWindow *m_panel; wxButton *m_button; wxSpinCtrl *m_spinCtrl; + wxStaticText *m_mouseText; private: void OnMouse( wxMouseEvent &event ); @@ -118,9 +119,9 @@ SimpleTransientPopup::SimpleTransientPopup( wxWindow *parent ) // Keep this code to verify if mouse events work, they're required if // you're making a control like a combobox where the items are highlighted // under the cursor, the m_panel is set focus in the Popup() function - //m_panel->Connect(wxEVT_MOTION, - // wxMouseEventHandler(SimpleTransientPopup::OnMouse), - // NULL, this); + m_panel->Connect(wxEVT_MOTION, + wxMouseEventHandler(SimpleTransientPopup::OnMouse), + NULL, this); wxStaticText *text = new wxStaticText( m_panel, wxID_ANY, wxT("wx.PopupTransientWindow is a\n") @@ -128,16 +129,23 @@ SimpleTransientPopup::SimpleTransientPopup( wxWindow *parent ) wxT("automatically when the user\n") wxT("clicks the mouse outside it or if it\n") wxT("(or its first child) loses focus in \n") - wxT("any other way."), wxPoint( 10,10) ); - wxSize size = text->GetBestSize(); + wxT("any other way.") ); - m_button = new wxButton(m_panel, Minimal_PopupButton, wxT("Press Me"), wxPoint(0, size.y + 10)); - size.y = m_button->GetRect().GetBottom(); - m_spinCtrl = new wxSpinCtrl(m_panel, Minimal_PopupSpinctrl, wxT("Hello"), wxPoint(0, size.y + 5)); - size.y = m_spinCtrl->GetRect().GetBottom(); + m_button = new wxButton(m_panel, Minimal_PopupButton, wxT("Press Me")); + m_spinCtrl = new wxSpinCtrl(m_panel, Minimal_PopupSpinctrl, wxT("Hello")); + m_mouseText = new wxStaticText(m_panel, wxID_ANY, + wxT("<- Test Mouse ->")); - m_panel->SetSize( size.x+20, size.y+20 ); - SetClientSize( size.x+20, size.y+20 ); + wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL ); + topSizer->Add( text, 0, wxALL, 5 ); + topSizer->Add( m_button, 0, wxALL, 5 ); + topSizer->Add( m_spinCtrl, 0, wxALL, 5 ); + topSizer->Add( m_mouseText, 0, wxCENTRE|wxALL, 5 ); + + m_panel->SetAutoLayout( true ); + m_panel->SetSizer( topSizer ); + topSizer->Fit(m_panel); + topSizer->Fit(this); } SimpleTransientPopup::~SimpleTransientPopup() @@ -187,7 +195,22 @@ void SimpleTransientPopup::OnKillFocus(wxFocusEvent &event) void SimpleTransientPopup::OnMouse(wxMouseEvent &event) { + wxRect rect(m_mouseText->GetRect()); + rect.SetX(-100000); + rect.SetWidth(1000000); + wxColour colour(*wxLIGHT_GREY); + + if (rect.Inside(event.GetPosition())) + { + colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); wxLogMessage( wxT("0x%lx SimpleTransientPopup::OnMouse pos(%d, %d)"), long(event.GetEventObject()), event.GetX(), event.GetY()); + } + + if (colour != m_mouseText->GetBackgroundColour()) + { + m_mouseText->SetBackgroundColour(colour); + m_mouseText->Refresh(); + } event.Skip(); } @@ -317,6 +340,12 @@ MyFrame::MyFrame(const wxString& title) SetMenuBar(menuBar); #endif // wxUSE_MENUS +#if wxUSE_STATUSBAR + // create a status bar just for fun (by default with 1 pane only) + CreateStatusBar(2); + SetStatusText(_T("Welcome to wxWidgets!")); +#endif // wxUSE_STATUSBAR + wxPanel *panel = new wxPanel(this, -1); wxButton *button1 = new wxButton( panel, Minimal_StartSimplePopup, wxT("Show simple popup"), wxPoint(20,20) ); wxButton *button2 = new wxButton( panel, Minimal_StartScrolledPopup, wxT("Show scrolled popup"), wxPoint(20,70) ); @@ -336,11 +365,6 @@ MyFrame::MyFrame(const wxString& title) panel->SetAutoLayout( true ); panel->SetSizer( topSizer ); -#if wxUSE_STATUSBAR - // create a status bar just for fun (by default with 1 pane only) - CreateStatusBar(2); - SetStatusText(_T("Welcome to wxWidgets!")); -#endif // wxUSE_STATUSBAR } MyFrame::~MyFrame() diff --git a/src/common/popupcmn.cpp b/src/common/popupcmn.cpp index 50b97f5080..b480386124 100644 --- a/src/common/popupcmn.cpp +++ b/src/common/popupcmn.cpp @@ -110,6 +110,12 @@ BEGIN_EVENT_TABLE(wxPopupFocusHandler, wxEvtHandler) EVT_KEY_DOWN(wxPopupFocusHandler::OnKeyDown) END_EVENT_TABLE() +BEGIN_EVENT_TABLE(wxPopupTransientWindow, wxPopupWindow) +#ifdef __WXMSW__ + EVT_IDLE(wxPopupTransientWindow::OnIdle) +#endif +END_EVENT_TABLE() + // ============================================================================ // implementation // ============================================================================ @@ -199,7 +205,10 @@ void wxPopupTransientWindow::PopHandlers() // handler - so don't risk deleting it second time m_handlerPopup = NULL; } - + if (m_child->HasCapture()) + { + m_child->ReleaseMouse(); + } m_child = NULL; } @@ -303,6 +312,13 @@ bool wxPopupTransientWindow::Show( bool show ) } #endif +#ifdef __WXMSW__ + if (!show && m_child && m_child->HasCapture()) + { + m_child->ReleaseMouse(); + } +#endif + bool ret = wxPopupWindow::Show( show ); #ifdef __WXGTK__ @@ -337,20 +353,27 @@ bool wxPopupTransientWindow::Show( bool show ) CurrentTime ); } #endif + +#ifdef __WXMSW__ + if (show && m_child) + { + // Assume that the mouse is outside the popup to begin with + m_child->CaptureMouse(); + } +#endif + return ret; } void wxPopupTransientWindow::Dismiss() { - PopHandlers(); - Hide(); + PopHandlers(); } void wxPopupTransientWindow::DismissAndNotify() { Dismiss(); - OnDismiss(); } @@ -373,6 +396,35 @@ void wxPopupTransientWindow::OnDestroy(wxWindowDestroyEvent& event) m_focus = NULL; } +#ifdef __WXMSW__ +void wxPopupTransientWindow::OnIdle(wxIdleEvent& event) +{ + event.Skip(); + + if (IsShown() && m_child) + { + wxPoint pos = ScreenToClient(wxGetMousePosition()); + wxRect rect(wxPoint(0,0), GetSize()); + + if ( rect.Inside(pos) ) + { + if ( m_child->HasCapture() ) + { + m_child->ReleaseMouse(); + } + } + else + { + if ( !m_child->HasCapture() ) + { + m_child->CaptureMouse(); + } + } + } +} +#endif + + #if wxUSE_COMBOBOX && defined(__WXUNIVERSAL__) // ---------------------------------------------------------------------------- -- 2.45.2