Search code examples
c++winapimouse-cursor

Notifications about cursor changes


Is it possible to get notifications of mouse cursor changes? I'm interested in changes caused within my process but a system wide notification would be just as good. Since I'm using third party libraries, there might be several reasons for the cursor to change.

In particular, I'd like to know when the cursor becomes IDC_HAND. Reading online, there doesn't appear to be a notification driven approach to this.

My current solution is to check if the mouse cursor is the same as LoadCursor(nullptr, IDC_HAND). However:

  • Could this is causing resource leaks? The documentation for LoadCursor indicates that if the resource already exists, then a reference to said resource is returned instead of a new resource. Therefore it seems that I should not attempt to release the handle.
  • Is it costly to perform this check often since LoadCursor would be called many times?
  • Should I cache the IDC_HAND cursor? If it doesn't exist when I perform LoadCursor, when the hand cursor is created, will it necessarily have the same handle? From my tests, the answers appears to be yes.

As far as I can tell, the ideal scenario is that there is a Windows message indicating a cursor change at which stage I could perform the LoadCursor handle check. Are there perhaps alternatives?

Thank you for your time and assistance.


Solution

  • A late reply, apologies. Based off Raymond Chen's feedback (thank you kindly), and his post, I setup a hook for just the EVENT_OBJECT_NAMECHANGE event (which triggered when the mouse cursor changed):

    SetWinEventHook(EVENT_OBJECT_NAMECHANGE, EVENT_OBJECT_NAMECHANGE, nullptr, WinEventProc, GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_INCONTEXT);
    

    And listened for the OBJID_CURSOR object id:

    void CALLBACK WinEventProc(
      HWINEVENTHOOK hWinEventHook,
      DWORD         event,
      HWND          hwnd,
      LONG          idObject,
      LONG          idChild,
      DWORD         dwEventThread,
      DWORD         dwmsEventTime
      )
    {
      if (idObject == OBJID_CURSOR)
      {
        ...
      }
    }