本篇演示实现仿QQ界面的中间客户区。QQ是可以调整界面透明度的,但是调整了透明度却连中间客户区也变得半透明了。客户区毕竟是软件最重要的部分,是要与用户交互的,透明了就影响操作了,因此这里的客户区不学QQ,始终不透明。要实现不透明控件,只能创建一个弹出窗口,遮住主界面的客户区域,然后设定与主界面连动,即始终跟着主窗口移动及调整尺寸。这个方法并不是很好,但却几乎是唯一的方法。为什么说几乎是唯一的方法呢?的确存在着另外的解决方案,但是这个方法太麻烦了,在此讨论一下这个方法。
实现半透明窗体,不透明控件,应该有不少朋友碰到过这个问题:为什么设定了窗口透明,窗口上的子窗口及控件也变得透明了?这个是受系统限制的,创建一个窗口,这个窗口区域就相当于一块画布,最终系统要在这块画布上绘制出窗口标题,客户区,控件等等,而窗口和控件绘制时的GetDC,BeginPaint等不过是获取到了跟自己相关的这块画布的一部分,在限定的区域内绘制,最终是画到这块画布上,系统最后显示窗口就是在桌面上显示这块画布,透明度也是认这块画布,因此上面的子窗口及控件也一起变得透明了。另建一个弹出式窗口,相当于创建了另一块画布,就不受主窗口的透明度限制。
知道了原因,现在来讨论如何不创建弹出式窗口,实现不透明控件。透明窗口有两种实现方法,一种是调用SetLayeredWindowAttributes,设定统一的窗口透明度,既整个窗口采用同样的透明度,QQ2009和这里的演示程序采用的就是这个方法,这个方法不创建弹出窗口是无法实现不透明控件的,因为想要控件不透明,就必须在控件区域采用不同的透明度,SetLayeredWindowAttributes无法做到,只能通过调用另一个函数UpdateLayeredWindow来实现可指定不同区域不同透明度的窗口,API代码大致如下:
C/C++ code
HDC hdc,hMemDC;
RECT rc;
GetWindowRect(hWnd,&rc);
POINT ptSrc = {0,0};
POINT ptWinPos = {rc.left,rc.top};
SIZE szWin = {rc.right-rc.left,rc.bottom-rc.top};
BLENDFUNCTION stBlend = { AC_SRC_OVER, 0,255,AC_SRC_ALPHA};
hdc = GetWindowDC(m_hWnd);
hMemDC = CreateCompatibleDC(hdc);
SelectObject(hMemDC,hbmp); //hbmp为整个窗口贴图
UpdateLayeredWindow(hWnd,hdc,&ptWinPos,&szWin,hMemDC,&ptSrc,0,&stBlend,ULW_ALPHA);
最关键的部分就是SelectObject(hMemDC,hbmp);实现不同区域不同透明度,全在这个选入设备的hbmp的图象数据,Windows的32位色图像的像素数据是COLORREF类型,0x00bbggrr格式,关键就在最高位的字节0x00,UpdateLayeredWindow是认这个字节来设定透明度,0x00为全透明,0xFF为不透明,这个字节的集合有个专门名称叫ALPHA通道。设定hbmp图象每一个像素的这个最高位字节数据,就可以实现像素级别的透明度。网上应该能搜到大把利用PNG图片实现半透明窗口的例子,因为PNG图片是可以带ALPHA通道的,解码PNG图片,自然就有了ALPHA通道,即设定了这个最高位字节,就不需要用代码来一个个像素指定透明度了。实现这样的半透明窗口是这样一个过程:首先要用双缓冲,创建与窗口相同大小的内存图象,然后在这个内存图象上绘制窗口的各个部分,标题栏,背景等等,一般是用PNG图片实现,这样就不用逐个像素指定透明度了,最后把这个内存图象绘制到窗口。想实现不透明控件,就要把控件区域的ALPHA通道值设为0xFF,然而不幸的是,几乎所有的GDI操作,除了TransparentBlt,那些最常用的BitBlt,TextOut,FillRect等等都是忽略ALPHA通道的,绘制过后这些区域的ALPHA值都变成了0,即全透明。因此想要实现不透明控件,就要实现所有控件的自绘,使控件绘制到内存图象上,常规GDI操作过后再设定这些区域的ALPHA值为0xFF。是不是头大了?这个方法太麻烦了,而且仅仅是为了在半透明窗口上实现不透明控件这样一个效果,代价太大,因此并不实用。QQ2009所用的DirectUI应该能很容易实现这个效果,但是并没实现,估计跟执行效率有关,因为这种像素级透明的程序在绘制时很耗时,调整窗口大小时可能会有延迟现象,在速度慢一点的机器上更是明显。
现在来讲模仿QQ的客户区,有很多种方法,这里选用相对比较简单的方法,有更好的解决方案欢迎留言讨论。首先是上部的搜索栏,当然是子类化EDIT控件进行自绘,处理WM_NCCALCSIZE消息加大其非客户区,画个外方内圆的边框。在编辑框输入内容后会有个自绘的下拉列表出来,这个其实跟点了“更改外观”按钮后出现的界面调色对话框是一样的,不过是把那对话框改一下表现形式,然后搬到编辑框下面,就不演示了,还有右边会出现清除和执行按钮,又是贴图,属于非典型编辑框功能,也不演示了,有兴趣的可以自己完成。
然后是侧边栏,看起来是TAB控件的功能,其实用工具栏更简单一些,添加TBSTYLE_BUTTON|TBSTYLE_CHECKGROUP类型的按钮就跟TAB控件的效果差不多。怎么绘制前面一篇已经讲过了,收起和展开只是隐藏和显示而已。最重要的好友列表部分,这个要用到TAB控件了,调整窗口尺寸时3个标签的宽度是跟着变的,这个需要创建TAB控件时指定TCS_FIXEDWIDTH窗口类型,子类化后在WM_SIZE消息里发送TCM_SETITEMSIZE消息调整标签的宽度。标签需要自绘,鼠标点击上面的下拉箭头会弹出菜单,这个需要在WM_LBUTTONDOWN消息里判断一下,子类化后其实想干什么都行,只是麻烦一点罢了:)点击标签后下面列表子窗口的滑动效果切换也很简单,把两个窗口并排然后连续移动就可以,不过因为刷新的关系,可能会有重影,如果想要更好的效果,应该是把子窗口截图,然后用双缓冲绘制出滑动效果,这里就简单一点,不用这个方法了。
好友列表,群列表和最近联系人列表是用ListBox控件实现,本来不需要子类化,不过ListBox不支持鼠标移到选项上的高亮功能,因此还是实现了子类化,处理WM_MOUSEMOVE消息进行判断。好友列表里面是有“我的好友”,“陌生人”,“黑名单”等分类的,这些分类选项的高度与用户项的高度不同,因此创建控件时需要指定LBS_OWNERDRAWVARIABLE类型,还有ListBox控件默认是会计算控件高度并调整尺寸适应列表项的高度,不会在客户区显示不完整的列表选项,这个功能我们不需要,因此还需指定LBS_NOINTEGRALHEIGHT类型,不自动调整高度,再指定一下LBS_HASSTRINGS|LBS_NOTIFY|WS_VSCROLL常规类型,然后就是在父窗口的WM_DRAWITEM消息里进行列表选项的自绘了。加入选项时需要指定选项的高度,为了区分分类选项和用户信息选项,通过发送LB_SETITEMDATA消息绑定了不同的数据,这样就能通过绑定的DATA来确定如何绘制。点击分类选项是可以收起/展开该类下的用户列表的,本来想收起时通过设定其下的用户列表高度为0来实现,结果发现LB_SETITEMHEIGHT消息只能设定选项的高度为1~255之间的值,残念,只能是收起时删掉用户列表,展开时再添加进来。用户列表项高亮状态时会有“发送短信”,“发送邮件”等按钮,这里只演示了“发送邮件”按钮,同样是通过静态文本控件实现,前面一篇文章已经讲过了。信息提示和右键菜单这里就不演示了,那个菜单项实在太多,看着就害怕:)
现在看看程序的截图:
差不多快完成了,还差滚动条和异型菜单,下一篇再说了。
演示程序下载地址:http://download.csdn.net/source/2059841
分享到:
相关推荐
RingPhone大侠实现的,循序渐进实现仿QQ界面,做成的pdf文档供大家学习。 最终实现效果图:http://hi.csdn.net/attachment/201003/13/23990_12684890525zzo.jpg
序渐进实现仿QQ界面(一):园角矩形与双缓冲贴图窗口 - CSDN论坛 - CSDN.NET.mht
自己花时间整理的,什么都不少,VC6编译通过
编译有问题的,请到以下地址去看: ... 循序渐进实现仿QQ界面(五):半透明窗体与不透明控件的配套源码,文章请见: http://blog.csdn.net/ringphone/archive/2010/02/11/5306231.aspx
仿迅雷资讯窗体,半透明的窗体,但里面的控件不透明, 有一个缺点就是移动窗体时,会感觉窗体看到的背景不实时. 如有高手将此功能完善,请发一份代码给我,谢谢. 236469173@qq.com
1.QQ:513187410 2.保证无毒 3.简单,方便,实用 4.实例可以自行改用 5.如有非法,本人无法律责任,由改动代码人负责! 6.需要更多本人作品,查找标签“朱建强” 7.请下载,杀毒后再使用! 本人Delphi开发7年,有C++,IOS,...
循序渐进实现仿QQ界面(三):界面调色与控件自绘的配套源码,文章请见:http://blog.csdn.net/ringphone/archive/2010/01/15/5191809.aspx
这个项目是基于韩顺平循序渐进学Java视频制作完成的,包含两个项目:QQ客户端和服务器端。具有登录、好友聊天、在线提示等功能。
python 循序渐进题库.从基础到困难.一步一步走向大神,
vs2013_winform实现360_QQ窗体与控件
高仿QQ界面,飞信界面,源代码,c++;循序渐进实现仿QQ界面(二):贴图按钮的三态模拟
利用winform的gdi+控件实现的QQ窗体与控件
Visual.Basic.6.0循序渐进教程中文版,系统介绍了vb程序语言的用法 勾月科技www.gouyue.net QQ17878387
《循序渐进Linux 第2版》PDF下载 试读
缺头文件的,请到下面文章的地址去看。 循序渐进实现仿QQ界面(二):贴图按钮的三态模拟的配套源码,文章请见:http://blog.csdn.net/ringphone/archive/2010/01/10/5171490.aspx
仿QQ登陆界面 仿QQ登陆界面 仿QQ登陆界面 仿QQ登陆界面
windows编程循序渐进一书为我们详细而全面地介绍了vc++的编程基础知识,本书共20章,内容全面丰富,适合于vc++初学者和相关的工程技术人员。 此部分为配套的code源码,方便学习使用,祝大家学习愉快。
仿QQ主界面分组菜单的C#窗体源代码 仿QQ主界面菜单的C#窗体源代码,虽然没有QQ的精细,但是但帮出了主要思路,至于细节就请细心的编程者慢慢修改完善,它完成了像QQ主窗体上分组菜单一样的功能,另外还有小头像功能...
资源名称:循序渐进学java视频教程之山寨版QQ资源目录:【】abbr_2b0a956c6deaffd161055bcc69352490【】abbr_69fe1d0216f529000a178ba7a943dbd8【】abbr_83be30c3d0d895e0b4887fe4e9c049f2【】abbr_89247c1a9c971d54...
韩顺平.循序渐进学.java.从入门到精通-之一PPT.pp