In my app, I want to keep my window full screen. So I added resizing window function when received WM_DISPLAYCHANGE event.
In the resizing window function, I use EnumDisplayMonitors to get current size of monitor, the size is correct. Then I use SetWindowPos function to set my window size equal to the monitor. But after SetWindowPos called, I found my window is still a little smaller than the monitor size some time. It seems that the desktop is not ready enough. I also set SWP_NOSENDCHANGING flag in the SetWindowPos function but still not work.
Is there any way to solve this problem?
The usual approach to make a window full screen is not by reacting dynamically to WM_DISPLAYCHANGE or query the display dimensions. The canonical way to make a window full screen is to set its style to WS_MAXIMIZE | WS_POPUP | WS_VISIBLE its extended style to WS_EX_TOPMOST using SetWindowLong, followed by a call to SetWindowPos with flag SWP_FRAMECHANGED, then maximize it with *ShowWindowwith flagsSW_SHOWMAXIMIZED`.
Related
I have a window which is set to AlwaysOnTop using the WS_EX_TOPMOST flag. Now, it is possible that some other application might also have a window which has WS_EX_TOPMOST set and override the topmost flag for my window.
How should I check if my window is indeed the window that is the top most window and nothing is being painted over it (the nothing is being painted over my window is the important part). If something is painting over my window, I want to hide my window and show it again when I can make it the top most window (but that's probably the second step)
Call GetWindow passing your topmost window's handle and the GW_HWNDFIRST flag. The window returned will be the topmost window that is highest in the Z-order. You can then use the GW_HWNDNEXT flag to walk through the topmost windows in order of decreasing Z-order until you find yours. If any of the windows overlap your window, then your window is underneath.
The old standard way was to call WindowFromPoint for a point on your supposedly visible window and compare the returned handle against your own window handle. There is a better way using the clipping system. I discuss this here.
I have created a window using the WS_EX_NOACTIVATE flag and it works great as far as not taking focus when you click the window. However when I drag the window or try to resize it, it doesn't redraw the window as your are moving and resizing it, only at the very end once you release the mouse button. Is there a way around this? I would like to see the window as I am resizing it. I have searched many documents, but I still don't find the resolution...
If you need a window that doesn't take focus when clicked, but can still be interacted with, you need to handle the WM_MOUSEACTIVATE, and return MA_NOACTIVATE.
Additional information and fully working sample code has been published by Raymond Chen. See How can I have a window that rejects activation but still receives pointer input?
It's a Windows bug. You need to call SetWindowPos(hwnd, 0, x, y, width, height, 0) on WM_MOVING. The coordinates to set are given to you in lParam which is a RECT*.
Note that doing this will activate the owned window and deactivate the owner, which is not what you want (and SWP_NOACTIVATE has no effect either).
To avoid that, you need to set WS_CHILD on the owned window. But set it after you created the window, via SetWindowLong(), otherwise your owned window will get clipped, like any child window.
And, as you probably already figured out, this only works for windows with WS_EX_TOOLWINDOW ex style. I wasn't able to make the owned window stay deactivated with any other style combination that doesn't include WS_EX_TOOLWINDOW.
That's winapi for you :(
I have an QML application (also tested it with QWidgets, same problem) and to make it borderless (but still support the native WM features like aero snap, etc) I followed this by implementing an QAbstractNativeEventFilter and responding to the WM_NCCALSIZE signal with zero:
switch(msg->message) {
case WM_NCCALCSIZE:
*r = 0;
return 1;
...
}
I also set some window flags which are not in the Qt Namespace with
SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME);
This works fine until I move or resize the window which causes Qt to rerender and a unpainted area width the width of the title and the borders appears:
Before moving/resizing
After moving/resizing
I also found a workaround for this by adding the FramelessWindowHint flag in Qt:
window->setFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::Dialog);
But now this margins occurs again when the window state changes (maximizing, minimizing, ...). By blocking the WM_SIZE event for example when SIZE_MAXIMIZED is the parameter the margin doesn't appear but then I also am not able to maximize the window from Qt. This means it is a Qt side problem.
I also noticed by inspecting the window style with winspector, that after I have maximized it a new property atom appears:
Can you help me fixing this?
I think using SetWindowLong on your window handle and using the Qt Window Flags/Qt Widget Attributes is asking for trouble. You can go and look at the Qt source to see what happens when processing those window flags.
When I've created frameless windows, I've usually done it to prevent moving and resizing, because I am managing all that separately.
One problem that I had related to it, was when the On Screen Keyboard came up and docked, it would resize my windows. So besides calling resize() I had to also use setFixedSize to prevent my widget from getting manipulated when the operating system attempted to change the size of the window.
So in other words, I would add an application wide QShortcut, listening for the snapping keyboard shortcuts and resize your window the way you want it to when it happens, if you are managing a frameless window.
Hope that helps.
I wonder if this was a flaw of Qt message relay, coz I met with a similar problem which occurs on nested windows. If you press SIZE_MAXIMIZE or SIZE_MINIMIZE button of the parent window, the child window sometimes is not able to receive WM_SIZE message. I suppose there are roughly two solutions: 1. Fix Qt, 2. Work it around.
Here I have a OGL rendering child window, sometimes even the WM_SIZE message is not correctly passed. That is, if you resize parent window, you get part of the client area black.
I just use a simple workaround to fix this, which check the current size with the cached one, and make a sort of manually resize myself.
I tried to implement a switch-to-fullscreen mode for an ActiveX control. This currently works by removing and hiding the parent window and changing my control's placement and position.
However, I have a problem with switching between applications while the control is in fullscreen mode. If I switch to another application and then click on my window area (not in the taskbar), it seems to not be activated. You can see in the taskbar, that another application still has the highlight and on the main screen, my window is partly hidden behind the taskbar unless it has the focus.
I process the WM_LBUTTONDOWN window message to detect if my window is clicked. And I already tried to call the following WINAPI functions:
::ShowWindow(m_hWnd, SW_RESTORE);
::SwitchToThisWindow(m_hWnd, FALSE);
::SetForegroundWindow(m_hWnd);
::SetActiveWindow(m_hWnd);
::SetFocus(m_hWnd);
::BringWindowToTop(m_hWnd);
::SetWindowPos(m_hWnd, HWND_TOP, m_monitorInfo.rcMonitor.left, m_monitorInfo.rcMonitor.top, m_monitorInfo.rcMonitor.right, m_monitorInfo.rcMonitor.bottom, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); // SWP_NOACTIVATE, SWP_NOOWNERZORDER
I also tried to use ::SetWindowLongW(m_hWnd, GWL_STYLE, WS_VISIBLE); which surprisingly gave my window the focus back. But it then suddenly disappeared when trying to switch back from fullscreen mode again.
I have no idea why there are so many different functions that for me seem all to do roughly the same. But it doesn't matter as none of them worked anyway.
What is the/one correct way to behave my control correctly?
Windows might be getting a bit confused because you're filling the screen with a child window, but you want it to behave like a top-level (overlapped) window. The host application is probably not getting activated because you've hidden its window.
You might do better to create a new top-level full-screen window for full-screen mode. If this is owned by the top-level window that (ultimately) hosts your control then your new window will always be above it, so you don't need to hide the existing window. Activation should just work. In short, you want your window to behave like a pop-up modal dialog.
Adobe's flash player seems to do something similar. Full-screen playback is in a window of class ShockwaveFlashFullScreen.
In WTL, CBitmapButton does not support picture with transparent layer, like PNG.
so i customize the code to use GDI+ to draw PNG, name it as CPNGButton.
But things are strange on win XP.
When the button is overlaped by other window, the button receives WM_PAINT first, and then the parent, causing incorrect result.
--->
I check the resource and remove WS_TABSTOP attribute from the template of the button, things go ok,parent window receives WM_PAINT first, then the button.
What cause WS_TABSTOP to affect window painting order?
This is what happens when you don't draw the background. That leaves a 'hole' in the window, you see the pixels of whatever window is behind yours. Or the desktop if there is no such window. Not otherwise sure what this has to do with WS_TABSTOP.
Use the WS_EX_TRANSPARENT style flag. That tells Windows that you want the parent of the button to draw itself in the client window to provide the background pixels.