.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 }
博客参考:
作者:唐宋元明清2188
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。