tags:

views:

6305

answers:

5

I want to use an image or icon as a custom cursor in WPF app. What's the best way to do it?

+1  A: 

You could try this

<Window Cursor=""C:\WINDOWS\Cursors\dinosaur.ani"" />
palehorse
Xamlog link is for members-only :(
jschroedl
A: 

Also check out Scott Hanselman's BabySmash (www.codeplex.com/babysmash). He used a more "brute force" method of hiding the windows cursor and showing his new cursor on a canvas and then moving the cursor to were the "real" cursor would have been

Read more here: http://www.hanselman.com/blog/DeveloperDesigner.aspx

rudigrobler
+10  A: 

You have two basic options:

  1. When the mouse cursor is over your control, hide the system cursor by setting this.Cursor = Cursors.None; and draw your own cursor using whatever technique you like. Then, update the position and appearance of your cursor by responding to mouse events. Here are two examples:

  2. Create a new Cursor object by loading an image from a .cur or .ani file. You can create and edit these kinds of files in Visual Studio. There are also some free utilites floating around for dealing with them. Basically they're images (or animated images) which specify a "hot spot" indicating what point in the image the cursor is positioned at.

If you choose to load from a file, note that you need an absolute file-system path to use the Cursor(string fileName) constructor. Lamely, a relative path or Pack URI will not work. If you need to load the cursor from a relative path or from a resource packed with your assembly, you will need to get a stream from the file and pass it in to the Cursor(Stream cursorStream) constructor. Annoying but true.

On the other hand, specifying a cursor as a relative path when loading it using a XAML attribute does work, a fact you could use to get your cursor loaded onto a hidden control and then copy the reference to use on another control. I haven't tried it, but it should work.

PeterAllenWebb
unfortunately the 1st example does no longer work without authorization.
MAD9
Also note that you can construct your cursor on the fly from any WPF content. See http://stackoverflow.com/questions/2835502/rotating-cursor-according-to-rotated-textbox/2836904#2836904 for an example of how this is done.
Ray Burns
The link I posted in the previous commment deals with rotating an existing cursor. I just posted a new answer to this question (see below) that tells how to convert an arbitrary Visual into a Cursor.
Ray Burns
+9  A: 

Like Peter mentioned above, if you already have a .cur file, you can use it as an embedded resource by creating a dummy element in the resource section, and then referencing the dummy's cursor when you need it.

For example, say you wanted to display non-standard cursors depending on the selected tool.

Add to resources:

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

Example of embedded cursor referenced in code:

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;

-Ben

Ben McIntosh
+2  A: 

There is an easier way than managing the cursor display yourself or using Visual Studio to construct lots of custom cursors.

If you have a Visual you can construct a Cursor from it using the following code:

public Cursor ConvertToCursor(Visual 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);
  resultSource.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();
  new System.Drawing.Icon(resultBitmap.GetHIcon()).Save(stream);

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

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

Note that your Visual's size must be a standard cursor size (eg 16x16 or 32x32), for example:

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

It would be used like this:

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

Obviously your Visual could be an <Image> control if you have an existing image, or you can draw anything you like using WPF's built-in drawing tools.

Note that details on the .cur file format can be found at ICO (file format).

Ray Burns