How To Detect When the Cursor Leaves the Window (183107)



The information in this article applies to:

  • Microsoft Windows 2000 Server
  • Microsoft Windows 2000 Advanced Server
  • Microsoft Windows 2000 Professional
  • Microsoft Platform Software Development Kit (SDK) 1.0
  • Microsoft Windows NT Server 3.5
  • Microsoft Windows NT Server 3.51
  • Microsoft Windows NT Server 4.0
  • Microsoft Windows NT Workstation 3.5
  • Microsoft Windows NT Workstation 3.51
  • Microsoft Windows NT Workstation 4.0
  • Microsoft Windows 95
  • Microsoft Windows 98

This article was previously published under Q183107

SUMMARY

Microsoft Windows NT 4.0, Windows 2000 and Microsoft Windows 98 provide the TrackMouseEvent API to notify a window that the mouse has left the window. Windows 95 does not provide any such notification. An application can detect when the mouse exits a window by starting a timer when the mouse enters the window, and using that timer to monitor the mouse position and find when it is no longer within the window.

MORE INFORMATION

The following sample code provides an example of how to implement mouse leave detection on Windows NT 3.51 and Windows 95 so that it follows TrackMouseEvent's interface. Implementation of the WM_MOUSEHOVER functionality is left to the discretion of the reader.

Sample Code

   #if(_WIN32_WINNT < 0x0400)
   #define WM_MOUSELEAVE   WM_USER+2
   #define TME_LEAVE               1

   typedef struct tagTRACKMOUSEEVENT {
       DWORD cbSize;
       DWORD dwFlags;
       HWND  hwndTrack;
   } TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;

   VOID CALLBACK
   TrackMouseTimerProc(HWND hWnd,UINT uMsg,UINT idEvent,DWORD dwTime) {
      RECT rect;
      POINT pt;

      GetClientRect(hWnd,&rect);
      MapWindowPoints(hWnd,NULL,(LPPOINT)&rect,2);
      GetCursorPos(&pt);
      if (!PtInRect(&rect,pt) || (WindowFromPoint(pt) != hWnd)) {
         if (!KillTimer(hWnd,idEvent)) {
            // Error killing the timer!
         }

         PostMessage(hWnd,WM_MOUSELEAVE,0,0);
      }
   }

   BOOL
   TrackMouseEvent(LPTRACKMOUSEEVENT ptme) {
      OutputDebugString(TEXT("TrackMouseEvent\n"));

      if (!ptme || ptme->cbSize < sizeof(TRACKMOUSEEVENT)) {
         OutputDebugString(TEXT("TrackMouseEvent: invalid "
                                "TRACKMOUSEEVENT structure\n"));
         return FALSE;
      }

      if (!IsWindow(ptme->hwndTrack)) {
         OutputDebugString(
            TEXT("TrackMouseEvent: invalid hwndTrack\n"));
         return FALSE;
      }

      if (!(ptme->dwFlags & TME_LEAVE)) {
         OutputDebugString(TEXT("TrackMouseEvent: invalid dwFlags\n"));
         return FALSE;
      }

      return SetTimer(ptme->hwndTrack, ptme->dwFlags,
                      100,(TIMERPROC)TrackMouseTimerProc);
   }
   #endif

   LRESULT CALLBACK
   MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
      TRACKMOUSEEVENT tme;
      static BOOL fInWindow;
      static BOOL fInMenu;
      switch (uMsg) {
         case WM_CREATE:
            fInWindow = FALSE;
            fInMenu = FALSE;
            return 0;

         case WM_MOUSEMOVE:
            if (!fInWindow) {
               fInWindow = TRUE;
               tme.cbSize = sizeof(TRACKMOUSEEVENT);
               tme.dwFlags = TME_LEAVE;
               tme.hwndTrack = hWnd;
               if (!TrackMouseEvent(&tme)) {
                  MessageBox(hWnd,
                             TEXT("TrackMouseEvent Failed"),
                             TEXT("Mouse Leave"),MB_OK);
               }
            }
         break;

         case WM_MOUSELEAVE:
            fInWindow = FALSE;
            if (!fInMenu)
               MessageBox(hWnd,TEXT("Elvis has left the building"),
                          TEXT("Mouse Leave"),MB_OK);
            break;
         case WM_ENTERMENULOOP:
            fInMenu = TRUE;
            break;

         case WM_EXITMENULOOP:
            fInMenu = FALSE;
            break;

         default:
            return DefWindowProc(hWnd,uMsg,wParam,lParam);
      }
      return FALSE;
   }
				

Modification Type:MinorLast Reviewed:7/11/2005
Keywords:kbcode kbhowto kbInput kbWndw KB183107