How to Customize and add Cursor Files to a project?
In order to get a cursor like that you would need to get (or create) a custom one. There's no such cursor built into Windows. Creating your own cursor can be done using Visual Studio's built-in Image Editor for Icons.
Creating your own cursor
To start with open the
Add New Item
dialog.
Then scroll down and select
Cursor File
, give it a name of your choice.
It'll now open your new cursor file in the so called Image Editor for Icons. Now you can just start drawing using the pencil or any of the other different drawing tools (images can also be pasted, but as you see the cursor initially has the 1 bit color format - meaning there's only two colors: black and white. This can be changed by adding a new image type).
Now we must specify a hot spot for the cursor. The hot spot is the position in the icon which Windows uses to track where the pointer is actually located (for simplicity you could call it the cursor's click point). The normal Windows 7 Aero Arrow has its hot spot at (0, 0) - the top left corner.
To specify the cursor's hots pot we must use the
Set Hot Spot Tool
. Then you click at the specific pixel that you want to use as the hot spot in your cursor icon. For this cursor I chose (9, 8).Setting the hot spot at (9, 8):
Save everything, then go to the
Solution Explorer
, right-click your project and pressProperties
. Then go to theResources
tab and clickAdd Resource
andAdd Existing File...
.Now locate your project's folder and select and open your cursor file.
The final non-code step is to select your cursor in the
Solution Explorer
, go to theProperties
pane and setBuild Action
toNone
. This is to prevent it from being added two times to your compiled executable, since it's already added as a resource.IMPORTANT: Do NOT do this for the cursor file located in the
Resources
folder!
Using your custom cursor in your application
Now onto the code, which is rather simple actually. As your cursor is now added as a byte array resource you only have to load that into a MemoryStream
, then pass that memory stream into the constructor of a Cursor
class. For simplicity and readability I put this code in another class.
public static class CursorHelper
{
public static Cursor FromByteArray(byte[] array)
{
using (MemoryStream memoryStream = new MemoryStream(array))
{
return new Cursor(memoryStream);
}
}
}
Now you can just go ahead and declare your cursor at class-level in your form/control/etc. and you'll be ready to use it!
private Cursor OpenHand = CursorHelper.FromByteArray(Properties.Resources.CursorOpenHand);
public MainWindow()
{
InitializeComponent();
this.Cursor = OpenHand;
}
Example usage
I made an example per your specifications; a normal open hand that changes to a grabbing hand when you hold down your mouse:
private Cursor OpenHand = CursorHelper.FromByteArray(Properties.Resources.CursorOpenHand);
private Cursor GrabbingHand = CursorHelper.FromByteArray(Properties.Resources.CursorGrabbingHand);
public MainWindow()
{
InitializeComponent();
this.Cursor = OpenHand;
this.MouseDown += this.MainWindow_MouseDown;
this.MouseUp += this.MainWindow_MouseUp;
}
private void MainWindow_MouseDown(object sender, MouseEventArgs e)
{
((Control)sender).Cursor = GrabbingHand;
}
private void MainWindow_MouseUp(object sender, MouseEventArgs e)
{
((Control)sender).Cursor = OpenHand;
}
Profit!
Here are the cursors that I used:
http://www.mydoomsite.com/sourcecodes/HandOpen.cur
http://www.mydoomsite.com/sourcecodes/HandGrabbing.cur
As others have mentioned, you need a custom cursor for this shape.
I'm not particularly proud of this code, but I managed to get myself into a corner and needed to do this in a situation where I couldn't have any new resources in a project, so here's a standalone custom cursor creator for this particular cursor.
You can assign the HandCursor it creates to your form like any other cursor, as an example:
public Example()
{
PictureBox box = new PictureBox();
box.Bounds = new Rectangle(10, 10, 100, 100);
box.Cursor = HandCursor;
box.MouseDown += Box_MouseDown;
box.MouseUp += Box_MouseUp;
box.BorderStyle = BorderStyle.Fixed3D;
Controls.Add(box);
}
void Box_MouseUp(object sender, MouseEventArgs e)
{
((Control)sender).Cursor = HandCursor;
}
void Box_MouseDown(object sender, MouseEventArgs e)
{
((Control)sender).Cursor = HandGrabCursor;
}
And here's the core of the code:
Cursor m_HandCursor = null;
Cursor HandCursor
{
get
{
if (m_HandCursor == null)
{
m_HandCursor = CursorFromString(
"AAACAAEAICAAABAAFACoEAAAFgAAACgAAAAgAAAAQ{A5}EAI{A62}aBgM3GgYD/xoGA/8a" +
"BgP/GgYD/xoGA/8aBgP/GgYD/xoGA/8aBgO6{A70}GgYDNxoGA73Ny8r/39/f/93d3f/a2" +
"tr/2NjY/9bW1v/V1dX/09PT/xoGA94{A6a}BoGAzcaBgO909HR/+Xl5f/j4+P/4eHh/97e" +
"3v/c3Nz/2tra/9jY2P/W1tb/GgYD3hoGAz{A61}aBgM3GgYDvdnX1//s7Oz/6urq/+fn5/" +
"/l5eX/4+Pj/+Dg4P/e3t7/3Nzc/9ra2v8aBgOHGgYDhw{A5f}BoGA73f3dz/8/Pz//Hx8f" +
"/u7u7/7Ozs/+np6f/n5+f/5OTk/+Li4v/g4OD/3d3d/7Kurf8aBgPV{A5b}aBgNjGgYDtP" +
"n5+f/IxMP/9fX1//Ly8v/w8PD/7u7u/+vr6//p6en/5ubm/+Tk5P/i4uL/39/f/xoGA94a" +
"BgMw{A50}GgYDNhoGA7rm5OT//Pz8/4N5d//4+Pj/9vb2//T09P/y8vL/8PDw/+3t7f/r6" +
"+v/6Ojo/+bm5v/j4+P/GgYDhxoGA4c{A50}aBgO66Obl{/7}+/v7/GgYD//v7+//6+vr/+" +
"Pj4//b29v/09PT/8vLy/+/v7//t7e3/6urq/+jo6P+6trX/GgYD1Q{A4f}BoGA//o5uX/6" +
"Obl/xoGA7oaBgP//v7+//39/f/7+/v/+fn5//j4+P/19fX/8/Pz//Hx8f/v7+//7Ozs/+r" +
"q6v8aBgP/{A50}GgYDuhoGA/8aBgO6GgYDNhoGA{/d}7+/v/8/Pz/+/v7//n5+f/39/f/9" +
"fX1//Pz8//x8fH/7u7u/xoGA/8{A65}GgYD{/17}9/f3//Pz8//r6+v/5+fn/GgYD//X19" +
"f/y8vL/GgYD/w{A65}aBgP{/c}Pysr{/b}8aBgP//f39//z8/P8aBgP/+Pj4//b29v8aBg" +
"P/{A60}GgYDMDgmJP{/b}4Z7ev{/b}xoGA{/8}v7+/xoGA//7+/v/+vr6/xoGA/8{A60}a" +
"BgOHhnt6{/c}QC8t{/c}GgYD{/c}GgYD//7+/v/9/f3/GgYD/w{A5f}BoGA9XPysr{/6}8" +
"/Kyv8aBgP{/b}8aBgP{/b}8aBgP{/6}8/Kyv8aBgO6{A60}GgYD{/c}GgYDhxoGA{/c}xo" +
"GA{/c}xoGA//Pysr/GgYDuhoGAxo{A60}aBgP{/b}8aBgOHGgYD{/c}GgYD{/7}Pysr/Gg" +
"YD/xoGA7oaBgMa{A65}BoGA7r{/a}xoGA4caBgP{/b}8aBgP/GgYD/xoGA7oaBgM2{A70}" +
"GgYDNhoGA7oaBgO6GgYDNhoGA7r{/a}xoGA7o{A95}GgYDNhoGA7oaBgO6GgYDNg{A84a}" +
"//AD///gA///wAH//4AB//+AAf//AAD//gAA//4AAP/+AAD//gAA///gAP//4AD//8AA//" +
"/AAP//wAD//8AA///AAf//wAf//8A////8P{/41}8=");
}
return m_HandCursor;
}
}
Cursor m_HandGrabCursor = null;
Cursor HandGrabCursor
{
get
{
if (m_HandGrabCursor == null)
{
m_HandGrabCursor = CursorFromString(
"AAACAAEAICAAABAAFACoEAAAFgAAACgAAAAgAAAAQ{A5}EAI{A62}aBgM3GgYD/xoGA/8a" +
"BgP/GgYD/xoGA/8aBgP/GgYD/xoGA/8aBgO6{A70}GgYDNxoGA73Pzc3/4eHh/97e3v/b2" +
"9v/2dnZ/9bW1v/U1NT/0tLS/xoGA94{A6a}BoGAzcaBgO919XV/+rq6v/n5+f/4+Pj/+Dg" +
"4P/d3d3/29vb/9jY2P/W1tb/GgYD3hoGAz{A61}aBgM3GgYDvd/d3P/y8vL/7+/v/+zs7P" +
"/p6en/5ubm/+Pj4//g4OD/3d3d/9ra2v8aBgOHGgYDhw{A5f}BoGA73l4+P/+vr6//f39/" +
"/19fX/8vLy/+/v7//r6+v/6Ojo/+Xl5f/i4uL/39/f/7Ovrv8aBgPV{A5b}aBgNjGgYDtP" +
"{/5}Nycj/+/v7//n5+f/39/f/9PT0//Hx8f/u7u7/6+vr/+fn5//k5OT/4eHh/xoGA94aB" +
"gMw{A50}GgYDNhoGA7ro5uX{/6}4Z7ev/+/v7//f39//v7+//5+fn/9vb2//Pz8//w8PD/" +
"7e3t/+rq6v/n5+f/GgYDhxoGA4c{A50}aBgO66Obl{/c}GgYD{/d}v7+//z8/P/6+vr/+P" +
"j4//X19f/y8vL/7+/v/+zs7P+9ubj/GgYD1Q{A4f}BoGA//o5uX/6Obl/xoGA7oaBgP{/1" +
"7}7+/v/8/Pz/+vr6//f39//19fX/8vLy/+/v7/8aBgP/{A50}GgYDuhoGA/8aBgO6GgYDN" +
"hoGA{/22}9/f3/+/v7//n5+f/39/f/9PT0/xoGA/8{A65}GgYD{/27}+/v7/GgYD//v7+/" +
"/5+fn/GgYD/w{A65}aBgP{/b}8aBgP{/b}8aBgP{/b}8aBgP//v7+/8zIx/8aBgO6{A65}" +
"BoGA{/c}xoGA{/c}xoGA{/c}xoGA//Pysr/GgYDuhoGAxo{A65}GgYD/8/Kyv{/6}GgYD{" +
"/c}GgYD{/7}Pysr/GgYD/xoGA7oaBgMa{A6b}aBgM2GgYDuhoGA/8aBgO6{/a}8aBgO6Gg" +
"YD/xoGA7oaBgM2{A85}BoGAzYaBgO6GgYDuhoGAzY{Aaf5}//AD///gA///wAH//4AB//+" +
"AAf//AAD//gAA//4AAP/+AAD//gAA///gAP//4AD//+AA///gAf//4Af///w{/57}8=");
}
return m_HandGrabCursor;
}
}
Cursor CursorFromString(string data)
{
byte[] bits = Convert.FromBase64String(
Regex.Replace(data,
"\\{(.)([0-9a-f]+)\\}",
delegate(Match m)
{
return new string(
m.Groups[1].Value[0],
int.Parse(m.Groups[2].Value,
System.Globalization.NumberStyles.HexNumber));
}
)
);
bits[2] = 1;
using (MemoryStream stream = new MemoryStream(bits))
{
return new Cursor(stream);
#if false
// Version for Windows Forms
using (Icon icon = new Icon(stream))
{
WinAPI.ICONINFO info = new WinAPI.ICONINFO();
WinAPI.GetIconInfo(icon.Handle, out info);
info.fIcon = false;
info.xHotspot = bits[10];
info.yHotspot = bits[12];
IntPtr hCursor = WinAPI.CreateIconIndirect(ref info);
Cursor ret = new Cursor(hCursor);
return ret;
}
#endif
}
}
static class WinAPI
{
[DllImport("user32.dll")]
public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
[DllImport("user32.dll")]
public static extern IntPtr CreateIconIndirect(ref ICONINFO piconinfo);
[StructLayout(LayoutKind.Sequential)]
public struct ICONINFO
{
public bool fIcon;
public Int32 xHotspot;
public Int32 yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
}