SetWindowPos() not moving or resizing window - windows

I have a GUI application that is using GStreamer to capture video from capture cards, and then play the video. The audio and video streams are sent to GStreamer, and GStreamer automatically opens its own window to play the video. Once the video window is open, I need to take the video window and remove the border and set the window size and position and make my GUI window the parent of that window so that it will be "anchored" to my GUI window.
Since I know the name of the video window I am using FindWindow() to get an HWND handle to the window. I am then passing that HWND to SetWindowPos() as follows SetWindowPos(VideoWindow, GUIWindow, GUIWindowLeft, GUIWindowTop, 640, 360, SWP_SHOWWINDOW). Then I set the parent of the video window SetParent(VideoWindow, GUIWindow).
When I start my application, for a very brief moment it looks like my window is being resized and placed correctly but then the window returns to its default position (almost like it is just neglecting that SetWindowPos() was even called). Is there an obvious reason for why this happens? I am new to window manipulation so it is very possible I am making a simple mistake, but it does not make since why my window would be positioned correctly for a very brief moment but then move back to default position.

This is because the SWP_SHOWWINDOW or SWP_HIDEWINDOW is set, the window won't be moved or resized (see SetWindowPos documentation). Seems a little strange. Try using a different flag.
From the docs:
If the SWP_SHOWWINDOW or SWP_HIDEWINDOW flag is set, the window cannot be moved or sized.

Related

Opacity in a reparenting WM

I'm writing a reparenting window manager for X11 (and have asked a number of questions about it here already). Right now, the issue I'm having isn't so much a bug to fix as much as a question on how to implement something.
Applications can request transparency, and if a compositor like xcompmgr or picom is running, they will provide it. However, this doesn't seem to work when I reparent the window; in this case the client window's background just shows a black background behind (maybe the frame window? but the background of that isn't black). I do indicate I have a frame by setting _NET_FRAME_EXTENTS.
What I've tried:
It looks like awesomewm's code for opacity listens to a property notify with a _NET_WM_OPACITY. I don't get any PropertyNotify event when I change opacity of a window, despite selecting SubstructureRedirect|SubstructureNotify|PropertyChange on the root window.
You need to create your frame window with reparenting with depth=32 (i.e.: Made to work with transparency). Since you are already looking at AwesomeWM: It finds the right visual for this at startup and then creates all of its windows this way. That is only necessary since Lua code might want transparency. AFAIR, other WMs look at the program's window bit depth and create their frame window based on that.

How can I change the owner of a Windows window?

I have a floating window that is owned by my app's main frame window. Now, I have created a new frame window and I want to change the owner of the floating window to the new frame window I created. But, I have not been able to find a way to do so.
Essentially, as a user activates either of my frame windows, I want to make the newly activated frame the owner of the floating window.
I tried SetParent hoping if I didn't change the style of the floating window from WS_POPUP to WS_CHILD, that would be a trick that would work but the floating window just fails to display after doing that. And, it is actually becomes a child window in that it shows up when enumerating the child windows of the frame I passed to SetParent.
Is it possible to change the owner of a window after calling CreateEx where I pass in the initial owner?

BitBlt not able to capture the title bar correctly

I am using the code below to capture a screenshot of a window using bltblt. However the titlebar appears completely black in the captured screenshot. I am running the code on Windows 8.1. Is there a way i can correctly capture the title bar.
// Retrieve the handle to a display device context for the sourceWindow
hdcScreen = GetDC(ss);
// Retrieve the handle to a display device context for the dest window
hdcWindow = GetDC(hWnd);
//Get the client area for size calculation
RECT rcClient;
GetWindowRect(ss, &rcClient);
if (!BitBlt(hdcWindow,
0, 0,
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top,
hdcScreen,
0, 0,
SRCCOPY|CAPTUREBLT))
{
MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
goto done;
}
EDIT:
The window i am displaying the screenshot in would cover the entire desktop and will be constantly updating the screenshot of the window just behind it. Also, the window displaying the screenshot will always be the topmost window.
The information you want is not all available from the window DC. Themes get painted over the top.
If you want an exactly visual representation you need to find the screen coordinates of the window (or part of it) and then blit from the screen DC.
If the window is not displayed, you may have an insurmountable problem. As far as I know the theme (since at least Windows Vista) is not part of the Window DC but is painted over the top using non-GDI techniques. The GDI simply does not have the capabilities to paint sophisticated blends and transparency effect. Until Windows 8 it was still possible to select the old classic themes but now they're gone. You may find that the title bar simply isn't painted in the NCPAINT handler any more.

How to stop OpenGL from pausing when the window is out of focus or resizing?

I'm trying to prevent my rendering from stopping when my window is out of focus or resizing. In addition to the resizing, if I resize my window smaller, then bigger again anything that wasn't visible when it was smaller is now black. Is there any way to fix this?
There are really two distinct things going on here. The moving/resizing problem is caused by the windows DefWindowProc function which applications use to handle messages that aren't explicitly handled by the application itself. In the case of moving or resizing, it blocks, creating a new message queue to handle most messages, but there are a few that it will still dispatch to the application's main event queue, like WM_TIMER. You can find lots more information in this answer.
The second issue is that your program only "owns" the pixels inside your window, and only those that are not covered up by other windows. When you make the window smaller, the pixels at the edge need to be overwritten to show the window border or whatever's behind the window. When the window is made bigger, some drivers automatically set the newly acquired pixels to black, while others leave them at whatever they were before (usually part of the window border). The OS doesn't remember if those pixels had some specific color the last time the window was that size, because most of the time the program doesn't care. Instead, windows sends a WM_PAINT message to indicate that the application should redraw the window. Your program should either directly handle this, or use a library like GLFW that abstracts it. In addition, you need to handle resize events by calling glViewport with the new size of the window.

Why might WS_CLIPCHILDREN be necessary for the display of DirectShow window on XP (but not Vista or Windows 7)?

I wrote a program to play MPEG video on a window (of course, DirectShow will open its own window as the sub-window of that window). On Windows Vista and 7, the program works fine. But on XP, the video is only visible when I set the WS_CLIPCHILDREN style on the outer window (i.e. not the DirectShow one). Is this a bug in XP or some model change in Vista?
Actually, it sounds like a bug in your code...
WS_CLIPCHILDREN affects the drawing of the parent window. More specifically, it prevents it from drawing in the areas occupied by its children. So if you're re-drawing the parent on a regular basis and WS_CLIPCHILDREN isn't set, you'll end up stomping on the child window's display...
As for why this might affect XP and not Vista or Win7, well... This is just a guess, but many video players on XP used a feature provided by most video cards known as "overlays": essentially, the window was filled with a key color and this was then recognized by the hardware as indicating the area on screen where the video would be displayed. Since the window itself would not be repainted often (it would need to be filled with the key color initially and when resized, but wouldn't be repainted for every frame in the video), allowing the parent to draw over it could seriously mess up your output!
Potential solutions
Use WS_CLIPCHILDREN on your parent window. This is almost always a good idea anyway.
If you have custom painting code for your parent window, modify it to manually avoid drawing over the area occupied by the child.

Resources