VC++UpdateLayeredWindow实现半透明窗体

最近看了桌面天气秀这款小软件其界面精致漂亮而且可以透明显示还有个特别有趣的功能就是能让窗体固定在桌面上并且鼠标可以穿透而窗体不受任何影响这就是带着些许神秘的有影无形的功能。 事实上要实现这种有影无形的功能很简单我相信聪明的您一定很快会想到怎么做。几句代码就可以搞定给你点提示只有在2000以上的Win操作系 统才支持当然如果你有足够的时间可以完全可以在98上实现。那么今天我们主要讨论一下窗体的半透明显示其实如果仅仅要实现窗体的半透明显示很简 UpdateLayeredWindow调用就可以了网上去搜一下几乎都是贴的这个函数怎么怎么实现窗体的半透明在往下就没了比如此函数有个缺 陷就是经过此函数处理过的窗体其上面的控件都透明了。诸如此类的问题至少到现在我在网上没到一个让人感觉满意的解决方案。 记得在一个所谓专业的C网站上看到一篇题为“XP下透明窗体的完美实现当时看了还真高兴一阵子可是把代码下下来一看又是被忽悠了里面就调用了 UpdateLayeredWindow函数实现透明然后加个旋转显示这样子就算完美了我晕这个函数查查资料谁不会。看来还是自己动手不知道有心 的朋友注意到没有在桌面天气秀里打开设置然后快速拖动会看到上面的窗体明显脱离这就是多层窗口留下的尾巴。下面的透明窗体是背景上面的窗体承 载控件。在拖动下层窗体的时候让上层窗体跟着一起动。对于小软件来说效果还可以。事实上今天我实现的也和这个思路差不多不过我这个上下两层窗体是父 子关系它们各
人体结构学施其职但是又没有拖动时留下的尾巴窗口移动的处理我把这些功能都封装在一起了只需要简单地把你要在透明窗体上显示的窗体传过去以 及透明处理的图片就OK了。限于篇幅下面给绘制函数以及调用示例 bool DrawAlphaImage pBgImg HWND hWnd if ::IsWindowhWnd return false CWndDecorate wndDecorhWnd //wndDecor.SetAlpha255 20 / 100 //wndDecor.ShowOnDesk RECT rcWnd ::GetWindowRecthWnd rcWnd int nWid rcWnd.right - rcWnd.left int nHei rcWnd.bottom - p HDC hdcTemp ::GetWindowDChWnd HDC hdcMemory ::CreateCompatibleDChdcTemp HBITMAP hBitMap CreateCompatibleBitmaphdcTemp nWid nHei SelectObjecthdcMemory hBitMap HDC hdcScreen ::GetWindowDChWnd POINT ptWinPos rcWnd.p Graphics graphhdcMemory Point points Point0 0PointnWid 0Point0 nHei graph.DrawImagepBgImg points3 SIZE sizeWindownWid nHei POINT ptSrc00 DWORD dwExStyle ::GetWindowLonghWnd GWL_EXSTYLE if dwExStyle 0x80000 0x80000 ::SetWindowLonghWnd GWL_EXSTYLE dwExStyle 0x80000 CString strTitle m_alWnd.GetWindowTextstrTitle Gdiplus::Font fontL宋体12FontStyleBoldUnitPixel StringFormat strFormat SolidBrush brushColor0xff000 graph.DrawStringstrTitle -1 font Po
intF3230strFormat brush ::UpdateLayeredWindowhWnd hdcScreen ptWinPos sizeWindow hdcMemory ptSrc 0 m_alBlend ULW_ALPHA graph.ReleaseHDChdcMemory ::ReleaseDChWndhdcScreen hdcScreen NULL ::ReleaseDChWndhdcTemp hdcTemp NULL DeleteObjecthBitMap DeleteDChdcMemory hdcMemory NULL return true 调用示例: CWndAlpha wndAl wndAl.InitAlphaLC:bg.png NULL rcMargin true m_pMainWnd wndAl.GetMainWnd wndAl.DoModal 本篇演示实现仿QQ界面的中间客户区。QQ是可以调整界面透明度的但是调整了透明度却连中间客户区也变得半透明了。客户区毕竟是软件最重要的部分是要 与用户交互的透明了就影响操作了因此这里的客户区不学QQ始终不透明。要实现不透明控件只能创建一个弹出窗口遮住主界面的客户区域然后设定与 主界面连动即始终跟着主窗口移动及调整尺寸。这个方法并不是很好但却几乎是唯一的方法。为什么说几乎是唯一的方法呢的确存在着另外的解决方案但是 这个方法太麻烦了在此讨论一下这个方法。 现半透明窗体不透明控件应该有不少朋友碰到过这个问题为什么设定了窗口透明窗口上的子窗口及控件也变得透明了这个是受系统限制的创建一个窗 口这个窗口区域就相当于一块画布最终系统要在这块画布上绘制出窗口标题客户区控件等等而窗口和控件绘制时的GetDCBeginPaint 惯性矩不过是获取到了跟自己相关的这块画布的一部分在限定的区
域内绘制最终是画到这块画布上系统最后显示窗口就是在桌面上显示这块画布透明度也是认这块 画布因此上面的子窗口及控件也一起变得透明了。另建一个弹出式窗口相当于创建了另一块画布就不受主窗口的透明度限制。 道了原因现在来讨论如何不创建弹出式窗口实现不透明控件。透明窗口有两种实现方法一种是调用 SetLayeredWindowAttributes设定统一的窗口透明度既整个窗口采用同样的透明度QQ2009和这里的演示程序采用的就是这 个方法这个方法不创建弹出窗口是无法实现不透明控件的因为想要控件不透明就必须在控件区域采用不同的透明 SetLayeredWindowAttributes无法做到只能通过调用另一个函数UpdateLayeredWindow来实现可指定不同区 域不同透明度的窗口API代码大致如下 C/C code HDC hdchMemDC RECT rc GetWindowRecthWndrc POINT ptSrc 00 POINT ptWinPos p SIZE szWin rc.right-rc.p BLENDFUNCTION stBlend AC_SRC_OVER 0255AC_SRC_ALPHA hdc GetWindowDCm_hWnd hMemDC CreateCompatibleDChdc SelectObjecthMemDChbmp //hbmp为整个窗口贴图 UpdateLayeredWindowhWndhdcptWinPosszWinhMemDCptSrc0stBlendULW_ALPHA 关键的部分就是SelectObjecthMemDChbmp实现不同区域不同透明度全在这个选入设备的hbmp的图象数据Windows 32位图像的像素数据是COLORREF类型0x00bbggrr格式关
键就在最高位的字节0x00UpdateLayeredWindow是认 这个字节来设定透明度0x00为全透明0xFF为不透明这个字节的集合有个专门名称叫ALPHA通道。设定hbmp图象每一个像素的这个最高位字节 数据就可以实现像素级别的透明度。网上应该能搜到大把利用PNG图片实现半透明窗口的例子因为PNG图片是可以带ALPHA通道的解码PNG图片 自然就有了ALPHA通道即设定了这个最高位字节就不需要用代码来一个个像素指定透明度了。实现这样的半透明窗口是这样一个过程首先要用双缓冲创 建与窗口相同大小的内存图象然后在这个内存图象上绘制窗口的各个部分标题栏背景等等一般是用PNG图片实现这样就不用逐个像素指定透明度了最 环糊精后把这个内存图象绘制到窗口。想实现不透明控件就要把控件区域的ALPHA通道值设为0xFF然而不幸的是几乎所有的GDI操作除了 TransparentBlt那些最常用的BitBltTextOutFillRect等等都是忽略ALPHA通道的绘制过后这些区域的 ALPHA值都变成了0即全透明。因此想要实现不透明控件就要实现所有控件的自绘使控件绘制到内存图象上常规GDI操作过后再设定这些区域的 ALPHA值为0xFF。是不是头大了这个方法太麻烦了而且仅仅是为了在半透明窗口上实现不透明控件这样一个效果代价太大因此并不实用。 QQ2009所用的DirectUI应该能很容易实现这个效果但是并没实现估计跟执行效率有关因为这种像素级透明的程序在绘制时很耗时调整窗口大 小时可能会有延迟现象在速度慢一点的
机器上更是明显。 在来讲模仿QQ的客户区有很多种方法这里选用相对比较简单的方法有更好的解决方案欢迎留言讨论。首先是上部的搜索栏当然是子类化近海风荷载EDIT控件进行 自绘处理WM_NCCALCSIZE消息加大其非客户区画个外方内圆的边框。在编辑框输入内容后会有个自绘的下拉列表出来这个其实跟点了更改外 按钮后出现的界面调对话框是一样的不过是把那对话框改一下表现形式然后搬到编辑框下面就不演示了还有右边会出现清除和执行按钮又是贴图 属于非典型编辑框功能也不演示了有兴趣的可以自己完成。 后是侧边栏看起来是TAB控件的功能其实用工具栏更简单一些添加TBSTYLE_BUTTONTBSTYLE_CHECKGROUP类型的按钮就 TAB控件的效果差不多。怎么绘制前面一篇已经讲过了收起和展开只是隐藏和显示而已。最重要的好友列表部分这个要用到TAB控件了调整窗口尺寸时 3个标签的宽度是跟着变的这个需要创建TAB控件时指定TCS_FIXEDWIDTH窗口类型子类化后在WM_SIZE消息里发送 TCM_SETITEMSIZE消息调整标签的宽度。标签需要自绘鼠标点击上面的下拉箭头会弹出菜单这个需要在WM_LBUTTONDOWN消息里判 断一下子类化后其实想干什么都行只是麻烦一点罢了rrkkk:点击标签后下面列表子窗口的滑动效果切换也很简单把两个窗口并排然后连续移动就可以不过因为 刷新的关系可能会有重影如果想要更好的效果应该是把子窗口截图然后用双缓冲绘制
出滑动效果这里就简单一点不用这个方法了。 友列表列表和最近联系人列表是用ListBox控件实现本来不需要子类化不过ListBox不支持鼠标移到选项上的高亮功能因此还是实现了子类 化处理WM_MOUSEMOVE消息进行判断。好友列表里面是有我的好友”“陌生人”“黑名单等分类的这些分类选项的高度与用户项的高度不 同因此创建控件时需要指定LBS_OWNERDRAWVARIABLE类型还有ListBox控件默认是会计算控件高度并调整尺寸适应列表项的高度 不会在客户区显示不完整的列表选项这个功能我们不需要因此还需指定LBS_NOINTEGRALHEIGHT类型不自动调整高度再指定一下 LBS_HASSTRINGSLBS_NOTIFYWS_VSCROLL常规类型然后就是在父窗口的WM_DRAWITEM消息里进行列表选项的自 绘了。加入选项时需要指定选项的高度为了区分分类选项和用户信息选项通过发送LB_SETITEMDATA消息绑定了不同的数据这样就能通过绑定的 DATA来确定如何绘制。点击分类选项是可以收起/展开该类下的用户列表的本来想收起时通过设定其下的用户列表高度为0烟焦油来实现结果发现 LB_SETITEMHEIGHT消息只能设定选项的高度为1255之间的值残念只能是收起时删掉用户列表展开时再添加进来。用户列表项高亮状态 时会有”“发送邮件等按钮这里只演示了发送邮件按钮同样是通过静态文本控件实现前面一篇文章已经讲过了。信息提示和右键菜单这里 就不演示了那个菜单项实在太多看着就害怕: 现在看看程序的截图

本文发布于:2024-09-20 20:36:54,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/685468.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:控件   实现   透明   列表   选项   窗体
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议