MFC窗口透明化以及透明穿透

MFC编程时,有时候我们需要实现窗口透明化,可以通过SetLayeredWindowAttributes设置窗口透明色和透明度来实现窗口透明化。而要使窗口拥有透明效果,前提是窗口要有WS_EX_LAYERED扩展属性,需用SetWindowLong设置窗口支持拓展风格。

一、窗口透明化说明
1.窗口透明化有三种模式:
第一种是全窗口按透明度透明化,透明度为0时,窗口不可见,鼠标可以点击其覆盖的下层窗口;
第二种是窗口指定颜色全透明化;
第三种是窗口指定颜色全透明化,其余颜色按透明度进行透明化。
而第二、三种模式全透明化区域,根据指定颜色的不同又分为两种方式:
(1)透明,但不穿透:鼠标不能穿透窗口透明区域点击其覆盖的下层窗口。
(2)透明且穿透:鼠标可以穿透窗口透明区域点击其覆盖的下层窗口。

2.透明色特性:
(1)红色和蓝色透明色透明区域不穿透,绿色透明色透明区域穿透(其它颜色没细究过,需要自己摸索);
(2)透明色会影响画笔绘画颜色,原因不明,但可以调节透明色和画笔颜色,获得需要的绘画显示颜色,不过比较麻烦,且得不到精确RGB值的颜色。比如:红色(RGB(255,0,0))的画笔,透明色为RGB(255,0,0),在透明化窗口绘画,画笔颜色显示不为红色;透明色为RGB(0, 0, 255),在透明穿透窗口绘画,蓝色(RGB(0, 0, 255))画笔颜色显示为红色。

#define TRANSPARENT_COLOR	RGB(255,0,0)	//透明色
#define TRANSPARENT_COLOR	RGB(0,0,255)	//透明色
#define TRANSPARENT_COLOR_THROUGH	RGB(0,255,0)//透明穿透色
#define TRANSPARENT_COLOR	RGB(255,200,200) //透明色,此透明颜色时画笔颜色为RGB(255,0,0)时绘画显示仍为红色

二、SetLayeredWindowAttributes函数说明
BOOL SetLayeredWindowAttributes(
HWND hwnd, // 需要透明化窗口的句柄
COLORREF crKey, // 透明色,以RGB(r,g,b)的格式
BYTE bAlpha, // 透明度,0是全透明,255是完全不透明
DWORD dwFlags // 透明模式,有LWA_COLORKEY, LWA_ALPHA,LWA_ALPHA | LWA_COLORKEY
);
hwnd是透明窗口的句柄,
crKey为透明色,
bAlpha是透明度,取值范围是[0,255],
dwFlags是透明模式:
1.LWA_ALPHA时,crKey参数无效,bAlpha参数有效,整个窗口透明化,鼠标不能点击窗口覆盖的下层窗口,不需要在OnCtlColor指定透明色画刷,即第一种透明化模式;
2.LWA_COLORKEY时,窗体中的所有颜色为crKey的地方将变为全透明,bAlpha参数无效,需要在OnCtlColor指定透明色画刷,即第二种透明化模式。
3.LWA_ALPHA | LWA_COLORKEY时,窗体中的所有颜色为crKey的地方将变为全透明,而其它地方根据透明度bAlpha进行透明化,需要在OnCtlColor指定透明色画刷,即第三种透明化模式。
注:LWA_COLORKEY=1,LWA_ALPHA =2, LWA_ALPHA | LWA_COLORKEY=3,dwFlags亦可以设为1或者2或者3。

二、实现
在这里插入图片描述

1.全窗口按透明度透明化
在这里插入图片描述

HINSTANCE hInst = NULL;//DLL指针
typedef BOOL(WINAPI *MYFUNC)(HWND, COLORREF, BYTE, DWORD);
MYFUNC pFun = NULL;//函数指针

BOOL CSelectrectDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	SetWindowLong(this->m_hWnd, GWL_EXSTYLE, GetWindowLong(this->m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);//要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性
	hInst = LoadLibrary(L"User32.DLL"); //显式加载DLL
	if (hInst != NULL)
	{
		pFun = (MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");//取得SetLayeredWindowAttributes函数指针
		if (pFun != NULL)
			pFun(this->m_hWnd, 0, 0, LWA_ALPHA);//整个窗口按透明度透明化			
	}
	return TRUE;  
}

注:窗口透明化后,在窗口内绘画,绘图也会按透明度进行透明化。

2.窗口指定颜色全透明化
在这里插入图片描述

#define TRANSPARENT_COLOR	RGB(255,200,200)	//透明色
HINSTANCE hInst = NULL;//DLL指针
typedef BOOL(WINAPI *MYFUNC)(HWND, COLORREF, BYTE, DWORD);
MYFUNC pFun = NULL;//函数指针
CBrush m_brush;//透明色画刷

//OnCtlColor在OnInitDialog前就调用了,故需在对话框构造函数中创建透明色画刷
CtestDlg::CtestDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CtestDlg::IDD, pParent)
{
	//需要此处初始化画刷,OnCtlColor才能使用
	m_brush.CreateSolidBrush(RESERVED_COLOR);//透明色画刷
}

BOOL CSelectrectDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	SetWindowLong(this->m_hWnd, GWL_EXSTYLE, GetWindowLong(this->m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);//要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性
	hInst = LoadLibrary(L"User32.DLL"); //显式加载DLL
	if (hInst != NULL)
	{
		pFun = (MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");//取得SetLayeredWindowAttributes函数指针
		if (pFun != NULL)
			pFun(this->m_hWnd, TRANSPARENT_COLOR, 0, LWA_COLORKEY);//窗口指定颜色全透明化			
	}
	return TRUE;  
}
//将窗口的画刷改为透明色画刷
HBRUSH CtestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	// TODO:  在此更改 DC 的任何特性		
	return m_brush;
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

实现原理:先在OnCtlColor中将窗口的画刷改为透明色画刷,然后窗口就变成透明色,然后OnInitDialog中SetLayeredWindowAttributes将窗口颜色为透明色的区域变成全透明。
注:如果想实现透明穿透效果,将TRANSPARENT_COLOR换成TRANSPARENT_COLOR_THROUGH。

3.窗口指定颜色全透明化,其余颜色按透明度进行透明化
在这里插入图片描述

#define TRANSPARENT_COLOR	RGB(255,200,200)	//透明色
HINSTANCE hInst = NULL;//DLL指针
typedef BOOL(WINAPI *MYFUNC)(HWND, COLORREF, BYTE, DWORD);
MYFUNC pFun = NULL;//函数指针
CBrush m_brush;//透明色画刷

//OnCtlColor在OnInitDialog前就调用了,故需在对话框构造函数中创建透明色画刷
CtestDlg::CtestDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CtestDlg::IDD, pParent)
{
	//需要此处初始化画刷,OnCtlColor才能使用
	m_brush.CreateSolidBrush(RESERVED_COLOR);//透明色画刷
}

BOOL CSelectrectDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	SetWindowLong(this->m_hWnd, GWL_EXSTYLE, GetWindowLong(this->m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);//要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性
	hInst = LoadLibrary(L"User32.DLL"); //显式加载DLL
	if (hInst != NULL)
	{
		pFun = (MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");//取得SetLayeredWindowAttributes函数指针
		if (pFun != NULL)
			pFun(this->m_hWnd, TRANSPARENT_COLOR, 0, LWA_ALPHA | LWA_COLORKEY);//窗口指定颜色全透明化,其余颜色按透明度进行透明化			
	}
	return TRUE;  
}
//将窗口的画刷改为透明色画刷
HBRUSH CtestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	// TODO:  在此更改 DC 的任何特性		
	return m_brush;
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

实现原理:先在OnCtlColor中将窗口的画刷改为透明色画刷,然后窗口就变成透明色,然后OnInitDialog中SetLayeredWindowAttributes将窗口颜色为透明色的区域变成全透明,不是透明色的区域按透明度进行透明化处理。
注:如果透明度为0,效果跟第一种透明化模式一样,整个窗口不可见,鼠标可以点击其覆盖的下层窗口;如果想实现透明穿透效果,将TRANSPARENT_COLOR换成TRANSPARENT_COLOR_THROUGH。
三、拓展
OnCtlColor中通过参数pWnd或者nCtlColor判断,可以透明化客户区或者指定某几类控件或者某一控件透明化。以第二种模式为例:
1.改变某类控件的颜色进行透明化
在这里插入图片描述

//将窗口的画刷改为透明色画刷
HBRUSH CtestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	// TODO:  在此更改 DC 的任何特性		
	if (nCtlColor == CTLCOLOR_STATIC)
	{
		//有些控件需要改变字体颜色和字体背景色才能全透明 
		pDC->SetTextColor(TRANSPARENT_COLOR);   //设置字体颜色,字体全透明
		pDC->SetBkColor(TRANSPARENT_COLOR); //字体背景色,字体背景色全透明
		return m_brush;
	}		
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

2.改变某一控件的颜色进行透明化
在这里插入图片描述

//将窗口的画刷改为透明色画刷
HBRUSH CtestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	// TODO:  在此更改 DC 的任何特性		
	if (pWnd->GetDlgCtrlID() == IDC_STATIC)
	{
		//有些控件需要改变字体颜色和字体背景色才能全透明 
		pDC->SetTextColor(TRANSPARENT_COLOR);   //设置字体颜色,字体全透明
		pDC->SetBkColor(TRANSPARENT_COLOR); //字体背景色,字体背景色全透明
		return m_brush;
	}		
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

注:OnCtlColor可以改变客户区和某些控件的画刷颜色,但是改变不了窗口边框的颜色以及某些控件的画刷颜色,例如:Button、Slider、Picture等控件。要想将这些控件也全透明,可以使用ShowWindow(SW_HIDE)隐藏控件,在需要的时候再用ShowWindow(SW_SHOW)显示控件。如果想要将这些控件半透明,可以使用第三种透明化模式,但窗口边框也会半透明;如果想要将这些控件半透明,边框全透明,可以使用第三种透明化模式,同时用SetWindowLong去掉边框。

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MFC透明窗口穿透是指在使用Microsoft Foundation Classes(MFC)进行窗口界面设计时,实现窗口透明效果和穿透效果。 透明窗口是指窗口的背景部分可以显示出后面的内容。MFC提供了一些API和功能来实现窗口透明效果。可以通过设置窗口的样式和扩展样式来启用窗口透明效果。可以调用SetLayeredWindowAttributes函数来设置窗口透明度,通过设置透明度值来控制窗口的显示效果。使用这些功能和方法,可以实现不同程度的透明窗口效果。 穿透是指窗口透明或半透明状态下,鼠标点击事件不会被该窗口拦截,而是会传递给后面的窗口MFC提供了一些功能和方法来实现窗口穿透效果。可以通过设置窗口的样式和扩展样式来启用窗口穿透效果。通过设置窗口透明度和穿透属性,可以使鼠标点击事件透过窗口传递给后面的窗口,实现穿透效果。 需要注意的是,实现透明窗口穿透效果会涉及到系统级的API和函数调用,需要对MFC框架和Windows操作系统有一定的了解和掌握。同时,由于Windows操作系统的版本和系统设置的差异,透明窗口穿透效果在不同环境下的表现可能会有所不同。 总之,MFC透明窗口穿透是一种在Windows系统中实现窗口透明穿透效果的方法,可以通过使用MFC提供的API和函数来控制窗口透明度和穿透属性,以实现不同程度的透明窗口效果和让鼠标点击事件透过窗口传递给后面的窗口穿透效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hzl2323406

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值