VC++UpdateLayeredWindow实现半透明窗体_第1页
VC++UpdateLayeredWindow实现半透明窗体_第2页
VC++UpdateLayeredWindow实现半透明窗体_第3页
VC++UpdateLayeredWindow实现半透明窗体_第4页
VC++UpdateLayeredWindow实现半透明窗体_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

最近看了桌面天气秀这款小软件其界面精致漂亮而且可以透明显示还有个特别有趣的功能就是能让窗体固定在桌面上并且鼠标可以“穿透”而窗体不受任何影响这就是带着些许神秘的“有影无形”的功能。事实上要实现这种“有影无形”的功能很简单我相信聪明的您一定很快会想到怎么做。几句代码就可以搞定给你点提示只有在2000以上的Win操作系统才支持当然如果你有足够的时间可以完全可以在98上实现。那么今天我们主要讨论一下窗体的半透明显示其实如果仅仅要实现窗体的半透明显示很简单UpdateLayeredWindow调用就可以了网上去搜一下几乎都是贴的这个函数怎么怎么实现窗体的半透明在往下就没了比如此函数有个缺陷就是经过此函数处理过的窗体其上面的控件都透明了。诸如此类的问题至少到现在我在网上没找到一个让人感觉满意的解决方案。记得在一个所谓专业的C网站上看到一篇题为“XP下透明窗体的完美实现”当时看了还真高兴一阵子可是把代码下下来一看又是被忽悠了里面就调用了UpdateLayeredWindow函数实现透明然后加个旋转显示这样子就算完美了我晕这个函数查查资料谁不会。看来还是自己动手不知道有心的朋友注意到没有在桌面天气秀里打开设置然后快速拖动会看到上面的窗体明显脱离这就是多层窗口留下的尾巴。下面的透明窗体是背景上面的窗体承载控件。在拖动下层窗体的时候让上层窗体跟着一起动。对于小软件来说效果还可以。事实上今天我实现的也和这个思路差不多不过我这个上下两层窗体是父子关系它们各施其职但是又没有拖动时留下的尾巴窗口移动的处理我把这些功能都封装在一起了只需要简单地把你要在透明窗体上显示的窗体传过去以及透明处理的图片就OK了。限于篇幅下面给绘制函数以及调用示例boolDrawAlphalmagepBglmgHWNDhWndif::IsWindowhWndreturnfalseCWndDecoratewndDecorhWnd//wndDecor.SetAlpha25520/100//wndDecor.ShowOnDeskRECTrcWnd::GetWindowRecthWndrcWndintnWidrcWnd.right-rcWnd.leftintnHeircWnd.bottom-rcWnd.topHDChdcTemp::GetWindowDChWndHDChdcMemory::CreateCompatibleDChdcTempHBITMAPhBitMapCreateCompatibleBitmaphdcTempnWidnHeiSelectObjecthdcMemoryhBitMapHDChdcScreen::GetWindowDChWndPOINTptWinPosrcWnd.leftrcWnd.topGraphicsgraphhdcMemoryPointpointsPoint00PointnWid0Point0nHeigraph.DrawImagepBgImgpoints3SIZEsizeWindownWidnHeiPOINTptSrc00DWORDdwExStyle::GetWindowLonghWndGWL_EXSTYLEifdwExStyle0x800000x80000::SetWindowLonghWndGWL_EXSTYLEdwExStyle0x80000CStringstrTitlem_alWnd.GetWindowTextstrTitleGdiplus::FontfontL宋体12FontStyleBoldUnitPixelStringFormatstrFormatSolidBrushbrushColor0xff000graph.DrawStringstrTitle-1fontPointF3230strFormatbrush::UpdateLayeredWindowhWndhdcScreenptWinPossizeWindowhdcMemoryptSrc0m_alBlendULW_ALPHAgraph.ReleaseHDChdcMemory::ReleaseDChWndhdcScreenhdcScreenNULL::ReleaseDChWndhdcTemphdcTempNULLDeleteObjecthBitMapDeleteDChdcMemoryhdcMemoryNULLreturntrue调用示例:CWndAlphawndAlwndAl.InitAlphaLC:bg.pngNULLrcMargintruem_pMainWndwndAl.GetMainWndwndAl.DoModal本篇演示实现仿QQ界面的中间客户区。QQ是可以调整界面透明度的但是调整了透明度却连中间客户区也变得半透明了。客户区毕竟是软件最重要的部分是要与用户交互的透明了就影响操作了因此这里的客户区不学QQ始终不透明。要实现不透明控件只能创建一个弹出窗口遮住主界面的客户区域然后设定与主界面连动即始终跟着主窗口移动及调整尺寸。这个方法并不是很好但却几乎是唯一的方法。为什么说几乎是唯一的方法呢的确存在着另外的解决方案但是这个方法太麻烦了在此讨论一下这个方法。实现半透明窗体不透明控件应该有不少朋友碰到过这个问题为什么设定了窗口透明窗口上的子窗口及控件也变得透明了这个是受系统限制的创建一个窗口这个窗口区域就相当于一块画布最终系统要在这块画布上绘制出窗口标题客户区控件等等而窗口和控件绘制时的GetDCBeginPaint等不过是获取到了跟自己相关的这块画布的一部分在限定的区域内绘制最终是画到这块画布上系统最后显示窗口就是在桌面上显示这块画布透明度也是认这块画布因此上面的子窗口及控件也一起变得透明了。另建一个弹出式窗口相当于创建了另一块画布就不受主窗口的透明度限制。知道了原因现在来讨论如何不创建弹出式窗口实现不透明控件。透明窗口有两种实现方法一种是调用SetLayeredWindowAttributes设定统一的窗口透明度既整个窗口采用同样的透明度QQ2009和这里的演示程序采用的就是这个方法这个方法不创建弹出窗口是无法实现不透明控件的因为想要控件不透明就必须在控件区域采用不同的透明度SetLayeredWindowAttributes无法做到只能通过调用另一个函数UpdateLayeredWindow来实现可指定不同区域不同透明度的窗口API代码大致如下C/CcodeHDChdchMemDCRECTrcGetWindowRecthWndrcPOINTptSrc00POINTptWinPosrc.leftrc.topSIZEszWinrc.right-rc.leftrc.bottom-rc.topBLENDFUNCTIONstBlendAC_SRC_OVER0255AC_SRC_ALPHAhdcGetWindowDCm_hWndhMemDCCreateCompatibleDChdcSelectObjecthMemDChbmp//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消息里判断一下子类化后其实想干什么都行只是麻烦一点罢了:点击标签后下面列表子窗口的滑动效果切换也很简单把两个窗口并排然后连续移动就可以不过因为刷新的关系可能会有重影如果想要更好的效果应该是把子窗口截图然后用双缓冲绘制出滑动效果这里就简单一点不用这个方法了。好友列表群列表和最近联系人列表是用ListBox控件实现本来不需要子类化不过ListBox不支持鼠标移到选项上的高亮功能因此还是实现了子类化处理WM_MOUSEMOVE消息进行判断。好友列表里面是有“我的好友”“陌生人”“黑名单”等分类的这些分类选项的高度与用户项的高度不同因此创建控件时需要指定LBS_OWNERDRAWVARIABLE类型还有ListBox控件默认是会计算控件高度并调整尺寸适应列表项的高度不会在客户区显示不完整的列表选项这个功能我们不需要因此还需指定LBS_NOINTEGRALHEIGHT类型不自动调整高度再指定一下LBS_HASSTRINGSLBS_NOTIFYWS_VSCROLL常规类型然后就是在父窗口的WM_DRAWITEM消息里进行列表选项的自绘了。加入选项时需要指定选项的高度为了区分分类选项和用户信息选项通过发送LB_SETITE

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论