本文介绍如何操作windows系统光标。正常我们设置/隐藏光标,只能改变当前窗体或者控件范围,无法全局操作windows光标。接到一个需求,想隐藏windows全局的鼠标光标显示,下面讲下如何操作

先了解下系统鼠标光标,在鼠标属性-自定义列表中可以看到一共有13种类型,对应13种工作状态:

操作系统提供了一组预定义的光标,如箭头、手形、沙漏等,位于 C:\Windows\Cursors目录下。

对应的Windows.Input.CursorType枚举:

 1   public enum CursorType
2 {
3 None,
4 No,
5 Arrow,
6 AppStarting,
7 Cross,
8 Help,
9 IBeam,
10 SizeAll,
11 SizeNESW,
12 SizeNS,
13 SizeNWSE,
14 SizeWE,
15 UpArrow,
16 Wait,
17 Hand,
18 Pen,
19 ScrollNS,
20 ScrollWE,
21 ScrollAll,
22 ScrollN,
23 ScrollS,
24 ScrollW,
25 ScrollE,
26 ScrollNW,
27 ScrollNE,
28 ScrollSW,
29 ScrollSE,
30 ArrowCD,
31 }

光标显示逻辑:

  • 全局光标设置:在桌面或非控件区域,使用默认系统光标。
  • 窗口控件的设置:每个窗口控件可以设置自己的光标类型。当鼠标移动到该控件上时,将自动切换到该设置的光标。如果未设置则显示系统光标
  • 当鼠标移动、点击或执行其他操作时,系统会检测并相应更新光标形状。应用程序也可以改变拖放等操作的光标

对当前鼠标状态有获取需求的,可以通过GetCursorInfo获取,当前鼠标光标id以及句柄:

1     private IntPtr GetCurrentCursor()
2 {
3 CURSORINFO cursorInfo;
4 cursorInfo.cbSize = Marshal.SizeOf(typeof(CURSORINFO));
5 GetCursorInfo(out cursorInfo);
6 var cursorId = cursorInfo.hCursor;
7 var cursorHandle = CopyIcon(cursorId);
8 return cursorHandle;
9 }

那如何隐藏系统光标呢?系统光标可以通过SetSystemCursor function (winuser.h) - Win32 apps | Microsoft Learn函数设置,不过貌似没有隐藏光标的入口

可以换个思路,创建一个空白光标即可。我做了一个blank.cur:自己动手制作 windows鼠标光标文件(.cur格式)-CSDN博客

然后隐藏系统光标:

1   private void HideCursor()
2 {
3 _cursorHandle = GetCurrentCursor();
4 //替换为空白鼠标光标
5 var cursorFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Blank.cur");
6 IntPtr cursor = LoadCursorFromFile(cursorFile);
7 SetSystemCursor(cursor, OcrNormal);
8 }

恢复系统光标的显示,将之前光标Handle设置回去:

1 var success = SetSystemCursor(_cursorHandle, OcrNormal);

以上是实现了当前光标的替换。但上面有介绍过鼠标光标状态有13种,会根据应用程序状态进行切换,所以其它光标也要处理。

对13种光标都替换为空白光标:

 1     private readonly int[] _systemCursorIds = new int[] { 32512, 32513, 32514, 32515, 32516, 32642, 32643, 32644, 32645, 32646, 32648, 32649, 32650 };
2 private readonly IntPtr[] _previousCursorHandles = new IntPtr[13];
3 private void HideCursor()
4 {
5 for (int i = 0; i < _systemCursorIds.Length; i++)
6 {
7 var cursor = LoadCursor(IntPtr.Zero, _systemCursorIds[i]);
8 var cursorHandle = CopyIcon(cursor);
9 _previousCursorHandles[i] = cursorHandle;
10 //替换为空白鼠标光标
11 var cursorFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Blank.cur");
12 IntPtr blankCursor = LoadCursorFromFile(cursorFile);
13 SetSystemCursor(blankCursor, (uint)_systemCursorIds[i]);
14 }
15 }

运行验证:系统桌面、应用窗体如VisualStudio以及网页等光标编辑状态,都成功隐藏

还原光标状态:

1     private void ShowCursor()
2 {
3 for (int i = 0; i < _systemCursorIds.Length; i++)
4 {
5 SetSystemCursor(_previousCursorHandles[i], (uint)_systemCursorIds[i]);
6 }
7 }

用到的User32及参数类:

 1    [DllImport("user32.dll", SetLastError = true)]
2 public static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
3 [DllImport("user32.dll")]
4 public static extern IntPtr CopyIcon(IntPtr cusorId);
5 [DllImport("user32.dll")]
6 public static extern IntPtr LoadCursorFromFile(string lpFileName);
7 [DllImport("user32.dll")]
8 public static extern bool SetSystemCursor(IntPtr hcur, uint id);
9 [DllImport("user32.dll")]
10 static extern bool GetCursorInfo(out CURSORINFO pci);
11
12 [StructLayout(LayoutKind.Sequential)]
13 public struct POINT
14 {
15 public Int32 x;
16 public Int32 y;
17 }
18
19 [StructLayout(LayoutKind.Sequential)]
20 public struct CURSORINFO
21 {
22 public Int32 cbSize; // Specifies the size, in bytes, of the structure.
23 // The caller must set this to Marshal.SizeOf(typeof(CURSORINFO)).
24 public Int32 flags; // Specifies the cursor state. This parameter can be one of the following values:
25 // 0 The cursor is hidden.
26 // CURSOR_SHOWING The cursor is showing.
27 public IntPtr hCursor; // Handle to the cursor.
28 public POINT ptScreenPos; // A POINT structure that receives the screen coordinates of the cursor.
29 }

需要说明的是,系统光标修改请谨慎处理,光标修改后人工操作不太容易恢复,对应用程序退出、崩溃等情况做好光标恢复操作。

以上demo代码见:kybs00/HideSystemCursorDemo: 隐藏windows系统光标 (github.com)

参考资料:

AllAPI.net - Your #1 source for using API-functions in Visual Basic! (mentalis.org)

createCursor 函数 (winuser.h) - Win32 apps | Microsoft Learn

SetSystemCursor function (winuser.h) - Win32 apps | Microsoft Learn

.NET 隐藏/自定义windows系统光标的更多相关文章

  1. 内网安全之:Windows系统帐号隐藏

    Windows系统帐号隐藏 目录 Windows系统帐号隐藏 1 CMD下创建隐藏账户 2 注册表创建隐藏账户 3 利用工具隐藏账户 1 CMD下创建隐藏账户 CMD下创建隐藏账户 net user ...

  2. C# 全屏坐标及区域坐标获取。自定义光标及系统光标描边捕捉显示。

    最近手头工作比较轻松了一点就继续研究和完善之前的录屏软件,使用AForge最大的问题在于:最原始的只能够录全屏,而自定义的录屏需要更改非常多的细节:like follows: 1.需要支持区域化录屏: ...

  3. 一些 Windows 系统不常见的 鼠标光标常数

    一些 Windows  系统不常见的 鼠标光标常数 Private Declare Function SetCursor Lib "user32" (ByVal hCursor A ...

  4. 将Windows系统默认的Administrator帐号改名为我们自定义的名称

    将Windows系统默认的Administrator帐号改名为我们自定义的名称.. ---------如何将Administrator帐号改名为我们自定义的名称:Win+R--->>输入g ...

  5. windows系统定时重启自定义exe程序

    工作需要, Windows系统定时重启自定义exe程序. 写了如下程序, 按照说明(readme.txt)修改批处理文件中的四个参数即可: 1.readme.txt 第一个参数:进程名(不用带exe) ...

  6. 渗透技巧——Windows系统的帐户隐藏

    渗透技巧——Windows系统的帐户隐藏 2017-11-28-00:08:55  0x01 帐户隐藏的方法 该方法在网上已有相关资料,本节只做简单复现 测试系统:·Win7 x86/WinXP 1. ...

  7. How to use the windows active directory to authenticate user via logon form 如何自定义权限系统,使用 active directory验证用户登录

    https://www.devexpress.com/Support/Center/Question/Details/Q345615/how-to-use-the-windows-active-dir ...

  8. Linux下使用VirtualBox安装Windows系统

    (文档比较长,只是写的详细,实际操作起来相对简单.) 由于一些特殊原因,我们并不能完全抛下Windows而使用Linux.VirtualBox 是一款虚拟机软件,支持多系统.在Linux下安装 Vir ...

  9. Django框架搭建(windows系统)

    Django框架搭建(windows系统) 一.Django简介 开放源代码的Web应用框架,由Python语言编写,一个大而全的框架. 1.web框架介绍 具体介绍Django之前,必须先介绍WEB ...

  10. Windows系统常见问题

    1.Windows自动更新灰色不能修改HKEY_LOCAL_MACHINE/Software/Policies/Microsoft/WindowsWindowsUpdate的资料夹,在WindowsU ...

随机推荐

  1. 【转载】 arch linux下nvidia 驱动死机问题

    原文地址: https://my.oschina.net/u/947271/blog/288063 ================================================== ...

  2. 从数据到洞察:DataOps加速AI模型开发的秘密实践大公开!

    作者 | 代立冬,白鲸开源科技联合创始人&CTO 引言 在AI驱动的商业世界中,DataOps作为连接数据与洞察的桥梁,正迅速成为企业数据战略的核心. 在WOT全球技术创新大会2024·北京站 ...

  3. stm32中NVIC如何配置?

    1.NVIC优先级分组 2.初始化NVIC // NVIC优先级分组 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // NVIC初始化 NVIC_I ...

  4. games101 作业1及作业2分析及解决 详解透视矩阵

    games101 作业1及作业2分析及解决 去年的时候把games101的课程以及作业完成,但是整个过程比较粗略,也借助了不少外界的力量(doge),于是最近准备抽几天集中再把作业(1-7)过一遍,常 ...

  5. PCSR:已开源,三星提出像素级路由的超分辨率方法 | ECCV 2024

    基于像素级分类器的单图像超分辨率方法(PCSR)是一种针对大图像高效超分辨率的新方法,在像素级别分配计算资源,处理不同的恢复难度,并通过更精细的粒度减少冗余计算.它还在推断过程中提供可调节性,平衡性能 ...

  6. Android 获取当前获取焦点的组件

    在Activity中,使用this.getCurrentFocus(),获取当前焦点所在的View, 再判断是否是EditText(可调整成其他组件),看个人需要再做特定的逻辑处理 String co ...

  7. 【YashanDB知识库】yasdb jdbc驱动集成BeetISQL中间件,业务(java)报autoAssignKey failure异常

    问题现象 BeetISQL中间件版本:2.13.8.RELEASE 客户在调用BeetISQL提供的api向yashandb的表中执行batch insert并将返回sequence设置到传入的jav ...

  8. 防御DDOS攻击

    如何防御DDOS攻击 1.采用高性能的网络设备 首先要保证网络设备不能成为瓶颈,因此选择路由器.交换机.硬件防火墙等设备的时候要尽量选用知名度高.口碑好的产品.再就是假如和网络提供商有特殊关系或协议的 ...

  9. React函数式组件避免无用渲染的方案

    在class组件中可以使用shouldComponentUpdate钩子函数,但是函数式组件中是没有这种钩子函数的,那么在函数式组件中来达到类似的效果呢? 答案是:React.Memo,如以下使用案例 ...

  10. wxpython开发gui界面基础

    wxpython 开发gui 基础知识 一 .前言 记录使用wxpython开发gui工具吧.gui界面主要就是先布局,每个模块都是一个对象. 二.基础知识 import wx class MyFra ...