Почему GetClassName и RealGetWindowClass возвращают одно и то же значение? - PullRequest
0 голосов
/ 07 марта 2020

Цель

Я разработал клавиатуру в Unity3D (C#) и хочу, чтобы она всплывала, когда пользователи нажимают на элемент управления типа «РЕДАКТИРОВАТЬ», такой как адресная строка или поле ввода. Поэтому мне нужно определить, когда нажимается элемент управления «EDIT».

Что я пробовал

В настоящее время я использую SetWinEventHook и слушаю на событие EVENT_OBJECT_FOCUS , чтобы получить дескриптор объекта, который получает фокус. После этого я использую GetClassName , чтобы увидеть, является ли сфокусированный объект элементом управления «РЕДАКТИРОВАТЬ», который отображает мигающую каретку при нажатии. Тем не менее, возьмем Google Chrome в качестве примера, я всегда получаю Chrome_WidgetWin_1 , нажимаю ли я на адресную строку или обычный текст страницы. После некоторого поиска в Google я нашел это сообщение в блоге Что делает RealGetWindowClass намного более реальным, чем GetClassName? , говоря, что RealGetWindowClass может получить базовый класс, который, я думаю, будет чем-то вроде "EDIT" или «COMBOBOX» в списке здесь . Дела шли не так хорошо. Я попытался использовать RealGetWindowClass и все еще получить тот же результат Chrome_WidgetWin_1 .

Проблема

Почему возвращаются GetClassName и RealGetWindowClass такое же значение? Как заставить RealGetWindowClass возвращать базовый класс?

Код

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, WinEventProc lpfnWinEventProc, int idProcess, int idThread, int dwflags);
[DllImport("user32.dll", SetLastError = true)]
private static extern int UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RealGetWindowClass(IntPtr hwnd, [Out] StringBuilder pszType, uint cchType);

private delegate void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
private const int WINEVENT_SKIPOWNPROCESS = 2;
private IntPtr windowEventHook;
private const int EVENT_OBJECT_FOCUS = 0x8005;

private void Start()
{
    if (windowEventHook == IntPtr.Zero)
    {
        windowEventHook = SetWinEventHook(
            EVENT_OBJECT_FOCUS,
            EVENT_OBJECT_FOCUS,
            IntPtr.Zero,        
            WindowEventCallback,
            0,                  
            0,                  
            WINEVENT_SKIPOWNPROCESS);

        if (windowEventHook == IntPtr.Zero)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }
    }

}

private void OnDestroy()
{
    UnhookWinEvent(windowEventHook);
}

private void WindowEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hWnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
    UnityEngine.Debug.Log($"[EventType]: {(EventEnum)eventType} [Class Name]: {GetClassName(hWnd)} [Real Class]: {RealGetWindowClassM(hWnd)}");
    // Will print out the same log whether I click an address bar or plain text.
    // [EventType]: EVENT_OBJECT_FOCUS [Class Name]: Chrome_WidgetWin_1 [Real Class]: Chrome_WidgetWin_1
}

private string GetClassName(IntPtr hWnd)
{
    StringBuilder className = new StringBuilder(256);
    GetClassName(hWnd, className, className.Capacity);
    return className.ToString();
}

private string RealGetWindowClassM(IntPtr hWnd)
{
    StringBuilder className = new StringBuilder(256);
    RealGetWindowClass(hWnd, className, (UInt32)className.Capacity);
    return className.ToString();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...