You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现Windows全桌面全局隐藏鼠标光标(不限窗口焦点)

Windows平台全局桌面鼠标光标隐藏实现方案

你之前尝试的两种方案失效的根本原因:

  • Cursor.Hide是WinForms封装的线程级API,仅对调用线程所属的窗口生效,无法跨进程作用于全局桌面
  • ShowCursor同样是线程级的显示计数接口,仅在调用线程持有前台窗口焦点时才会生效,全局场景下调用无效果

核心实现思路

使用user32.dll提供的系统级光标替换接口SetSystemCursor,触发隐藏时将系统标准光标临时替换为1x1大小的完全透明光标,该修改对所有前台应用全局生效;需要恢复时直接重置系统光标配置即可。
该方案不会修改鼠标实际坐标,完全匹配系统原生「打字时隐藏指针」的表现:光标在原位置直接隐藏,移动后在原位置重新显示,不会出现移动到边角方案带来的操作位置偏移、干扰其他软件逻辑的问题。

核心实现代码(C#)

using System;
using System.Drawing;
using System.Runtime.InteropServices;

internal static class GlobalCursorController
{
    #region Win32 常量定义
    // 系统标准光标类型ID
    private const int OCR_NORMAL = 32512;    // 常规箭头光标
    private const int OCR_IBEAM = 32513;     // 文本输入I型光标
    private const int OCR_HAND = 32649;      // 链接手型光标
    private const int OCR_WAIT = 32514;      // 等待沙漏光标
    private const int OCR_CROSS = 32515;     // 十字选择光标
    // 可根据需要补充调整大小、移动等其他光标类型ID

    private const uint SPI_SETCURSORS = 0x0057;
    private const uint SPIF_SENDCHANGE = 0x0002;
    #endregion

    #region Win32 API 声明
    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool SetSystemCursor(IntPtr hcur, uint id);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, IntPtr pvParam, uint fWinIni);

    [DllImport("user32.dll")]
    private static extern IntPtr CopyCursor(IntPtr pcur);

    [DllImport("user32.dll")]
    private static extern bool DestroyCursor(IntPtr hCursor);

    [DllImport("user32.dll")]
    private static extern bool DestroyIcon(IntPtr hIcon);

    [DllImport("user32.dll")]
    private static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);

    [DllImport("user32.dll")]
    private static extern IntPtr CreateIconIndirect(ref IconInfo icon);

    [StructLayout(LayoutKind.Sequential)]
    private struct IconInfo
    {
        public bool fIcon;
        public int xHotspot;
        public int yHotspot;
        public IntPtr hbmMask;
        public IntPtr hbmColor;
    }
    #endregion

    private static IntPtr _transparentCursor = IntPtr.Zero;

    /// <summary>
    /// 全局隐藏桌面所有光标
    /// </summary>
    public static void Hide()
    {
        // 初始化透明光标资源
        if (_transparentCursor == IntPtr.Zero)
        {
            using (Bitmap transparentBmp = new Bitmap(1, 1))
            {
                transparentBmp.SetPixel(0, 0, Color.Transparent);
                IntPtr hIcon = transparentBmp.GetHicon();
                IconInfo iconInfo = new IconInfo();
                GetIconInfo(hIcon, ref iconInfo);
                iconInfo.fIcon = false; // 标记资源为光标而非图标
                iconInfo.xHotspot = 0;
                iconInfo.yHotspot = 0;
                _transparentCursor = CreateIconIndirect(ref iconInfo);
                DestroyIcon(hIcon);
            }
        }

        // 将所有标准系统光标替换为透明光标
        uint[] targetCursorIds = { OCR_NORMAL, OCR_IBEAM, OCR_HAND, OCR_WAIT, OCR_CROSS };
        foreach (uint cursorId in targetCursorIds)
        {
            IntPtr cursorCopy = CopyCursor(_transparentCursor);
            SetSystemCursor(cursorCopy, cursorId);
        }
    }

    /// <summary>
    /// 恢复系统默认光标显示
    /// </summary>
    public static void Show()
    {
        // 重置系统光标为默认配置
        SystemParametersInfo(SPI_SETCURSORS, 0, IntPtr.Zero, SPIF_SENDCHANGE);

        // 释放透明光标资源
        if (_transparentCursor != IntPtr.Zero)
        {
            DestroyCursor(_transparentCursor);
            _transparentCursor = IntPtr.Zero;
        }
    }
}

使用注意事项

  • 热键触发隐藏时直接调用GlobalCursorController.Hide()即可,无需关注当前前台窗口所属进程,修改对所有应用全局生效
  • 监听全局鼠标移动事件,检测到鼠标坐标变动时调用GlobalCursorController.Show()即可实现移动自动恢复的效果
  • 必须在程序退出、全局异常捕获逻辑中加入Show()方法调用,避免程序异常退出后系统光标持续为透明状态
  • 如果需要覆盖更多光标场景(比如窗口调整大小光标、移动光标),只需要在targetCursorIds数组中补充对应光标类型ID即可

内容的提问来源于stack exchange,提问作者Ryan Griggs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 10:51:27