想大家都见过那种透明的窗体,例如:QQ的透明设置,千千静听的透明,....高级的如:win7的透明窗体...。
也许我们最先联想到的函数有SetLayeredWindowAttributes和UpdateLayeredWindow
先不说这两个函数的限制有多大,就拿毛玻璃透明来说,我想用这两个函数就很难实现了。
因此,不能纠结在这两个函数上,而是要了解其内部原理。可是其原理是什么呢?我就不得而知了...
我曾想过,透明的话,要获取背景然后和窗体进行透明融合计算,不过这种即使能勉强做好,估计也很占cpu,而且要时时更新(不知道背景是否变,所以要实时的重新计算),这显然不可取...
因此,我想知道的是,这个透明是怎么实现的呢?换言之,窗体应该只是一个矩形,而呈现在桌面这个更大的矩形里(我的想法),只是存在图层的差异,那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来,如果是要怎么做呢?
由于对windows窗体理解不深,如果发现有言误之处还望指出,谢谢大家还是总结一下吧,怎么不用上述的两个函数来实现窗体透明呢?如果大牛你知道,还望告知小虾,谢谢~\(≧▽≦)/~啦啦啦,再同时,分不是问题,问题如题
也许我们最先联想到的函数有SetLayeredWindowAttributes和UpdateLayeredWindow
先不说这两个函数的限制有多大,就拿毛玻璃透明来说,我想用这两个函数就很难实现了。
因此,不能纠结在这两个函数上,而是要了解其内部原理。可是其原理是什么呢?我就不得而知了...
我曾想过,透明的话,要获取背景然后和窗体进行透明融合计算,不过这种即使能勉强做好,估计也很占cpu,而且要时时更新(不知道背景是否变,所以要实时的重新计算),这显然不可取...
因此,我想知道的是,这个透明是怎么实现的呢?换言之,窗体应该只是一个矩形,而呈现在桌面这个更大的矩形里(我的想法),只是存在图层的差异,那是否是要像素从最底层的图层一直计算到最高的图层,最终在显示出来,如果是要怎么做呢?
由于对windows窗体理解不深,如果发现有言误之处还望指出,谢谢大家还是总结一下吧,怎么不用上述的两个函数来实现窗体透明呢?如果大牛你知道,还望告知小虾,谢谢~\(≧▽≦)/~啦啦啦,再同时,分不是问题,问题如题
解决方案 »
- 网页刷新时OCX有时OnCreate()未调用
- windows 重叠模型原理,谁知道的讲解下?
- 如果判断一个CWnd的显示状态(显示或隐藏)
- 由于windows编程非常菜 所以出现了几个错误 大家帮忙看看
- GetQueuedCompletionStatus() 的问题,
- 有谁用BCG作过加入图片的toolbar,我调用SetUserImages(),怎么TOOLBAR还是原来的图标呢?而且这个函数的示例程序里,TOOLBAR的图标也没
- 网络字节顺序和机器顺序什么区别?
- EOF小问题
- 如何能看到扩展名bin和rom的文件的内容,要看到源代码!
- MessageBox(hDlg,TEXT("您输入的密码是:")+lpszUser,TEXT("输入成功"),MB_ICONWARNING);编译通不过
- 求教:增加http请求头报文出错
- 请教如何解决双缓冲刷新和半透明控件显示背景的矛盾
使用png少不了用UpdateLayeredWindow函数的
O(∩_∩)O~,谢谢你的回答
SetLayeredWindowAttributes和UpdateLayeredWindow不是纯软件的做法,如果你更换显卡,效果很明显.
我觉得没有理由小看SetLayeredWindowAttributes和UpdateLayeredWindow.自己计算alpha值,用ddraw等画上去并不见的高明,我觉得微软自己也会这些.
SetLayeredWindowAttributes(this->m_hWnd,0,128,2);
如何利用GPU可能你要自己查资料了,可能GPU提供的功能不止alpha融合这么简单,可能还有图层的功能,不了解.
SetLayeredWindowAttributes没有公开源码,以上仅是猜测.
UpdateLayeredWindow 内部如何实现?
直接用GDI+画透明图片上去就可以透明
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;
不用从最底层融合到最高层吧,第n层就是n层和n-1 层的融合,n-1 是 n-1 和n-2 融合出来的。SetLayeredWindowAttributes 我个人认为就是设置了一个标志量,当第n层的标志位表示
需要融合时,就与第n-1 层进行像素的融合。
这也是我想知道的哦,其内部是什么原理呢?
仅仅GDI+画图片是不可能实现的
后来我改用穿透色来实现, 虽然显示效果就比PNG差得多, 但是至少可以应付一下.