求MFC下透明界面实现方法

时间:2021-07-25 13:19:10
求MFC下透明界面实现方法


求如上图程序透明界面的实现方法
试了半天,SetLayeredWindowAttributes如果设置透明颜色,鼠标就会透过窗口;如果设置透明度,窗口上所有控件的透明度也随之改变。
如果要实现只使窗口透明,窗口上控件的透明度不变,同时窗口仍可以相应鼠标消息有什么解决方案?

21 个解决方案

#1


那就设置成颜色和透明度两个共同作用吧

#2


可以在上面创建一个悬浮对话框的镂空来放控件,然后再判断处理WM_WINDOWPOSCHANGED和WM_WINDOWPOSCHANGING来使两个窗口一起移动

#3


引用 1 楼 Frank_dishui 的回复:
那就设置成颜色和透明度两个共同作用吧


貌似只要设置了颜色,鼠标就直接透过了

#4


引用 2 楼 fishion 的回复:
可以在上面创建一个悬浮对话框的镂空来放控件,然后再判断处理WM_WINDOWPOSCHANGED和WM_WINDOWPOSCHANGING来使两个窗口一起移动


镂空是指……

#5


除了控件部分,其于部分可以用SetWindowRgn去掉,但你得计算这个rgn

#6


顶下呃……我还是木有解决 求MFC下透明界面实现方法

#7


求MFC下透明界面实现方法

#8


窗口背景透明?

#9


引用 8 楼 zxwangyun 的回复:
窗口背景透明?


看程序的效果图的话应该是对话框全透明的同时,上面的控件也透明了。
从控件中的字符显示看,应该是设置的透明色,但是界面却又能响应鼠标消息,找不到思路啊

#10


SetLayeredWindowAttributes设置好透明度,然后背景贴一个PNG图片把对话框背景搞成透明的,不知行不行?

#11


mfc在半透明窗口比较逊,只有在win8中才变得非常简单了。
http://download.csdn.net/detail/zhoujielunzhimi/5538917
这是一个半透明的例子,缺点是放在窗口上的控件看不见(我没有设置隐藏),但是可以响应。这个改变要在win8才行,到了win8,控件和窗口都可以半透明了。

目前像360,qq这样的半透明窗口,不透明或半透明控件,都是基于directui思想,就是我上面这个例子,把所有的绘制都画在一个窗口上,那些控件都是画出来的,没有句柄。

#12


引用 10 楼 zxwangyun 的回复:
SetLayeredWindowAttributes设置好透明度,然后背景贴一个PNG图片把对话框背景搞成透明的,不知行不行?


多谢关注,对话框透明包括控件透明都好解决,如下图
求MFC下透明界面实现方法
但问题在于,这样解决会使所有鼠标事件都透过窗口和控件

另外如果如fishion提到的,分层解决的话,不管怎样,控件上字符的透明度始终还是和控件的透明度一致呃……

#13


“要实现只使窗口透明,窗口上控件的不透明”
void CTransDlgDlg::OnButton1() 
{
// TODO: Add your control notification handler code here
static BOOL sw=FALSE;
if(!sw)
{
sw=TRUE;
CRect rcWin;
GetWindowRect(&rcWin);
CRect rcClt;
GetClientRect(&rcClt);
ClientToScreen(&rcClt);
//
rcClt.OffsetRect(-rcWin.left,-rcWin.top);
int offX=rcClt.left;
int offY=rcClt.top;
rcWin.OffsetRect(-rcWin.left,-rcWin.top);
//
CRgn tmp;
tmp.CreateRectRgnIndirect(&rcClt);
//
RgnSubtractCtrls(tmp,offX,offY);
//
CRgn rgn;  
rgn.CreateRectRgnIndirect(&rcWin);

rgn.CombineRgn(&rgn, &tmp, RGN_DIFF);
SetWindowRgn(rgn,TRUE);
tmp.DeleteObject();
rgn.DeleteObject();
m_Trans.SetWindowText("不透明");

}
else
{
sw=FALSE;
SetWindowRgn(0,TRUE);
m_Trans.SetWindowText("透明");
}
}

void CTransDlgDlg::RgnSubtractCtrls(CRgn &rgn,int offX,int offY)
{
CWnd *pWnd=0;
int ID[]={IDOK,IDC_BUTTON1,IDCANCEL};
for(int jj=0;jj<sizeof(ID)/sizeof(int);jj++)
{
pWnd=GetDlgItem(ID[jj]);
CRect rc;
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
rc.OffsetRect(offX,offY);
CRgn ctlRgn;
ctlRgn.CreateRectRgnIndirect(&rc);
rgn.CombineRgn(&rgn,&ctlRgn,RGN_XOR);
ctlRgn.DeleteObject();
}

#14


引用 11 楼 zhoujielunzhimi 的回复:
mfc在半透明窗口比较逊,只有在win8中才变得非常简单了。
http://download.csdn.net/detail/zhoujielunzhimi/5538917
这是一个半透明的例子,缺点是放在窗口上的控件看不见(我没有设置隐藏),但是可以响应。这个改变要在win8才行,到了win8,控件和窗口都可以半透明了。

目前像360,qq这样的半透明窗口,不透明或半透明控件,都是基于directui思想,就是我上面这个例子,把所有的绘制都画在一个窗口上,那些控件都是画出来的,没有句柄。


引用 13 楼 schlafenhamster 的回复:
“要实现只使窗口透明,窗口上控件的不透明”
void CTransDlgDlg::OnButton1() 
{
// TODO: Add your control notification handler code here
static BOOL sw=FALSE;
if(!sw)
{
sw=TRUE;
CRect rcWin;
GetWindowRect(&rcWin);
CRect rcClt;
GetClientRect(&rcClt);
ClientToScreen(&rcClt);
//
rcClt.OffsetRect(-rcWin.left,-rcWin.top);
int offX=rcClt.left;
int offY=rcClt.top;
rcWin.OffsetRect(-rcWin.left,-rcWin.top);
//
CRgn tmp;
tmp.CreateRectRgnIndirect(&rcClt);
//
RgnSubtractCtrls(tmp,offX,offY);
//
CRgn rgn;  
rgn.CreateRectRgnIndirect(&rcWin);

rgn.CombineRgn(&rgn, &tmp, RGN_DIFF);
SetWindowRgn(rgn,TRUE);
tmp.DeleteObject();
rgn.DeleteObject();
m_Trans.SetWindowText("不透明");

}
else
{
sw=FALSE;
SetWindowRgn(0,TRUE);
m_Trans.SetWindowText("透明");
}
}

void CTransDlgDlg::RgnSubtractCtrls(CRgn &rgn,int offX,int offY)
{
CWnd *pWnd=0;
int ID[]={IDOK,IDC_BUTTON1,IDCANCEL};
for(int jj=0;jj<sizeof(ID)/sizeof(int);jj++)
{
pWnd=GetDlgItem(ID[jj]);
CRect rc;
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
rc.OffsetRect(offX,offY);
CRgn ctlRgn;
ctlRgn.CreateRectRgnIndirect(&rc);
rgn.CombineRgn(&rgn,&ctlRgn,RGN_XOR);
ctlRgn.DeleteObject();
}


感谢两位大牛的回复~学习了。窗口透明,空间不透明的方法参照了论坛某贴控件使用SetParent()后即可对窗口和控件分别设置透明度,但是问题依然存在,即控件上的字符的透明度始终和控件本身透明度一致,无法达到帖子开始的控件也透明,但是控件上的字符不透明的效果。

#15


另外,还发现一个问题,win7下,完全相同的代码,在aero开关时,表现完全不一致。
如下图,使用aero主题,窗口设置了透明色,但是窗口依然能响应鼠标消息,控件也透明,但是控件上的字符不受影响。
求MFC下透明界面实现方法

同样的程序,在aero关闭时,如下图,鼠标直接透过窗口,而且控件也未透明
求MFC下透明界面实现方法

问题是,能否在非aero主题下使程序达到相同效果呢

#16


UpdateLayeredWindow+一个上层窗口
理论上可行
普通的情况 的确是可以的 因为我做过
想真的达到完美 就困难了 难点就是 如果背景是播放的某种格式的视频 可能就透不过去了 如果可以的话 放弃吧 我当时研究了很久 也没最终解决视频透明 在多种操作系统 多种视频格式的情况下 总会有例外 还有闪烁的情况 让人揪心 请果断放弃 不然必然有bug 包括迅雷那个半透的小窗口 在某些情况下都闪烁 或透不过去

#17


引用 16 楼 allenhiman 的回复:
UpdateLayeredWindow+一个上层窗口
理论上可行
普通的情况 的确是可以的 因为我做过
想真的达到完美 就困难了 难点就是 如果背景是播放的某种格式的视频 可能就透不过去了 如果可以的话 放弃吧 我当时研究了很久 也没最终解决视频透明 在多种操作系统 多种视频格式的情况下 总会有例外 还有闪烁的情况 让人揪心 请果断放弃 不然必然有bug 包括迅雷那个半透的小窗口 在某些情况下都闪烁 或透不过去

求MFC下透明界面实现方法

#18


如果有什么办法让不打开aero时,效果和打开aero一样问题就解决了……

#19


inline BOOL SetWindowTransparent(HWND hwnd, BOOL bOpaque, UINT nAlpha)
{
    // Check parameter
    if (!::IsWindow(hwnd)) {
        return FALSE;
    }
    // nAlpha needs between 0 and 255
    if (nAlpha > 255) {
        return FALSE;
    }

    if (bOpaque) {
        // Set WS_EX_LAYERED on this window 
        SetWindowLong(hwnd, 
            GWL_EXSTYLE, 
            GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);

        // Make this window 70% alpha
        ::SetLayeredWindowAttributes(hwnd, 0, (255 * nAlpha) / 100, LWA_ALPHA);
    } else {
        // Remove WS_EX_LAYERED from this window styles
        ::SetWindowLong(hwnd, 
            GWL_EXSTYLE,
            GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
    }

    // Ask the window and its children to repaint
    ::RedrawWindow(hwnd, 
        NULL, 
        NULL, 
        RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);

    return TRUE;
}


#20


求MFC下透明界面实现方法

#21


您好
我是本版版主
此帖已多日无人关注
请您及时结帖
如您认为问题没有解决可按无满意结帖处理
另外本版设置了 疑难问题汇总帖
并已在版面置顶
相关规定其帖子中有说明
您可以根据规定提交您帖子的链接
如您目前不想结帖只需回帖说明
我们会删除此结帖通知

见此回复三日内无回应
我们将强制结帖
相关规定详见界面 界面版关于版主结帖工作的具体办法

#1


那就设置成颜色和透明度两个共同作用吧

#2


可以在上面创建一个悬浮对话框的镂空来放控件,然后再判断处理WM_WINDOWPOSCHANGED和WM_WINDOWPOSCHANGING来使两个窗口一起移动

#3


引用 1 楼 Frank_dishui 的回复:
那就设置成颜色和透明度两个共同作用吧


貌似只要设置了颜色,鼠标就直接透过了

#4


引用 2 楼 fishion 的回复:
可以在上面创建一个悬浮对话框的镂空来放控件,然后再判断处理WM_WINDOWPOSCHANGED和WM_WINDOWPOSCHANGING来使两个窗口一起移动


镂空是指……

#5


除了控件部分,其于部分可以用SetWindowRgn去掉,但你得计算这个rgn

#6


顶下呃……我还是木有解决 求MFC下透明界面实现方法

#7


求MFC下透明界面实现方法

#8


窗口背景透明?

#9


引用 8 楼 zxwangyun 的回复:
窗口背景透明?


看程序的效果图的话应该是对话框全透明的同时,上面的控件也透明了。
从控件中的字符显示看,应该是设置的透明色,但是界面却又能响应鼠标消息,找不到思路啊

#10


SetLayeredWindowAttributes设置好透明度,然后背景贴一个PNG图片把对话框背景搞成透明的,不知行不行?

#11


mfc在半透明窗口比较逊,只有在win8中才变得非常简单了。
http://download.csdn.net/detail/zhoujielunzhimi/5538917
这是一个半透明的例子,缺点是放在窗口上的控件看不见(我没有设置隐藏),但是可以响应。这个改变要在win8才行,到了win8,控件和窗口都可以半透明了。

目前像360,qq这样的半透明窗口,不透明或半透明控件,都是基于directui思想,就是我上面这个例子,把所有的绘制都画在一个窗口上,那些控件都是画出来的,没有句柄。

#12


引用 10 楼 zxwangyun 的回复:
SetLayeredWindowAttributes设置好透明度,然后背景贴一个PNG图片把对话框背景搞成透明的,不知行不行?


多谢关注,对话框透明包括控件透明都好解决,如下图
求MFC下透明界面实现方法
但问题在于,这样解决会使所有鼠标事件都透过窗口和控件

另外如果如fishion提到的,分层解决的话,不管怎样,控件上字符的透明度始终还是和控件的透明度一致呃……

#13


“要实现只使窗口透明,窗口上控件的不透明”
void CTransDlgDlg::OnButton1() 
{
// TODO: Add your control notification handler code here
static BOOL sw=FALSE;
if(!sw)
{
sw=TRUE;
CRect rcWin;
GetWindowRect(&rcWin);
CRect rcClt;
GetClientRect(&rcClt);
ClientToScreen(&rcClt);
//
rcClt.OffsetRect(-rcWin.left,-rcWin.top);
int offX=rcClt.left;
int offY=rcClt.top;
rcWin.OffsetRect(-rcWin.left,-rcWin.top);
//
CRgn tmp;
tmp.CreateRectRgnIndirect(&rcClt);
//
RgnSubtractCtrls(tmp,offX,offY);
//
CRgn rgn;  
rgn.CreateRectRgnIndirect(&rcWin);

rgn.CombineRgn(&rgn, &tmp, RGN_DIFF);
SetWindowRgn(rgn,TRUE);
tmp.DeleteObject();
rgn.DeleteObject();
m_Trans.SetWindowText("不透明");

}
else
{
sw=FALSE;
SetWindowRgn(0,TRUE);
m_Trans.SetWindowText("透明");
}
}

void CTransDlgDlg::RgnSubtractCtrls(CRgn &rgn,int offX,int offY)
{
CWnd *pWnd=0;
int ID[]={IDOK,IDC_BUTTON1,IDCANCEL};
for(int jj=0;jj<sizeof(ID)/sizeof(int);jj++)
{
pWnd=GetDlgItem(ID[jj]);
CRect rc;
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
rc.OffsetRect(offX,offY);
CRgn ctlRgn;
ctlRgn.CreateRectRgnIndirect(&rc);
rgn.CombineRgn(&rgn,&ctlRgn,RGN_XOR);
ctlRgn.DeleteObject();
}

#14


引用 11 楼 zhoujielunzhimi 的回复:
mfc在半透明窗口比较逊,只有在win8中才变得非常简单了。
http://download.csdn.net/detail/zhoujielunzhimi/5538917
这是一个半透明的例子,缺点是放在窗口上的控件看不见(我没有设置隐藏),但是可以响应。这个改变要在win8才行,到了win8,控件和窗口都可以半透明了。

目前像360,qq这样的半透明窗口,不透明或半透明控件,都是基于directui思想,就是我上面这个例子,把所有的绘制都画在一个窗口上,那些控件都是画出来的,没有句柄。


引用 13 楼 schlafenhamster 的回复:
“要实现只使窗口透明,窗口上控件的不透明”
void CTransDlgDlg::OnButton1() 
{
// TODO: Add your control notification handler code here
static BOOL sw=FALSE;
if(!sw)
{
sw=TRUE;
CRect rcWin;
GetWindowRect(&rcWin);
CRect rcClt;
GetClientRect(&rcClt);
ClientToScreen(&rcClt);
//
rcClt.OffsetRect(-rcWin.left,-rcWin.top);
int offX=rcClt.left;
int offY=rcClt.top;
rcWin.OffsetRect(-rcWin.left,-rcWin.top);
//
CRgn tmp;
tmp.CreateRectRgnIndirect(&rcClt);
//
RgnSubtractCtrls(tmp,offX,offY);
//
CRgn rgn;  
rgn.CreateRectRgnIndirect(&rcWin);

rgn.CombineRgn(&rgn, &tmp, RGN_DIFF);
SetWindowRgn(rgn,TRUE);
tmp.DeleteObject();
rgn.DeleteObject();
m_Trans.SetWindowText("不透明");

}
else
{
sw=FALSE;
SetWindowRgn(0,TRUE);
m_Trans.SetWindowText("透明");
}
}

void CTransDlgDlg::RgnSubtractCtrls(CRgn &rgn,int offX,int offY)
{
CWnd *pWnd=0;
int ID[]={IDOK,IDC_BUTTON1,IDCANCEL};
for(int jj=0;jj<sizeof(ID)/sizeof(int);jj++)
{
pWnd=GetDlgItem(ID[jj]);
CRect rc;
pWnd->GetWindowRect(&rc);
ScreenToClient(&rc);
rc.OffsetRect(offX,offY);
CRgn ctlRgn;
ctlRgn.CreateRectRgnIndirect(&rc);
rgn.CombineRgn(&rgn,&ctlRgn,RGN_XOR);
ctlRgn.DeleteObject();
}


感谢两位大牛的回复~学习了。窗口透明,空间不透明的方法参照了论坛某贴控件使用SetParent()后即可对窗口和控件分别设置透明度,但是问题依然存在,即控件上的字符的透明度始终和控件本身透明度一致,无法达到帖子开始的控件也透明,但是控件上的字符不透明的效果。

#15


另外,还发现一个问题,win7下,完全相同的代码,在aero开关时,表现完全不一致。
如下图,使用aero主题,窗口设置了透明色,但是窗口依然能响应鼠标消息,控件也透明,但是控件上的字符不受影响。
求MFC下透明界面实现方法

同样的程序,在aero关闭时,如下图,鼠标直接透过窗口,而且控件也未透明
求MFC下透明界面实现方法

问题是,能否在非aero主题下使程序达到相同效果呢

#16


UpdateLayeredWindow+一个上层窗口
理论上可行
普通的情况 的确是可以的 因为我做过
想真的达到完美 就困难了 难点就是 如果背景是播放的某种格式的视频 可能就透不过去了 如果可以的话 放弃吧 我当时研究了很久 也没最终解决视频透明 在多种操作系统 多种视频格式的情况下 总会有例外 还有闪烁的情况 让人揪心 请果断放弃 不然必然有bug 包括迅雷那个半透的小窗口 在某些情况下都闪烁 或透不过去

#17


引用 16 楼 allenhiman 的回复:
UpdateLayeredWindow+一个上层窗口
理论上可行
普通的情况 的确是可以的 因为我做过
想真的达到完美 就困难了 难点就是 如果背景是播放的某种格式的视频 可能就透不过去了 如果可以的话 放弃吧 我当时研究了很久 也没最终解决视频透明 在多种操作系统 多种视频格式的情况下 总会有例外 还有闪烁的情况 让人揪心 请果断放弃 不然必然有bug 包括迅雷那个半透的小窗口 在某些情况下都闪烁 或透不过去

求MFC下透明界面实现方法

#18


如果有什么办法让不打开aero时,效果和打开aero一样问题就解决了……

#19


inline BOOL SetWindowTransparent(HWND hwnd, BOOL bOpaque, UINT nAlpha)
{
    // Check parameter
    if (!::IsWindow(hwnd)) {
        return FALSE;
    }
    // nAlpha needs between 0 and 255
    if (nAlpha > 255) {
        return FALSE;
    }

    if (bOpaque) {
        // Set WS_EX_LAYERED on this window 
        SetWindowLong(hwnd, 
            GWL_EXSTYLE, 
            GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);

        // Make this window 70% alpha
        ::SetLayeredWindowAttributes(hwnd, 0, (255 * nAlpha) / 100, LWA_ALPHA);
    } else {
        // Remove WS_EX_LAYERED from this window styles
        ::SetWindowLong(hwnd, 
            GWL_EXSTYLE,
            GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
    }

    // Ask the window and its children to repaint
    ::RedrawWindow(hwnd, 
        NULL, 
        NULL, 
        RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);

    return TRUE;
}


#20


求MFC下透明界面实现方法

#21


您好
我是本版版主
此帖已多日无人关注
请您及时结帖
如您认为问题没有解决可按无满意结帖处理
另外本版设置了 疑难问题汇总帖
并已在版面置顶
相关规定其帖子中有说明
您可以根据规定提交您帖子的链接
如您目前不想结帖只需回帖说明
我们会删除此结帖通知

见此回复三日内无回应
我们将强制结帖
相关规定详见界面 界面版关于版主结帖工作的具体办法