在.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     }

测试代码为:

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     }

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

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

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

时间: 2024-12-30 01:39:55

在.net桌面程序中自定义鼠标光标的相关文章

自定义鼠标光标cursor

通过css属性 Cursor:url()自定义鼠标光标 {cursor:url('图标路径'),default;} url是自定义鼠标图标路径 default指的是定义默认的光标(通常是一个箭头),以防没有由 URL 定义的可用光标. 图标的格式根据不同的浏览器来分: IE支持cur,ani,ico这三种格式. Google,FF支持bmp,gif,jpg,cur,ico这几种格式,不 支持ani格式,也不支持gif动画格式. 在项目中,用到自定义鼠标样式遇到的问题: IE浏览器下图标地址需要为

unity中自定义鼠标样式

在用unity制作游戏过程中,运行游戏时,有没有感觉到原来的鼠标看着是不是特别不爽了?反正我是看腻了,哈哈! 下面来看看自定义鼠标样式的自作:首先你需要在unity中将图片的样式改为Cursor类型的: 然后我们来看看代码: public Texture2D cursorTexture;    //在外面为该变量赋值; void OnGUI() {      Vector2 mouse_Pos=Input.MousePosition;      GUI.DrawTexture(new Rect(

Combox程序中自定义数据源

有combox控件,命名为cbxPutStatus,在程序中为其手工定义数据源,并绑定 private void POrderSplitFrm_Load(object sender, EventArgs e) { //绑定定单状态 this.cbxPutStatus.DataSource = DataTableForPutStatus(); this.cbxPutStatus.DisplayMember = "PutStatusString"; this.cbxPutStatus.Va

MFC程序中屏蔽鼠标

屏蔽鼠标功能需要用到钩子,使用过程如下: 1.定义全局变量 HHOOK g_hMouse = NULL; 2.定义全局回调函数 LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam,LPARAM lParam) {      return 1; } 3.安装钩子 g_hMouse = SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId()); 执行此行代码后,应用程序的鼠标便被屏蔽

自定义鼠标光标,制作cur,设置热点,中心点。

..没哈好说的,,只是推荐一个软件 ArtCursor..非常好用. 关于另外一个更改光标的重要问题:鼠标的hotspot,也就是鼠标的作用点问题,本人关于这个问题纠结了很久,始终无法找到更改HCURSOR作用点的函数.后来终于在网上发现,其实在制作.cur格式的图片时就可以设置hotspot(热点).这样就解决了光标大,而作用点在光标的左上角问题!(PS 制作.cur格式的图片可以用ArtCursor这个软件很好用)

一脸懵逼学习Hadoop中的MapReduce程序中自定义分组的实现

1:首先搞好实体类对象: write 是把每个对象序列化到输出流,readFields是把输入流字节反序列化,实现WritableComparable,Java值对象的比较:一般需要重写toString(),hashCode(),equals()方法 1 package com.areapartition; 2 3 import java.io.DataInput; 4 import java.io.DataOutput; 5 import java.io.IOException; 6 7 im

web中自定义鼠标样式

position:static(静态定位) 当position属性定义为static时,可以将元素定义为静态位置,所谓静态位置就是各个元素在HTML文档流中应有的位置 podisition定位问题.所以当没有定义position属性时,并不说明该元素没有自己的位置,它会遵循默认显示为静态位置,在静态定位状态下无法通过坐标值(top,left,right,bottom)来改变它的位置. position:absolute(绝对定位) 当position属性定义为absolute时,元素会脱离文档流

java桌面程序中使用联动菜单遇到与解决的问题

最近在做一个小小的系统,想实现联动菜单,故尝试了几种方法. 1.想通过一个线程来监控下拉菜单的变化,从而控制从菜单. 遇到的问题: ①:开始,我是用一个外部线程类,不过我要通过外部线程类来改变主窗口的下拉菜单, ②:所以,就需要一个传递一个类参数才能引用, ③:我在主窗口中调用线程类. ④:由于我需要把从数据中得来的数据在线程类中使用,所以就需要在线程类中使用数据库连接 当然不是在run方法中使用,而是在最开始定义数据时就初始化赋值好. ⑤:我以为,在最开始使用数据库连接,就连一次,应该没事.

小程序中自定义组件

一般单独放在一个文件夹中 类似以线面的这种结构,(单独出来) 和一般新建的page页面不同的是  后缀名是js 文件中的page 变成了component   后缀名为json的文件中多了“component”:"true"使用的时候 需要在指定使用页面的json  文件中做配置[参考如下配置:前面的是组件的名称,后面的是组件的的路径地址] 在页面中使用: 特别注意的是我们使用组件的目的之一是减少代码量,并且使用的组件能够支撑起使用页面的数据,这也就要求组件中的数据是可以变化的 [动态