How do I find out the size of the mouse cursor?

Raymond Chen

A customer wanted to know how to find out the size of the mouse cursor. They called Get­System­Metrics(SM_CXICON), but the value that was returned didn’t seem to be right.

The SM_CXICON system metric gives you the size of “standard” icons, which is loosely correlated with the size of the mouse cursor, in the sense that people who choose bigger icons tend also to choose bigger mouse cursors. This is, however, just a correlation; there is no requirement that the two values be aligned with each other in any way.

We learned last time that the SM_CXCURSOR tells you the size the mouse cursor would have been in some hypothetical universe, which doesn’t really help you find out what the size of the cursor is in the current universe based in reality.

In order to answer the question “What is the size of the mouse cursor?” you first have to specify which mouse cursor you are interested in, in the form of an HCURSOR. For example, if you are interested in the size of the arrow cursor, you can call LoadCursor(nullptr, IDC_ARROW)

Once you have your HCURSOR, you can call Get­Icon­Info² to obtain information about it. The bitmaps that are used to draw the cursor are available as the hbmMask and hbmCursor. Interpreting these bitmaps is a bit tricky.

For color cursors, the hbmMask and hbmColor bitmaps are the same size, each of which is the size of the cursor.

For monochrome cursors, the hbmMask is twice the height of the cursor (with the AND mask on top and the XOR mask on the bottom), and there is no hbmColor.

Now, the sizes of the bitmap tell you the nominal size of the mouse cursor, but that’s not the same as the apparent size. For example, the bitmaps for the I-beam cursor may be 32 × 32, but on the screen, the I-beam cursor is tall and skinny. To identify the pixels that will be drawn, you need to study the mask (color cursors) or top half of the mask (monochrome cursors) and look for the black pixels.

You can also use the xHotspot and yHotspot members to tell you how the bitmap is positioned relative to the cursor position.

Don’t forget to delete the hbmMask and hbmColor bitmaps when you’re done. Forgetting to clean up these bitmaps is a common source of GDI resource leaks.

¹ If you aren’t interested in any particular cursor, but rather want to know how big the cursors are “in general”, you could make the assumption that the current set of default cursors consists of cursors that are all roughly the same size, and just measure the arrow cursor. This is not too unreasonable an assumption, because users generally prefer consistency among their cursors, and they are unlikely to choose a set of cursors where, say, the arrow cursor is ten times bigger than the I-beam cursor.

² Even though the name of the function says that it gets icon info, the documentation notes that it also works for cursors.