From a5e84126fcb673217660170ab871738f21972b49 Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Fri, 12 Apr 2002 20:26:43 +0000
Subject: [PATCH] Implemented wxMouseCaptureChangedEvent and made
 wxGenericDragImage check it the capture before release it. Documented
 wxMouseCaptureChangedEvent and GetCapture/FindCapture.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15117 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt           |  3 +++
 docs/latex/wx/category.tex |  1 +
 docs/latex/wx/classes.tex  |  1 +
 docs/latex/wx/mcaptevt.tex | 50 ++++++++++++++++++++++++++++++++++++++
 docs/latex/wx/window.tex   | 30 ++++++++++++++++++++++-
 include/wx/event.h         | 23 ++++++++++++++++++
 include/wx/msw/window.h    |  2 +-
 src/common/event.cpp       |  1 +
 src/generic/dragimgg.cpp   |  8 +++++-
 src/msw/window.cpp         | 12 +++++++++
 10 files changed, 128 insertions(+), 3 deletions(-)
 create mode 100644 docs/latex/wx/mcaptevt.tex

diff --git a/docs/changes.txt b/docs/changes.txt
index 4fd6357921..9aa739d0e0 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -157,6 +157,7 @@ All (GUI):
   for GTK+, Mac, MGL, X11, Motif ports (Chris Elliott)
 - added (platform-dependent) scan code to wxKeyEvent (Bryce Denney)
 - added wxTextCtrl::EmulateKeyPress()
+- Added wxMouseCaptureChangedEvent
 
 wxMSW:
 
@@ -180,6 +181,8 @@ wxMSW:
 - wxWindowDC and wxClientDC::GetSize() works correctly now
 - Added wxTB_NODIVIDER and wxTB_NOALIGN so native toolbar can be used in FL
 - Multiline labels in buttons are now supoprted (simply use "\n" in the label)
+- Implemented wxMouseCaptureChangedEvent and made wxGenericDragImage check it
+  has the capture before release it.
 
 wxGTK:
 
diff --git a/docs/latex/wx/category.tex b/docs/latex/wx/category.tex
index 9f4e00b35e..4909916033 100644
--- a/docs/latex/wx/category.tex
+++ b/docs/latex/wx/category.tex
@@ -222,6 +222,7 @@ An event object contains information about a specific event. Event handlers
 \twocolitem{\helpref{wxListEvent}{wxlistevent}}{A list control event}
 \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{wxMouseEvent}{wxmouseevent}}{A mouse event}
 \twocolitem{\helpref{wxMoveEvent}{wxmoveevent}}{A move event}
 \twocolitem{\helpref{wxNotebookEvent}{wxnotebookevent}}{A notebook control event}
diff --git a/docs/latex/wx/classes.tex b/docs/latex/wx/classes.tex
index 18e77a0da7..5120418bcb 100644
--- a/docs/latex/wx/classes.tex
+++ b/docs/latex/wx/classes.tex
@@ -202,6 +202,7 @@
 \input mimetype.tex
 \input minifram.tex
 \input module.tex
+\input mcaptevt.tex
 \input mouseevt.tex
 \input moveevt.tex
 \input mltchdlg.tex
diff --git a/docs/latex/wx/mcaptevt.tex b/docs/latex/wx/mcaptevt.tex
new file mode 100644
index 0000000000..05810e3430
--- /dev/null
+++ b/docs/latex/wx/mcaptevt.tex
@@ -0,0 +1,50 @@
+\section{\class{wxMouseCaptureChangedEvent}}\label{wxmousecapturechangedevent}
+
+An mouse capture changed event is sent to a window that loses its
+mouse capture. This is called even if wxWindow::ReleaseCapture
+was called by the application code. Handling this event allows
+an application to cater for unexpected capture releases which
+might otherwise confuse mouse handling code.
+
+This event is implemented 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 wxMouseCaptureChangedEvent argument.
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_MOUSE\_CAPTURE\_CHANGED(func)}}{Process a wxEVT\_MOUSE\_CAPTURE\_CHANGED event.}
+\end{twocollist}%
+
+\wxheading{See also}
+
+\helpref{Event handling overview}{eventhandlingoverview}, 
+\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}, 
+\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}, 
+\helpref{wxWindow::GetCapture}{wxwindowgetcapture}
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxMouseCaptureChangedEvent::wxMouseCaptureChangedEvent}
+
+\func{}{wxMouseCaptureChangedEvent}{\param{wxWindowID }{windowId = 0}, \param{wxWindow*}{ gainedCapture = NULL}}
+
+Constructor.
+
+\membersection{wxActivateEvent::GetCapturedWindow}\label{wxmousecapturechangedeventgetcapturedwindow}
+
+\constfunc{wxWindow*}{GetCapturedWindow}{\void}
+
+Returns the window that gained the capture, or NULL if it was a non-wxWindows window.
+
diff --git a/docs/latex/wx/window.tex b/docs/latex/wx/window.tex
index ca648a2f1f..c5846f1cd0 100644
--- a/docs/latex/wx/window.tex
+++ b/docs/latex/wx/window.tex
@@ -509,6 +509,19 @@ same as the size the window would have had after calling
 
 Returns the \helpref{caret}{wxcaret} associated with the window.
 
+\membersection{wxWindow::GetCapture}\label{wxwindowgetcapture}
+
+\func{static wxWindow *}{GetCapture}{\void}
+
+Returns the currently captured window.
+
+\wxheading{See also}
+
+\helpref{wxWindow::HasCapture}{wxwindowhascapture}, 
+\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}, 
+\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}, 
+\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
+
 \membersection{wxWindow::GetCharHeight}
 
 \constfunc{virtual int}{GetCharHeight}{\void}
@@ -896,6 +909,18 @@ Returns a pointer to the current validator for the window, or NULL if there is n
 Gets the window style that was passed to the constructor or {\bf Create}
 method. {\bf GetWindowStyle()} is another name for the same function.
 
+\membersection{wxWindow::HasCapture}\label{wxwindowhascapture}
+
+\constfunc{virtual bool}{HasCapture}{\void}
+
+Returns TRUE if this window has the current mouse capture.
+
+\wxheading{See also}
+
+\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}, 
+\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}, 
+\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
+
 \membersection{wxWindow::Hide}\label{wxwindowhide}
 
 \func{bool}{Hide}{\void}
@@ -1665,7 +1690,10 @@ Releases mouse input captured with \helpref{wxWindow::CaptureMouse}{wxwindowcapt
 
 \wxheading{See also}
 
-\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}
+\helpref{wxWindow::CaptureMouse}{wxwindowcapturemouse}, 
+\helpref{wxWindow::HasCapture}{wxwindowhascapture}, 
+\helpref{wxWindow::ReleaseMouse}{wxwindowreleasemouse}, 
+\helpref{wxMouseCaptureChangedEvent}{wxmousecapturechangedevent}
 
 \membersection{wxWindow::RemoveChild}\label{wxwindowremovechild}
 
diff --git a/include/wx/event.h b/include/wx/event.h
index 42ad307d7f..d4aa880a67 100644
--- a/include/wx/event.h
+++ b/include/wx/event.h
@@ -1397,6 +1397,27 @@ private:
     DECLARE_DYNAMIC_CLASS(wxSysColourChangedEvent)
 };
 
+/*
+ wxEVT_MOUSE_CAPTURE_CHANGED
+ The window losing the capture receives this message
+ (even if it released the capture itself).
+ */
+
+class WXDLLEXPORT wxMouseCaptureChangedEvent : public wxEvent
+{
+public:
+    wxMouseCaptureChangedEvent(wxWindowID id = 0, wxWindow* gainedCapture = NULL): wxEvent(id)
+        { m_eventType = wxEVT_MOUSE_CAPTURE_CHANGED; m_gainedCapture = gainedCapture; }
+
+    virtual wxEvent *Clone() const { return new wxMouseCaptureChangedEvent(*this); }
+
+    wxWindow* GetCapturedWindow() const { return m_gainedCapture; };
+
+private:
+    wxWindow* m_gainedCapture;
+    DECLARE_DYNAMIC_CLASS(wxMouseCaptureChangedEvent)
+};
+
 /*
  wxEVT_DISPLAY_CHANGED
  */
@@ -1947,6 +1968,7 @@ typedef void (wxEvtHandler::*wxSetCursorEventFunction)(wxSetCursorEvent&);
 typedef void (wxEvtHandler::*wxNotifyEventFunction)(wxNotifyEvent&);
 typedef void (wxEvtHandler::*wxHelpEventFunction)(wxHelpEvent&);
 typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&);
+typedef void (wxEvtHandler::*wxMouseCaptureChangedEventFunction)(wxMouseCaptureChangedEvent&);
 #endif // wxUSE_GUI
 
 // N.B. In GNU-WIN32, you *have* to take the address of a member function
@@ -2013,6 +2035,7 @@ typedef void (wxEvtHandler::*wxContextMenuEventFunction)(wxContextMenuEvent&);
 #define EVT_WINDOW_CREATE(func) DECLARE_EVENT_TABLE_ENTRY( wxEVT_CREATE, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxWindowCreateEventFunction) & func, (wxObject *) NULL ),
 #define EVT_WINDOW_DESTROY(func) DECLARE_EVENT_TABLE_ENTRY( wxEVT_DESTROY, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxWindowDestroyEventFunction) & func, (wxObject *) NULL ),
 #define EVT_SET_CURSOR(func) DECLARE_EVENT_TABLE_ENTRY( wxEVT_SET_CURSOR, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxSetCursorEventFunction) & func, (wxObject *) NULL ),
+#define EVT_MOUSE_CAPTURE_CHANGED(func) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MOUSE_CAPTURE_CHANGED, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxMouseCaptureChangedEventFunction) & func, (wxObject *) NULL ),
 
 // Mouse events
 #define EVT_LEFT_DOWN(func) DECLARE_EVENT_TABLE_ENTRY( wxEVT_LEFT_DOWN, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxMouseEventFunction) & func, (wxObject *) NULL ),
diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h
index 21baed1557..a65bdbc191 100644
--- a/include/wx/msw/window.h
+++ b/include/wx/msw/window.h
@@ -341,7 +341,7 @@ public:
     bool HandleQueryNewPalette();
     bool HandleSysColorChange();
     bool HandleDisplayChange();
-
+    bool HandleCaptureChanged(WXHWND gainedCapture);
 
     bool HandleQueryEndSession(long logOff, bool *mayEnd);
     bool HandleEndSession(bool endSession, long logOff);
diff --git a/src/common/event.cpp b/src/common/event.cpp
index df2d8c4477..425df9d857 100644
--- a/src/common/event.cpp
+++ b/src/common/event.cpp
@@ -88,6 +88,7 @@ IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject)
     IMPLEMENT_DYNAMIC_CLASS(wxWindowDestroyEvent, wxEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxHelpEvent, wxCommandEvent)
     IMPLEMENT_DYNAMIC_CLASS(wxContextMenuEvent, wxCommandEvent)
+    IMPLEMENT_DYNAMIC_CLASS(wxMouseCaptureChangedEvent, wxEvent)
 #endif // wxUSE_GUI
 
 const wxEventTable *wxEvtHandler::GetEventTable() const
diff --git a/src/generic/dragimgg.cpp b/src/generic/dragimgg.cpp
index 8c1b4ab485..d625524ed3 100644
--- a/src/generic/dragimgg.cpp
+++ b/src/generic/dragimgg.cpp
@@ -295,7 +295,13 @@ bool wxGenericDragImage::EndDrag()
 {
     if (m_window)
     {
-        m_window->ReleaseMouse();
+#ifdef __WXMSW__
+        // Under Windows we can be pretty sure this test will give
+        // the correct results
+        if (wxWindow::GetCapture() == m_window)
+#endif
+            m_window->ReleaseMouse();
+
         if (m_cursor.Ok() && m_oldCursor.Ok())
         {
             m_window->SetCursor(m_oldCursor);
diff --git a/src/msw/window.cpp b/src/msw/window.cpp
index 5869ed162c..8bb6886ec3 100644
--- a/src/msw/window.cpp
+++ b/src/msw/window.cpp
@@ -2647,6 +2647,10 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
             processed = HandlePaletteChanged((WXHWND) (HWND) wParam);
             break;
 
+        case WM_CAPTURECHANGED:
+            processed = HandleCaptureChanged((WXHWND) (HWND) lParam);
+            break;
+
         case WM_QUERYNEWPALETTE:
             processed = HandleQueryNewPalette();
             break;
@@ -3511,6 +3515,14 @@ bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
     return GetEventHandler()->ProcessEvent(event);
 }
 
+bool wxWindowMSW::HandleCaptureChanged(WXHWND hWndGainedCapture)
+{
+    wxMouseCaptureChangedEvent event(GetId(), wxFindWinFromHandle(hWndGainedCapture));
+    event.SetEventObject(this);
+
+    return GetEventHandler()->ProcessEvent(event);
+}
+
 bool wxWindowMSW::HandleQueryNewPalette()
 {
 
-- 
2.50.0

