windows去掉标题栏保留阴影

30 篇文章 3 订阅

参考

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 <Windows.h>
#include <windowsx.h>
#include <Dwmapi.h>

#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, &params, &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个像素用来移动,虽然不明显,但是还有有点阴影

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值