在WPF中设置自定义光标图像热点

我试图在Cursor上使用自定义图像,我用这些代码做了。

public static class cursorHelper { public static Cursor vertical = new Cursor(Application.GetResourceStream(getFromResource("PenCADwpf", "Images/cursors/Vertical.ico")).Stream); public static Cursor horizontal = new Cursor(Application.GetResourceStream(getFromResource("PenCADwpf", "Images/cursors/Horizontal.ico")).Stream); public static Uri getFromResource(string psAssemblyName, string psResourceName) { Uri oUri = new Uri("pack://application:,,,/" + psAssemblyName + ";component/" + psResourceName, UriKind.RelativeOrAbsolute); return oUri; } public static ImageSource getImageSourceFromResource(string psAssemblyName, string psResourceName) { Uri oUri = getFromResource(psAssemblyName, psResourceName); return BitmapFrame.Create(oUri); } } 

在代码中使用是

  private void btnVerticalMullion_Click(object sender, RoutedEventArgs e) { this.Cursor = cursorHelper.vertical; } 

我的问题是光标的热点是左下角。 我需要将其更改为图像的0,0(左上角)点。 有人可以帮帮我吗? 提前致谢,

这是因为您使用.ICO文件而不是.CUR文件作为Cursor类的数据。

虽然.ICO和.CUR文件格式类似,但.ICO格式不包含热点信息。

你有2个选择:

  • 将.ICO文件转换为.CUR文件,并将其作为资源嵌入

    通过使用您可以在网上找到的转换实用程序来做到这一点,
    要么
    在Visual Studio中创建一个新的.CUR文件,然后复制并粘贴.ICO文件中的数据。

  • 将它们保存为.ICO文件但是破解数据,以便在传递给Cursor类时遵循CUR格式。

下面是一些示例代码,用于修改ICO流以将其转换为CUR格式。

在这个例子中,我用一个包含单个32X32X4bit BMP图像的ICO文件测试它,我希望光标有一个(15,15)热点。

这段代码只是为了让你开始沿着这条路走下去……它需要更多的代码来处理错误,以及处理包含多个图标图像的ICO文件的能力(即如果有多个条目)等。

您还可以使用BinaryWriter更自然地处理数据,例如使用Write(UInt16)使用2个字节(即超过255)的热点坐标。

在此处输入图像描述

在此处输入图像描述

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.IO; using System.Windows.Resources; namespace WpfApplication2 { ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Uri uri = new Uri("pack://application:,,,/test.ico"); Stream iconstream = GetCURFromICO(uri, 15, 15 ); Cursor cursor = new Cursor(iconstream); this.Cursor = cursor; } public static Stream GetCursorFromICO(Uri uri, byte hotspotx, byte hotspoty) { StreamResourceInfo sri = Application.GetResourceStream(uri); Stream s = sri.Stream; byte []buffer = new byte[s.Length]; s.Read(buffer, 0, (int)s.Length); MemoryStream ms = new MemoryStream(); buffer[2] = 2; // change to CUR file type buffer[10] = hotspotx; buffer[12] = hotspoty; ms.Write(buffer, 0, (int)s.Length); ms.Position = 0; return ms; } public static Stream GetCURFromICOAlternativeMethod(Uri uri, byte hotspotx, byte hotspoty) { StreamResourceInfo sri = Application.GetResourceStream(uri); Stream s = sri.Stream; byte []buffer = new byte[s.Length]; MemoryStream ms = new MemoryStream(); ms.WriteByte(0); // always 0 ms.WriteByte(0); ms.WriteByte(2); // change file type to CUR ms.WriteByte(0); ms.WriteByte(1); // 1 icon in table ms.WriteByte(0); s.Position = 6; // skip over first 6 bytes in ICO as we just wrote s.Read(buffer, 0, 4); ms.Write(buffer, 0, 4); ms.WriteByte(hotspotx); ms.WriteByte(0); ms.WriteByte(hotspoty); ms.WriteByte(0); s.Position += 4; // skip 4 bytes as we just wrote our own int remaining = (int)s.Length - 14; s.Read(buffer, 0, remaining); ms.Write(buffer, 0, remaining); ms.Position = 0; return ms; } } }