\twocolitem{\helpref{wxMaximizeEvent}{wxmaximizeevent}}{A maximize event}
\twocolitem{\helpref{wxMenuEvent}{wxmenuevent}}{A menu event}
\twocolitem{\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}}{A mouse capture changed event}
+\twocolitem{\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}}{A mouse capture lost event}
\twocolitem{\helpref{wxMouseEvent}{wxmouseevent}}{A mouse event}
\twocolitem{\helpref{wxMoveEvent}{wxmoveevent}}{A move event}
\twocolitem{\helpref{wxNotebookEvent}{wxnotebookevent}}{A notebook control event}
\wxheading{See also}
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
\helpref{Event handling overview}{eventhandlingoverview},
\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
Returns the window that gained the capture, or NULL if it was a non-wxWidgets window.
+
+\section{\class{wxMouseCaptureLostEvent}}\label{wxmousecapturelostevent}
+
+An mouse capture lost event is sent to a window that obtained mouse capture,
+which was subsequently loss due to "external" event, for example when a dialog
+box is shown or if another application captures the mouse.
+
+If this happens, this event is sent to all windows that are on capture stack
+(i.e. called CaptureMouse, but didn't call ReleaseMouse yet). The event is
+{\em not} sent if the capture changes because of a call to CaptureMouse or
+ReleaseMouse.
+
+This event is currently emitted under Windows only.
+
+\wxheading{Derived from}
+
+\helpref{wxEvent}{wxevent}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Include files}
+
+<wx/event.h>
+
+\wxheading{Event table macros}
+
+To process this event, use the following event handler macro to direct input to
+a member function that takes a wxMouseCaptureLostEvent argument.
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_MOUSE\_CAPTURE\_LOST(func)}}{Process a wxEVT\_MOUSE\_CAPTURE\_LOST event.}
+\end{twocollist}
+
+\wxheading{See also}
+
+\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
+\helpref{Event handling overview}{eventhandlingoverview},
+\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
+\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
+\helpref{wxWindow::GetCapture}{wxwindowgetcapture}
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxMouseCaptureLostEvent::wxMouseCaptureLostEvent}\label{wxmousecapturelosteventctor}
+
+\func{}{wxMouseCaptureLostEvent}{\param{wxWindowID }{windowId = 0}}
+
+Constructor.
and when the mouse is released the capture returns to the window which had had
captured it previously and it is only really released if there were no previous
window. In particular, this means that you must release the mouse as many times
-as you capture it.
+as you capture it, unless the window receives
+the \helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent} event.
+
+Any application which captures the mouse in the beginning of some operation
+{\em must} handle \helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
+and cancel this operation when it receives the event. The event handler must
+not recapture mouse.
\wxheading{See also}
\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
\membersection{wxWindow::Center}\label{wxwindowcenter}
\helpref{wxWindow::HasCapture}{wxwindowhascapture},
\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse},
\helpref{wxWindow::HasCapture}{wxwindowhascapture},
\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse},
+\helpref{wxMouseCaptureLostEvent}{wxmousecapturelostevent}
\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
DECLARE_EVENT_TYPE(wxEVT_ICONIZE, 413)
DECLARE_EVENT_TYPE(wxEVT_MAXIMIZE, 414)
DECLARE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED, 415)
- DECLARE_EVENT_TYPE(wxEVT_PAINT, 416)
- DECLARE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND, 417)
- DECLARE_EVENT_TYPE(wxEVT_NC_PAINT, 418)
- DECLARE_EVENT_TYPE(wxEVT_PAINT_ICON, 419)
- DECLARE_EVENT_TYPE(wxEVT_MENU_OPEN, 420)
- DECLARE_EVENT_TYPE(wxEVT_MENU_CLOSE, 421)
- DECLARE_EVENT_TYPE(wxEVT_MENU_HIGHLIGHT, 422)
- // DECLARE_EVENT_TYPE(wxEVT_POPUP_MENU_INIT, 423) -- free slot
+ DECLARE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST, 416)
+ DECLARE_EVENT_TYPE(wxEVT_PAINT, 417)
+ DECLARE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND, 418)
+ DECLARE_EVENT_TYPE(wxEVT_NC_PAINT, 419)
+ DECLARE_EVENT_TYPE(wxEVT_PAINT_ICON, 420)
+ DECLARE_EVENT_TYPE(wxEVT_MENU_OPEN, 421)
+ DECLARE_EVENT_TYPE(wxEVT_MENU_CLOSE, 422)
+ DECLARE_EVENT_TYPE(wxEVT_MENU_HIGHLIGHT, 423)
DECLARE_EVENT_TYPE(wxEVT_CONTEXT_MENU, 424)
DECLARE_EVENT_TYPE(wxEVT_SYS_COLOUR_CHANGED, 425)
DECLARE_EVENT_TYPE(wxEVT_DISPLAY_CHANGED, 426)
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxMouseCaptureChangedEvent)
};
+/*
+ wxEVT_MOUSE_CAPTURE_LOST
+ The window losing the capture receives this message, unless it released it
+ it itself or unless wxWindow::CaptureMouse was called on another window
+ (and so capture will be restored when the new capturer releases it).
+ */
+
+class WXDLLIMPEXP_CORE wxMouseCaptureLostEvent : public wxEvent
+{
+public:
+ wxMouseCaptureLostEvent(wxWindowID winid = 0)
+ : wxEvent(winid, wxEVT_MOUSE_CAPTURE_LOST)
+ {}
+
+ wxMouseCaptureLostEvent(const wxMouseCaptureLostEvent& event)
+ : wxEvent(event)
+ {}
+
+ virtual wxEvent *Clone() const { return new wxMouseCaptureLostEvent(*this); }
+
+ DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxMouseCaptureLostEvent)
+};
+
/*
wxEVT_DISPLAY_CHANGED
*/
typedef void (wxEvtHandler::*wxHelpEventFunction)(wxHelpEvent&);
typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&);
typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&);
+typedef void (wxEvtHandler::*wxMouseCaptureLostEventFunction)(wxMouseCaptureLostEvent&);
typedef void (wxEvtHandler::*wxClipboardTextEventFunction)(wxClipboardTextEvent&);
// these typedefs don't have the same name structure as the others, keep for
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxContextMenuEventFunction, &func)
#define wxMouseCaptureChangedEventHandler(func) \
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMouseCaptureChangedEventFunction, &func)
+#define wxMouseCaptureLostEventHandler(func) \
+ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxMouseCaptureLostEventFunction, &func)
#define wxClipboardTextEventHandler(func) \
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxClipboardTextEventFunction, &func)
#define EVT_WINDOW_DESTROY(func) wx__DECLARE_EVT0(wxEVT_DESTROY, wxWindowDestroyEventHandler(func))
#define EVT_SET_CURSOR(func) wx__DECLARE_EVT0(wxEVT_SET_CURSOR, wxSetCursorEventHandler(func))
#define EVT_MOUSE_CAPTURE_CHANGED(func) wx__DECLARE_EVT0(wxEVT_MOUSE_CAPTURE_CHANGED, wxMouseCaptureChangedEventHandler(func))
+#define EVT_MOUSE_CAPTURE_LOST(func) wx__DECLARE_EVT0(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(func))
// Mouse events
#define EVT_LEFT_DOWN(func) wx__DECLARE_EVT0(wxEVT_LEFT_DOWN, wxMouseEventHandler(func))
void OnCopy(wxCommandEvent& event);
void OnMouseEnter(wxMouseEvent& event);
void OnMouseLeave(wxMouseEvent& event);
+ void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
#endif // wxUSE_CLIPBOARD
// Returns new filter (will be stored into m_DefaultFilter variable)
// implements the window variants
virtual void DoSetWindowVariant( wxWindowVariant variant ) ;
+ // Must be called when mouse capture is lost to send
+ // wxMouseCaptureLostEvent to windows on capture stack. The argument is
+ // the window gaining capture or NULL if outside of wx code or none.
+ static void NotifyCaptureLost(wxWindow *gainedCapture);
+
private:
// contains the last id generated by NewControlId
static int ms_lastControlId;
// the stack of windows which have captured the mouse
static struct WXDLLEXPORT wxWindowNext *ms_winCaptureNext;
+ // the window that currently has mouse capture
+ static wxWindow *ms_winCaptureCurrent;
+ // indicates if execution is inside CaptureMouse/ReleaseMouse
+ static bool ms_winCaptureChanging;
DECLARE_ABSTRACT_CLASS(wxWindowBase)
DECLARE_NO_COPY_CLASS(wxWindowBase)
IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent, wxCommandEvent)
IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent, wxCommandEvent)
IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent)
+ IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureLostEvent, wxEvent)
IMPLEMENT_DYNAMIC_CLASS(wxClipboardTextEvent, wxCommandEvent)
#endif // wxUSE_GUI
DEFINE_EVENT_TYPE(wxEVT_ICONIZE)
DEFINE_EVENT_TYPE(wxEVT_MAXIMIZE)
DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_CHANGED)
+DEFINE_EVENT_TYPE(wxEVT_MOUSE_CAPTURE_LOST)
DEFINE_EVENT_TYPE(wxEVT_PAINT)
DEFINE_EVENT_TYPE(wxEVT_ERASE_BACKGROUND)
DEFINE_EVENT_TYPE(wxEVT_NC_PAINT)
wxWindow *win;
wxWindowNext *next;
} *wxWindowBase::ms_winCaptureNext = NULL;
+wxWindow *wxWindowBase::ms_winCaptureCurrent = NULL;
+bool wxWindowBase::ms_winCaptureChanging = false;
void wxWindowBase::CaptureMouse()
{
wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), wx_static_cast(void*, this));
+ wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive CaptureMouse call?") );
+
+ ms_winCaptureChanging = true;
+
wxWindow *winOld = GetCapture();
if ( winOld )
{
//else: no mouse capture to save
DoCaptureMouse();
+ ms_winCaptureCurrent = (wxWindow*)this;
+
+ ms_winCaptureChanging = false;
}
void wxWindowBase::ReleaseMouse()
{
wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), wx_static_cast(void*, this));
+ wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive ReleaseMouse call?") );
+
wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
+ ms_winCaptureChanging = true;
+
DoReleaseMouse();
+ ms_winCaptureCurrent = NULL;
if ( ms_winCaptureNext )
{
((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse();
+ ms_winCaptureCurrent = ms_winCaptureNext->win;
wxWindowNext *item = ms_winCaptureNext;
ms_winCaptureNext = item->next;
}
//else: stack is empty, no previous capture
+ ms_winCaptureChanging = false;
+
wxLogTrace(_T("mousecapture"),
(const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
wx_static_cast(void*, GetCapture()));
}
+static void DoNotifyWindowAboutCaptureLost(wxWindow *win)
+{
+ wxMouseCaptureLostEvent event(win->GetId());
+ event.SetEventObject(win);
+ bool processed = win->GetEventHandler()->ProcessEvent(event);
+
+ wxASSERT_MSG( processed,
+ _T("window that captured mouse didn't process wxEVT_MOUSE_CAPTURE_LOST") );
+}
+
+/* static */
+void wxWindowBase::NotifyCaptureLost(wxWindow *gainedCapture)
+{
+ // don't do anything if capture lost was expected, i.e. resulted from
+ // a wx call to ReleaseMouse or CaptureMouse:
+ if ( ms_winCaptureChanging )
+ return;
+
+ // if the capture was lost unexpectedly, notify every window that has
+ // capture (on stack or current) about it and clear the stack:
+
+ if ( ms_winCaptureCurrent )
+ {
+ DoNotifyWindowAboutCaptureLost(ms_winCaptureCurrent);
+ ms_winCaptureCurrent = NULL;
+ }
+
+ while ( ms_winCaptureNext )
+ {
+ wxWindowNext *item = ms_winCaptureNext;
+ ms_winCaptureNext = item->next;
+
+ DoNotifyWindowAboutCaptureLost(item->win);
+
+ delete item;
+ }
+}
+
#if wxUSE_HOTKEY
bool
wxHtmlWindowMouseHelper::HandleMouseClick(m_Cell, pos, event);
}
+#if wxUSE_CLIPBOARD
+void wxHtmlWindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+{
+ if ( !m_makingSelection )
+ return;
+
+ // discard the selecting operation
+ m_makingSelection = false;
+ wxDELETE(m_selection);
+ m_tmpSelFromCell = NULL;
+ Refresh();
+}
+#endif // wxUSE_CLIPBOARD
void wxHtmlWindow::OnInternalIdle()
EVT_LEFT_DCLICK(wxHtmlWindow::OnDoubleClick)
EVT_ENTER_WINDOW(wxHtmlWindow::OnMouseEnter)
EVT_LEAVE_WINDOW(wxHtmlWindow::OnMouseLeave)
+ EVT_MOUSE_CAPTURE_LOST(wxHtmlWindow::OnMouseCaptureLost)
EVT_KEY_UP(wxHtmlWindow::OnKeyUp)
EVT_MENU(wxID_COPY, wxHtmlWindow::OnCopy)
#endif // wxUSE_CLIPBOARD
bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
{
- wxMouseCaptureChangedEvent event(GetId(), wxFindWinFromHandle(hWndGainedCapture));
- event.SetEventObject(this);
+ wxWindow *win = wxFindWinFromHandle(hWndGainedCapture);
+
+ // notify windows on the capture stack about lost capture
+ // (see http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863):
+ wxWindowBase::NotifyCaptureLost(win);
+ wxMouseCaptureChangedEvent event(GetId(), win);
+ event.SetEventObject(this);
return GetEventHandler()->ProcessEvent(event);
}