Win32 API - 如何使用分层透明 window WNDPROC 或挂钩访问鼠标事件?
Win32 API - how to access mouse events with layered transparent window WNDPROC or hook?
我有一个 window 作为覆盖层,只有一部分不透明。 window 已扩展样式
WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED
透明度设置为:
SetLayeredWindowAttributes(hwnd, RGB(255, 255, 255), 0, LWA_COLORKEY);
我确实想读取鼠标事件来实现覆盖的交互部分。
到目前为止,我尝试捕捉像
这样的消息
WM_MOUSEMOVE,
WM_KEYDOWN,
WM_NCLBUTTONDOWN,
在我的 WNDPROC 中,它们没有开火。我认为这是由于某些 window 扩展样式造成的,通过一次删除一个样式,我发现它是由分层 window 属性引起的。遗憾的是,我的应用程序的透明度确实依赖于此属性。
然后我尝试为那个进程和线程注册一个 windows 挂钩来拦截鼠标事件。我根本不知道钩子的内部结构——但我认为它们在消息进入应用程序队列之前就可以访问它们,因此我希望我能在任何干扰传递它们之前阅读它们。可悲的是,这没有用。
我这样注册了钩子:
app_state.hhook = SetWindowsHookExW(WH_MOUSE,
Some(Self::HOOKPROC),
GetModuleHandleW(null_mut()),
GetCurrentThreadId();
而实际的 HOOKPROC 是这样定义的:
pub unsafe extern "system" fn HOOKPROC(ncode: c_int, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
println!("fired!");
CallNextHookEx(null_mut(), ncode, wparam, lparam)
}
遗憾的是,这没有向 STDOUT 输出任何内容,但我确实认为挂钩被注册为 unhook 函数没有 return 0.
我的下一个想法是将钩子放在管理前一个 window 的进程中。但是以下不起作用。
app_state.hhook = SetWindowsHookExW(WH_MOUSE,
Some(Self::HOOKPROC),
GetModuleHandleW(null_mut()),
GetWindowThreadProcessId(
GetWindow(hwnd, GW_HWNDPREV), null_mut())
);
我认为这是因为我需要将挂钩放在一个单独的 dll 中,但如果它确实有效的话,这个解决方案似乎很脏,并且可能在极少数情况下不需要提升权限就可以工作.我可以做些什么来通过公认的和有凝聚力的代码实现所需的目标?
只需摆脱 WS_EX_TRANSPARENT
样式并单独使用 WS_EX_LAYERED
,让 OS 正常处理鼠标输入(不需要挂钩)。完全透明的像素将按预期 fall-through,并且 window 将在 non-transparent 像素上接收输入消息。
我有一个 window 作为覆盖层,只有一部分不透明。 window 已扩展样式
WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED
透明度设置为:
SetLayeredWindowAttributes(hwnd, RGB(255, 255, 255), 0, LWA_COLORKEY);
我确实想读取鼠标事件来实现覆盖的交互部分。
到目前为止,我尝试捕捉像
这样的消息WM_MOUSEMOVE,
WM_KEYDOWN,
WM_NCLBUTTONDOWN,
在我的 WNDPROC 中,它们没有开火。我认为这是由于某些 window 扩展样式造成的,通过一次删除一个样式,我发现它是由分层 window 属性引起的。遗憾的是,我的应用程序的透明度确实依赖于此属性。
然后我尝试为那个进程和线程注册一个 windows 挂钩来拦截鼠标事件。我根本不知道钩子的内部结构——但我认为它们在消息进入应用程序队列之前就可以访问它们,因此我希望我能在任何干扰传递它们之前阅读它们。可悲的是,这没有用。 我这样注册了钩子:
app_state.hhook = SetWindowsHookExW(WH_MOUSE,
Some(Self::HOOKPROC),
GetModuleHandleW(null_mut()),
GetCurrentThreadId();
而实际的 HOOKPROC 是这样定义的:
pub unsafe extern "system" fn HOOKPROC(ncode: c_int, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
println!("fired!");
CallNextHookEx(null_mut(), ncode, wparam, lparam)
}
遗憾的是,这没有向 STDOUT 输出任何内容,但我确实认为挂钩被注册为 unhook 函数没有 return 0.
我的下一个想法是将钩子放在管理前一个 window 的进程中。但是以下不起作用。
app_state.hhook = SetWindowsHookExW(WH_MOUSE,
Some(Self::HOOKPROC),
GetModuleHandleW(null_mut()),
GetWindowThreadProcessId(
GetWindow(hwnd, GW_HWNDPREV), null_mut())
);
我认为这是因为我需要将挂钩放在一个单独的 dll 中,但如果它确实有效的话,这个解决方案似乎很脏,并且可能在极少数情况下不需要提升权限就可以工作.我可以做些什么来通过公认的和有凝聚力的代码实现所需的目标?
只需摆脱 WS_EX_TRANSPARENT
样式并单独使用 WS_EX_LAYERED
,让 OS 正常处理鼠标输入(不需要挂钩)。完全透明的像素将按预期 fall-through,并且 window 将在 non-transparent 像素上接收输入消息。