14.5.2 捕获鼠标消息
上述问题的原因在于Windows将鼠标消息发送到光标下方的窗口。光标一离开应用程序视图窗口的工作区,WM_MOUSEMOVE消息就将发送到别的地方。使用CSketcherView类的一些继承成员可以解决这个问题。
视图类从CWnd继承了函数SetCapture(),通过调用这个函数,可以告诉Windows,视图窗口希望获取所有鼠标消息,这称为捕获鼠标,直到通过调用视图类的另一个继承函数ReleaseCapture()结束捕获为止。
通过修改WM_LBUTTONDOWN消息的处理程序,可以在一按下鼠标左键时就捕获鼠标:
- // Handler for left mouse button down message
- void CSketcherView::OnLButtonDown(UINT nFlags, CPoint point)
- {
- m_FirstPoint = point; // Record the cursor position
- SetCapture(); // Capture subsequent mouse messages
- }
现在,必须在WM_LBUTTONUP消息处理程序中调用函数ReleaseCapture()。否则,只要您的程序继续运行,其他程序就不能接收任何鼠标消息。当然,只有在已经捕获鼠标之后才能释放鼠标键。视图类继承的函数GetCapture()将返回一个指向已经捕获鼠标的窗口的指针,这样就可以表明是否已经捕获鼠标消息。只需要要在WM_LBUTTONUP的处理程序中添加下列代码:
- void CSketcherView::OnLButtonUp(UINT nFlags, CPoint point)
- {
- if(this == GetCapture())
- ReleaseCapture(); // Stop capturing mouse messages
- // Make sure there is an element
- if(m_pTempElement)
- {
- GetDocument()->AddElement(m_pTempElement);
- m_pTempElement.reset(); // Reset the element pointer
- }
- }
如果函数GetCapture()返回的指针等于指针this,那么视图已经捕获了鼠标,所以可以释放按钮。
应当做的最后一个修改是修改WM_MOUSEMOVE处理程序,使它只处理已经由视图捕获的消息。这时只需要进行一个小改动:
- void CSketcherView::OnMouseMove(UINT nFlags, CPoint point)
- {
- // Define a Device Context object for the view
- CClientDC aDC(this); // DC is for this view
- // Verify the left button is down and mouse messages are captured
- if((nFlags & MK_LBUTTON) && (this == GetCapture()))
- {
- // Code as before...
- }
- }
现在,只有按下鼠标左键,视图窗口已经捕获了鼠标,这个处理程序才处理鼠标消息。
如果利用这些添加的代码重新构建Sketcher程序,就将发现以前光标拖出工作区时产生的问题不再出现了。