首页 > 解决方案 > 如何在 Rust 中使用 SetWindowsHookEx?

问题描述

我试图弄清楚如何在 Rust 中设置全局 Windows 挂钩。我可以找到其他语言的多个示例,但 Rust 似乎没有任何示例。

到目前为止我设法做到的:

extern crate user32;
extern crate winapi;

const WH_KEYBOARD_LL: i32 = 13;
fn main() {
    let hook_id = user32::SetWindowsHookExA(
        WH_KEYBOARD_LL,
        Some(hook_callback),
        // No idea what goes here ,
        0,
    );
}

fn hook_callback(code: i32, wParam: u64, lParam: i64) -> i64 {
    // ...
}

编译器抱怨它需要一个fn回调函数的“系统”,但得到一个 Rust fn,这是有道理的,但我仍然不知道如何使它工作。

根据我从文档中收集到的信息,第三个参数hMod 应该指向具有回调函数的同一个模块,而其他语言的示例使用了一些获取当前模块句柄的函数,但我不知道如何在锈。

标签: windowswinapicallbackrusthook

解决方案


编译器抱怨它需要一个fn回调函数的“系统”,但得到一个 Rust fn,这是有道理的,但我仍然不知道如何使它工作。

编译器实际上为您提供您所需要的……如果您继续阅读错误,您将看到:

expected type `unsafe extern "system" fn(i32, u64, i64) -> i64`
   found type `fn(i32, u64, i64) -> i64 {hook_callback}`

添加它,给出:

extern "system" fn hook_callback(code: i32, wParam: u64, lParam: i64) -> i64 {
    0
}

根据我从文档中收集到的信息,第三个参数hMod应该指向具有回调函数的同一个模块,而其他语言的示例使用了一些获取当前模块句柄的函数,但我不知道如何在锈。

同样,进一步阅读 WinAPI 文档表明,NULL如果线程 ID(最后一个参数)指定它在同一进程中,则应该是此参数的值。由于您已通过零 - 文档状态与当前进程中的所有线程相关联......这就是它应该是NULL...... 所以现在我们得到:

let hook_id =
    user32::SetWindowsHookExA(WH_KEYBOARD_LL, Some(hook_callback), std::ptr::null_mut(), 0);

这编译。

考虑到你会得到的其他错误unsafe......这给了你(完整的工作代码):

extern crate user32;
extern crate winapi;

const WH_KEYBOARD_LL: i32 = 13;

fn main() {
    unsafe {
        let hook_id =
            user32::SetWindowsHookExA(WH_KEYBOARD_LL, Some(hook_callback), std::ptr::null_mut(), 0);

        // Don't forget to release the hook eventually
        user32::UnhookWindowsHookEx(hook_id);
    }
}

extern "system" fn hook_callback(code: i32, wParam: u64, lParam: i64) -> i64 {
    0
}

推荐阅读