.NET 自定义并动态切换光标

系统有很多光标类型 :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     }
View Code

 

博客参考:

posted @ 2021-06-10 22:37  唐宋元明清2188  阅读(635)  评论(0编辑  收藏  举报