LoadCursor and Mixed DPI Multiple Monitors

Viewed 226

When the LoadCursor function is used to load a cursor from a resource, the resulting HCURSOR can be used across different monitors and always appears at the correct size.

ie: typically:

  • on a 96 dpi monitor the 32x32 resource is used,
  • on a 192 dpi monitor the 64x64 resource is used.

However, when a cursor is programmatically created from memory (say using LookupIconIdFromDirectoryEx and CreateIconFromResourceEx) the resulting cursor has a fixed resolution. This means it appears at the wrong size on at least one monitor in a mixed DPI multi-monitor setup.

I also checked out the LoadCursorFromFile and it too provides this dynamic resolution behaviour like LoadCursor.

Is there a way to programmatically create a cursor that dynamically switches depending which monitor it's shown on? What magic is going on behind the scenes for cursors loaded with LoadCursor to work differently?

1 Answers

After much experimentation I finally discovered that WPF can load cursors from resource and memory streams and get the correct DPI behaviour if the scaleWithDpi option is used:

public Cursor(Stream cursorStream, bool scaleWithDpi)

Looking at the reference source it ends up in the function LoadFromStream which loads the stream by writing it to a temporary file and the loading from the file. See source

To sum up:

  • It seems the only way to get a dynamic DPI cursor like this is with the Win32 native resource loading functions and by loading from a file. It doesn't seem like you can load a cursor directly from memory with this behavior.
  • The "dynamic dpi" part of this behavior seems to be related to the LR_DEFAULTSIZE flag passed to the LoadImage function.
Related