如何在 Rust 中使用 SetWindowsHookEx?

How to use SetWindowsHookEx in Rust?

我想知道如何在 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 {
    // ...
}

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

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

The compiler complains that it needs a "system" fn for the callback function, but is getting a Rust fn, which makes sense, but I still don't know how to make that work.

编译器实际上 准确地 提供了您所需要的...如果您继续阅读错误,您将看到:

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
}

From what I gathered from the documentation, the third parameter hMod should point to the same module that has the callback function, and the examples in other languages uses some function that gets the current module handle, but I don't know how to do that in Rust.

同样,进一步阅读 WinAPI 文档表明,如果线程 ID(最后一个参数)指定它在同一进程中,则 NULL 应该是该参数的值。由于您已经通过了零 - 文档说明它与当前进程中的所有线程相关联......这就是它应该是的......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
}