Окно не получает фокус даже при перемещении вверх

Я работаю над программой, которая использует низкоуровневые перехватчики клавиатуры (LowLevelKeyboardProc) для обнаружения комбинаций клавиш и переключения фокуса между окнами определенных процессов. Цель состоит в том, чтобы программа переместила фокус на следующее или предыдущее окно набора программ при обнаружении Shift + E или Shift + Q.

Однако, когда текущее окно не является окном моей программы, функция SetForegroundWindow не работает, поэтому мне приходится использовать AttachThreadInput, чтобы вывести окно наверх. Проблема в том, что окно не получает фокуса, поэтому, когда я отправляю команды с клавиатуры, они все равно переходят к предыдущему окну.

Как включить фокус для окна, которое находится сверху?

Вот фрагмент функции, которую я использую:

    let target_window =
        self.get_window_by_name(process_id, "Window Name".to_string());

    if let Some(target_window) = target_window {
        unsafe {
            if current_process_id.is_none() {
                ShowWindow(target_window.0, SW_NORMAL);
                SetForegroundWindow(target_window.0);
                SetActiveWindow(target_window.0);
            } else {
                let foreground_window = GetForegroundWindow();
                let foreground_thread_id =
                    GetWindowThreadProcessId(foreground_window, std::ptr::null_mut());
                let target_thread_id =
                    GetWindowThreadProcessId(target_window.0, std::ptr::null_mut());

                AttachThreadInput(foreground_thread_id, target_thread_id, TRUE);

                BringWindowToTop(target_window.0);
                ShowWindow(target_window.0, SW_NORMAL);
                // SetForegroundWindow(target_window.0);
                // SetFocus(target_window.0);
                SetActiveWindow(target_window.0);

                AttachThreadInput(foreground_thread_id, target_thread_id, FALSE);
            }
        }
    }

Наблюдение:

Когда current_process_id имеет значение None, это означает, что текущий процесс — моя программа, поэтому я выполняю только SetForegroundWindow, и все работает. Когда это «Некоторые», это означает, что я нахожусь в одном из окон, между которыми хочу перейти, и оно работает неправильно.

Это не проблема фокуса. Вам не удалось установить окно переднего плана. Разрешение на активацию переднего плана похоже на любовь: его нельзя украсть, его нужно дать вам , а хак AttachThreadInput перестал работать много лет назад. Теперь реальный вопрос: почему бы вам не вызвать RegisterHotKey вместо дорогостоящего и сложного низкоуровневого хука? Я не удивлюсь, если это также предоставит вам разрешение на активацию на переднем плане.

IInspectable 26.07.2024 10:48

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

rick 26.07.2024 17:15

Почему это сложно и дорого? Я думал, что это самый легкий вариант.

rick 26.07.2024 17:16

«Почему это сложно и дорого?» — Перехватчик низкого уровня — один из немногих способов, влияющих на глобальную отзывчивость системы. Вся цепочка установленных хуков обязательно должна вызываться последовательно для поддержки отклонения ввода. Каждый вызов функции-перехватчика влечет за собой дорогостоящее переключение контекста (перехват низкого уровня вызывается в потоке, который его установил). Это быстро складывается для каждого ввода с клавиатуры. Гораздо менее навязчивый способ контролировать ввод с клавиатуры — это Необработанный ввод.

IInspectable 26.07.2024 17:44
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как было предложено @IInspectable в комментариях, переключение с LowLevelKeyboardProc на RegisterHotKey позволило вызвать SetForegroundWindow, чтобы вывести окна на передний план и сфокусировать их для приема ввода с клавиатуры.

Благодаря этому изменению также отпала необходимость использовать AttachThreadInput.

Вот краткий фрагмент обновленного кода:

hotkey.rs

//call in main trehad 
pub struct HotkeyEvent {}

impl HotkeyEvent {
    pub fn register() -> Result<(), ()> {
        unsafe {
            if RegisterHotKey(null_mut(), HOTKEY_ID_Q, MOD_SHIFT as u32, 0x51 as u32) == 0 {
                eprintln!("Failed to register hotkey SHIFT + Q");
                return Err(());
            }
            if RegisterHotKey(null_mut(), HOTKEY_ID_E, MOD_SHIFT as u32, 0x45 as u32) == 0 {
                eprintln!("Failed to register hotkey SHIFT + E");
                return Err(());
            }

            Ok(())
        }
    }

    pub fn start_loop_message() {
        unsafe {
            let mut msg: MSG = std::mem::zeroed();

            while GetMessageW(&mut msg, null_mut(), 0, 0) > 0 {
                if msg.message == WM_HOTKEY {
                // Here, I perform the logic to obtain the ID of the next window 
                //  and call the set_window_foreground function.
                    process_message_hotkey(msg.wParam as u32) 
                }
                TranslateMessage(&msg);
                DispatchMessageW(&msg);
            }
        }
    }
}

pub fn set_window_foreground(
    &self,
    process_id: u32,
    current_process_id: Option<u32>,
) -> Option<bool> {
    let target_window =
        self.get_window_by_name(process_id, "Window Name".to_string());

    if let Some(target_window) = target_window {
        unsafe {
            ShowWindow(target_window.0, SW_NORMAL);
            SetForegroundWindow(target_window.0);
            SetActiveWindow(target_window.0);
        }
    }
    None
}

Другие вопросы по теме

Похожие вопросы

После перемещения файла в другое место и последующего создания файла с тем же именем в исходном месте время создания неверно
Java Graphics2D.drawImage() отображает размытое изображение только в Windows с масштабированием 125% и только в версиях Java после Java 8
Кто-нибудь знает, почему моя переменная (x) изменила свое значение с 3 на 0 (1 после x++) в этой программе? Я пытаюсь создать систему регистрации, но она перезаписывает
Как я могу установить текстовое значение в соответствии с позицией
Можно ли определить функцию C++, в которой один параметр передается через регистр EAX?
Получение имени пользователя Windows в формате «Имя Фамилия», когда пользователь является частью группы
Мой чат-сервер Python не отправляет сообщения должным образом
Собственный диалог открытия файла в Windows Ruby
Пытаюсь запустить сервер Minecraft и постоянно получаю сообщение об ошибке: невозможно получить доступ к jarfile
Не могу установить Flutter в Windows