Windows 透明绿边窗口

需求

在 Windows 上,一些视频会议软件进行屏幕分享的时候,分享的屏幕时会有一个绿色边框将其标记出来,方便分享人知道当前正在分享的是哪一个屏幕,这篇博客主要就介绍一下如何实现这么一个窗口。

我们要做到下面几个点

1、始终置顶窗口(WS_EX_TOPMOST)

2、透明并且可穿透(WS_EX_LAYERED | WS_EX_TRANSPARENT)

3、没有最大化、最小化等(WS_EX_TOOLWINDOW)

4、有绿边(使用 Gdiplus::SolidBrush)

具体实现

1、创建一个透明窗口,这里使用到的扩展属性是 WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW

#include <Windows.h>

LRESULT CALLBACK WndProc(HWND hWND, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_ERASEBKGND:
		return 0;
	case WM_CLOSE:
		DestroyWindow(hWND);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWND, msg, wParam, lParam);
	}
	return 0;
}

int main(void) {
	HINSTANCE hinstance = GetModuleHandle(0);
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = 0;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hinstance;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = "TransparentWindow";
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	if (!RegisterClassEx(&wc))
	{
		return NULL;
	}
	HWND hwnd = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, "TransparentWindow", "TransparentWindow", WS_POPUP | WS_VISIBLE, 0, 0, 1920, 1080, NULL, NULL, hinstance, NULL);
	if (!hwnd)
	{
		return NULL;
	}
	MSG msg = { 0 };
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

2、上面我们创建了一个大小为 1920 x 1080 的窗口,也就是我的屏幕大小,接下来需要给这个窗口带上绿边,这里我们填充 4 个矩形区域,可以先看下面的图

就像上面两张图片这样,假设绿边的宽度为 4,那么我们需要将

上方:{0,0,width,4}

下方:{0,height-4,width,4}

左方:{0,4,4,height-4}

右方:{width-4,4,4,height-4}

这四个区域填充为绿色,接下来我们填充区域

全部代码

#include <Windows.h>

extern "C" {
#include <gdiplus.h>
}

#pragma comment(lib, "Gdiplus.lib")

LRESULT CALLBACK WndProc(HWND hWND, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_ERASEBKGND:
		return 0;
	case WM_CLOSE:
		DestroyWindow(hWND);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWND, msg, wParam, lParam);
	}
	return 0;
}

void FillWindow(HWND hwnd) {
	RECT rect;
	GetClientRect(hwnd, &rect);
	int width = rect.right - rect.left;
	int height = rect.bottom - rect.top;
	int linesize = 4;

	HDC hdc = GetDC(hwnd);

	HDC mem_dc = ::CreateCompatibleDC(hdc);
	HBITMAP hbitmap = ::CreateCompatibleBitmap(hdc, width, height);
	HBITMAP old_hbitmap = (HBITMAP)::SelectObject(mem_dc, hbitmap);

	Gdiplus::Graphics graphics(mem_dc);
	graphics.Clear(Gdiplus::Color(255, 0, 0));
	Gdiplus::SolidBrush brush(Gdiplus::Color(0, 230, 0));

	graphics.FillRectangle(&brush, 0, 0, width, linesize);
	graphics.FillRectangle(&brush, 0, height - linesize, width, linesize);
	graphics.FillRectangle(&brush, 0, linesize, linesize, height-4);
	graphics.FillRectangle(&brush, width - linesize, linesize, linesize, height-4);

	BLENDFUNCTION bs = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
	tagPOINT pos{ 0,0 };
	tagPOINT dstPos = { rect.left, rect.top };
	tagSIZE  dstSize = { width, height };
	BOOL bRes = ::UpdateLayeredWindow(hwnd, hdc, &dstPos, &dstSize, graphics.GetHDC(), &pos, RGB(255, 0, 0), &bs, ULW_COLORKEY);

	graphics.ReleaseHDC(mem_dc);
	::SelectObject(mem_dc, old_hbitmap);
	::DeleteDC(mem_dc);
	::DeleteObject(hbitmap);
	ReleaseDC(hwnd, hdc);

	mem_dc = NULL;
	hbitmap = NULL;
	old_hbitmap = NULL;
}

int main(void) {
	SetProcessDPIAware();
	HINSTANCE hinstance = GetModuleHandle(0);
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = 0;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hinstance;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = "TransparentWindow";
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	if (!RegisterClassEx(&wc))
	{
		return NULL;
	}
	HWND hwnd = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, "TransparentWindow", "TransparentWindow", 
		WS_POPUP | WS_VISIBLE, 0, 0, 1920, 1080, NULL, NULL, hinstance, NULL);
	if (!hwnd)
	{
		return NULL;
	}
	Gdiplus::GdiplusStartupInput input;
	Gdiplus::GdiplusStartupOutput output;
	ULONG_PTR token;
	Gdiplus::Status status = GdiplusStartup(&token, &input, &output);
	
	FillWindow(hwnd);
	MSG msg = { 0 };
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	Gdiplus::GdiplusShutdown(token);
	return 0;
}

可以自己手动运行观察效果

Windows操作系统是由微软公司开发的一款广泛应用于个人计算机的操作系统。它的各个版本都有不同的桌面设计。 Windows 1.0是最早的版本,于1985年发布。它的桌面设计非常简单,只有一些基本图标,如计算器和日历。用户可以通过键盘和鼠标进行操作。 然后是Windows 3.0/3.1,发布于1990年代初。它的桌面设计更加丰富,增加了图形界面的支持。用户可以使用窗口和菜单来操作应用程序。此外,还增加了底部任务栏和开始菜单,以方便用户访问应用程序和设置。 Windows 95是Windows操作系统的一个重大升级,于1995年发布。它引入了“开始”按钮和任务栏的概念,用户可以通过开始菜单快速访问应用程序和文件。此外,桌面图标和窗口的设计也更加美观。 Windows XP是Windows系统最受欢迎的版本之一,于2001年发布。它的桌面设计相对简洁,采用了蓝色的背景和绿色的开始按钮。用户可以通过开始菜单访问应用程序、设置和文件夹等。 Windows 7是Windows操作系统的另一个经典版本,于2009年发布。它的桌面设计更加现代化,增加了透明效果和任务栏预览等功能。开始菜单也面临了一些改变,增加了搜索和快速启动等功能。 Windows 10是目前最新的Windows版本,于2015年发布。它的桌面设计延续了Windows 7和Windows 8的特点,同时加入了一些新的功能,如虚拟桌面和通知中心。 总之,随着Windows操作系统的不断发展,其桌面设计也在不断演变。不同版本的桌面设计都有其独特的特点和优势,以满足用户的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值