Windows核心编程_组件透明

效果图:

其实实现方法非常简单,只需要两个窗口,一个负责主窗口另外一个负责透明即可:

首先依旧创建一个Win32工程:

#include "stdafx.h"
#include <windows.h>

HWND hWnd;	//progman

//消息函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	//判断消息ID
	switch (uMsg){

	case WM_DESTROY:    // 窗口销毁消息
		PostQuitMessage(0);   //  发送退出消息
		return 0;
	}
	// 其他的消息调用缺省的消息处理程序
	return DefWindowProc(hwnd, uMsg, wParam, lParam);

}
// 3、注册窗口类型
BOOL RegisterWindow(LPCSTR lpcWndName, HINSTANCE hInstance)
{
	ATOM nAtom = 0;
	// 构造创建窗口参数
	WNDCLASS wndClass = { 0 };
	wndClass.style = CS_HREDRAW | CS_VREDRAW;
	wndClass.lpfnWndProc = WindowProc;      // 指向窗口过程函数
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hInstance = hInstance;
	wndClass.hIcon = NULL;
	wndClass.hCursor = NULL;
	wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wndClass.lpszMenuName = NULL;
	wndClass.lpszClassName = lpcWndName;    // 注册的窗口名称,并非标题,以后创建窗口根据此注册的名称创建
	nAtom = RegisterClass(&wndClass);
	return TRUE;
}
//创建窗口(lpClassName 一定是已经注册过的窗口类型)
HWND CreateMyWindow(LPCTSTR lpClassName, HINSTANCE hInstance)
{
	HWND hWnd = NULL;
	// 创建窗口
	hWnd = CreateWindow(lpClassName, "test", WS_OVERLAPPEDWINDOW^WS_THICKFRAME, 0, 0, 1000, 800, NULL, NULL, hInstance, NULL);
	return hWnd;
}
//显示窗口
void DisplayMyWnd(HWND hWnd)
{
	//获得屏幕尺寸

	int scrWidth = GetSystemMetrics(SM_CXSCREEN);
	int scrHeight = GetSystemMetrics(SM_CYSCREEN);
	RECT rect;
	GetWindowRect(hWnd, &rect);
	ShowWindow(hWnd, SW_SHOW);
	//重新设置rect里的值
	rect.left = (scrWidth - rect.right) / 2;
	rect.top = (scrHeight - rect.bottom) / 2;
	//移动窗口到指定的位置
	SetWindowPos(hWnd, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);
	UpdateWindow(hWnd);
}

void doMessage()        // 消息循环处理函数
{
	MSG msg = { 0 };
	// 获取消息
	while (GetMessage(&msg, NULL, 0, 0)) // 当接收到WM_QIUT消息时,GetMessage函数返回0,结束循环
	{
		DispatchMessage(&msg); // 派发消息,到WindowPro函数处理
	}
}

// 入口函数
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nShowCmd)
{
	LPCTSTR lpClassName = "MyWnd";  // 注册窗口的名称
	RegisterWindow(lpClassName, hInstance);
	hWnd = CreateMyWindow(lpClassName, hInstance);
	DisplayMyWnd(hWnd);
	doMessage();
	return 0;
}

在主窗口消息循环里添加绘图消息绘制背景图:

case WM_PAINT:
		PAINTSTRUCT ps;
		HDC hdc;
		HBITMAP hbmp;// 位图绘制对象句柄,模糊图像
		HDC mdc;
		hdc = BeginPaint(hwnd, &ps);
		mdc = CreateCompatibleDC(hdc); // 创建兼容的缓存DC对象
		//加载位图
		hbmp = (HBITMAP)LoadImage(
			NULL, // 模块实例句柄
			"C:\\Users\\ZZH\\Desktop\\D.bmp", // 位图路径。注意双斜杠,单斜杠表示转义,此时文件会加载不成功!!!
			IMAGE_BITMAP, // 图片类型
			1000,
			800,
			LR_LOADFROMFILE // 从路径处加载图片
			);
		// 缓存DC(mdc)选择位图绘制对象(可以理解为将图片保存到mdc中)
		SelectObject(mdc, hbmp);
		BitBlt(
			hdc, // 目的DC
			0, 0,
			1000, // 目的DC的 x,y 坐标
			800,
			mdc, // 缓存DC
			0, 0, // 缓存DC的x,y坐标
			SRCCOPY // 粘贴方式
			);
		DeleteObject(hbmp);
		DeleteDC(mdc);
		EndPaint(hwnd, &ps);
		break;

在Main函数里创建一个透明窗口,并在上面添加edit控件:

在此之前添加一个全局的句柄变量用于保存透明窗口的HWND方便移动:

HWND M_hwnd;

	//CREATE
	GetClientRect(hWnd, &rect);	//对于客户区左上角为0
	PO.x = rect.left;		//0
	PO.y = rect.top;		//0
	//屏幕坐标转换,转换前需要给PO结构体赋予客户区坐标,也就是给PO结构体赋予初始值Windows才能转换
	ClientToScreen(hWnd, &PO);
	M_hwnd = CreateWindowEx(WS_EX_LAYERED, lpClassName, NULL, WS_POPUP, PO.x + 10, PO.y + 10, 33, 22, hWnd, NULL, GetModuleHandle(NULL), NULL);	//坐标是左上角坐标所以我们要+偏移量得到对应的客户区坐标
	//透明化
	SetLayeredWindowAttributes(M_hwnd, RGB(0, 0, 0), 155, LWA_ALPHA);
	//创建控件
	Edit = CreateWindow(   //edit控件
		"edit",
		"SS",
		WS_VISIBLE | WS_CHILD | WS_BORDER/*|DT_CENTER*/ | DT_VCENTER,
		0, 0, 33, 22,
		M_hwnd,
		NULL,
		NULL,
		NULL);
	//SHOW
	ShowWindow(M_hwnd, SW_SHOW);

在主窗口的消息循环函数里修改MOVE消息:

case WM_MOVE:
		RECT rect; //RECT
		POINT PO;	//屏幕坐标
		//获取窗口的客户区坐标
		GetClientRect(hWnd, &rect);	//对于客户区左上角为0
		PO.x = rect.left;		//0
		PO.y = rect.top;		//0
		//屏幕坐标转换,转换前需要给PO结构体赋予客户区坐标,也就是给PO结构体赋予初始值Windows才能转换
		ClientToScreen(hWnd, &PO);
		MoveWindow(M_hwnd, PO.x + 10, PO.y + 10, 33, 22, TRUE);
		break;

运行效果:

完整代码:

#include "stdafx.h"
#include <windows.h>

HWND hWnd;	//progman
HWND M_hwnd;
//消息函数
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	//判断消息ID
	switch (uMsg){
	case WM_PAINT:
		PAINTSTRUCT ps;
		HDC hdc;
		HBITMAP hbmp;// 位图绘制对象句柄,模糊图像
		HDC mdc;
		hdc = BeginPaint(hwnd, &ps);
		mdc = CreateCompatibleDC(hdc); // 创建兼容的缓存DC对象
		//加载位图
		hbmp = (HBITMAP)LoadImage(
			NULL, // 模块实例句柄
			"C:\\Users\\ZZH\\Desktop\\D.bmp", // 位图路径。注意双斜杠,单斜杠表示转义,此时文件会加载不成功!!!
			IMAGE_BITMAP, // 图片类型
			1000,
			800,
			LR_LOADFROMFILE // 从路径处加载图片
			);
		// 缓存DC(mdc)选择位图绘制对象(可以理解为将图片保存到mdc中)
		SelectObject(mdc, hbmp);
		BitBlt(
			hdc, // 目的DC
			0, 0,
			1000, // 目的DC的 x,y 坐标
			800,
			mdc, // 缓存DC
			0, 0, // 缓存DC的x,y坐标
			SRCCOPY // 粘贴方式
			);
		DeleteObject(hbmp);
		DeleteDC(mdc);
		EndPaint(hwnd, &ps);
		break;
	case WM_MOVE:
		RECT rect; //RECT
		POINT PO;	//屏幕坐标
		//获取窗口的客户区坐标
		GetClientRect(hWnd, &rect);	//对于客户区左上角为0
		PO.x = rect.left;		//0
		PO.y = rect.top;		//0
		//屏幕坐标转换,转换前需要给PO结构体赋予客户区坐标,也就是给PO结构体赋予初始值Windows才能转换
		ClientToScreen(hWnd, &PO);
		MoveWindow(M_hwnd, PO.x + 10, PO.y + 10, 33, 22, TRUE);
		break;
	case WM_DESTROY:    // 窗口销毁消息
		PostQuitMessage(0);   //  发送退出消息
		return 0;
	}
	// 其他的消息调用缺省的消息处理程序
	return DefWindowProc(hwnd, uMsg, wParam, lParam);

}
// 3、注册窗口类型
BOOL RegisterWindow(LPCSTR lpcWndName, HINSTANCE hInstance)
{
	ATOM nAtom = 0;
	// 构造创建窗口参数
	WNDCLASS wndClass = { 0 };
	wndClass.style = CS_HREDRAW | CS_VREDRAW;
	wndClass.lpfnWndProc = WindowProc;      // 指向窗口过程函数
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hInstance = hInstance;
	wndClass.hIcon = NULL;
	wndClass.hCursor = NULL;
	wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wndClass.lpszMenuName = NULL;
	wndClass.lpszClassName = lpcWndName;    // 注册的窗口名称,并非标题,以后创建窗口根据此注册的名称创建
	nAtom = RegisterClass(&wndClass);
	return TRUE;
}
//创建窗口(lpClassName 一定是已经注册过的窗口类型)
HWND CreateMyWindow(LPCTSTR lpClassName, HINSTANCE hInstance)
{
	HWND hWnd = NULL;
	// 创建窗口
	hWnd = CreateWindow(lpClassName, "test", WS_OVERLAPPEDWINDOW^WS_THICKFRAME, 0, 0, 1000, 800, NULL, NULL, hInstance, NULL);
	return hWnd;
}
//显示窗口
void DisplayMyWnd(HWND hWnd)
{
	//获得屏幕尺寸

	int scrWidth = GetSystemMetrics(SM_CXSCREEN);
	int scrHeight = GetSystemMetrics(SM_CYSCREEN);
	RECT rect;
	GetWindowRect(hWnd, &rect);
	ShowWindow(hWnd, SW_SHOW);
	//重新设置rect里的值
	rect.left = (scrWidth - rect.right) / 2;
	rect.top = (scrHeight - rect.bottom) / 2;
	//移动窗口到指定的位置
	SetWindowPos(hWnd, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);
	UpdateWindow(hWnd);
}

void doMessage()        // 消息循环处理函数
{
	MSG msg = { 0 };
	// 获取消息
	while (GetMessage(&msg, NULL, 0, 0)) // 当接收到WM_QIUT消息时,GetMessage函数返回0,结束循环
	{
		DispatchMessage(&msg); // 派发消息,到WindowPro函数处理
	}
}

// 入口函数
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nShowCmd)
{
	LPCTSTR lpClassName = "MyWnd";  // 注册窗口的名称
	RegisterWindow(lpClassName, hInstance);
	hWnd = CreateMyWindow(lpClassName, hInstance);
	HWND Edit;	//EDIT
	RECT rect; //RECT
	POINT PO;	//屏幕坐标
	//创建具有扩展风格的窗口
	//获取窗口的客户区坐标
	DisplayMyWnd(hWnd);
	//CREATE
	GetClientRect(hWnd, &rect);	//对于客户区左上角为0
	PO.x = rect.left;		//0
	PO.y = rect.top;		//0
	//屏幕坐标转换,转换前需要给PO结构体赋予客户区坐标,也就是给PO结构体赋予初始值Windows才能转换
	ClientToScreen(hWnd, &PO);
	M_hwnd = CreateWindowEx(WS_EX_LAYERED, lpClassName, NULL, WS_POPUP, PO.x + 10, PO.y + 10, 33, 22, hWnd, NULL, GetModuleHandle(NULL), NULL);	//坐标是左上角坐标所以我们要+偏移量得到对应的客户区坐标
	//透明化
	SetLayeredWindowAttributes(M_hwnd, RGB(0, 0, 0), 155, LWA_ALPHA);
	//创建控件
	Edit = CreateWindow(   //edit控件
		"edit",
		"SS",
		WS_VISIBLE | WS_CHILD | WS_BORDER/*|DT_CENTER*/ | DT_VCENTER,
		0, 0, 33, 22,
		M_hwnd,
		NULL,
		NULL,
		NULL);
	//SHOW
	ShowWindow(M_hwnd, SW_SHOW);
	doMessage();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

17岁boy想当攻城狮

感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值