2

我有一个不是我写的程序。我没有它的来源,该程序的开发人员正在独立开发。他给了我那个程序的HWNDHINSTANCE句柄。

我使用win32api 在他的窗口上创建了一个子窗口。

我需要的第一件事是让这个子窗口在某些区域具有透明度,而在其他区域不透明(例如游戏的平视显示器(HUD)),以便用户可以在两个窗口中看到东西。

我需要的第二件事是将所有输入定向到父窗口。我的子窗口不需要输入。

我知道WS_EX_TRANSPARENT这只会让孩子像画家算法一样在最后画画。

我不能使用WS_EX_LAYERED,因为它是一个子窗口。

ps

尽管互联网上有类似的问题,但我到处寻找,但没有找到任何解决方案。

实际上,这是一款类似于 HUD 的游戏。由于多线程的复杂性以及其他许多原因,我无法直接在父窗口上绘制。

- 编辑 - - - - - - - - - - - - - -

我仍在努力。我正在尝试不同的方式与你们所有人的建议。有没有办法结合和directX功能SetWindowRgn()或功能?我认为这会奏效。目前我正在测试所有的东西作为一个子窗口和一个分层窗口。directxBitBlt()

4

3 回答 3

3

好的朋友,最后我做了一些疯狂的事情来实现它。但效率不高,比如直接使用 DirectX 进行绘图。

我反对:

  • 使用(WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW)()开启CreateWindowEx
  • 创建窗口后,(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)从窗口样式中删除,也(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_APPWINDOW)从扩展窗口样式中删除。
  • 这给了我一个没有边框的窗口,它现在也显示在任务栏中。hittest 也被传递给我窗户后面的任何东西。
  • 子类化另一个窗口的窗口过程并得到
    • WM_CLOSE, WM_DESTROY, 将WM_CLOSEorWM_DESTROY分别发送到我的窗口
    • WM_SIZE, WM_MOVE, 根据另一个窗口调整和移动我的窗口
    • WM_LBUTTONUP, WM_RBUTTONUP, WM_MBUTTONUP, 使我的窗口被带到顶部,并且仍然保持焦点在另一个窗口上,这样我的窗口就不会隐藏在另一个窗口后面
  • 使 DirectX 设备有两个通道:
    • 在第一遍中,它在白色背景上绘制黑色的所有元素,并将后缓冲数据复制到另一个表面(因此它给出了黑白的二进制图像)。
    • 在第二遍中,它正常绘制事物。
  • SetWindowRgn()创建另一个线程以通过使用该函数读取该黑白表面来保持窗口透明。

这工作得很好,唯一的问题是它不太擅长让事情变得透明。

另一个问题是对绘制的对象进行 alpha 混合。

SetLayeredWindowAttributes()但是您可以使用该功能轻松设置总 alpha(透明度) 。

感谢你们提供的所有帮助,你们告诉我的所有东西都被使用了,他们指导了我,正如你所看到的。:)

可悲的是,由于效率问题,我们决定不使用这种方法:(

但我学到了很多东西,这是一次很棒的经历。这对我来说很重要:)

谢谢你 :)

于 2012-05-30T05:24:20.117 回答
2

您可以WS_EX_LAYERED用于Windows 8 及更高版本的子窗口

要支持早期版本的窗口,只需创建一个水平分层窗口作为弹出窗口(没有镶边)并确保其位于游戏窗口上的适当位置。大多数用户不会一直移动他们正在使用的窗口,因此,虽然您需要监视父窗口的移动,并重新定位 HUD,但这不应该成为阻碍。

不获取焦点(在子窗口的情况下)或激活(在弹出窗口的情况下)更有趣,但仍然非常可行:- 操作系统实际上不会自动分配焦点或激活,到单击的窗口 - Windows WindowProc 始终通过调用或自身SetFocus的某种变体来获得焦点或激活。这里重要的是,如果您使用所有鼠标和非客户端鼠标消息而不将它们传递给 DefWindowProc,您的 HUD 将永远不会因单击而从游戏窗口窃取激活或键盘焦点。SetActiveWindowSetForegroundWindow

作为弹出窗口或另一个线程上的窗口,您可能必须手动处理您的窗口 proc 确实获得的任何鼠标消息,并将它们发布到游戏窗口。否则,响应WM_NCHITTESTwith HTTRANSPARENT(与实现的效果类似WS_EX_TRANSPARENT)可以让系统继续将鼠标消息向下传递到堆栈,直到找到目标。

于 2012-05-09T16:02:55.243 回答
1

您可以使用在父窗口中打一个洞SetWindowRgn

此外,仅仅因为它不是您的窗口并不意味着您不能使其成为分层窗口。

http://msdn.microsoft.com/en-us/library/ms997507.aspx

最后,您可以通过使用子类来控制另一个窗口 - 本质上,您将 Wndproc 替换为他们的,以处理您希望处理的消息,然后将其余部分传递给他们原来的 wndproc。

于 2012-05-09T12:43:08.873 回答