Creating a Transparent Child window on top of non-transparent Parent Window (win32) - c++

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.
I have created a child window ON his window, using 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.
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.
I cant use WS_EX_LAYERED because its a child window.
p.s.
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. 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? I think that will do the trick. Currently I am testing all the stuff as a child window and a Layered window.

You can use WS_EX_LAYERED for child windows from Windows 8 and up.
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.
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. 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.
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. 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.

OK friends, finally I did some crazy things to make it happen. but its not very efficient, like using DirectX directly for drawing.
What I dis:
Used (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW) and () on CreateWindowEx
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.
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.
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_SIZE,WM_MOVE, to resize and move my window according to the other window
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
Made the DirectX device have two passes:
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.
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.
But you can easily set the total alpha (transparency) using the SetLayeredWindowAttributes() function.
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 make a hole in the parent window using 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
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.

Related

How to achieve Steam-like window using winapi?

This is a screenshot of Steam's client window being resized.
Steam's client window has two cool features.
Custom window which is very responsive.
Cool glass resize effect, different from standard windows (Thought it might be a side effect strongly related to 1)
Let's say I wanna create similar window using winapi. How can I do it?
I don't ask about widget-management related stuff, but about technical winapi tricks.
Basically, you can do almost anything with your window. But most of the tricks are to be implemented manually.
What is 'very responsive' I don't know. If you mean that the window has no standart border, it is easy to implement: do not specify WS_BORDER and WS_CAPTION when creating a WS_POPUP window. After that you will have to draw a border and a caption yourself. Handle WM_ERASEBKGND and WM_PAINT messages, draw background, menus, all as usual.
This effect seems to me more like a bug. It happens this way: the window is resized, it gets a WM_SIZE message, processes it, Windows sends a WM_ERASEBKGND message which the window ignores. Thus, the system draws a new shadow around new window frame which is not yet filled with new window image. And here we get this cool glass effect: old image of underlaying windows with a windows aero shadow. You can try to disable windows shadows and look at this effect.
In order to create a custom resizing border, you might find useful these functions: LoadCursor, SetCursor, MoveWindow.
In order to draw your custom borders, you can use standart GDI functions. Also you can create a handful of child windows and delegate drawing to them. This is basics of winapi.

flicker free tab control with WS_EX_COMPOSITED

I have a VS2008 C++ application for Windows XP SP3 developed using WTL 8.1. My application contains a tab control that flickers when the application border is resized.
My window hierarchy looks like this:
CFrameWindowImpl CMainFrm
|-CSplitterWindow Splitter
|-CTabView Configuration Tabs
| |-CDialogImpl Configuration View 1
| |-CDialogImpl Configuration View 2
| |-CDialogImpl Configuration View 3
|-CDialogImpl Control View
The solution I'm trying is to make the CFrameWindowImpl derived class use the WS_EX_COMPOSITED style and all windows beneath it use the WS_EX_TRANSPARENT style. Unfortunately, this makes the tab control buttons show as an empty black bar and the controls of any Configuration View to not show at all.
If I remove the WS_EX_COMPOSITED and WS_EX_TRANSPARENT styles, the form displays properly, but the CTabView and everything beneath it flickers horribly when resized.
What do I need to change to eliminate the flicker and draw the controls properly?
Thanks,
PaulH
Edit:
Got it working. I removed all the WS_EX_TRANSPARENT styles per Mark Ransom's suggestion. I put the WS_EX_COMPOSITED style on only the CTabCtrl (contained within the CTabView). Other controls get double-buffering as needed through WTL::CDoubleBufferImpl<>.
A window flickers because it gets erased before it's drawn. To eliminate this you need to disable erasing of the window entirely and use double buffering - draw the window contents into a bitmap, then copy the bitmap to the window. Because the bitmap contains the entire contents including the background, there's no need to erase anymore.
It looks like WS_EX_COMPOSITED will handle the double buffering automatically, but you still probably need to use a NULL background brush and/or handle the WM_ERASEBKGND message.
Whats not mentioned in MSDN is that the Desktop Window Manager - the component that hooks window painting on Windows Vista and 7 to perform the desktop composition necessary to get the aero glass effect - does NOT implement WS_EX_COMPOSITED.
Which means all the work you put into getting this style to work on XP, is doomed to become irrelevent on Vista or later.
The other problem with WS_EX_COMPOSITED - and why it was an optional style and not a default on XP: The double buffering only picks up painting performed during the BeginPaint / EndPaint block of the parent window. Lots of, even standard controls, perform painting outside of their WM_PAINT handlers, and as a result the backbuffer gets only partially painted.
Sadly, the result is, the only way to "eliminate" flicker in native API apps is to try to minimize it: WS_CLIPCHILDREN and WS_CLIPSIBLINGS can help if you dont have overlapping controls - to ensure that each control's area is painted only once. And ensure that the main dialog does not perform any flood filling in WM_ERASEBKGND
It is not, in my experience, possible to use double-buffering for anything that contains child controls (unless they all fully support WM_PRINT, which most do not).

How to add statusbar correctly?

Currently it is floating on top of my rendered window, i dont think thats good for few reasons:
1) i waste rendering time for rendering stuff that isnt visible.
2) it must be rendered every frame again when i wouldnt be updating the whole statusbar every frame anyways.
So how i could create a window where it leaves space for my statusbar and none of my OpenGL stuff could be rendered in that area?
At this moment i just adjust my viewports in a way that creates empty space for statusbar, but it causes some problems in my current way of doing things. i would have to make my code look much more messier to make it work.
http://www.gamedev.net/community/forums/topic.asp?topic_id=291682
Edit: Its not a simple question to answer. If you don't know what a child window is under Win32 then you may be in a much better position. However asking someone to give you a full explanation of the windows windowing system is no mean feat.
Here is an overview:
Basically you need to create a child window which can be done using CreateWindow to create a window with the WS_CHILD style and with its hWndParent parameter set to the window handle you want the new window to be a child of.
When you created the window you will have, necessarily, create a window procedure When you call DispatchMessage from your message pump (The Loop that does a Get/PeekMessage and then dispatches the messages is the message pump). Inside the window procedure you can then switch on the message type and handle each message sent to your window.
From here you can handle things like setup. Your initial window will have either a WM_CREATE or a WM_INITDIALOG (Depending on what type of window you create). It is from there that you need to create the child windows (Don't forget to call ShowWindow to make them visible!!). From this point you can then set up the DirectX device to be attached to the child window handle (HWND).
Furthermore if you want to be able to re-size the window then you ALSO need to take into account the WM_SIZE mesage. However I'd strongly recommend trying to get the rest working before even beginning to look into this as it gets very complicated as you will need to destroy and re-create your DirectX device so that it is the right size.
Anyway thats just a simple overview. I hope it helps!
One way may be to make your "rendered window" and "statusbar" both children of a containing window, and to add some code for the WM_SIZE message for that containing window to position the children so they don't overlap.

Problems encountered when implement a float, translucent sub-window in MFC with C++

I have tried several methods, but problems always exist. Sometimes the sub-window didn't refresh and sometimes the sub-window will keep blink.
This is a sample project that i have written
http://rapidshare.com/files/283950611/TestProject.7z.html
My method to implement that is:
Put a scroll bar on the top of sub-window, whenever the scroll bar was dragged, the sub-window would be moved as well.
And every dialog is inherited from CDialogBase, All the drawing is done in this class, Drawer.h is a helper for drawing.
Only when the DC that user assigned is dirty, then system will redraw the window, it is used for accelerating the painting.
WS_EX_LAYERED only can be added to with top level window, not sub-window; I've tried to modify the window style from WS_CHILD to WS_OVERLAPPED, and then using layed window, and then clip the visiable area of the window, but, the result is not what I expected.
Anywhere, thank you for your advice...
Have you considered using WS_EX_LAYERED and then using UpdateLayeredWindow. It can get quite complicated but allows for things like per-pixel alpha and eliminates flicker like you are seeing.
Look here:
http://www.nuonsoft.com/blog/2009/05/27/how-to-use-updatelayeredwindow/
for more info.

How to select and highlight a window in another application?

I would like to send some keystrokes from a C++ program into another window.
For that reason I would like to have the user select the target window similar to how it is done in the Spy++ utility that comes with Visual Studio (drag a crosshair cursor over target window and have target window highlighted by a frame).
How is this dragging and selecting done in Windows? I am completely lost as to where I might start to look for a mechanism to implement this feature.
Here's how it's usually done:
Capture the mouse using SetCapture. This will cause all mouse messages to be routed toward your app's window.
Handle the WM_MOUSEMOVE message. In your handler code, grab the window underneath the mouse using WindowFromPoint. That will get you the HWND of the window the mouse is currently over.
Now that you've got the window, you need a device context (HDC). You can get one using GetWindowDC for the specified window.
Now you can draw into the DC using typical GDI functions.
There are some things you have to look out for - cleanly erasing the selection rectangle and so forth, but that's one way to do it.
You could also draw into a screen DC to do this, but in any case you'll need the window handle in order to get the window rect.
If you Google around Spy++ source code you'll see a few examples of this technique.
Formers answers are wrong.
Spy++ source code has been given on G. Groups for years (see mainly Win32 api ng news://194.177.96.26/comp.os.ms-windows.programmer.win32)