I want a window without title bar but with resizable frames and shadow. This can easily be achieved by removing WS_CAPTION and adding WS_THICKFRAME, however, since Windows 10, there's a 6px white non-client area.
With the following code I create a window and paint all the client area with black, the window gets a left, right and bottom 6px transparent margins, however the top margin is white.
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"", // Window text
0,
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
ShowWindow(hwnd, nCmdShow);
LONG lStyle = GetWindowLong(hwnd, GWL_STYLE);
lStyle |= WS_THICKFRAME;
lStyle = lStyle & ~WS_CAPTION;
SetWindowLong(hwnd, GWL_STYLE, lStyle);
SetWindowPos(hwnd, NULL, 0,0,0,0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// Paint everything black
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOWTEXT));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
How can I remove the white stripe ? I also found this related Qt bug report QTBUG-47543 which was closed as not being a Qt problem, because it can be reproduced with win32 api.
That's not a bug. In Windows 10 the borders on left/right/bottom are transparent. The top border is not transparent. You should leave it as is. Probably nobody will complain.
To change it, you must modify the non-client area. This is rather difficult in Windows Vista and above. See Custom Window Frame Using DWM for reference.
Find border thickness
Use
DwmExtendFrameIntoClientArea
to get access to non-client areaUse
BeginBufferedPaint
to draw opaque color over non-client areaWindows 10 example:
(See the next example for compatibility with Windows Vista, 7, 8)
For compatibility with Windows Vista/7/8 use this procedure instead. This will paint over left/top/bottom borders as well as top border. This window will appear as a simple rectangle, with resizing borders:
Just to expand on this a little; in order to remove the white stripe one just has to remove the corresponding value from the first rect in NCCALCSIZE. pywin32 code would be:
Change the style of dialog.