WPF中的自定义光标?

时间:2020-03-05 18:48:30  来源:igfitidea点击:

我想在WPF应用程序中使用图像或者图标作为自定义光标。最好的方法是什么?

解决方案

回答

你可以试试这个

<Window Cursor=""C:\WINDOWS\Cursors\dinosaur.ani"" />

回答

另请参阅Scott Hanselman的BabySmash(www.codeplex.com/babysmash)。他使用了一种更"强力"的方法,即隐藏Windows光标并将新光标显示在画布上,然后将光标移动到"真实"光标原本为

在这里阅读更多:
http://www.hanselman.com/blog/DeveloperDesigner.aspx

回答

我们有两个基本选择:

  • http://www.hanselman.com/blog/DeveloperDesigner.aspx
  • 通过从.cur或者.ani文件加载图像来创建新的Cursor对象。我们可以在Visual Studio中创建和编辑这些类型的文件。还有一些免费的实用程序可以用来处理它们。基本上,它们是图像(或者动画图像),它们指定"热点",该"热点"指示光标位于图像中的哪个点。

如果选择从文件加载,请注意,我们需要一个绝对的文件系统路径才能使用Cursor(string fileName)构造函数。相对而言,相对路径或者Pack URI无效。如果我们需要从相对路径或者程序集打包的资源中加载光标,则需要从文件中获取流,并将其传递给Cursor(Stream cursorStream)构造函数。烦人但真实。

另一方面,在使用XAML属性加载游标时将游标指定为相对路径确实可行,这是事实,我们可以用来将游标加载到隐藏控件上,然后复制引用以在另一个控件上使用。我没有尝试过,但是应该可以。

回答

就像上面提到的Peter一样,如果我们已经有一个.cur文件,则可以通过在资源部分中创建一个虚拟元素,然后在需要时引用该虚拟对象的光标,将其用作嵌入式资源。

例如,假设我们要显示非标准光标,具体取决于所选工具。

添加到资源:

<Window.Resources>
    <ResourceDictionary>
        <TextBlock x:Key="CursorGrab" Cursor="Resources/Cursors/grab.cur"/>
        <TextBlock x:Key="CursorMagnify" Cursor="Resources/Cursors/magnify.cur"/>
    </ResourceDictionary>
</Window.Resources>

代码中引用的嵌入式游标的示例:

if (selectedTool == "Hand")
    myCanvas.Cursor = ((TextBlock)this.Resources["CursorGrab"]).Cursor;
else if (selectedTool == "Magnify")
    myCanvas.Cursor = ((TextBlock)this.Resources["CursorMagnify"]).Cursor;
else
    myCanvas.Cursor = Cursor.Arrow;

-本

回答

有一种比自己管理光标显示或者使用Visual Studio构造大量自定义光标更简单的方法。

如果我们有FrameworkElement,则可以使用以下代码从中构造一个Cursor:

public Cursor ConvertToCursor(FrameworkElement visual, Point hotSpot)
{
  int width = (int)visual.Width;
  int height = (int)visual.Height;

  // Render to a bitmap
  var bitmapSource = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
  bitmapSource.Render(visual);

  // Convert to System.Drawing.Bitmap
  var pixels = new int[width*height];
  bitmapSource.CopyPixels(pixels, width, 0);
  var bitmap = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
  for(int y=0; y<height; y++)
    for(int x=0; x<width; x++)
      bitmap.SetPixel(x, y, Color.FromArgb(pixels[y*width+x]));

  // Save to .ico format
  var stream = new MemoryStream();
  System.Drawing.Icon.FromHandle(resultBitmap.GetHicon()).Save(stream);

  // Convert saved file into .cur format
  stream.Seek(2, SeekOrigin.Begin);
  stream.WriteByte(2);
  stream.Seek(10, SeekOrigin.Begin);
  stream.WriteByte((byte)(int)(hotSpot.X * width));
  stream.WriteByte((byte)(int)(hotSpot.Y * height));
  stream.Seek(0, SeekOrigin.Begin);

  // Construct Cursor
  return new Cursor(stream);
}

请注意,FrameworkElement的大小必须是标准光标大小(例如16x16或者32x32),例如:

<Grid x:Name="customCursor" Width="32" Height="32">
  ...
</Grid>

它的用法如下:

someControl.Cursor = ConvertToCursor(customCursor, new Point(0.5, 0.5));

显然,如果我们已有图像,那么FrameworkElement可能是一个<Image>控件,或者我们可以使用WPF的内置绘图工具来绘制所需的任何图像。

请注意,有关.cur文件格式的详细信息,可以在ICO(文件格式)中找到。