zoukankan      html  css  js  c++  java
  • 在.net桌面程序中自定义鼠标光标

    有的时候,一个自定义的鼠标光标能给你的程序增色不少。本文这里介绍一下如何在.net桌面程序中自定义鼠标光标。由于.net的桌面程序分为WinForm和WPF两种,这里分别介绍一下。

    WinForm程序

    对于WinForm程序,可以通过修改Control.Cursor属性来实现光标的修改,如果我们有光标文件的话,可以直接通过如下代码实现自定义光标:

        this.Cursor = new Cursor("myCursor.cur");

    但这种方式不是本文介绍的重点,本文主要介绍如何自己绘制光标,这样则具有更多的可控性和灵活性。

    创建一个自定义光标,首先需要定义需要一个光标结构 ICONINFO ,它的.net版本如下:

        public struct IconInfo
        {
            public bool fIcon;
            public int xHotspot;
            public int yHotspot;
            public IntPtr hbmMask;
            public IntPtr hbmColor;
        }

    然后通过GetIconInfo and CreateIconIndirect两个函数来合成光标。完整代码如下: 

     1     public class CursorHelper
     2     {
     3         static class NativeMethods
     4         {
     5             public struct IconInfo
     6             {
     7                 public bool fIcon;
     8                 public int xHotspot;
     9                 public int yHotspot;
    10                 public IntPtr hbmMask;
    11                 public IntPtr hbmColor;
    12             }
    13 
    14             [DllImport("user32.dll")]
    15             public static extern IntPtr CreateIconIndirect(ref IconInfo icon);
    16 
    17 
    18             [DllImport("user32.dll")]
    19             [return: MarshalAs(UnmanagedType.Bool)]
    20             public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
    21         }
    22 
    23         public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot)
    24         {
    25             var icon = new NativeMethods.IconInfo
    26             {
    27                 xHotspot = xHotSpot,
    28                 yHotspot = yHotSpot,
    29                 fIcon = false
    30             };
    31 
    32             NativeMethods.GetIconInfo(bmp.GetHicon(), ref icon);
    33             return new Cursor(NativeMethods.CreateIconIndirect(ref icon));
    34         }
    35     }
    View Code

    测试代码为:

        using (Bitmap bitmap = new Bitmap(21, 26))
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.DrawRectangle(Pens.Red, 0, 0, 20, 25);
            this.Cursor = CursorHelper.CreateCursor(bitmap, 3, 3);
        }

    WPF程序

    至于WPF程序,和WinForm程序是非常类似的,一方面,它也可以通过光标文件来实现写入Cursor属性来自定义光标文件。

    至于自己绘制光标,上面的代码基本上也是可以复用的,不过相对的要重新封装一下,完整代码如下: 

     1     public class CursorHelper
     2     {
     3         static class NativeMethods
     4         {
     5             public struct IconInfo
     6             {
     7                 public bool fIcon;
     8                 public int xHotspot;
     9                 public int yHotspot;
    10                 public IntPtr hbmMask;
    11                 public IntPtr hbmColor;
    12             }
    13 
    14             [DllImport("user32.dll")]
    15             public static extern SafeIconHandle CreateIconIndirect(ref IconInfo icon);
    16 
    17             [DllImport("user32.dll")]
    18             public static extern bool DestroyIcon(IntPtr hIcon);
    19 
    20             [DllImport("user32.dll")]
    21             [return: MarshalAs(UnmanagedType.Bool)]
    22             public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
    23         }
    24 
    25         [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
    26         class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
    27         {
    28             public SafeIconHandle()
    29                 : base(true)
    30             {
    31             }
    32 
    33             protected override bool ReleaseHandle()
    34             {
    35                 return NativeMethods.DestroyIcon(handle);
    36             }
    37         }
    38 
    39         static Cursor InternalCreateCursor(System.Drawing.Bitmap bitmap, int xHotSpot, int yHotSpot)
    40         {
    41             var iconInfo = new NativeMethods.IconInfo
    42             {
    43                 xHotspot = xHotSpot,
    44                 yHotspot = yHotSpot,
    45                 fIcon = false
    46             };
    47 
    48             NativeMethods.GetIconInfo(bitmap.GetHicon(), ref iconInfo);
    49 
    50             var cursorHandle = NativeMethods.CreateIconIndirect(ref iconInfo);
    51             return CursorInteropHelper.Create(cursorHandle);
    52         }
    53 
    54         public static Cursor CreateCursor(UIElement element, int xHotSpot = 0, int yHotSpot = 0)
    55         {
    56             element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    57             element.Arrange(new Rect(new Point(), element.DesiredSize));
    58 
    59             var renderTargetBitmap = new RenderTargetBitmap(
    60                 (int)element.DesiredSize.Width, (int)element.DesiredSize.Height,
    61                 96, 96, PixelFormats.Pbgra32);
    62 
    63             renderTargetBitmap.Render(element);
    64 
    65             var encoder = new PngBitmapEncoder();
    66             encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
    67 
    68             using (var memoryStream = new MemoryStream())
    69             {
    70                 encoder.Save(memoryStream);
    71                 using (var bitmap = new System.Drawing.Bitmap(memoryStream))
    72                 {
    73                     return InternalCreateCursor(bitmap, xHotSpot, yHotSpot);
    74                 }
    75             }
    76         }
    77     }
    View Code

    需要注意的是,由于使用的System.Drawing.BitMap,是需要引用System.Drawing.dll的

    封装之后,是可以直接传入UIElement作为自绘制的光标的,得益于WPF的强大绘图功能,是可以非常容易的绘制漂亮的光标的。测试代码如下:

        this.Cursor= CursorHelper.CreateCursor(new UserControl1());

  • 相关阅读:
    高精度计算
    c++ sort
    算法分类小结
    二叉树层序遍历
    clion windows c++环境配置 mingw
    kafka,filebeat 配置
    centos7 源码安装mysql5.7
    如何优雅的生成及遍历python嵌套字典
    Java Swing 绝对布局管理方法,null布局【图】
    python3.4+pymssql 中文乱码问题解决
  • 原文地址:https://www.cnblogs.com/TianFang/p/5186497.html
Copyright © 2011-2022 走看看