C#检测光标是否隐藏

标签 c# windows

是的,我确实知道有很多这样的问题,但没有一个对我有用。 我需要检查系统光标是否被隐藏。

我试过了Cursor.Current == null .它什么也没做,从来没有。 (我用全屏 Youtube、Discord 和 Krita 隐藏了光标)。

我也试过使用 GetCursorInfo来自 user32.dll 并检查标志是否为 0(隐藏)。什么都没有。

[StructLayout( LayoutKind.Sequential )]
struct POINT {
    public Int32 x;
    public Int32 y;
}

[StructLayout( LayoutKind.Sequential )]
struct CURSORINFO {
    public Int32 cbSize;        

    public Int32 flags;         

    public IntPtr hCursor;
    public POINT ptScreenPos;
}

[DllImport( "user32.dll" )]
static extern bool GetCursorInfo ( out CURSORINFO pci );

public static bool CursorHidden () {
    CURSORINFO cinfo;
    cinfo.cbSize = Marshal.SizeOf( typeof( CURSORINFO ) );
    GetCursorInfo( out cinfo );
    return cinfo.flags == 0;
}

我的目标是在光标隐藏时隐藏屏幕覆盖 UI。

那么,如何检查系统光标是否以任何其他方式隐藏?

编辑:

好的,在 Ahmed Abdelhameed 的帮助下,我有了一个发现。基本上,浏览器等不会呈现光标,但它仍然被系统认为是可见的。但是,句柄已更改。系统默认提供的句柄数量有限 ( Cursors.<Name>.Handle ),不可见的浏览器光标不使用任何句柄。

enum CursorTypes { ... }
...
CURSORINFO cinfo;
... // see code above
Cursor[] cursors = new Cursor[] { ... }; // listed all of them in the same order as CursorTypes
int type = 1;
foreach ( Cursor cursor in cursors ) {
    if ( cinfo.hCursor == cursor.Handle ) {
        return (CursorTypes)type;
    }
    type++;
}
return CursorTypes.Other;

但这不是一个完整的解决方案,因为浏览器和其他软件可以创建一种新类型的光标,而不是不可见的(如 VS 中向后倾斜),它也将返回 CursorTypes.Other .

正如 Herohtar 指出的那样,隐藏游标通常具有较大的指针值(在我的例子中,Math.Abs( pointer ) > 10000000 大部分时间都有效)。这涵盖了大多数浏览器。

老实说,我认为在检测隐藏光标方面我们无能为力。在极少数情况下,光标未隐藏但我的应用程序认为它是隐藏的或相反,我决定只让用户单击设置中的按钮,在设定的时间后将当前光标句柄添加到异常(exception)情况。

最佳答案

检测光标是否隐藏的方法不止一种。有时,系统会被告知不要渲染它,有时软件本身不会渲染它,有时它会将其渲染为不是光标的东西(例如数字艺术画笔轮廓)。

在最常见的情况下,当系统本身不呈现光标时,您所要做的就是检查光标标志是否为 0(隐藏)。 (或者走捷径检查 Cursor.Current == null )

[StructLayout( LayoutKind.Sequential )]
struct POINT {
    public Int32 x;
    public Int32 y;
}

[StructLayout( LayoutKind.Sequential )]
struct CURSORINFO {
    public Int32 cbSize;        

    public Int32 flags;         

    public IntPtr hCursor;
    public POINT ptScreenPos;
}

[DllImport( "user32.dll" )]
static extern bool GetCursorInfo ( out CURSORINFO pci );

CURSORINFO GetCinfo () {
    CURSORINFO cinfo;
    cinfo.cbSize = Marshal.SizeOf( typeof( CURSORINFO ) );
    GetCursorInfo( out cinfo );
    return cinfo;
}
public bool FlagHidden () {
    CURSORINFO cinfo = GetCinfo();
    return cingo.flags == 0 || Cursor.Current == null; // using both for extra safety
}

现在我们遇到了网络浏览器。浏览器不会呈现隐藏的光标,但会更改光标句柄。大多数时候,但不一定总是句柄的值会很大。

public bool BrowserHidden () {
    CURSORINFO cinfo = GetCinfo();
    return Math.Abs( cinfo.hCursor.ToInt64() ) > 10000000;
}

现在,我们几乎完成了,但不要忘记会有异常(exception)。例如,Krita 在隐藏光标的同时渲染出画笔的轮廓,但就系统而言,光标仍然可见。没有一种简单、通用的方法来处理这个问题,所以我们几乎必须明确告诉我们的软件注意这些特殊情况。

List<IntPtr> exceptions = new List<IntPtr>{ ... }; // put all the common exceptions here, implement some way to add / remove them
public bool IsException () {
    CURSORINFO cinfo = GetCinfo();
    return exceptions.Contains( cinfo.hCursor );
}

public bool CursorHidden () {
    bool hidden = FlagHidden() || BrowserHidden();
    return hidden != IsException(); // hidden xor exception ( inverts hidden if its an exception )
}

可能有这样一种情况,指针 X 可能意味着 A 指向软件 B,但 C 指向软件 D。这不太可能,但如果你想更加安全,异常(exception)列表应该是应用程序和句柄的列表.

关于C#检测光标是否隐藏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58652184/

相关文章:

c# - RSA 创建时间,为什么在 16384bit 之后就下降了?

c# - 通过 MVVM 客户端查看和操作 MVC Web 应用程序的模型

c# - 我可以使用 System.Linq.Expressions 动态生成异步方法吗?

c# - 如何在 C# 中对泛型数字求和?

php - 使用 php 获取窗口标题在浏览器调用中不起作用

c# - 如何检测动态绘制图形的点击?

windows - 使用 PowerShell 创建 Windows 计划任务时停止现有实例选项

windows - 使用 Unix 换行符将行回显到 Windows 上的文件

java - 将 JDK 添加到 netbeans 8.1

windows - 文件移动计划任务未运行bat文件