How to create a child window is transparent and the parent window is not transparent? - c++

I want to create a window with two child windows. Only the background of the top child window is transparent. I can directly see the background of the parent window and not the content of other child windows.Like the picture, A is parent, B is child 1, C is child 2.The background of child 2 is the same as parent.enter image description here

A-a-m,
You paint background on child window by yourself.
There is method OnPaint (in MFC) or message WM_PAINT.
And you should draw transparent background (it means to draw nothing).
Does it work?
If you use non-standart framework to create windows, you should specify background is painted programmatically.

A few options to experiment with:
If in your open source UI framework you can remove the WM_PAINT
handler entry in the Def­Window­Proc then you could do that.
Handle the WM_PAINT message yourself and do nothing in the handler except clear any flag that indicates that the client area
needs to be re-drawn. You'll need to find something equivalent to
ValidateRect.
Both of these methods MIGHT cause non client areas like the window frame to artifact within the client area as you move window C around but I can't be sure.

Related

Get control under mouse on GUI with WS_EX_TRANSPARENT style

I have a LayeredWindow GUI that contains some child's and all of them contains the WS_EX_TRANSPARENT style.
The style is used to be able to remove their background.
When i move the mouse over the GUI only the LayeredWindow receives the message WM_MOUSEMOVE.
I tried calling ChildWindowFromPointEx using the XY pos got from the WM_MOUSEMOVE lParam
to detect the control being hovered, but the API didn't recognize any of the controls belonging to the child GUI's.
Docs says:
The search is restricted to immediate child windows. Grandchildren and deeper descendants are not searched.
The other option i tried was EnumChildWindow and compare each control rect to the XY position of the message, this method is using around 1% of CPU only from moving the mouse.
I wonder if there's any 'better' option?
According to the Doc:Layered Windows
Hit testing of a layered window is based on the shape and transparency
of the window. This means that the areas of the window that are
color-keyed or whose alpha value is zero will let the mouse messages
through. However, if the layered window has the WS_EX_TRANSPARENT
extended window style, the shape of the layered window will be ignored
and the mouse events will be passed to other windows underneath the
layered window.
You could try to use GetCursorPos function to get the position of the mouse cursor, in screen coordinates.

Redraw in parent window in child window's onPaint in mfc

I am trying to implement something like this in mfc:
A parent window that contains a few child windows. I want some horizontal and vertical grid lines to appear around a child window when ever the window is being dragged anywhere inside the parent. For that, I am tracking movement in my OnPaint() handler for the child and accessing the parent and drawing these grid lines around the child. But its not behaving the way I want it to.
My guess is that the child's OnPaint() only updates the child's drawing region, so even if I do access the parent's DC, I cant draw anything on it unless it's being redrawn?
Can anybody suggest a neater method of achieving above functionality? What am I doing wrong? I need everything to happen in the child's OnPaint()
One way is to just pass data to the parent window and call its Invalidate function. Then it would paint the grid lines in its own OnPaint.
Or you could paint directly on the parent window from the child, but use the parent's GetDC function instead of using the child's DC.
One way to solve this problem is to draw a semi-transparent grid window using UpdateLayeredWindow on top of the parent client area while you arrange the child window on top of it. The grid window can then be destroy after the arrangement is done. In this way, there will be minimum changes required to the existing display code.

Child Windows that does not occupy client area

In the Win32 API (pure win32), The Menu bar does not occupy any area from the client area of the window. Which means the origin coordinates of the client area is right under the menu bar to the left.
When we create child window controls using CreateWindow (or any other method), that window takes some area of the client-area.
eg:- Creating a button which is at (xPos = 0, yPos = 0) and (width=width_of_client_area, height=20).
After creating the button if you'll use a GDI function like this, it'll be drew below the button:
Rectangle(hdc, 0,0, 200, 200);
But when creating a menu bar, it doesn't occupy client area. (GDI will not be drew under menu).
FINAL QUESTION:
How can i create a control on my parent window like the menu bar ?
The menu is rendered in the non-client area of the window, which is driven by a completely different set of window messages. Keep in mind that you don't actually create child windows for these types of controls. You will need to provide all the rendering and event handling for the customization you want to add. This means that if you want to add a button or checkbox you will need to implement it yourself. You can get your started with a handful of steps but there may be other things that need to be done depending on your requirements.
The first step is to process the WM_NCCALCSIZE message. This will allow you to adjust the size of the non-client area so that you have more space to draw the custom control. Basically you will pass this message on to the default window proc then modify the location and dimensions (just drop the top down X pixels) before returning.
The next step is to handle WM_NCPAINT message. Pass the message on to the default window proc then draw your custom visuals in the area you have reserved. You will be working with a window DC so you can draw to the entire window. It's important to keep this in mind so you don't destroy anything in the client area.
The last item that needs to be done is to handle mouse messages like WM_NCMOUSEMOVE. If the mouse event occurs outside the area where your control is located pass the message to the default window proc, otherwise handle the message yourself and skip the default proc. you will need to manage some state data for keeping track of when a button is down or not so as not to cause conflicts with the default window proc.
Keep in mind that when you want to draw directly to the non-client area you need to call GetWindowDC() instead of GetDC() to acquire a device context.
[Note: A good Google dance will be something like "WinAPI non-client area"]

Custom button shape

I want to implement a simple volume up/down button using a custom bitmap, and all it's going to have is a simple hover effect, and mouse down effect.
My first idea was to process WM_MOUSEMOVE for the hover, and process WM_LBUTTONUP and WM_LBUTTONDOWN for the mouse down effect.
First, is this the easiest way to do this? I could superclass a button and just paint the bitmap and forget about the text...
Then I have the problem with the background, which should be transparent, I know I can use a mask by passing SRCAND to BitBlt, but this requires me to have 2 images for each button. Is there any way to do this with just one image? Like if I put a green background on it in my image editor, could I mask that out with a green screen like effect?
You need to create a regular button, and subclass it with SetWindowSubclass. The button must have the owner-draw style on it, which means in the parent WndProc, you are handling WM_DRAWITEM. As you correctly say, you will be BitBlt'ing or StretchBlt'ing the background of the image on.
For hover events you must do the following:
Have some sort of shared boolean between the parent and subclassed WndProc, eg. IsMousedOver
In the subclassed WndProc, process WM_MOUSEMOVE. When this message is hit, you should set IsMousedOver, then invalidate the control with InvalidateRect (this will trigger WM_DRAWITEM in the parent)
In the parent WndProc, if you receive WM_MOUSEMOVE, you should clear IsMousedOver
In WM_DRAWITEM in the parent WndProc, you should check IsMousedOver and BitBlt based on that state
If you want to process MouseUp/MouseDown, you can change the boolean to an int instead and have a tri-state. However, most implementations have MouseDown being the same as the regular button, and MouseUp is then simply the regular moused over background.
As for your query about 2 images, it may well be possible to do it with one but I haven't tried that before.

Child Window painting problem on Vista only

I have a dialog-based MFC C++ app. My dialog displays a number of "pages" (similar to a tab page or property dialog box).
I display each "page" by displaying a Child window over the top of the parent's client area. This works fine on Vista until I then open another window on top of the child.
Vista then seems to draw a thick white rectangular frame within my parent dialog box which paints over the top of my "page" child window(s). If I move another window over the top of this white rectangle, it will repaint the obscured area just fine.
Can somebody please tell me what is going on? Is Vista trying to clear my non-client (frame) area using incorrect coordinates perhaps?
My parent dialog is a skinned class derived from CDialog which handles the painting of my own window titlebar and frames. I've found that if I don't call CDialog::OnNcActivate() within my own OnNcActivate() method, the white rectangle doesn't appear. Of course if I do this then I can't use my child windows.. but OnNcActivate would appear to be related to the problem.
I've figured out the problem.. I shouldn't be calling CDialog::OnNcActivate() - I should have just been returning TRUE instead. All working fine now.