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.改变某一控件的颜色进行透明化
文章来源:https://www.toymoban.com/news/detail-492190.html
//将窗口的画刷改为透明色画刷
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去掉边框。文章来源地址https://www.toymoban.com/news/detail-492190.html
到了这里,关于MFC窗口透明化以及透明穿透的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!