Clipping window rendering to a region - winapi

I have a window that is 100x100, but I only want to draw 50x100 and leave the right-side transparent without using WS_EX_LAYERED. The Windows Taskbar appears to do this when auto-hide is enabled. The Taskbar is 40px tall according to GetWindowRect, but only 2px is visible. How is it possible to have a window that is larger than what is shown on the screen without making it a layered window?

SetWindowRgn makes your window smaller than its GetWindowRect.

If you look more closely, you'll see that the taskbar is 40 pixels tall, but 38 of those pixels are off the screen.

Related

DirectX Resize shows win32 background at Edges

When resizing down in DirectX I noticed a flicker along the bottom/right edges.
If you fix the size of the swapchain (in red), and set the win32 background to green you will get the following on a resize down:
It appears that the window size lags behind the mouse position ("Drag Rectangle") but the area DirectX fills (in red and black) matches the Drag Rectangle, with the remainder to be painted with the window background color (green).
The DirectX Utility Toolkit (DXUT) didn't have this problem. Experimenting with their settings I found that setting DXGI_SWAP_CHAIN_DESC::SwapEffect = DXGI_SWAP_EFFECT_DISCARD would just paint the screen green (the window background color) during a sizemove. I assume that DXUT has their own special handling for when win32 enters a modal sizemove loop in order to display DirectX content during a sizemove.
DXGI_SWAP_EFFECT_DISCARD is part of the old blit mode presentation model. Notably it cant have DXGI_SWAP_CHAIN_DESC1::Scaling = DXGI_SCALING_NONE the scaling must be stretched to the window size. So my best guess is this behavior is due to the implementation of the flip presentation model (it flips a rectangle too small (black) and then covers by painting the rest green).
Does anyone know how to stop the win32 background from showing?
Edit:
Thanks to IInspectable! I can confirm the WS_EX_NOREDIRECTIONBITMAP extended style works: it stops the artifact from the win32 background showing
I reproduced the exact same behavior when using CreateSwapChainForComposition() with DirectComposition as I got using CreateSwapChainForHwnd().
This means that there are two path for pixels to get to the screen. The green pixels are going through the Redirection Surface. Hence, explicitly requesting WS_EX_NOREDIRECTIONBITMAP prevents any drawing through a Redirection Surface stopping the win32 background from showing.
The other path is the flip presentation behavior which is how the red and black pixels are get displayed. Hence, not using flip presentation when resizing also stops the win32 background from being shown.
There must be a bug with DWM: when there is a Redirection Surface, the clipping to prevent the swapchain's contents extending past the window is smaller than the redirection surface allowing it to be seen along the bottom/right edges.
There are two observations of interest:
when using WS_EX_LAYOUTRTL or manually positioning a IDCompositionVisual to the right edge of the screen with GetClientRect(), the swapchains contents are correctly position, but still clipped.
when using WS_EX_NOREDIRECTIONBITMAP the window`s nonclient area lines up with the contents of the swapchain rather than the swapchains contents being clipped
These observations would seam to imply that the cause of the issue is that DWM is using it's prefered size for the window size sometimes and the size of the redirection surface othertimes.

Changing size of non-client area in NCCALCSIZE when window is maximized causes flickering when maximizing with Aero Snap only

I'm trying to make a borderless window where the maximized window properly fits the work area of the screen when maximized. This has turned out to be more difficult than I could've ever imagined, and every solution I can find has some sort of downside or glitch that prevents it from being perfect. Some of the glitches are very minor and probably wouldn't be a big deal to most people, but it bothers me.
I know it's possible to do this somehow because I've used a few programs that clearly draw their own non-client area but have proper maximize behavior and appear to be without glitches. Steam and Twitch clients are two examples. However, I have no idea how much code or what sort of tricks they used to get their windows to have that behavior.
Background Info:
When maximizing a window, the window manager positions the window in such a way that the non-client area falls just outside of the visible work area so that the non-client area is not visible when the window is maximized. I remove the non-client area by returning 0 from WM_NCCALCSIZE because I want to be able to draw my own non-client area. The result is that the window manager is trying to account for a non-client area that doesn't exist and my maximized borderless window extends off the screen approximately 7 or 8 pixels in all directions.
What I've tried to fix this:
I've tried handling WM_MINMAXINFO, which doesn't work because the window manager ignores any dimensions passed unless they are smaller than the work area or monitor area. For example, if I subtract 1 from the ptMaxSize.x coordinate, the window fits almost perfectly except there's a 1 pixel transparent space where you can click whatever is behind the window. See this post for more info.
What almost works:
I found this post which contains a solution that almost works perfectly, except that when maximizing the window with Aero Snap, there's a very brief flicker where you can see everything behind the window. This doesn't occur when maximizing the window by double clicking the title bar or using the maximize buttons, even when adjusting the size of the non-client area on maximize. Here's a video that demonstrates the issue.
Video explanation:
First, I maximize the window several times with Aero Snap without the adjustments being made to the non-client area to demonstrate that the maximize transition is flicker-free. Then I show that the window flickers after having adjusted the size of the non-client area on maximizing.
My Question:
Is there a way to prevent the flicker from happening when using this method to fit the maximized borderless window to the work area? Or is there a better way to go about making the maximized window fit the screen? Handling WM_MINMAXINFO seemed like the best hack-free approach, but because of the quirky way windows responds to dimensions that are greater than or equal to the work area, it doesn't seem to work.

How to get the size in pixels of the Resize Corners of a Window

Is there a way (API) of getting the size (vertical and horizontal) in pixels of the resize corners?
I am referring to the area at each of the corners of a window where you can resize the window in both directions (Left-to-Right and Top-to-Bottom) at the same time using your mouse. You will know you are there with your mouse cursor when you hover over the corners of the window and the mouse cursor is a Diagonal Resizing cursor.
Thank you
Edit:
An example: Hover your mouse over the right edge of a sizable window. Start in the middle (vertically) of the window and move the mouse up along the edge until the horizontal sizing cursor changes to a diagonal sizing cursor. How do I determine by asking the OS how far that position when the cursor changes, is from the top of the window.
I would suggest to use the size of the scrollbars. Call GetSystemMetrics with SM_CYHSCROLL and SM_CXVSCROLL. May be also SM_CYSIZEFRAME and SM_CXSIZEFRAME sizes can be combined.
But I think a better value is to use the height of the status bar. However even Microsoft Windows seems to use some fixed value as can seen on the screenshot.
Comparing the results of GetClientRect and GetWindowRect will tell you how wide the non-client (border) area is along each edge of the window.
If you're concerned that it might not all be active for sizing (true especially along the top), or you want to distinguish the diagonal sizing areas from edge sizing areas, you can take the coordinates discovered in step 1 and pass them to SendMessage(WM_NCHITTEST) See its documentation for the various return codes. There's no problem sending this message repeatedly -- it's designed to be called for each mouse move event and therefore is very fast.

How to get the top frame height of a dwm extended and maximized window?

I created a window using dwmextendframeintoclientarea, everything is ok except the top frame height is less than the value I settled while the window is maximized.
So the text drawn using drawthemetext will not align absolutly vertical center as following picture shows.
the first one is the caption bar while the window is normal size, while the second window is maximized.
It is because the height of the top frame actually is less than the value I setted in DwmExtendFrameIntoClientArea.
The problem is how could I get the real height of the top frame while dwm is enable and the window is maximized?
When your application is maximized, Windows actually sizes it slightly larger than the screen. The edges of your window thus extend offscreen, resulting in the rendering you observed. You can use the position and size received in the MINMAXINFO struct in the WM_GETMINMAXINFO message sent to your window to determine just how far offscreen your window extends, and use that to adjust your rendering when maximized.

Window border width and height

I'm writing a direct3d application and after noticing strange bugs such as anti-aliasing occurring even when it was turned off and the mouse pointer not lining up to things with the same coordinates as itself I discovered that when creating a window the width and height parameters include the border. The program was rendering a 800x600 graphics output to a window of the same size, but because of the borders it was squished into 792x566 rectangle. I've increased the size of the window to compensate, but this does not work if the system uses a border style other the standard XP style. (Classic style, for example)
Is there a way to tell what the border width and heights will be before I create the window?
Another option would be to make sure the D3D surface is the same size as the client rectangle size (GetClientRect()). Then you know you'll render to the appropriate size and not have to worry at all about the width of menus, borders, etc.
It sounds like you are looking for the GetSystemMetrics function. For example, the border width in pixels is returned by
GetSystemMetrics(SM_CXBORDER)
ADDED: For the total size you will need to add together the various "pieces" of the non-client area: border, frame sizes, title bars, etc.

Resources