PDA

View Full Version : Detecting Mouse Movement Outside The Active Window


SpreeTree
06-03-2004, 03:50 AM
Hi guys

Is it possible for a window to recive mouse move messages when the mouse pointer is outside the client area? I know about WM_NCMOUSEMOVE, but that doesnt solve the problem of detecting movement when the cursor is totally out of the area of the window.

SetCapture only seems to work if the left mouse button is down, but this isnt good enough for what I'm after. It needs to detect it regardless of the mouse state

Thanks
Spree

anubis
06-04-2004, 12:39 AM
i tihnk you have the option to either totally direct all input to the window, then you will get mouse movements even if the position is beyond the window boundaries. or you share the input. in the second case you have no way to catch the input. i might be wrong though...

Dia
06-04-2004, 07:38 AM
Have you tried out the TrackMouseEvent function? You can call it to tell it to send the WM_MOUSELEAVE message when the mouse leaves your window. Also, the function GetCursorPos() gives you the mouse's position regardless of the which app has the focus. You can easily use it to make your own mouse-move detection scheme.

anubis
06-04-2004, 08:30 AM
oh, i only thought about directx :)
normally you onyl direct messages to your window that are meant for it. however you can peek the windows message stack at any time. this will allow you to intercept any mouse movement, even outside of your window

Mashhack
07-27-2004, 01:04 AM
This below code does the trick.

Also, on a related note... When a user holds down the mouse button (WM_LBUTTONDOWN), then drags the mouse out of the window and lets the mouse button up, you don't get the WM_LBUTTONUP message unless you use SetCapture() and ReleaseCapture() in your OnLButtonDown() and OnLButtonUp() functions respectively.


Code to detect the mouse leaving your window follows:


1. Add a timer UINT to your view class:

UINT m_uiMyTimer;


2. Initialise the timer UINT in your constructor:

void CMyView::CMyView()
{
 m_uiMyTimer = 0;
}


3. When the mouse is initally in your window, start the timer:

void CMyView::OnMouseMove(UINT nFlags, CPoint point)
{
 if( m_uiMyTimer == 0 )
  m_uiMyTimer = SetTimer(1, 100, NULL);

 CView::OnMouseMove(nFlags, point);
}


4. In OnTimer, detect if the mouse has left your window and post a message:

void CMyView::OnTimer(UINT nIDEvent)
{
 RECT rect;
 POINT pt;

 GetClientRect(&rect);
 MapWindowPoints(NULL,&rect);
 GetCursorPos(&pt);
 if (!PtInRect(&rect,pt) || (WindowFromPoint(pt) != this))
 {
  if (!KillTimer(m_uiMyTimer))
  {
   ASSERT(0); // Error killing the timer!
  }

  m_uiMyTimer = 0;
  PostMessage(WM_MOUSELEAVE,0,0);
 }

 CView::OnTimer(nIDEvent);
}


5. Add a OnMouseLeave(..) handler:

(i) In your afx message map, in the .h file:
afx_msg LONG OnMouseLeave(WPARAM wParam, LPARAM lParam);

(ii) In your message map:
ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)

(iii) OnMouseLeave Function
LONG CARCodeEditorView::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
TRACE( "MouseLeave\n" );
return 0;
}


.... and that, is that.