You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何仅在目标游戏窗口处于顶层时渲染透明点击穿透覆盖层?

如何仅在目标游戏窗口处于顶层时渲染透明点击穿透覆盖层?

我之前做游戏悬浮层时也踩过一模一样的坑——子窗口模式虽然能自动跟着游戏状态走,但直接废掉了点击穿透;独立窗口又会在切窗口后还尬在那儿。给你几个亲测有效的解决办法:

核心思路:保持独立窗口+监听窗口激活状态

不把悬浮层设为游戏的子窗口,用独立窗口保留WS_EX_TRANSPARENT的点击穿透能力,同时通过系统事件监听来控制悬浮层的显示/渲染时机。

1. 用窗口事件钩子监听前台窗口切换

这比定时轮询效率高多了,能实时感知哪个窗口拿到焦点:

  • 调用SetWinEventHook注册EVENT_SYSTEM_FOREGROUND事件的钩子,回调函数里能拿到当前前台窗口的HWND。
  • 在回调里对比这个HWND是不是你的目标游戏窗口:
    • 如果是,就显示悬浮层(ShowWindow(hOverlay, SW_SHOW)),并且同步游戏窗口的位置和大小到悬浮层(用GetWindowRect拿游戏窗口的RECT,再SetWindowPos设置悬浮层的位置大小)。
    • 如果不是,就隐藏悬浮层(ShowWindow(hOverlay, SW_HIDE))或者暂停渲染逻辑,避免无效绘制。

2. 确保悬浮层的窗口样式配置正确

要同时满足透明、点击穿透、不抢焦点这几个要求,窗口的扩展样式得配全:

DWORD exStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE;
SetWindowLongPtr(hOverlay, GWL_EXSTYLE, exStyle);
  • WS_EX_LAYERED:支持分层透明,配合SetLayeredWindowAttributes还能调整透明度。
  • WS_EX_TRANSPARENT:让窗口忽略鼠标点击,直接穿透到下层窗口。
  • WS_EX_NOACTIVATE:悬浮层永远不会成为前台窗口,避免切窗口时抢占焦点。

3. 同步游戏窗口的位置和大小变化

光监听焦点切换还不够,游戏窗口移动、拉伸时悬浮层也得跟着动:

  • 可以再注册EVENT_OBJECT_LOCATIONCHANGE事件钩子,当游戏窗口的位置或大小改变时,自动同步悬浮层的参数。
  • 或者在焦点切换的回调里,每次显示悬浮层时都做一次位置大小同步,简单粗暴但有效。

4. 处理游戏窗口最小化的情况

之前你说最小化时停止渲染是完美的,这个可以在监听里加上:用IsIconic判断游戏窗口状态,如果是最小化状态,直接隐藏悬浮层就行。

额外小技巧

  • 在悬浮层的窗口过程里,处理WM_NCHITTEST消息返回HTTRANSPARENT,双重保险确保点击穿透:
case WM_NCHITTEST:
    return HTTRANSPARENT;
  • 不要让悬浮层接收任何键盘或鼠标消息,避免干扰游戏的输入。

这样一套下来,悬浮层既能保持点击穿透的能力,又能精准地只在游戏窗口处于顶层时显示/渲染,完美解决你的矛盾点~

火山引擎 最新活动