I'm working with an application where one of the options which I have to develop is to change Windows 10 cursor size. In my case it its important to change cursor size for the whole windows, not only for a specific java application window. Currently I'm able to change size of specific cursor type by modifying Windows registry attributes under HKEY_CURRENT_USER → Control Panel → Cursors directory.
Unfortunately, I need to set cursor size bigger than 32x32px. Somewhere I've found a solution where there was a possibility to cover existing mouse cursor by a bitmap and just follow the position of a cursor, but I don't know how to start with the implementation. I searched on the Internet and I've found some applications that allow user to modify size of cursor for whole Windows 10—for example, this was CursorFX.
Do you know how to increase cursor size programmatically?
You can set any size cursor you want using the
SetSystemCursor
API. You are not limited to theSM_CXCURSOR
/SM_CYCURSOR
metrics (cf.GetSystemMetrics
function)—those just tell you the system's default cursor size, which is typically 32×32 (or 48×48 on high-DPI systems). I know for a fact that this works as far back as Windows XP; I'm pretty sure it works further back than that.The key lies in how you load the cursor resource. As you probably already know, you need an
HCURSOR
object to pass toSetSystemCursor
. This is a handle-to-cursor, in Windows API speak. The obvious way to load a cursor is by calling theLoadCursor
API function, but that is a very old function, introduced with 16-bit Windows and it is limited to loading cursors of sizeSM_CXCURSOR
×SM_CYCURSOR
. So you don't want that†; you want to callLoadImage
, which as the documentation indicates is the modern replacement function. It takes an enumerated integer parameter indicating which type of image to load:IMAGE_BITMAP
(0),IMAGE_ICON
(1),IMAGE_CURSOR
(2), orIMAGE_ENHMETAFILE
(3). Obviously,IMAGE_CURSOR
is what you want to use here.You can either load from a cursor resource embedded into your application's binary (as a Win32 resource), or you can load from a *.CUR/*.ANI file from the disk. To do the latter, pass the
LR_LOADFROMFILE
flag to theLoadImage
function.I don't know Java, so I can't translate this to Java with whatever syntax is required there to make native Windows API calls, but here is the code in C:
Note that the
SetSystemCursor
requires one of theOCR_*
constants to identify which system cursor type to change. These aren't included by default when you includeWindows.h
; you have to defineOEMRESOURCE
before includingWindows.h
. I'm assuming, though, that with Java, you're just defining the constants yourself as enumerated values. In that case, they're all available in the MSDN documentation forSetSystemCursor
. For example,OCR_NORMAL
is32512
.Notice, though, that what we're doing here is loading a new cursor (i.e., image) of the desired size, and then setting that. That works fine. What you can't easily do is just expand the size of the existing cursor glyph. To do that, you'd have to retrieve the current cursor glyph, draw it onto a bitmap, scale that bitmap to the desired size, convert that bitmap to an
HCURSOR
, and then set thatHCURSOR
usingSetSystemCursor
. And, naturally, the problem with that is Windows cursor glyphs are just bitmaps, so they're not infinitely scalable. You will start losing resolution quickly, so this is not recommended. If you need a large-size cursor, you will need to provide your own image.By "CursorFX", I believe you're thinking of AniFX (by the same fellow, Attila Kovrig, who wrote IcoFX). This is a cursor image editor and would be a great way to create the *.CUR/*.ANI file(s) you need. But you could just as easily use some other piece of software designed for creating cursors; there are myriad to choose from.
__
† Not that you wanted that function with
SetSystemCursor
anyway, sinceSetSystemCursor
destroys the specified cursor by callingDestroyCursor
. You would need to doLoadCursor
and thenCopyCursor
before callingSetSystemCursor
. This is all spelled out in the documentation forSetSystemCursor
, but as I said, you don't need to worry about this anymore because you just useLoadImage
(without theLR_SHARED
flag).