MFC Windowsプログラミング->マウスのキャプチャ
//In CMainWindow's message map ON_WM_LBUTTONDOWN () ON_WM_LBUTTONUP () void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point) { SetCapture (); } void CMainWindow::OnLButtonUp (UINT nFlags, CPoint point) {::ReleaseCapture (); }
In between, CMainWindow receives WM_MOUSEMOVE messages that report the cursor position even if the cursor leaves it. Client-area mouse messages continue to report cursor positions in client coordinates, but coordinates can now go negative and can also exceed the dimensions of the window's client area.
A related function, CWnd::GetCapture, returns a CWnd pointer to the window that owns the capture. In the Win32 environment, GetCapture returns NULL if the mouse is not captured or if it's captured by a window belonging to another thread. The most common use of GetCapture is for determining whether your own window has captured the mouse. The statement
is true if and only if the window identified by this currently has the mouse captured.
How does capturing the mouse solve the problem with the rubber-banded line? By capturing the mouse in response to a WM_LBUTTONDOWN message and releasing it when a WM_LBUTTONUP message arrives, you're guaranteed to get the WM_LBUTTONUP message when the mouse button is released. The sample program in the next section illustrates the practical effect of this technique.
void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point) {////Record the anchor point and set the tracking flag.//m_ptFrom = point; m_ptTo = point; m_bTracking = TRUE;////If capture is enabled, capture the mouse.//if (m_bCaptureEnabled) SetCapture (); } void CMainWindow::OnMouseMove (UINT nFlags, CPoint point) {////If the mouse is moved while we're "tracking"(that is, while a//line is being rubber-banded), erase the old rubber-band line and//draw a new one.//if (m_bTracking) { CClientDC dc (this); InvertLine (&dc, m_ptFrom, m_ptTo); InvertLine (&dc, m_ptFrom, point); m_ptTo = point; } } void CMainWindow::OnLButtonUp (UINT nFlags, CPoint point) {////If the left mouse button is released while we're tracking, release//the mouse if it's currently captured, erase the last rubber-band//line, and draw a thick red line in its place.//if (m_bTracking) { m_bTracking = FALSE; if (GetCapture () == this)::ReleaseCapture (); CClientDC dc (this); InvertLine (&dc, m_ptFrom, m_ptTo); CPen pen (PS_SOLID, 16, RGB (255, 0, 0)); dc.SelectObject (&pen); dc.MoveTo (m_ptFrom); dc.LineTo (point); } }
In between, CMainWindow receives WM_MOUSEMOVE messages that report the cursor position even if the cursor leaves it. Client-area mouse messages continue to report cursor positions in client coordinates, but coordinates can now go negative and can also exceed the dimensions of the window's client area.
A related function, CWnd::GetCapture, returns a CWnd pointer to the window that owns the capture. In the Win32 environment, GetCapture returns NULL if the mouse is not captured or if it's captured by a window belonging to another thread. The most common use of GetCapture is for determining whether your own window has captured the mouse. The statement
if (GetCapture () == this)
is true if and only if the window identified by this currently has the mouse captured.
How does capturing the mouse solve the problem with the rubber-banded line? By capturing the mouse in response to a WM_LBUTTONDOWN message and releasing it when a WM_LBUTTONUP message arrives, you're guaranteed to get the WM_LBUTTONUP message when the mouse button is released. The sample program in the next section illustrates the practical effect of this technique.
void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point) {////Record the anchor point and set the tracking flag.//m_ptFrom = point; m_ptTo = point; m_bTracking = TRUE;////If capture is enabled, capture the mouse.//if (m_bCaptureEnabled) SetCapture (); } void CMainWindow::OnMouseMove (UINT nFlags, CPoint point) {////If the mouse is moved while we're "tracking"(that is, while a//line is being rubber-banded), erase the old rubber-band line and//draw a new one.//if (m_bTracking) { CClientDC dc (this); InvertLine (&dc, m_ptFrom, m_ptTo); InvertLine (&dc, m_ptFrom, point); m_ptTo = point; } } void CMainWindow::OnLButtonUp (UINT nFlags, CPoint point) {////If the left mouse button is released while we're tracking, release//the mouse if it's currently captured, erase the last rubber-band//line, and draw a thick red line in its place.//if (m_bTracking) { m_bTracking = FALSE; if (GetCapture () == this)::ReleaseCapture (); CClientDC dc (this); InvertLine (&dc, m_ptFrom, m_ptTo); CPen pen (PS_SOLID, 16, RGB (255, 0, 0)); dc.SelectObject (&pen); dc.MoveTo (m_ptFrom); dc.LineTo (point); } }