.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 }
博客参考:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
2020-06-10 Html 设置标题栏顶部固定