Question

I am developing a SDG (Single Display Groupware) application, and for that I need multiple cursors (to the simplest of different colors) for the single window. I came to know that with C# you can just use black and white cursors, which does not solve my problem. So please help me with this problem.

Thanks in advance.

Was it helpful?

Solution

The Cursor class is rather poorly done. For some mysterious reason it uses a legacy COM interface (IPicture), that interface doesn't support colored and animated cursors. It is fixable with some fairly ugly elbow grease:

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;

static class NativeMethods {
    public static Cursor LoadCustomCursor(string path) {
        IntPtr hCurs = LoadCursorFromFile(path);
        if (hCurs == IntPtr.Zero) throw new Win32Exception();
        var curs = new Cursor(hCurs);
        // Note: force the cursor to own the handle so it gets released properly
        var fi = typeof(Cursor).GetField("ownHandle", BindingFlags.NonPublic | BindingFlags.Instance);
        fi.SetValue(curs, true);
        return curs;
    }
    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr LoadCursorFromFile(string path);
}

Sample usage:

this.Cursor = NativeMethods.LoadCustomCursor(@"c:\windows\cursors\aero_busy.ani");

OTHER TIPS

I also tried something different and it seems to work with different colored cursors, but the only problem with this piece of code is that the Hotspot coordinates for the mouse cursors are not exact i.e. the are moved slightly to the right. But this can be fixed by considering an offset in the code.

The code is as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace MID
{    
    public partial class CustomCursor : Form
    {
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr LoadCursorFromFile(string filename);

        public CustomCursor()
        {
            InitializeComponent();

            Bitmap bmp = (Bitmap)Bitmap.FromFile("Path of the cursor file saved as .bmp");
            bmp.MakeTransparent(Color.Black);
            IntPtr ptr1 = blue.GetHicon();

            Cursor cur = new Cursor(ptr1);
            this.Cursor = cur;

        }
    }
}

You can load cursors from file dynamically like this:

var myCursor = new Cursor("myCursor.cur");

After you have loaded it, you can set the cursor of any control like this:

myControl.Cursor = myCursor;

The cursor also accepts a stream as a constructor parameter. This means that you can load from a resource embedded in your application, rather than from the file system.

Windows will not let you have more than one cursor, but you can draw more than one on your control. You can use the cursor object's Draw method like so:

myCursor.Draw(g, new Rectangle(...));

If you are using TCP/IP to send the cursor data between clients, then this should be enough to work.

However, there have been a few applications that have supported multiple input on a single PC. (For example, Rag Doll Kung Fu) For this, you are looking at something that the .NET framework doesn't support.

You will probably have to look into PInvoking some USB calls. (I don't have much experience here, so I can't ellaborate.)

I once needed to create dynamic cursors on the fly. This turned out to pose weird issues, especially since semitransparency would blend against black and make the cursors too dark. In the end I solved the problem with some help from the SO community and the whole solution is displayed here:

Windows Forms: Making a cursor bitmap partially transparent

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top