WS_EX_LAYERED with SetParent() doesn't show the window - c++

I have this one problem I just can't solve. I'm trying to make a window from my application that is transparent (using flags WS_EX_TRANSPARENT | WS_EX_LAYERED) a child to another window, which is not transparent.
When I don't use the call SetParent( my_window, target_parent_window ) with my_window having the WS_EX_LAYERED flag, the new child window won't be visible.
I found out that a manifest entry could help me, since having a child window with flag WS_EX_LAYERED is supported since Windows 8. I tried it without any success.
::SetWindowLongW( process_window, GWL_STYLE, WS_CLIPSIBLINGS | WS_POPUP | WS_VISIBLE );
::SetWindowLongW( process_window, GWL_EXSTYLE, WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW );
::SetWindowPos( process_window, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
::ShowWindow( process_window, SW_SHOW );
::SetParent( process_window, new_parent_window); // if i skip this call the window will render perfectly

https://learn.microsoft.com/en-us/windows/win32/winmsg/window-features
To create a layered window, specify the WS_EX_LAYERED extended window style when calling the CreateWindowEx function, or call the SetWindowLong function to set WS_EX_LAYERED after the window has been created. After the CreateWindowEx call, the layered window will not become visible until the SetLayeredWindowAttributes or UpdateLayeredWindow function has been called for this window.

Related

Win32 semi transparent window

I'm trying to get a semi transparent window with the Win32 API and C++. Despite the fact, that there
are around a million results trying to answer that question, none of those seem to have worked for my case.
I have a native Win32 window with a hosted WPF content inside it. Because I'm trying to create a custom
window frame (and that also works by now), I want the top part of the self drawn frame to be semi
transparent, possibly also applying the acrylic blur.
Looking at WPF, I could archive my goal using AllowTransparency = True on the window and with a
transparent background. Now I need a way to replicate that behavior with the Win32 API.
Technically, I can make the entire main window transparent (because the main window is the frame entirely
and the WPF hosted content is the client area), but even that didn't work (no transparency).
For reference, here is how I'm creating my window:
WNDCLASSEXW window_class_ex = {
sizeof(WNDCLASSEXW),
CS_HREDRAW | CS_VREDRAW,
window_callback,
0,
0,
application_instance,
nullptr,
LoadCursorW(nullptr, IDC_ARROW),
CreateSolidBrush(RGB(0, 0, 0)),
nullptr,
window_class,
nullptr
};
const HWND window_handle = CreateWindowExW(
0,
window_class,
L"WinSoup",
WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_EX_LAYERED,
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
nullptr,
nullptr,
application_instance,
reinterpret_cast<LPVOID>(owner)
);
I have seen that I should use WS_EX_LAYERED, but also that didn't have the desired effect.
Of course the WPF content itself should not be transparent!
Ok, so, despite all the answers telling me to read the documentation and look at other
examples... turns out, I misplaced the WS_EX_LAYERED.
const HWND window_handle = CreateWindowExW(
WS_EX_LAYERED, // Needs to be placed here (extended style)
window_class,
L"WinSoup",
WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, // Not here!
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
nullptr,
nullptr,
application_instance,
reinterpret_cast<LPVOID>(owner)
);
Your question says
The WPF content itself should not be transparent!
You can use Set/UpdateLayeredWindowAttributes, but the opacity for your WPF content will change too.
If you really want to create a high-performance transparent/semi-transparent window, you need to specify the WS_EX_NOREDIRECTIONBITMAP flag instead of WS_EX_LAYERED. Then use DirectComposition with another graphics API to render your content.
Look at https://msdn.microsoft.com/magazine/dn745861.aspx for more details.

Win32 programming child window does not have exit button

Hi I am writing a Win32 Windows program. I created a child window with the following command
case ID_VIEW_CARVIEW:
carViewHwnd = CreateWindowEx(WS_EX_TOPMOST, L"Edit", L"Edit",
WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_BORDER,
000, 00, 656, 519, hWnd, (HMENU)NULL, GetModuleHandle(NULL), NULL);
SetWindowLongPtr(carViewHwnd, GWLP_WNDPROC, (LONG_PTR)CarViewWndProc);
However, this child windows has two problems:
It does not have a "close" button on the top right.
It always stay on top of all windows on my desktop top.
How can I change it?
It does not have a "close" button on the top right.
You need set WS_SYSMENU flag for dwStyle parameter to have a window menu on its title bar.
It always stay on top of all windows on my desktop top.
Because you define WS_EX_TOPMOST style: "The window should be placed above all non-topmost windows and should stay above them, even when the window is deactivated."

SetWindowPos not moving or resizing window

When I call SWP to try and move a resize a specific window. It does not move or resize.
SetWindowPos(hWndWindow, NULL, 0, 0, 500, 500, SWP_NOZORDER);
The window handle is valid. I tried both getting the handle with FindWindow and by manually setting the handle value to the window I wanted to resize.
When I use GetWindowPlacement, it says the window is SW_NORMAL and not SW_MAXIMIZE.
The window style is
0x160b0000 (WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU | WS_MINMIZEBOX | WS_MAXIMIZEBOX)
and the extend style is 0x0.
I have also tried setting the window to SW_NORMAL with ShowWindow before calling SetWindowPos.
SetWindowPos and MoveWindow both return non false values saying that they didn't fail.
Why is SetWindowPos and MoveWindow unable to move or resize this window?

C++ Altering the borders of an external application window

I want to make a custom border or simply remove the border for another window (another application). However the way I've done it currently (with GetWindowLong, SetWindowLong & SetWindowPos functions) removing the border causes graphical issues for one program (cmd.exe) and does nothing at all for another (heroes of might and magic II).
I'm not very familiar with C++ yet and don't know how to go about doing this. I want simple and clean-cut borders so I for example could place a cmd.exe on the taskbar or play HoMM2 in borderless full screen.
Anyone knows how this can be achieved?
Here's my current function:
void noBorder(HWND win)
{
LONG style = GetWindowLong(win, GWL_STYLE);
style &= ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
WS_MINIMIZE | WS_MAXIMIZEBOX | WS_BORDER);
SetWindowLong(win, GWL_STYLE, style);
style = GetWindowLong(win, GWL_EXSTYLE);
SetWindowLong(win, GWL_EXSTYLE, style | WS_EX_DLGMODALFRAME);
SetWindowPos(win, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE |
SWP_NOSIZE | SWP_FRAMECHANGED);
}

`SetWindowLong()` function doesn't change window style even after calling `SetWindowPos()`

I create the static control with the code below:
hWnd = CreateWindowExW( 0,
L"STATIC",
Content.c_str(),
SS_LEFT | WS_VISIBLE | WS_CHILD /*| SS_SUNKEN*/,
200,
120,
120,
40,
hWndParent,
NULL,
hInstance,
NULL);
If I enable the SS_SUNKEN style in the creation code above, the created static control appears sunken successfully.
But, what I'm trying to do is the change the control style after its creation.
I tried this:
void BaseWindowClass::AddStyle(DWORD NewStyle)
{
// NewStyle = 0x00001000 = SS_SUNKEN
LONG oldstyle, changedstyle;
oldstyle=SetWindowLongW(hWnd, GWL_STYLE, changedstyle=GetWindowLongW(hWnd, GWL_STYLE) | NewStyle);
UpdateWindowStyles();
// oldstyle = 0x50000000
// changedstyle = 0x50001000 (everything looks normal)
}
void BaseWindowClass::UpdateWindowStyles()
{
BOOL success;
success=SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
// success = 0x00000001 (non-zero: SetWindowPos sucseeded)
}
Documentation:
SetWindowLong()
SetWindowPos()
I call SetWindowPos() after calling SetWindowLongW() because in the documentation of SetWindowLong, it says:
Certain window data is cached, so changes you make using SetWindowLong will not take effect until you call the SetWindowPos function. Specifically, if you change any of the frame styles, you must call SetWindowPos with the SWP_FRAMECHANGED flag for the cache to be updated properly.
And, in the documentation of SetWindowPos, it says:
If you have changed certain window data using SetWindowLong, you must call SetWindowPos for the changes to take effect. Use the following combination for uFlags: SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED.
Even after changing SetWindowLongW() and SetWindowPos() the style of my static control does not change.
What am I doing wrong, or what am I missing?
SS_SUNKEN effectively sets WS_EX_STATICEDGE in the extended styles (GWL_EXSTYLE) window long, so you can update GWL_EXSTYLE appropriately and reposition as you're currently doing.
Even though SS_SUNKEN does affect the frame of a static control, it isn't one of the "frame styles" that note is referring to.
That note refers to generic frame styles that affect all windows like WS_BORDER or WS_EX_CLIENTEDGE - styles that require a recalculation of a window's non-client area when changed.
Many of the system controls cache their styles upon creation and don't update the cache even if you change the styles via SetWindowLong. I would guess that's what's happening here - if you don't create the static control with SS_SUNKEN, you can't add it later. Your best option would be to simply destroy and recreate the control with the new style.