C# 自定义并动态切换光标

2023-07-29,,

系统有很多光标类型 :Cursors 类 (System.Windows.Input) | Microsoft Docs

本章介绍如何自定义光标、并动态切换光标类型。

动态切换光标类型

以白板书写为例:鼠标操作时,Cursor为红点;触摸时,Cursor为空;

 1     public MainWindow()
2 {
3 InitializeComponent();
4 MouseEnter += (s, e) =>
5 {
6 ShowMouseCursor(e);
7 };
8 MouseMove += (s, e) =>
9 {
10 ShowMouseCursor(e);
11 };
12 StylusMove += (s, e) =>
13 {
14 ShowNoneCursor();
15 };
16 }

设置光标显示:

 1     private void ShowNoneCursor()
2 {
3 if (Cursor == Cursors.None)
4 {
5 return;
6 }
7 Cursor = Cursors.None;
8 Mouse.UpdateCursor();
9 }
10 private void ShowMouseCursor(MouseEventArgs e)
11 {
12 if (e.StylusDevice != null && e.StylusDevice.Id > -1)
13 {
14 return;
15 }
16 if (Cursor == GetFillCursor())
17 {
18 return;
19 }
20 Cursor = GetFillCursor();
21 Mouse.UpdateCursor();
22 }
23 private Cursor _fillCursor = null;
24 private Cursor GetFillCursor()
25 {
26 return _fillCursor ?? (_fillCursor = CursorHelper.CreateFillCursor());
27 }

触摸书写时,会有个默认光标,所以此处把触摸时的光标置空Cursors.None。

Mouse.UpdateCursor()能强制更新光标。当然,不调用这个更新方法肉眼其实也看不出啥。。。

光标切换效果如上,前面一段是用鼠标书写,后面是触摸书写,光标类型有切换。红点光标自定义方案见下方。

自定义光标

自定义一个纯色的圆形光标:

 1     public static Cursor CreateFillCursor(int size = 24, Brush fillBrush = null)
2 {
3 int unitSize = size / 4;
4 var bmp = new Bitmap(size, size);
5 using (Graphics g = Graphics.FromImage(bmp))
6 {
7 g.Clip = new Region(new Rectangle(0, 0, size, size));
8 g.SmoothingMode = SmoothingMode.HighQuality;
9 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
10 using (var pen = new Pen(fillBrush ?? Brushes.Red, unitSize))
11 {
12
13 g.DrawEllipse(pen, new Rectangle(unitSize, unitSize, unitSize, unitSize));
14 }
15 }
16 return BitmapCursor.CreateBmpCursor(bmp);
17 }

也可以通过图片资源BitmapSource来生成光标:

 1     public static Cursor CreateFromBitmapSource(BitmapSource source)
2 {
3 var bitmap = BitmapSourceToBitmap(source);
4 return BitmapCursor.CreateBmpCursor(bitmap);
5 }
6 private static Bitmap BitmapSourceToBitmap(BitmapSource source)
7 {
8 using (var stream = new MemoryStream())
9 {
10 var e = new BmpBitmapEncoder();
11 e.Frames.Add(BitmapFrame.Create(source));
12 e.Save(stream);
13
14 var bmp = new Bitmap(stream);
15
16 return bmp;
17 }
18 }

BitmapCursor:

 1     internal class BitmapCursor : SafeHandle
2 {
3 public override bool IsInvalid => handle == (IntPtr)(-1);
4
5 public static Cursor CreateBmpCursor(Bitmap cursorBitmap)
6 {
7
8 var c = new BitmapCursor(cursorBitmap);
9
10 return CursorInteropHelper.Create(c);
11 }
12 protected BitmapCursor(Bitmap cursorBitmap)
13 : base((IntPtr)(-1), true)
14 {
15 handle = cursorBitmap.GetHicon();
16 }
17 protected override bool ReleaseHandle()
18 {
19 bool result = DestroyIcon(handle);
20
21 handle = (IntPtr)(-1);
22
23 return result;
24 }
25 [DllImport("user32")]
26 private static extern bool DestroyIcon(IntPtr hIcon);
27 }

博客参考:

WPF 自定义鼠标光标 - DH_青叶 - 博客园 (cnblogs.com)
[WPF]自定义鼠标指针 - 周银辉 - 博客园 (cnblogs.com)

C# 自定义并动态切换光标的相关教程结束。

《C# 自定义并动态切换光标.doc》

下载本文的Word格式文档,以方便收藏与打印。