Search code examples
c#wpfwindowsinteropextern

How do you use a Cursor from ole32.dll in a WPF application?


I want to use one of Windows' built-in cursors that are not included in the 'Cursors' class. I found this question to which the answer appears to provide the information I need, but there is a problem. System.Windows.Input.Cursor does not have a constructor that accepts IntPtr. Here is the code snippet provided by that answer (comment is mine):

[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("user32.dll")]
public static extern IntPtr LoadCursor(IntPtr hInstance, UInt16 lpCursorName);

private void button1_Click(object sender, EventArgs e)
{
    var l = LoadLibrary("ole32.dll");
    var h = LoadCursor(l, 6);
    this.Cursor = new Cursor(h);//this does not compile!
}

My question is: How can I make a System.Windows.Input.Cursor from one of the cursors contained in ole32.dll?


Solution

  • I figured it out by using the answer to this question.

    Here is my code:

    static class WindowsCursors
    {
        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary(string dllToLoad);
    
        [DllImport("user32.dll")]
        private static extern IntPtr LoadCursor(IntPtr hInstance, UInt16 lpCursorName);
    
        public static Cursor GetCursor(ushort cursorNumber)
        {
            var library = LoadLibrary("ole32.dll");
            var cursorPointer = LoadCursor(library, cursorNumber);
            return CursorInteropHelper.Create(new SafeCursorHandle(cursorPointer));
        }
    
        class SafeCursorHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
        {
            public SafeCursorHandle(IntPtr handle) : base(true)
            {
                base.SetHandle(handle);
            }
            protected override bool ReleaseHandle()
            {
                if (!this.IsInvalid)
                {
                    if (!DestroyCursor(this.handle))
                        throw new System.ComponentModel.Win32Exception();
                    this.handle = IntPtr.Zero;
                }
                return true;
            }
            [DllImport("user32.dll", SetLastError = true)]
            private static extern bool DestroyCursor(IntPtr handle);
        }
    }
    

    Usage:

    var cursor = WindowsCursors.GetCursor(3);