我正在开发一个程序,该程序使用低级键盘挂钩(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,一切正常。当它是 Some 时,这意味着我位于我想要在其之间转换的窗口之一,并且它无法正常工作。
正如评论中@IInspectable所建议的,从LowLevelKeyboardProc切换到RegisterHotKey允许调用SetForegroundWindow将窗口带到前台并聚焦它们接收键盘输入。
通过此更改,也不需要使用AttachThreadInput。
以下是更新代码的简短片段:
热键.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
}