Closed mrgreywater closed 7 years ago
First some observations:
GetSystemMetrics(SM_CXBORDER)
and GetSystemMetrics(SM_CYBORDER)
report the border size as 1
WS_OVERLAPPEDWINDOW
styled window, the offset from (top,left)
of the window rectangle to (top,left)
of the client rectangle is (8,31)
(on my machine).So it looks to me like 7 out of 8 pixels of the window frame are simply transparent, but still part of the window.
In theory, if we carefully construct the client rectangle in WM_NCCALCSIZE
like you mentioned, so that it does not simply expand to the entire window, we should achieve the desired effect.
A quick test shows that this almost works:
The transparent resizable border is still present and functional, unfortunately so is the 1 pixel border, and adjusting the client rect further out just pushes that border further out.
I was also unable to draw over this, since it's not part of the client area.
Maybe it's possible to do something in WM_NCPAINT
to get rid of it, but I don't really know GDI. Anything I tried to draw there seemed to wreck the entire non client area permanently, even after switching back to bordered mode.
Hm, it seems possible to invoke DefWindowProc
in WM_NCPAINT
to get the transparent border, then paint over the non-transparent part...
...but even if I was doing it correctly, this doesn't seem like a good solution if your window content doesn't have a flat backgroud color. You'd probably need to copy into a bitmap and draw the one pixel border using that to get a seamless look - for e.g. a video player or a game this seems like a bad idea.
Nice investigation! If that doesn't work, maybe we could increase DwmExtendFrameIntoClientArea on the bottom, right and left side by 8 pixels on Windows10 and draw a transparent color over the custom DWM border. Even though this would mean you need to manually modify the client rect when using GetClientRect for drawing the actual window contents, since the transparent border should not be part of the actual client area. And I don't know if the DWM shadow would work correctly.
Additionally, I think you would also have to handle all the special cases like maximizing and snapping to a screen quadrant/half manually, which is something I'd want to avoid...
Hi melak47 Thanks for sharing this window snippets. Here is a small window example based on your one https://github.com/IMAN4K/QtPro/blob/master/Ui/Qt5.5.1/_Other/window_frameless.cpp
It's borderless, has Drop Shadow, has snap feature and also can be resize from outside of it's frame These lines remove the caption And these lines remove the colored frame
But there is an issue and my window doesn't have animation on minimize,maximize and close like a native window! I will appreciate it if you take a look and help me on this i don't have strong knowledge in win32API
@IMAN4K WS_CAPTION is required for the minimize and maximize animation. If you remove it, it will also disable those animations. To my knowledge there is no way to enable the animations whilst not specifying WS_CAPTION.
@mrgreywater WM_NCCALCSIZE also removes the caption right ? but still animation are there
@IMAN4K Unfortunately, your sample only appears to work because the border and contents of the window are now white. If you try to fill the client area with another color, you will see that the border is not gone:
You are right, we can remove the titlebar by adjusting the client rect in WM_NCCALCSIZE
as I tried above, however I still can't seem to get rid of the other borders that way:
@melak47 What about InflateRect ? could it be helpful(at least for default color)?
case WM_NCCALCSIZE: {
const int cxBorder = -BORDER_WIDTH;
const int cyBorder = -BORDER_WIDTH;
InflateRect((LPRECT)lParam, cxBorder, cyBorder);
return 0;
} break;
It seem's work except the top! Do you have any idea on this ?
OR process WM_SIZING and use AdjustWindowRect ?
I was doing it manually as you can see here: https://github.com/melak47/BorderlessWindow/blob/Win10/BorderlessWindow/src/Window.cpp#L83-L96
I just noticed though that I'm not handling wParam == FALSE
in which case I'm possibly reading bogus memory.
While it is possible to paint over the title bar using DwmExtendFrameIntoClientArea
as demonstrated here: https://github.com/oberth/custom-chrome, in Windows 10 it's no longer possible to also have the left, right and bottom sides of the frame inside the client area as described in this msdn article.
Because of that, it is impossible to draw over the visible part of the frame without also destroying the transparent effect - at least using a single window.
Visual Studio 2012+ and Office 2013+ for example sidestep this by having multiple windows, a transparent window to which the shadow (or glow) is rendered (which also serves to capture the mouse and enable resizing outside the frame), and one or more "main" windows, with completely custom drawn title bars and window frames.
That's a lot of effort for a very small feature which I feel is beyond the scope of this little sample app, so I'm closing this issue.
I was wondering if there was any way to recreate the windows 10 behaviour that allows resizing on a transparent border around the (now frameless) window. Visual Studio 2015 seems to be the only other application that seems to have recreated a similar behaviour, even if slightly differently (It allows resizing above the caption aswell, which is not possible for default windows).
I imagine one way to do it would be enabling
WS_CAPTION | WS_POPUP | WS_THICKFRAME
, removing theWS_CAPTION
size from the top of the window inWM_NCCALCSIZE
(without returning 0) and then drawing a transparent color inWM_NCPAINT
, even though I'm not convinced it would work, and wonder if there may be an easier way to achieve the same effect.See comment: https://github.com/melak47/BorderlessWindow/blob/master/BorderlessWindow/src/Window.cpp#L103#L105