Cursor 类做得相当糟糕。由于某种神秘的原因,它使用传统的 COM 接口 (IPicture),该接口不支持彩色和动画光标。它可以用一些相当难看的苦劳来修复:
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);
}
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);
}
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;
}
}
}
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;
}
}
}
Windows 不允许您拥有多个光标,但您可以在控件上绘制多个光标。您可以像这样使用光标对象的 Draw 方法:
myCursor.Draw(g, new Rectangle(...));
如果您使用 TCP/IP 在客户端之间发送光标数据,那么这应该足以工作。
然而,有一些应用程序支持单台 PC 上的多个输入。 (例如,Rag Doll Kung Fu)为此,您正在查看 .NET 框架所不具备的功能支持。
您可能需要研究 PInvoking 一些 USB 调用。 (我没有太多经验,所以无法详细说明。)
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.)
发布评论
评论(5)
Cursor 类做得相当糟糕。由于某种神秘的原因,它使用传统的 COM 接口 (IPicture),该接口不支持彩色和动画光标。它可以用一些相当难看的苦劳来修复:
示例用法:
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:
Sample usage:
这个帖子已经很老了,但它是 Google 上的第一批热门帖子之一,所以这是 VS 2019 的答案:
您应该添加“somePNG.png”以及您喜欢的任何透明度作为项目资源。
希望它对 2020 年的人有所帮助。
This thread is pretty old, but it's one of the first hits on Google, so here's the answer for VS 2019:
You should add 'somePNG.png' with whatever transparency you like as a project resource.
Hope it helps someone in 2020.
我还尝试了不同的方法,它似乎适用于不同颜色的光标,但这段代码的唯一问题是鼠标光标的热点坐标不准确,即稍微向右移动。但这可以通过考虑代码中的偏移量来解决。
代码如下:
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:
您可以像这样动态地从文件加载游标:
加载后,您可以像这样设置任何控件的游标:
游标还接受流作为构造函数参数。这意味着您可以从应用程序中嵌入的资源加载,而不是从文件系统加载。
Windows 不允许您拥有多个光标,但您可以在控件上绘制多个光标。您可以像这样使用光标对象的
Draw
方法:如果您使用 TCP/IP 在客户端之间发送光标数据,那么这应该足以工作。
然而,有一些应用程序支持单台 PC 上的多个输入。 (例如,Rag Doll Kung Fu)为此,您正在查看 .NET 框架所不具备的功能支持。
您可能需要研究 PInvoking 一些 USB 调用。 (我没有太多经验,所以无法详细说明。)
You can load cursors from file dynamically like this:
After you have loaded it, you can set the cursor of any control like this:
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: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.)
唯一的问题是热点将位于文件的中心。因此,要么:
将文件的宽度和高度设置为两倍,然后将图标放在右下象限中。
或者
使用这个复杂的代码来调整热点:
更改 WinForms / .NET 中的光标热点
The only problem is that the hotspot will be in the centre of the file. So either:
Make the file twice as wide and twice as tall, and place the icon in the lower right quadrant.
Or
Use this complicated code to adjust the hotspot:
Change Cursor HotSpot in WinForms / .NET