How to Use Custom Cursors in C#
By FoxLearn 1/16/2025 7:33:29 AM 75
Changing the cursor on a WinForms control is simple if you are using one of the standard cursors.
You can easily set the Cursor
property to a value from the Cursors
object.
However, using a custom cursor is more complex. One way to do this is by loading a custom cursor file (with a .cur
extension).
You can create a new Cursor
object by passing the file path of your custom cursor to the Cursor
constructor.
Cursor myCursor = new Cursor("myCursor.cur"); myControl.Cursor = myCursor;
Using a custom cursor in WinForms becomes more challenging if you don't have a pre-made .cur
file and want to create the cursor programmatically.
Since .NET doesn't provide all the necessary functionality, you'll need to use interop methods to achieve this.
The first step is to define the C# equivalent of the ICONINFO
structure, which will store the necessary information about the cursor you're creating.
public struct IconInfo { public bool fIcon; public int xHotspot; public int yHotspot; public IntPtr hbmMask; public IntPtr hbmColor; }
The key members of the ICONINFO
structure are fIcon
, xHotspot
, and yHotspot
. The fIcon
member indicates whether the icon is a cursor (set to false
for a cursor). The xHotspot
and yHotspot
define the "click point" of the cursor, which is the critical pixel for interactions, even though the cursor may be larger than 1x1 pixel.
In this example, we create a 140x25 pixel bitmap and draw some text on it.
Bitmap bitmap = new Bitmap(140, 25); Graphics g = Graphics.FromImage(bitmap); using (Font f = new Font(FontFamily.GenericSansSerif, 10)) { g.DrawString("{ } Switch On The Code", f, Brushes.Green, 0, 0); }
This code initializes a Graphics
object from the bitmap, allowing us to draw the string { } Switch On The Code
in green text on the image.
Creating the Custom Cursor
Once the bitmap is ready, the next step is to create a custom cursor using this bitmap. A cursor in .NET can be created using the CreateCursor
method, which requires a Bitmap
object and the hot spot coordinates (the point on the cursor that will interact with the interface, typically the tip of the arrow).
this.Cursor = CreateCursor(bitmap, 3, 3);
Here, the custom cursor is set with the bitmap, and the hot spot is located at coordinates (3, 3)
.
To create a cursor from a bitmap, we must interact with the Windows API to handle the icon creation and hot spot settings. The following P/Invoke methods allow us to interface with the necessary Windows functions:
[DllImport("user32.dll")] public static extern IntPtr CreateIconIndirect(ref IconInfo icon); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
The core of creating a custom cursor is the CreateCursor
method, which is responsible for constructing a Cursor
object using the bitmap and the hot spot parameters.
public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot) { IconInfo tmp = new IconInfo(); GetIconInfo(bmp.GetHicon(), ref tmp); tmp.xHotspot = xHotSpot; tmp.yHotspot = yHotSpot; tmp.fIcon = false; // Indicates that it's a cursor, not an icon return new Cursor(CreateIconIndirect(ref tmp)); }
This function converts a bitmap into a cursor by first creating an IconInfo
structure and populating it with icon data using the native GetIconInfo
method. This method takes the bitmap's icon pointer (obtained via GetHicon()
) and a reference to the IconInfo
structure.
The hotspot coordinates are set, and fIcon
is marked as false
to indicate it's a cursor. The CreateIconIndirect
function is then called to generate a new cursor icon, and a new Cursor
is created from the returned pointer. The bitmap is not affected, as CreateIconIndirect
creates a separate copy for the cursor.
After the cursor is set, it’s good practice to dispose of any resources you no longer need.
bitmap.Dispose();
By manipulating the bitmap, you can create complex and interactive cursors, enhancing the user interface.
- How to fix 'Failure sending mail' in C#
- How to Parse a Comma-Separated String from App.config in C#
- How to convert a dictionary to a list in C#
- How to retrieve the Executable Path in C#
- How to validate an IP address in C#
- How to retrieve the Downloads Directory Path in C#
- C# Tutorial
- Dictionary with multiple values per key in C#