VC++调用UpdateLayeredWindow实现半透明窗体.doc

上传人:飞****9 文档编号:136128524 上传时间:2020-06-24 格式:DOC 页数:5 大小:69KB
返回 下载 相关 举报
VC++调用UpdateLayeredWindow实现半透明窗体.doc_第1页
第1页 / 共5页
VC++调用UpdateLayeredWindow实现半透明窗体.doc_第2页
第2页 / 共5页
VC++调用UpdateLayeredWindow实现半透明窗体.doc_第3页
第3页 / 共5页
VC++调用UpdateLayeredWindow实现半透明窗体.doc_第4页
第4页 / 共5页
VC++调用UpdateLayeredWindow实现半透明窗体.doc_第5页
第5页 / 共5页
亲,该文档总共5页,全部预览完了,如果喜欢就下载吧!
资源描述

《VC++调用UpdateLayeredWindow实现半透明窗体.doc》由会员分享,可在线阅读,更多相关《VC++调用UpdateLayeredWindow实现半透明窗体.doc(5页珍藏版)》请在金锄头文库上搜索。

1、最近看了桌面天气秀这款小软件,其界面精致漂亮,而且可以透明显示,还有个特别有趣的功能就是能让窗体固定在桌面上并且鼠标可以“穿透”而窗体不受任何影响,这就是带着些许神秘的“有影无形”的功能。 事实上要实现这种“有影无形”的功能,很简单,我相信聪明的您一定很快会想到怎么做。几句代码就可以搞定,给你点提示,只有在2000以上的Win操作系 统才支持(当然如果你有足够的时间可以完全可以在98上实现)。那么今天我们主要讨论一下窗体的半透明显示,其实,如果仅仅要实现窗体的半透明显示,很简 单,UpdateLayeredWindow调用就可以了,网上去搜一下几乎都是贴的这个函数怎么怎么实现窗体的半透明,在往

2、下就没了,比如此函数有个缺 陷,就是经过此函数处理过的窗体,其上面的控件都透明了。诸如此类的问题至少到现在我在网上没找到一个让人感觉满意的解决方案。 记得在一个所谓专业的C#网站上看到一篇题为“XP下透明窗体的完美实现”,当时看了还真高兴一阵子,可是把代码下下来一看,又是被忽悠了,里面就调用了 UpdateLayeredWindow函数实现透明然后加个旋转显示,这样子就算完美了,我晕!这个函数查查资料谁不会。看来还是自己动手,不知道有心 的朋友注意到没有,在桌面天气秀里,打开设置,然后快速拖动,会看到上面的窗体明显脱离,这就是多层窗口留下的尾巴。下面的透明窗体是背景,上面的窗体承 载控件。在拖

3、动下层窗体的时候让上层窗体跟着一起动。对于小软件来说,效果还可以。事实上,今天我实现的也和这个思路差不多,不过我这个上下两层窗体是父 子关系,它们各施其职,但是又没有拖动时留下的尾巴(窗口移动的处理),我把这些功能都封装在一起了,只需要简单地把你要在透明窗体上显示的窗体传过去以 及透明处理的图片就OK了。限于篇幅下面给绘制函数以及调用示例:bool DrawAlpha(Image* pBgImg, HWND hWnd)if (!:IsWindow(hWnd) return false;CWndDecorate wndDecor(hWnd);/wndDecor.SetAlpha(255 * 20

4、) / 100);/wndDecor.ShowOnDesk();RECT rcWnd;:GetWindowRect(hWnd, &rcWnd);int nWid = rcWnd.right - rcWnd.left;int nHei = rcWnd.bottom - rcWnd.top;HDC hdcTemp = :GetWindowDC(hWnd);HDC hdcMemory = :CreateCompatibleDC(hdcTemp);HBITMAP hBitMap = CreateCompatibleBitmap(hdcTemp, nWid, nHei);SelectObject(hdc

5、Memory, hBitMap);HDC hdcScreen = :GetWindowDC(hWnd);POINT ptWinPos = rcWnd.left, rcWnd.top;Graphics graph(hdcMemory);Point points = Point(0, 0),Point(nWid, 0),Point(0, nHei);graph.DrawImage(pBgImg, points,3);SIZE sizeWindow=nWid, nHei;POINT ptSrc=0,0;DWORD dwExStyle = :GetWindowLong(hWnd, GWL_EXSTYL

6、E);if (dwExStyle & 0x80000) != 0x80000):SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle 0x80000);CString strTitle;m_alWnd.GetWindowText(strTitle);Gdiplus:Font font(L宋体,12,FontStyleBold,UnitPixel);StringFormat strFormat;SolidBrush brush(Color(0xff,0,0,0);graph.DrawString(strTitle, -1, &font, PointF(32,30)

7、,&strFormat, &brush); :UpdateLayeredWindow(hWnd, hdcScreen, &ptWinPos, &sizeWindow, hdcMemory, &ptSrc, 0, &m_alBlend, ULW_ALPHA);graph.ReleaseHDC(hdcMemory);:ReleaseDC(hWnd,hdcScreen);hdcScreen = NULL;:ReleaseDC(hWnd,hdcTemp);hdcTemp = NULL;DeleteObject(hBitMap);DeleteDC(hdcMemory);hdcMemory = NULL;

8、return true;调用示例:CWndAlpha wndAl;wndAl.InitAlpha(LC:bg.png, NULL, rcMargin, true);m_pMainWnd = wndAl.GetMainWnd();wndAl.DoModal();本篇演示实现仿QQ界面的中间客户区。QQ是可以调整界面透明度的,但是调整了透明度却连中间客户区也变得半透明了。客户区毕竟是软件最重要的部分,是要 与用户交互的,透明了就影响操作了,因此这里的客户区不学QQ,始终不透明。要实现不透明控件,只能创建一个弹出窗口,遮住主界面的客户区域,然后设定与 主界面连动,即始终跟着主窗口移动及调整尺寸。这个

9、方法并不是很好,但却几乎是唯一的方法。为什么说几乎是唯一的方法呢?的确存在着另外的解决方案,但是 这个方法太麻烦了,在此讨论一下这个方法。 fVd_6Lf ph5i2U0 实 现半透明窗体,不透明控件,应该有不少朋友碰到过这个问题:为什么设定了窗口透明,窗口上的子窗口及控件也变得透明了?这个是受系统限制的,创建一个窗 口,这个窗口区域就相当于一块画布,最终系统要在这块画布上绘制出窗口标题,客户区,控件等等,而窗口和控件绘制时的GetDC,BeginPaint等 不过是获取到了跟自己相关的这块画布的一部分,在限定的区域内绘制,最终是画到这块画布上,系统最后显示窗口就是在桌面上显示这块画布,透明度

10、也是认这块 画布,因此上面的子窗口及控件也一起变得透明了。另建一个弹出式窗口,相当于创建了另一块画布,就不受主窗口的透明度限制。 dX/7n= nA 知 道了原因,现在来讨论如何不创建弹出式窗口,实现不透明控件。透明窗口有两种实现方法,一种是调用 SetLayeredWindowAttributes,设定统一的窗口透明度,既整个窗口采用同样的透明度,QQ2009和这里的演示程序采用的就是这 个方法,这个方法不创建弹出窗口是无法实现不透明控件的,因为想要控件不透明,就必须在控件区域采用不同的透明 度,SetLayeredWindowAttributes无法做到,只能通过调用另一个函数Update

11、LayeredWindow来实现可指定不同区 域不同透明度的窗口,API代码大致如下: 37kFbRx Ny7*MZ- C/C+ code HDC hdc,hMemDC; TSewq4K RECT rc; 0ex.S_Oj4 IXtG 36O GetWindowRect(hWnd,&rc); M; uFSU|SDd. POINT ptSrc = 0,0; _x(hlHFk POINT ptWinPos = rc.left,rc.top; GgY8u SIZE szWin = rc.right-rc.left,rc.bottom-rc.top; !0?o3,of- BLENDFUNCTION s

12、tBlend = AC_SRC_OVER, 0,255,AC_SRC_ALPHA; U=yvi8 !gWxVGv hdc = GetWindowDC(m_hWnd); &Iy58 hMemDC = CreateCompatibleDC(hdc); OQP;5 #K SelectObject(hMemDC,hbmp); /hbmp为整个窗口贴图 aXj UDu7 UpdateLayeredWindow(hWnd,hdc,&ptWinPos,&szWin,hMemDC,&ptSrc,0,&stBlend,ULW_ALPHA); gNP1UH4m 8%B_nVc ,zxRDI 最 关键的部分就是Se

13、lectObject(hMemDC,hbmp);实现不同区域不同透明度,全在这个选入设备的hbmp的图象数据,Windows的 32位色图像的像素数据是COLORREF类型,0x00bbggrr格式,关键就在最高位的字节0x00,UpdateLayeredWindow是认 这个字节来设定透明度,0x00为全透明,0xFF为不透明,这个字节的集合有个专门名称叫ALPHA通道。设定hbmp图象每一个像素的这个最高位字节 数据,就可以实现像素级别的透明度。网上应该能搜到大把利用PNG图片实现半透明窗口的例子,因为PNG图片是可以带ALPHA通道的,解码PNG图片, 自然就有了ALPHA通道,即设定了

14、这个最高位字节,就不需要用代码来一个个像素指定透明度了。实现这样的半透明窗口是这样一个过程:首先要用双缓冲,创 建与窗口相同大小的内存图象,然后在这个内存图象上绘制窗口的各个部分,标题栏,背景等等,一般是用PNG图片实现,这样就不用逐个像素指定透明度了,最 后把这个内存图象绘制到窗口。想实现不透明控件,就要把控件区域的ALPHA通道值设为0xFF,然而不幸的是,几乎所有的GDI操作,除了 TransparentBlt,那些最常用的BitBlt,TextOut,FillRect等等都是忽略ALPHA通道的,绘制过后这些区域的 ALPHA值都变成了0,即全透明。因此想要实现不透明控件,就要实现所有

15、控件的自绘,使控件绘制到内存图象上,常规GDI操作过后再设定这些区域的 ALPHA值为0xFF。是不是头大了?这个方法太麻烦了,而且仅仅是为了在半透明窗口上实现不透明控件这样一个效果,代价太大,因此并不实用。 QQ2009所用的DirectUI应该能很容易实现这个效果,但是并没实现,估计跟执行效率有关,因为这种像素级透明的程序在绘制时很耗时,调整窗口大 小时可能会有延迟现象,在速度慢一点的机器上更是明显。 C8|Ls(4Ck *1)P8# 现 在来讲模仿QQ的客户区,有很多种方法,这里选用相对比较简单的方法,有更好的解决方案欢迎留言讨论。首先是上部的搜索栏,当然是子类化EDIT控件进行 自绘,处理WM_NCCALCSIZE消息加大其非客户区,画个外方内圆的边

展开阅读全文
相关资源
相关搜索

当前位置:首页 > IT计算机/网络 > 其它相关文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号