参考
https://stackoverflow.com/questions/39731497/create-window-without-titlebar-with-resizable-border-and-without-bogus-6px-whit
阅读了windows窗口的若干属性后发现可以单独移除标题栏(&~WS_CAPTION),保留边框(|WS_THICKFRAME),可是窗口顶部会有6个像素的白边, 十分影响美观
不想用无边框的窗口自己重写拖动事件于是就想着去掉那难看的顶部白边
项目win32,不是控制台程序
#include
#include
#include
#pragma comment(lib, "dwmapi.lib")
#pragma comment(lib, "UxTheme.lib")
void my_paint(HDC hdc, RECT rc)
{
HBRUSH brush = CreateSolidBrush(RGB(0, 128, 0));
FillRect(hdc, &rc, brush);
DeleteObject(brush);
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static RECT border_thickness;
switch (uMsg)
{
case WM_CREATE:
{
//find border thickness
SetRectEmpty(&border_thickness);
if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_THICKFRAME)
{
AdjustWindowRectEx(&border_thickness, GetWindowLongPtr(hwnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
border_thickness.left *= -1;
border_thickness.top *= -1;
}
else if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_BORDER)
{
SetRect(&border_thickness, 1, 1, 1, 1);
}
MARGINS margins = { 0 };
DwmExtendFrameIntoClientArea(hwnd, &margins);
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc = ps.rcPaint;
BP_PAINTPARAMS params = { sizeof(params), BPPF_NOCLIP | BPPF_ERASE };
HDC memdc;
HPAINTBUFFER hbuffer = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, ¶ms, &memdc);
my_paint(memdc, rc);
BufferedPaintSetAlpha(hbuffer, &rc, 255);
EndBufferedPaint(hbuffer, TRUE);
EndPaint(hwnd, &ps);
return 0;
}
case WM_NCACTIVATE:
return 0;
case WM_NCCALCSIZE:
if (lParam)
{
NCCALCSIZE_PARAMS* sz = (NCCALCSIZE_PARAMS*)lParam;
sz->rgrc[0].left += border_thickness.left;
sz->rgrc[0].right -= border_thickness.right;
sz->rgrc[0].bottom -= border_thickness.bottom;
return 0;
}
break;
case WM_NCHITTEST:
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
ScreenToClient(hwnd, &pt);
RECT rc;
GetClientRect(hwnd, &rc);
enum { left = 1, top = 2, right = 4, bottom = 8, caption = 16 };
int hit = 0;
if (pt.x < border_thickness.left) hit |= left;
if (pt.x > rc.right - border_thickness.right) hit |= right;
if (pt.y < border_thickness.top) hit |= top;
if (pt.y > rc.bottom - border_thickness.bottom) hit |= bottom;
//设置窗口头部30个像素可以用来拖动
if (pt.y > border_thickness.top && pt.y < border_thickness.top + 30) hit |= caption;
if (hit & top && hit & left) return HTTOPLEFT;
if (hit & top && hit & right) return HTTOPRIGHT;
if (hit & bottom && hit & left) return HTBOTTOMLEFT;
if (hit & bottom && hit & right) return HTBOTTOMRIGHT;
if (hit & left) return HTLEFT;
if (hit & top) return HTTOP;
if (hit & right) return HTRIGHT;
if (hit & bottom) return HTBOTTOM;
if (hit & caption) return HTCAPTION;
return HTCLIENT;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
const char CLASS_NAME[] = "Sample Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
CreateWindowEx(0, CLASS_NAME, NULL,
WS_VISIBLE | WS_THICKFRAME | WS_POPUP,
10, 10, 600, 400, NULL, NULL, hInstance, NULL);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
效果
可以拖动边缘修改大小,可以拖拽顶部30个像素用来移动,虽然不明显,但是还有有点阴影