Как перехватить Win + Tab с помощью LowLevelKeyboardHook

В двух словах: блокировка Win up после Win + Tab заставляет Windows думать, что Win по-прежнему не работает, поэтому, например, нажатие S с клавишей Win вверх откроет окно поиска, а не просто наберет "s"... пока пользователь не нажмет Выиграй снова. Не блокировка означает, что появится меню "Пуск" Windows. Я в загадке!


У меня нет проблем с подключением ярлыков с помощью Alt + Tab с помощью LowLevelKeyboardHook или Win + Some Ubounded Key, используя RegisterHotKey, Проблема возникает только при использовании ключа Win LowLevelKeyboardHook,

В приведенном ниже примере я принимаю событие Win up при обнаружении комбинации Win + Tab. Это приводит к тому, что каждое последующее нажатие клавиши ведет себя так, как будто клавиша Win все еще нажата.

        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode != HC_ACTION)
                return CallNextHookEx(_hookID, nCode, wParam, lParam);

            var keyInfo = (Kbdllhookstruct)Marshal.PtrToStructure(lParam, typeof(Kbdllhookstruct));

            if (keyInfo.VkCode == VK_LWIN)
            {
                if (wParam == (IntPtr)WM_KEYDOWN) {
                    _isWinDown = true;
                } else {
                    _isWinDown = false;

                    if (_isWinTabDetected) {
                        _isWinTabDetected = false;
                        return (IntPtr)1;
                    }
                }
            }
            else if (keyInfo.VkCode == VK_TAB && _isWinDown) {
                _isWinTabDetected = true;

                if (wParam == (IntPtr)WM_KEYDOWN) {
                    return (IntPtr)1;
                } else {
                    _isWinTabDetected = true;
                    Console.WriteLine("WIN + TAB Pressed");
                    return (IntPtr)1;
                }
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    }
}

Вы можете найти полный код здесь (обратите внимание, что он должен заменить ваш Program.cs в пустом проекте WinForms для запуска): https://gist.github.com/christianrondeau/bdd03a3dc32a7a718d62 - нажмите Win + Tab и Form название должно обновляться при каждом нажатии ярлыка.

Обратите внимание, что целью подключения этой конкретной комбинации является предоставление альтернативы Alt + Tab без замены самой Alt + Tab. Также будет принят ответ, предоставляющий возможность запуска пользовательского кода с помощью Win + Tab.

Вот мои идеи, по которым я не смог найти документацию. Все потенциально могли бы успешно ответить на мой вопрос.

  • Скажите Windows, чтобы "отменить" Win Up без фактического запуска
  • Запретить запуск Windows меню "Пуск" один раз
  • Перехватывать непосредственно в Windows + событие Win +, а не вручную вводить нажатия клавиш (это был бы мой первый выбор, если таковой существует)

2 ответа

Решение

Похоже, это делает именно то, что вы хотите (опустите RWin, если хотите).

Будьте внимательны и отмените регистрацию этой ловушки KB, когда ваше приложение теряет фокус!

    [DllImport("user32.dll")]
    static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode == HC_ACTION)
        {
            var keyInfo = (Kbdllhookstruct) Marshal.PtrToStructure(lParam, typeof (Kbdllhookstruct));
            if ((int) wParam == WM_KEYDOWN
                && keyInfo.VkCode == VK_TAB
                && (GetAsyncKeyState(Keys.LWin) < 0 || GetAsyncKeyState(Keys.RWin) < 0))
            {
                _mainForm.Text = "Win + Tab was pressed " + (++_winTabPressCounter) + " times";
                return (IntPtr) 1;
            }
        }

        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

Я попробовал несколько вещей, прежде чем открыть эту технику. Этот пост был самым полезным /questions/30874959/perenaznachit-pereopredelit-goryachuyu-klavishu-win-l-dlya-blokirovki-okon/30874963#30874963

Система должна знать, что вы отпускаете ключ Windows. Я проверяю разницу между моим собственным хуком, у которого нет этой проблемы, и единственной разницей между вами и моей является эта строка:

if (_isWinTabDetected) {
    _isWinTabDetected = false;
     return (IntPtr)1; //THIS LINE 
}
Другие вопросы по тегам