Sign in to follow this  
Kija

[MDX + C#] Device.SetCursorProperties

Recommended Posts

Hello, I would like to use a custom cursor for my app, but if I understood things right the standard windows "Cursor" is grayscale and 16x16 pixels? Anyhow, there is a Device.SetCursorProperties(int hotSpotX, int hotSpotY, Surface cursorBitmap), so I tried to implement it. But it didn't show my custom cursor, it still showed the original windows cursor. So I made a key execute this code:
System.Windows.Forms.Cursor.Hide();
Device.SetCursorProperties(0, 0, new Surface(Device, new Bitmap(cursorFile), Pool.Default));
Device.ShowCursor(true);
System.Windows.Forms.Cursor.Show();

First I hide the standard windows cursor, then I load the new DX cursor, show the DX cursor and then I have to show the windows cursor again to get any cursor. After these calls it shows my custom cursor, but as fast as I move the cursor, the custom cursor goes away and the default is back. Any ideas on what I'm missing?

Share this post


Link to post
Share on other sites
It's probably polling your parent form for its cursor as soon as you move the mouse. You might want to try setting the cursor on the window/form instead of on the device. I didn't try this yet with a custom cursor, but for the built-in Windows cursors it works just fine.

Here's an old code snippet of my to load a custom cursor for a form. You may need to use LoadImageA to obtain the required IntPtr since you are using a .bmp file instead of a .cur file, but try this one first as Windows is normally smart enough to load it properly.

[source lang=c#]
private Cursor LoadCursor(string path)
{
IntPtr cur = LoadCursorFromFileA(path);
return new Cursor(cur);
}

[System.Runtime.InteropServices.DllImport("user32", EntryPoint="LoadCursorFromFile")]
public static extern IntPtr LoadCursorFromFileA(string lpFileName);

[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint="LoadCursor")]
public static extern IntPtr LoadCursorA(IntPtr hInstance, string lpCursorName);

[System.Runtime.InteropServices.DllImport("user32", EntryPoint="LoadImage")]
public static extern IntPtr LoadImageA(IntPtr hInst, string lpsz, int un1, int n1, int n2, int un2);



Aside from this approach, it seems strange that you first need to show your device/DX cursor and then show your windows cursor again. Are you sure it won't work without calling the final Cursor.Show()?

Anyway, I just checked out the documentation and though it didn't say anything about oyur problem, it does point out that the device/DX cursor is lost on a device reset. That hasn't got anything to do with your problem, but if my workaround does the trick for you, I'd go with that since you don't have to worry about reloading the cursor on a device reset with it.

Please let me know if this works for you, that way I won't need to test it myself :)

Share this post


Link to post
Share on other sites
Thanks for the answer remigius but either your code isn't doing the trick or my C# skills are insufficient :) In the windows for initialize code I have a line with "this.Cursor = System.Windows.Forms.Cursors.Default;" so I tried to replace that with "this.Cursor = LoadCursor("data/cursor.bmp");" and then right before that Initialize function I pasted your code. It compiled it fine but it crashes with the exception: "Win32 handle passed to Cursor is not valid or is the wrong type.".

Besides your approach I tried to do File->New->File->Cursor File then I get a cursor as a resource in my project. But all I can draw with is grayscale and 16x16 pixels.

And onto my original code, I need all lines to get the DX cursor to show. Without the last "System.Windows.Forms.Cursor.Show();" the cursor is hidden until I run that line (even if I move the mouse). And without the "Device.ShowCursor(true)" line it's not showing the dx cursor, just the default one.
I know that I could hide the windows cursor and draw my own sprite on the mouse coords, but it would be really sweet if I could get this custom cursor to work since it's not affected by the framerate of my game (it's in another thread).

Any help appreciated

Share this post


Link to post
Share on other sites
I just got an idea for loading the cursor from a bitmap without the external dll calls. It's a bit of a hack, but it works for me:

<code>
// 'this' is your Form object
Bitmap bitmap = new Bitmap( @"..\..\cursor.bmp" );
bitmap.MakeTransparent( Color.White );
this.Cursor = new Cursor( bitmap.GetHicon() );
</code>

Share this post


Link to post
Share on other sites
Works like a charm, thanks :)

EDIT: One thing though... The "hotspot" (where the cursor points) seems to be a bit off, not Point(0, 0) as it ought to be, but instead in the middle of the cursor Point(16, 16) for my 32x32 image.

this.Cursor.HotSpot is readonly so I can't set it. However I can put my 32x32 cursor in the bottomright corner of a 64x64 image to get it right. But that's just silly :D

[Edited by - Kija on November 24, 2005 1:38:53 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this