简体   繁体   English

在非透明父窗口 (win32) 之上创建透明子窗口

[英]Creating a Transparent Child window on top of non-transparent Parent Window (win32)

I have a program which is not written by me.我有一个不是我写的程序。 I dont have its source and the developer of that program is developing independently.我没有它的来源,该程序的开发人员正在独立开发。 He gives me the HWND and HINSTANCE handles of that program.他给了我那个程序的HWNDHINSTANCE句柄。

I have created a child window ON his window, using win32 api.我在他的窗口上创建了一个子窗口,使用win32 api。

First thing I need is to make this child window have transparency on some area and opaque on other area(like a Heads up display(HUD) for a game), so that the user may see things in both windows.我需要做的第一件事是使这个子窗口在某些区域具有透明性,而在其他区域不透明(例如游戏的平视显示器(HUD)),以便用户可以在两个窗口中看到内容。

The second thing that I need is to direct all the input to the parent window.我需要的第二件事是将所有输入定向到父窗口。 My child window needs no input.我的子窗口不需要输入。

I know that WS_EX_TRANSPARENT only makes the child draw at the end like in painters algorithm.我知道WS_EX_TRANSPARENT只会让孩子像画家算法一样在最后画画。

I cant use WS_EX_LAYERED because its a child window.我不能使用WS_EX_LAYERED因为它是一个子窗口。

ps ps

I have looked everywhere but didn't find any solution though there were similar questions around the internet.我到处找,但没有找到任何解决方案,尽管互联网上有类似的问题。

Actually this is a HUD like thing for that game.实际上,这是该游戏的 HUD 之类的东西。 I can't draw directly on parent window because of the complexity with multi-threads any many other reasons.由于多线程的复杂性以及其他许多原因,我无法直接在父窗口上绘制。

-- EDIT --------------------------- - 编辑 - - - - - - - - - - - - - -

I am still working on it.我还在努力。 I am trying different ways with what you all suggested.我正在尝试不同的方法来处理你们的建议。 Is there a way to combine directX and SetWindowRgn() function or directx with BitBlt() function?有没有办法将directXSetWindowRgn()函数或directxBitBlt()函数结合使用? I think that will do the trick.我认为这会奏效。 Currently I am testing all the stuff as a child window and a Layered window.目前我正在测试所有的东西作为一个子窗口和一个分层窗口。

OK friends, finally I did some crazy things to make it happen.好吧,朋友们,最后我做了一些疯狂的事情来实现它。 but its not very efficient, like using DirectX directly for drawing.但它不是很有效,比如直接使用 DirectX 进行绘图。

What I dis:我不喜欢:

  • Used (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW) and () on CreateWindowExCreateWindowEx上使用(WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW)()
  • After creating the window, removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) from window styles, and also removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_APPWINDOW) from extended window styles.创建窗口后,从窗口样式中删除(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) ,并从扩展窗口样式中删除(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_APPWINDOW)
  • This gives me a window with no borders and its also now shown in the taskbar.这给了我一个没有边框的窗口,它现在也显示在任务栏中。 also the hittest is passed to whatever that is behind my window.此外,hittest 也会传递给我窗户后面的任何东西。
  • Subclassed the window procedure of the other window and got the子类化另一个窗口的窗口过程,得到
    • WM_CLOSE , WM_DESTROY , to send the WM_CLOSE or WM_DESTROY respectively to my window WM_CLOSE , WM_DESTROY ,分别将WM_CLOSEWM_DESTROY发送到我的窗口
    • WM_SIZE , WM_MOVE , to resize and move my window according to the other window WM_SIZEWM_MOVE ,根据另一个窗口调整和移动我的窗口
    • WM_LBUTTONUP , WM_RBUTTONUP , WM_MBUTTONUP , to make my window brought to the top, and still keep focus on the other window, so that my window doesn't get hidden behind the other window WM_LBUTTONUP , WM_RBUTTONUP , WM_MBUTTONUP ,使我的窗口被带到顶部,并且仍然保持对另一个窗口的关注,这样我的窗口就不会被隐藏在另一个窗口后面
  • Made the DirectX device have two passes:使 DirectX 设备有两个 pass:
    • In the first pass it draws all the elements in black on top of a white background and copy the backbuffer data to an another surface (so it give a binary image of black & white).在第一遍中,它在白色背景上以黑色绘制所有元素,并将后台缓冲区数据复制到另一个表面(因此它给出了黑白的二进制图像)。
    • In the second pass it draws the things normally.在第二遍中,它正常绘制事物。
  • Another thread is created to keep making the window transparency by reading that black & white surface, using the SetWindowRgn() function.创建另一个线程,通过使用SetWindowRgn()函数读取黑白表面来保持窗口透明度。

This is working perfectly, the only thing is it's not very good at making things transparent.这工作得很好,唯一的问题是它不太擅长使事情透明。

And the other issue is giving alpha blending to the drawn objects.另一个问题是为绘制的对象提供 alpha 混合。

But you can easily set the total alpha (transparency) using the SetLayeredWindowAttributes() function.但是您可以使用SetLayeredWindowAttributes()函数轻松设置总 alpha(透明度)。

Thanks for all the help you guys gave, all the things you guys told me was used and they guided me, as you can see.感谢你们提供的所有帮助,你们告诉我的所有东西都被使用了,他们指导了我,正如你们所看到的。 :) :)

The sad thing is we decided not to use this method because of efficiency problems :(可悲的是,由于效率问题,我们决定不使用这种方法:(

But I learned a lot of things, and it was an awesome experience.但是我学到了很多东西,这是一次很棒的经历。 And that's all that matters to me :)这就是对我来说最重要的:)

Thank You :)谢谢 :)

You can use WS_EX_LAYERED for child windows from Windows 8 and up.您可以将WS_EX_LAYERED用于 Windows 8 及更高WS_EX_LAYERED子窗口

To support earlier versions of windows, just create a level layered window as a popup (With no chrome) and ensure its positioned over the game window at the appropriate location.要支持早期版本的窗口,只需创建一个水平分层窗口作为弹出窗口(无镶边)并确保其位于游戏窗口的适当位置。 Most users don't move the windows they are working with all the time, so, while you will need to monitor for the parent window moving, and re position the HUD, this should not be a show stopper.大多数用户不会一直移动他们正在使用的窗口,因此,虽然您需要监视父窗口的移动,并重新定位 HUD,但这不应该是一个障碍。

Not taking focus (in the case of being a child window) or activation (in the case of being a popup) is more interesting, but still quite do-able:- The operating system does not actually automatically assign either focus, or activation, to a clicked window - the Windows WindowProc always takes focus, or activation, by calling SetFocus , or some variant of SetActiveWindow or SetForegroundWindow on itself.不获取焦点(在子窗口的情况下)或激活(在弹出窗口的情况下)更有趣,但仍然非常可行:-操作系统实际上不会自动分配焦点或激活,到单击的窗口 - Windows WindowProc 始终通过调用SetFocusSetActiveWindowSetForegroundWindow某些变体来获得焦点或激活。 The important thing here is, if you consume all mouse and non client mouse messages without passing them on to DefWindowProc, your HUD will never steal activation or keyboard focus from the Game window as a result of a click.这里重要的是,如果您使用所有鼠标和非客户端鼠标消息而不将它们传递给 DefWindowProc,您的 HUD 将永远不会因为点击而从游戏窗口窃取激活或键盘焦点。

As a popup window, or a window on another thread, you might have to manually handle any mouse messages that your window proc does get, and post them to the game window.作为弹出窗口或另一个线程上的窗口,您可能必须手动处理您的窗口 proc 获取的任何鼠标消息,并将它们发布到游戏窗口。 Otherwise, responding to WM_NCHITTEST with HTTRANSPARENT (a similar effect to that which WS_EX_TRANSPARENT achieves) can get the system to keep on passing the mouse message down the stack until it finds a target.否则,使用HTTRANSPARENT响应WM_NCHITTEST (与WS_EX_TRANSPARENT实现的效果类似)可以让系统继续将鼠标消息向下传递到堆栈,直到找到目标。

You can make a hole in the parent window using SetWindowRgn .您可以使用SetWindowRgn在父窗口中打一个洞。

Also, just because it is not your window doesn't mean you can't make it a layered window.此外,仅仅因为它不是您的窗口并不意味着您不能将其设置为分层窗口。

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

Finally, you can take control of another window by using subclassing - essentially you substitute your Wndproc in place of theirs, to handle the messages you wish to handle, then pass the remainder to their original wndproc.最后,您可以通过使用子类化来控制另一个窗口 - 本质上,您可以用 Wndproc 代替它们的 Wndproc,以处理您希望处理的消息,然后将其余部分传递给它们的原始 wndproc。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM