C # Обнаружение, скрыт ли курсор - PullRequest
4 голосов
/ 01 ноября 2019

Да, я понимаю, что было много таких вопросов, но ни один из них не помог мне. Мне нужно проверить, скрыт ли системный курсор.

Я пробовал 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;
}

Моя цель - скрыть интерфейс наложения экрана, когда курсор скрывается.

Итак, как я могу проверить, скрыт ли системный курсор каким-либо другим способом?

Редактировать:

Хорошо, я сделал открытие с помощью Ахмеда Абдельхамида. По сути, браузеры и т.п. не отображают курсор, но система все еще считает его видимым. Однако ручка изменилась. По умолчанию система предлагает ограниченное количество дескрипторов (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работал большую часть времени). Это касается большинства браузеров.

Честно говоря, я не думаю, что мы можем сделать гораздо больше в плане обнаружения скрытого курсора. В редком случае, когда курсор не скрыт, но мое приложение думает, что это так или наоборот, я решил просто иметь возможность позволить пользователю нажимать кнопку в настройках, которые по истечении заданного времени добавляют текущий дескриптор курсора кисключения.

1 Ответ

0 голосов
/ 02 ноября 2019

Нет только одного способа определить, скрыт ли курсор. Иногда системе будет сказано не отображать ее, иногда само программное обеспечение не будет отображать ее, а иногда оно будет отображаться как нечто, не являющееся курсором (например, набросок кисти для цифрового искусства).

В наиболее распространенном случае, когда сама система не отображает курсор, все, что вам нужно сделать, это проверить, установлен ли флаг курсора в 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;
}

Теперь мы почти закончили, но не забывайте, что будут исключения. Например, 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. Это маловероятно, но если вы хотите быть более безопасным, список исключений должен представлять собой список наборов приложений и дескрипторов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...