vc怎么实现窗体透明呢?

时间:2022-09-25 11:45:39
想大家都见过那种透明的窗体,例如:QQ的透明设置,千千静听的透明,....高级的如:win7的透明窗体...。
也许我们最先联想到的函数有SetLayeredWindowAttributes和UpdateLayeredWindow
先不说这两个函数的限制有多大,就拿毛玻璃透明来说,我想用这两个函数就很难实现了。
因此,不能纠结在这两个函数上,而是要了解其内部原理。可是其原理是什么呢?我就不得而知了...
我曾想过,透明的话,要获取背景然后和窗体进行透明融合计算,不过这种即使能勉强做好,估计也很占cpu,而且要时时更新(不知道背景是否变,所以要实时的重新计算),这显然不可取...
因此,我想知道的是,这个透明是怎么实现的呢?换言之,窗体应该只是一个矩形,而呈现在桌面这个更大的矩形里(我的想法),只是存在图层的差异,那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来,如果是要怎么做呢?
由于对windows窗体理解不深,如果发现有言误之处还望指出,谢谢大家

还是总结一下吧,怎么不用上述的两个函数来实现窗体透明呢?如果大牛你知道,还望告知小虾,谢谢~\(≧▽≦)/~啦啦啦,再同时,分不是问题,问题如题

35 个解决方案

#1


该回复于2010-11-22 15:39:38被版主删除

#2


关注中,不过我的程序是用 PNG 图片实现透明的

#3


GUAN ZHU

#4


引用 2 楼 luawkk 的回复:
关注中,不过我的程序是用 PNG 图片实现透明的


使用png少不了用UpdateLayeredWindow函数的
O(∩_∩)O~,谢谢你的回答

#5


SetLayeredWindowAttributes用LWA_ALPHA就可以实现半透明,不知道你说的毛玻璃是什么.
SetLayeredWindowAttributes和UpdateLayeredWindow不是纯软件的做法,如果你更换显卡,效果很明显.
我觉得没有理由小看SetLayeredWindowAttributes和UpdateLayeredWindow.自己计算alpha值,用ddraw等画上去并不见的高明,我觉得微软自己也会这些.

#6


lz去看看WPF是不是你想要的吧.

#7


引用 5 楼 eyey1 的回复:
SetLayeredWindowAttributes用LWA_ALPHA就可以实现半透明,不知道你说的毛玻璃是什么.
SetLayeredWindowAttributes和UpdateLayeredWindow不是纯软件的做法,如果你更换显卡,效果很明显.
我觉得没有理由小看SetLayeredWindowAttributes和UpdateLayeredWindow.自己计算alpha值,用……

如果你用过WIN7,或者迅雷7,你就知道了,那两个函数确实很强大的,可是想知道具体原理,而并非用法

#8


SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^WS_EX_LAYERED); 
SetLayeredWindowAttributes(this->m_hWnd,0,128,2); 

#9


该回复于2010-11-23 10:08:34被版主删除

#10


引用 8 楼 linuxchenyy 的回复:
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^WS_EX_LAYERED); 
SetLayeredWindowAttributes(this->m_hWnd,0,128,2);


谢谢你的回答,可能你没注意看我的问题吧,不要用法哦,

#11


引用 7 楼 hkf314 的回复:
引用 5 楼 eyey1 的回复:

SetLayeredWindowAttributes用LWA_ALPHA就可以实现半透明,不知道你说的毛玻璃是什么.
SetLayeredWindowAttributes和UpdateLayeredWindow不是纯软件的做法,如果你更换显卡,效果很明显.
我觉得没有理由小看SetLayeredWindowAttributes和UpdateLayere……

原理就像你说的,用alpha融合和背景计算,但利用了GPU的计算能力, 对没有GPU的电脑(比如集成显卡)使用纯软件的方法,CPU的loading就会加重.
如何利用GPU可能你要自己查资料了,可能GPU提供的功能不止alpha融合这么简单,可能还有图层的功能,不了解.
SetLayeredWindowAttributes没有公开源码,以上仅是猜测.

#12


LZ,借地问个问题
UpdateLayeredWindow 内部如何实现?
直接用GDI+画透明图片上去就可以透明

#13


使用SetLayeredWindowAttributes可以方便的制作透明窗体,此函数在w2k以上才支持,而且如果希望直接使用的话,可能需要下载最新的SDK。不过此函数在w2k的user32.dll里有实现,所以如果你不希望下载巨大的sdk的话,可以直接使用GetProcAddress获取该函数的指针。


  SetLayeredWindowAttributes的函数原型如下:

BOOL SetLayeredWindowAttributes(
HWND hwnd, // handle to the layered window
COLORREF crKey, // specifies the color key
BYTE bAlpha, // value for the blend function
DWORD dwFlags // action
); 


Windows NT/2000/XP: Included in Windows 2000 and later.
Windows 95/98/Me: Unsupported.(注意了,在win9x里没法使用的)
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib. 
 

  一些常量:


WS_EX_LAYERED = 0x80000;
LWA_ALPHA = 0x2;
LWA_COLORKEY=0x1; 

  其中dwFlags有LWA_ALPHA和LWA_COLORKEY

  LWA_ALPHA被设置的话,通过bAlpha决定透明度.

  LWA_COLORKEY被设置的话,则指定被透明掉的颜色为crKey,其他颜色则正常显示.

  要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性(旧的sdk没有定义这个属性,所以可以直接指定为0x80000). 

  例子代码:

  在OnInitDialog()加入: 

//加入WS_EX_LAYERED扩展属性
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
HINSTANCE hInst = LoadLibrary("User32.DLL"); 
if(hInst) 

 typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD); 
 MYFUNC fun = NULL;
 //取得SetLayeredWindowAttributes函数指针 
 fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
 if(fun)fun(this->GetSafeHwnd(),0,128,2); 
 FreeLibrary(hInst); 


  稍加修改还可以作出淡出淡入的效果. 注意第三个参数(128)不要取得太小了,为0的话就完全透明,看不到了。

  如何使框架窗口的图标为动画显示

  可以用TIMER,但是TIMER不能有效的定时。因为TIMER发送的是窗口消息,当窗口忙于处理键盘、鼠标等消息时就不能及时处理TIMER,会使间隔时间变得很长 。

  可以考虑用一个单独得TIMER线程,用Sleep()定时来解决此问题。


UINT Timer(LPVOID param)
{
 HWND hWnd=(HWND)param;
 while(1)
 {
  Sleep(ms);
  PostMessage(hWnd,CH_PICTURE,NULL,NULL)
 }


  Sleep(ms)后发送自定义消息。消息处理函数就选择某一个ICON或BITMAP来显示。如 :


MyBotton.SetBitmap((HBITMAP)Bitmap[i]); 

  Bitmap是一个位图数组,存放有j个位图。消息处理函数运行一次,i就累加一次,当i==j时,i就回到0;

#14


该回复于2010-11-23 14:30:23被版主删除

#15


引用楼主 hkf314 的回复:
那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来


不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。

SetLayeredWindowAttributes 我个人认为就是设置了一个标志量,当第n层的标志位表示
需要融合时,就与第n-1 层进行像素的融合。

#16


学习,我只知道是ALPHA起了作用!导致上层图片可以融合到下面的图片层,就是一个通道的问题!

#17


引用 15 楼 wangbo56916860 的回复:
引用楼主 hkf314 的回复:
那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来


不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。

SetLayeredWindowAttributes 我个人认为就是设置了一个标志量,当第n层的标志位表示
需要融合时,就与第n-1 层进行像素的融合。


如果透明窗口下还一个或多个透明窗体呢?

#18


谢谢13楼详细的回答,不过那些我都知道,我想了解的是其大概的原理,不过你的回答还是相当有用的 

#19


引用 12 楼 a316586261 的回复:
LZ,借地问个问题
UpdateLayeredWindow 内部如何实现?
直接用GDI+画透明图片上去就可以透明


这也是我想知道的哦,其内部是什么原理呢?
仅仅GDI+画图片是不可能实现的

#20


引用 17 楼 hkf314 的回复:
引用 15 楼 wangbo56916860 的回复:
引用楼主 hkf314 的回复:
那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来


不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。

SetLayeredWindowAttributes 我个人认为就是设置了一个标志量,当第n层的标志位表示
需要融……

n-1 层是 n-1 和n-2  融合过的。 n 层和 n-1 层融合 就相当于 n 和 n-1 ,n-2 一起融合了

也就是说 n 层和 n-1 层融合就足够了

#21


引用 20 楼 wangbo56916860 的回复:
不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。
SetLayeredWindowAttributes 我个人认为就是设置……

n-1层依然要融合,也就是说要从底层融合到顶层,只是融合的窗体不一样,但是这个就是整个系统完成吧,而并非窗体自己完成的

#22


VISTA/WIN7的毛玻璃效果可是跟SetLayeredWindowAttributes/UpdateLayeredWindow毫无关系的,它只跟DWM相关,并以桌面主题的方式提供,任何一个具有边框的普通窗口都自动具备毛玻璃效果。

一旦DWM激活,整个桌面就是一个全屏的3D窗口,所有应用程序的窗口DC不再是真正的屏幕DC,而是一个3D纹理表面(这一点微软有文章介绍,跟DC相关的API都被重写了,一旦DWM激活,获取的窗口DC被重定向到一个D3D表面,GDI绘制的所有内容都是动态纹理的一部分),整个桌面中的所有窗口就是由这些纹理贴图而成,窗口内容的变化也被捕获以便DWM重新渲染。这种做法的好处是:VISTA下的ALT-TAB进行3D窗口切换效果很容易实现;窗口缩略图的内容能跟原始窗口内容实时同步。这些特性在GDI时代是无法实现的。

SetLayeredWindowAttributes/UpdateLayeredWindow跟3D没有关系,是纯软件方式实现的,仅仅是把窗口当作一个有ALPHA通道的图层来处理,它利用窗口的Z序,桌面会正确地把普通窗口和这些图层混合渲染。为了效率,分层窗口被约束成必须是一个静态的图片,或者拥有固定的ALPHA值,桌面渲染这些图层的效率达到了极致,纯软件混合的速度几乎赶上了硬件。但限制也是很强的,跟渲染相关的窗口消息被禁止了,保留的是鼠标、键盘、命中测试等低功耗消息。

#23


如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问题了,你怎么解决啊.

#24


引用 23 楼 wangbo56916860 的回复:
如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问题了,你怎么解决啊.

这就是我要问的了,呵呵,就是怎么获得呢?

#25


引用 22 楼 jameshooo 的回复:
VISTA/WIN7的毛玻璃效果可是跟SetLayeredWindowAttributes/UpdateLayeredWindow毫无关系的,它只跟DWM相关,并以桌面主题的方式提供,任何一个具有边框的普通窗口都自动具备毛玻璃效果。

一旦DWM激活,整个桌面就是一个全屏的3D窗口,所有应用程序的窗口DC不再是真正的屏幕DC,而是一个3D纹理表面(这一点微软有文章介绍,跟DC相关的API都被重……


谢谢你的回答,这个也许就是实现的方法 

#26


引用 24 楼 hkf314 的回复:
引用 23 楼 wangbo56916860 的回复:
如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问题了,你怎么解决啊.

这就是我要问的了……

既然你这么问了,我就猜猜吧,嘎嘎。隐藏你的当前窗口,GetDC(NULL) 直接获得当前桌面,匹配你窗口的前一位置和大小,获取图像,通过混合的方式,和你的图像进行操作,显示窗口。

#27


引用 26 楼 wangbo56916860 的回复:
引用 24 楼 hkf314 的回复:

引用 23 楼 wangbo56916860 的回复:
如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问……


这个我已经说过了,你觉得可行性呢?如果背景有某个窗口刷新?总之吧,单靠这个是不妥的,有方法如DX的显存操作,我会试的,总之要搞定它,谢谢大家的回答,完成了就结贴给分

#28


只是两个位图的操作你认为时间会是多少呢?  不是你的 从 0 层 到 n 层。  

#29


o(︶︿︶)o 唉 我也不知道了 。  一起见证 NB 答案的到来

#30


引用 28 楼 wangbo56916860 的回复:
只是两个位图的操作你认为时间会是多少呢? 不是你的 从 0 层 到 n 层。

获取桌面的像素可以很快,但是像素计算和再次生成bits,这样整个过程的时间不容忽视,而且最重要的要实时更新,也许你认为不会慢,你可以试着挪动一个透明的窗体,其CPU使用率会攀升不少,他们使用的方法至少要比我们好吧,你可以想一下这样做出来会如何。0->n层是针对系统来说,而并非一个程序。

#31


自己几乎没办法实现。不要在这上面浪费时间了。就连SetLayeredWindowAttributes和UpdateLayeredWindow都有很多问题,比如与正在播放的视频进行混合就没有实现。虽然微软管理显示是分层的,但你拿不到层的信息。你后面覆盖的那一层,不一定是窗口,你也不可能知道它是否改变了外观。

#32


引用 31 楼 psbeond 的回复:
自己几乎没办法实现。不要在这上面浪费时间了。就连SetLayeredWindowAttributes和UpdateLayeredWindow都有很多问题,比如与正在播放的视频进行混合就没有实现。虽然微软管理显示是分层的,但你拿不到层的信息。你后面覆盖的那一层,不一定是窗口,你也不可能知道它是否改变了外观。

谢谢你的忠告哦,不过不试永远都不知道哦,失败也没事哦,当学习了,O(∩_∩)O~

#33


如果哪天你有同样的问题看到该贴,或者有什么好方法或者问题,可以联系本人(Q,501219511),或者登陆myccode.com留言,因为结贴时问题并未解决,也许真的很难,等待时间吧...

#34


我也正遇到一个需要部分透明的问题, PNG图像是解决不了问题的, 刚开始可能会给你通透的效果, 但是一旦移动窗口, 你会发现原先被"透明"而看到的别的窗口内容, 已变成你的窗口的背景的一部分, 跟着一块移动. 需要自己解决刷新的问题, 但想要获取新位置的背景, 难度相当大, 也可能是无解的. 
后来我改用穿透色来实现, 虽然显示效果就比PNG差得多, 但是至少可以应付一下. 

#35


这个我知道,可以加我QQ

#1


该回复于2010-11-22 15:39:38被版主删除

#2


关注中,不过我的程序是用 PNG 图片实现透明的

#3


GUAN ZHU

#4


引用 2 楼 luawkk 的回复:
关注中,不过我的程序是用 PNG 图片实现透明的


使用png少不了用UpdateLayeredWindow函数的
O(∩_∩)O~,谢谢你的回答

#5


SetLayeredWindowAttributes用LWA_ALPHA就可以实现半透明,不知道你说的毛玻璃是什么.
SetLayeredWindowAttributes和UpdateLayeredWindow不是纯软件的做法,如果你更换显卡,效果很明显.
我觉得没有理由小看SetLayeredWindowAttributes和UpdateLayeredWindow.自己计算alpha值,用ddraw等画上去并不见的高明,我觉得微软自己也会这些.

#6


lz去看看WPF是不是你想要的吧.

#7


引用 5 楼 eyey1 的回复:
SetLayeredWindowAttributes用LWA_ALPHA就可以实现半透明,不知道你说的毛玻璃是什么.
SetLayeredWindowAttributes和UpdateLayeredWindow不是纯软件的做法,如果你更换显卡,效果很明显.
我觉得没有理由小看SetLayeredWindowAttributes和UpdateLayeredWindow.自己计算alpha值,用……

如果你用过WIN7,或者迅雷7,你就知道了,那两个函数确实很强大的,可是想知道具体原理,而并非用法

#8


SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^WS_EX_LAYERED); 
SetLayeredWindowAttributes(this->m_hWnd,0,128,2); 

#9


该回复于2010-11-23 10:08:34被版主删除

#10


引用 8 楼 linuxchenyy 的回复:
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^WS_EX_LAYERED); 
SetLayeredWindowAttributes(this->m_hWnd,0,128,2);


谢谢你的回答,可能你没注意看我的问题吧,不要用法哦,

#11


引用 7 楼 hkf314 的回复:
引用 5 楼 eyey1 的回复:

SetLayeredWindowAttributes用LWA_ALPHA就可以实现半透明,不知道你说的毛玻璃是什么.
SetLayeredWindowAttributes和UpdateLayeredWindow不是纯软件的做法,如果你更换显卡,效果很明显.
我觉得没有理由小看SetLayeredWindowAttributes和UpdateLayere……

原理就像你说的,用alpha融合和背景计算,但利用了GPU的计算能力, 对没有GPU的电脑(比如集成显卡)使用纯软件的方法,CPU的loading就会加重.
如何利用GPU可能你要自己查资料了,可能GPU提供的功能不止alpha融合这么简单,可能还有图层的功能,不了解.
SetLayeredWindowAttributes没有公开源码,以上仅是猜测.

#12


LZ,借地问个问题
UpdateLayeredWindow 内部如何实现?
直接用GDI+画透明图片上去就可以透明

#13


使用SetLayeredWindowAttributes可以方便的制作透明窗体,此函数在w2k以上才支持,而且如果希望直接使用的话,可能需要下载最新的SDK。不过此函数在w2k的user32.dll里有实现,所以如果你不希望下载巨大的sdk的话,可以直接使用GetProcAddress获取该函数的指针。


  SetLayeredWindowAttributes的函数原型如下:

BOOL SetLayeredWindowAttributes(
HWND hwnd, // handle to the layered window
COLORREF crKey, // specifies the color key
BYTE bAlpha, // value for the blend function
DWORD dwFlags // action
); 


Windows NT/2000/XP: Included in Windows 2000 and later.
Windows 95/98/Me: Unsupported.(注意了,在win9x里没法使用的)
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib. 
 

  一些常量:


WS_EX_LAYERED = 0x80000;
LWA_ALPHA = 0x2;
LWA_COLORKEY=0x1; 

  其中dwFlags有LWA_ALPHA和LWA_COLORKEY

  LWA_ALPHA被设置的话,通过bAlpha决定透明度.

  LWA_COLORKEY被设置的话,则指定被透明掉的颜色为crKey,其他颜色则正常显示.

  要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性(旧的sdk没有定义这个属性,所以可以直接指定为0x80000). 

  例子代码:

  在OnInitDialog()加入: 

//加入WS_EX_LAYERED扩展属性
SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
HINSTANCE hInst = LoadLibrary("User32.DLL"); 
if(hInst) 

 typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD); 
 MYFUNC fun = NULL;
 //取得SetLayeredWindowAttributes函数指针 
 fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
 if(fun)fun(this->GetSafeHwnd(),0,128,2); 
 FreeLibrary(hInst); 


  稍加修改还可以作出淡出淡入的效果. 注意第三个参数(128)不要取得太小了,为0的话就完全透明,看不到了。

  如何使框架窗口的图标为动画显示

  可以用TIMER,但是TIMER不能有效的定时。因为TIMER发送的是窗口消息,当窗口忙于处理键盘、鼠标等消息时就不能及时处理TIMER,会使间隔时间变得很长 。

  可以考虑用一个单独得TIMER线程,用Sleep()定时来解决此问题。


UINT Timer(LPVOID param)
{
 HWND hWnd=(HWND)param;
 while(1)
 {
  Sleep(ms);
  PostMessage(hWnd,CH_PICTURE,NULL,NULL)
 }


  Sleep(ms)后发送自定义消息。消息处理函数就选择某一个ICON或BITMAP来显示。如 :


MyBotton.SetBitmap((HBITMAP)Bitmap[i]); 

  Bitmap是一个位图数组,存放有j个位图。消息处理函数运行一次,i就累加一次,当i==j时,i就回到0;

#14


该回复于2010-11-23 14:30:23被版主删除

#15


引用楼主 hkf314 的回复:
那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来


不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。

SetLayeredWindowAttributes 我个人认为就是设置了一个标志量,当第n层的标志位表示
需要融合时,就与第n-1 层进行像素的融合。

#16


学习,我只知道是ALPHA起了作用!导致上层图片可以融合到下面的图片层,就是一个通道的问题!

#17


引用 15 楼 wangbo56916860 的回复:
引用楼主 hkf314 的回复:
那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来


不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。

SetLayeredWindowAttributes 我个人认为就是设置了一个标志量,当第n层的标志位表示
需要融合时,就与第n-1 层进行像素的融合。


如果透明窗口下还一个或多个透明窗体呢?

#18


谢谢13楼详细的回答,不过那些我都知道,我想了解的是其大概的原理,不过你的回答还是相当有用的 

#19


引用 12 楼 a316586261 的回复:
LZ,借地问个问题
UpdateLayeredWindow 内部如何实现?
直接用GDI+画透明图片上去就可以透明


这也是我想知道的哦,其内部是什么原理呢?
仅仅GDI+画图片是不可能实现的

#20


引用 17 楼 hkf314 的回复:
引用 15 楼 wangbo56916860 的回复:
引用楼主 hkf314 的回复:
那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来


不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。

SetLayeredWindowAttributes 我个人认为就是设置了一个标志量,当第n层的标志位表示
需要融……

n-1 层是 n-1 和n-2  融合过的。 n 层和 n-1 层融合 就相当于 n 和 n-1 ,n-2 一起融合了

也就是说 n 层和 n-1 层融合就足够了

#21


引用 20 楼 wangbo56916860 的回复:
不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。
SetLayeredWindowAttributes 我个人认为就是设置……

n-1层依然要融合,也就是说要从底层融合到顶层,只是融合的窗体不一样,但是这个就是整个系统完成吧,而并非窗体自己完成的

#22


VISTA/WIN7的毛玻璃效果可是跟SetLayeredWindowAttributes/UpdateLayeredWindow毫无关系的,它只跟DWM相关,并以桌面主题的方式提供,任何一个具有边框的普通窗口都自动具备毛玻璃效果。

一旦DWM激活,整个桌面就是一个全屏的3D窗口,所有应用程序的窗口DC不再是真正的屏幕DC,而是一个3D纹理表面(这一点微软有文章介绍,跟DC相关的API都被重写了,一旦DWM激活,获取的窗口DC被重定向到一个D3D表面,GDI绘制的所有内容都是动态纹理的一部分),整个桌面中的所有窗口就是由这些纹理贴图而成,窗口内容的变化也被捕获以便DWM重新渲染。这种做法的好处是:VISTA下的ALT-TAB进行3D窗口切换效果很容易实现;窗口缩略图的内容能跟原始窗口内容实时同步。这些特性在GDI时代是无法实现的。

SetLayeredWindowAttributes/UpdateLayeredWindow跟3D没有关系,是纯软件方式实现的,仅仅是把窗口当作一个有ALPHA通道的图层来处理,它利用窗口的Z序,桌面会正确地把普通窗口和这些图层混合渲染。为了效率,分层窗口被约束成必须是一个静态的图片,或者拥有固定的ALPHA值,桌面渲染这些图层的效率达到了极致,纯软件混合的速度几乎赶上了硬件。但限制也是很强的,跟渲染相关的窗口消息被禁止了,保留的是鼠标、键盘、命中测试等低功耗消息。

#23


如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问题了,你怎么解决啊.

#24


引用 23 楼 wangbo56916860 的回复:
如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问题了,你怎么解决啊.

这就是我要问的了,呵呵,就是怎么获得呢?

#25


引用 22 楼 jameshooo 的回复:
VISTA/WIN7的毛玻璃效果可是跟SetLayeredWindowAttributes/UpdateLayeredWindow毫无关系的,它只跟DWM相关,并以桌面主题的方式提供,任何一个具有边框的普通窗口都自动具备毛玻璃效果。

一旦DWM激活,整个桌面就是一个全屏的3D窗口,所有应用程序的窗口DC不再是真正的屏幕DC,而是一个3D纹理表面(这一点微软有文章介绍,跟DC相关的API都被重……


谢谢你的回答,这个也许就是实现的方法 

#26


引用 24 楼 hkf314 的回复:
引用 23 楼 wangbo56916860 的回复:
如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问题了,你怎么解决啊.

这就是我要问的了……

既然你这么问了,我就猜猜吧,嘎嘎。隐藏你的当前窗口,GetDC(NULL) 直接获得当前桌面,匹配你窗口的前一位置和大小,获取图像,通过混合的方式,和你的图像进行操作,显示窗口。

#27


引用 26 楼 wangbo56916860 的回复:
引用 24 楼 hkf314 的回复:

引用 23 楼 wangbo56916860 的回复:
如果你自己想做融合的话,你只需要完成你自己的第n层和n-1层的融合就足够了吧。如果n-1层以下你都要自己做? 有几个问题。第一,你如何获得每一层,如何知道那个窗口在第几层? 第二,你如何保证在你融合之后,第x层刷新了,但是你取到的是旧图像,你融合到最后的图像是和操作系统不同步的啊?第三就是效率问……


这个我已经说过了,你觉得可行性呢?如果背景有某个窗口刷新?总之吧,单靠这个是不妥的,有方法如DX的显存操作,我会试的,总之要搞定它,谢谢大家的回答,完成了就结贴给分

#28


只是两个位图的操作你认为时间会是多少呢?  不是你的 从 0 层 到 n 层。  

#29


o(︶︿︶)o 唉 我也不知道了 。  一起见证 NB 答案的到来

#30


引用 28 楼 wangbo56916860 的回复:
只是两个位图的操作你认为时间会是多少呢? 不是你的 从 0 层 到 n 层。

获取桌面的像素可以很快,但是像素计算和再次生成bits,这样整个过程的时间不容忽视,而且最重要的要实时更新,也许你认为不会慢,你可以试着挪动一个透明的窗体,其CPU使用率会攀升不少,他们使用的方法至少要比我们好吧,你可以想一下这样做出来会如何。0->n层是针对系统来说,而并非一个程序。

#31


自己几乎没办法实现。不要在这上面浪费时间了。就连SetLayeredWindowAttributes和UpdateLayeredWindow都有很多问题,比如与正在播放的视频进行混合就没有实现。虽然微软管理显示是分层的,但你拿不到层的信息。你后面覆盖的那一层,不一定是窗口,你也不可能知道它是否改变了外观。

#32


引用 31 楼 psbeond 的回复:
自己几乎没办法实现。不要在这上面浪费时间了。就连SetLayeredWindowAttributes和UpdateLayeredWindow都有很多问题,比如与正在播放的视频进行混合就没有实现。虽然微软管理显示是分层的,但你拿不到层的信息。你后面覆盖的那一层,不一定是窗口,你也不可能知道它是否改变了外观。

谢谢你的忠告哦,不过不试永远都不知道哦,失败也没事哦,当学习了,O(∩_∩)O~

#33


如果哪天你有同样的问题看到该贴,或者有什么好方法或者问题,可以联系本人(Q,501219511),或者登陆myccode.com留言,因为结贴时问题并未解决,也许真的很难,等待时间吧...

#34


我也正遇到一个需要部分透明的问题, PNG图像是解决不了问题的, 刚开始可能会给你通透的效果, 但是一旦移动窗口, 你会发现原先被"透明"而看到的别的窗口内容, 已变成你的窗口的背景的一部分, 跟着一块移动. 需要自己解决刷新的问题, 但想要获取新位置的背景, 难度相当大, 也可能是无解的. 
后来我改用穿透色来实现, 虽然显示效果就比PNG差得多, 但是至少可以应付一下. 

#35


这个我知道,可以加我QQ