`
snzipeng
  • 浏览: 22250 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[转]循序渐进实现仿QQ界面(一):园角矩形与双缓冲贴图窗口

阅读更多

印象里仿QQ界面的程序应该有很多,搜了一下,虽然出来一大堆,排除了重复的,却只有两三个,没我想象的好。经常看到CSDN上有人问,QQ这个功能怎么实现,那个界面怎么实现,归纳了一下,决定写这么一个仿QQ界面程序,实用功能一律不实现,仅仿界面:

异型窗口
贴图界面
界面可调色,换底纹
仿QQ界面上的各种自绘控件

QQ2009界面仔细研究起来,其实还是很复杂的,完全模拟做到一模一样还是很花工夫的,用API实现是个噩梦,因此这里是用RingSDK实现。关于RingSDK,请到这个链接http://blog.csdn.net/ringphone/archive/2008/09/11/2911244.aspx,最新版本请用SVN到svn://svnhost.cn/RingSDK下载。RingSDK的图象库与界面库结合,可以实现一些比较酷的界面。这里就是演示图象库与界面库结合实现QQ2009的界面。OK,Let's go!不过先声明一下,这里只是模仿界面,实际QQ的界面不是这么做的。

QQ2009是园角矩形窗口,不是复杂形状,因此实现起来很简单,CreateRoundRectRgn然后SetWindowRgn就行了。不过窗口可以拖动调整大小,因此不是简单的在开始设定就可以,需要在WM_SIZE消息里随时改变这个RGN:

C/C++ code
RECT rc; GetWindowRect(m_hWnd,&rc); OffsetRect(&rc,-rc.left,-rc.top); if(m_hrgn) DeleteObject(m_hrgn); m_hrgn = CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,NCB_CORNERSIZE,NCB_CORNERSIZE); SetWindowRgn(m_hWnd,m_hrgn,TRUE); InvalidateRect(m_hWnd,NULL,TRUE); RECT rc; GetWindowRect(m_hWnd,&rc); OffsetRect(&rc,-rc.left,-rc.top); if(m_hrgn) DeleteObject(m_hrgn); m_hrgn = CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,NCB_CORNERSIZE,NCB_CORNERSIZE); SetWindowRgn(m_hWnd,m_hrgn,TRUE); InvalidateRect(m_hWnd,NULL,TRUE);


然后需要在WM_NCPAINT的时候描边,创建QQ边框颜色的画笔,用RoundRect就可以画个圆角边框。

QQ的标题栏和系统按钮是自绘的,本来应该在WM_NCPAINT消息里绘制,但是发现点击“编辑个性签名”会出现一个编辑框供输入,而标题栏是不能放置控件的,因此主窗口创建时干脆不要标题栏,全部客户区,在客户区上方模拟一个标题栏区域出来。由于要支持调整窗口尺寸,因此创建窗口时窗口类型是WS_POPUPWINDOW|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,如此默认的窗口边框并不符合我们的要求,需要在WM_NCCALCSIZE消息里设置一下边框尺寸:

C/C++ code
RINGMAINMSG(WM_NCCALCSIZE) { LPRECT lprc = (LPRECT)param.lParam; lprc->top += WND_BORDER; lprc->left += WND_BORDER; lprc->right -= (WND_BORDER + 1); //右边框需要留出画边框线的位置,1 lprc->bottom -= (WND_BORDER + 1); //同理 return 0; }



设置边框尺寸为2。这里有一个有趣的现象:即使不响应WM_NCCALCSIZE消息,创建的窗口也是没有标题栏的,没有最小/大化,关闭按钮,但是在任务栏上的程序按钮上按鼠标右键,最小化,移动,大小,关闭的选项一个不少,并且窗口也响应这些命令。如果窗口加上WS_EX_TOOLWINDOW的扩展类型,则程序不会出现在任务栏上,就跟QQ的表现一样了,不过目前我们的程序暂时仅实现标题栏的贴图,不支持实际功能,因此暂时不加这个扩展类型,靠在任务栏上的程序按钮上按鼠标右键实现窗口的最小/大化和关闭操作。不过这也太那个了一点,因此还是在系统栏加个图标为上,怎么在系统栏加图标这个应该不成问题了,这里就不解释了,RingSDK对此进行了封装,一句AddInTaskBar(m_hWnd,LoadIcon(GetInstance(),MAKEINTRESOURCE(IDI_QQ)),"仿QQ2009界面");搞定。响应图标的点击弹出菜单这里也不解释了,看代码就知道了。

接下来就是界面贴图,实现QQ的上下两个区域的绘制,这里就要用到界面库了。首先就是要准备图片,QQ资源里没找到,懒得研究,就自己截图搞了,弄了个宽度为1,高95和55的图片平铺做上下两部分的背景,VISTA风格的系统按钮图案,因为是圆角,需要有透明色,就做成了GIF格式。底纹,右边的沙滩海鸥图案抠图没这个本事,另找了一个相似的,做成PNG格式,PS里面加个蒙板就有了ALPHA通道。图象库支持PNG的半透明绘制,只要调用AlphaTo就行。还有用户头像,随便截了一个,把这些素材加入资源,算准坐标进行双缓冲绘制,依次绘制到内存图象就可以了。这里说一下内存图象的创建,是一开始就创建了一个跟屏幕等宽,高95+55的内存图象,这样就不需要在WM_SIZE里频繁释放再创建了。代码如下:

C/C++ code
//先把各素材绘制到内存图象m_dibBanner //背景 m_dibBkg.StretchTo(&m_dibBanner,0,0,rc.right,m_dibBanner.Height(),0,0,m_dibBkg.Width(),m_dibBkg.Height(),FALSE); //标题(“QQ2009”) m_dibCaption.AlphaTo(&m_dibBanner,8,5,0,0); //装饰图案,即QQ所谓的“底纹” m_dibTatoo.AlphaTo(&m_dibBanner,rc.right-m_dibTatoo.Width(),0,0,0); //用户头像 m_dibUser.DrawTo(&m_dibBanner,7,25,0,0,m_dibUser.Width(),m_dibUser.Height()); //用户名及签名 m_dibUserBanner.DrawTo(&m_dibBanner,54,25,0,0,m_dibUserBanner.Width(),m_dibUserBanner.Height()); //系统按钮 //最小化 m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_ENTIREWIDTH - NCB_SPACE,yPos,gRcBtn[0].x,gRcBtn[0].y, NCB_MINWIDTH,NCB_HEIGHT); //关闭 m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_CLOSEWIDTH - NCB_SPACE,yPos, gRcBtn[NCB_CLOSENORMAL].x,gRcBtn[NCB_CLOSENORMAL].y,NCB_CLOSEWIDTH,NCB_HEIGHT); //最大化/还原 if(IsZoomed()) { m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_ENTIREWIDTH - NCB_SPACE + NCB_MINWIDTH,yPos, gRcBtn[NCB_RESTORENORMAL].x,gRcBtn[NCB_RESTORENORMAL].y,NCB_MAXWIDTH,NCB_HEIGHT); } else { m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_ENTIREWIDTH - NCB_SPACE + NCB_MINWIDTH,yPos, gRcBtn[NCB_MAXNORMAL].x,gRcBtn[NCB_MAXNORMAL].y,NCB_MAXWIDTH,NCB_HEIGHT); } //绘制到窗口 //标题栏区域 m_dibBanner.Draw(hdc,0,0,0,0,rc.right,NCB_TITLEHEIGHT,rc.right,NCB_TITLEHEIGHT); //底栏区域 m_dibBanner.Draw(hdc,0,rc.bottom - NCB_BOTTOMHEIGHT,0,NCB_TITLEHEIGHT,rc.right, NCB_BOTTOMHEIGHT,rc.right,NCB_BOTTOMHEIGHT); 先把各素材绘制到内存图象m_dibBanner //背景 m_dibBkg.StretchTo(&m_dibBanner,0,0,rc.right,m_dibBanner.Height(),0,0,m_dibBkg.Width(),m_dibBkg.Height(),FALSE); //标题(“QQ2009”) m_dibCaption.AlphaTo(&m_dibBanner,8,5,0,0); //装饰图案,即QQ所谓的“底纹” m_dibTatoo.AlphaTo(&m_dibBanner,rc.right-m_dibTatoo.Width(),0,0,0); //用户头像 m_dibUser.DrawTo(&m_dibBanner,7,25,0,0,m_dibUser.Width(),m_dibUser.Height()); //用户名及签名 m_dibUserBanner.DrawTo(&m_dibBanner,54,25,0,0,m_dibUserBanner.Width(),m_dibUserBanner.Height()); //系统按钮 //最小化 m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_ENTIREWIDTH - NCB_SPACE,yPos,gRcBtn[0].x,gRcBtn[0].y, NCB_MINWIDTH,NCB_HEIGHT); //关闭 m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_CLOSEWIDTH - NCB_SPACE,yPos, gRcBtn[NCB_CLOSENORMAL].x,gRcBtn[NCB_CLOSENORMAL].y,NCB_CLOSEWIDTH,NCB_HEIGHT); //最大化/还原 if(IsZoomed()) { m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_ENTIREWIDTH - NCB_SPACE + NCB_MINWIDTH,yPos, gRcBtn[NCB_RESTORENORMAL].x,gRcBtn[NCB_RESTORENORMAL].y,NCB_MAXWIDTH,NCB_HEIGHT); } else { m_dibBtnRc.DrawTo(&m_dibBanner,rc.right - NCB_ENTIREWIDTH - NCB_SPACE + NCB_MINWIDTH,yPos, gRcBtn[NCB_MAXNORMAL].x,gRcBtn[NCB_MAXNORMAL].y,NCB_MAXWIDTH,NCB_HEIGHT); } //绘制到窗口 //标题栏区域 m_dibBanner.Draw(hdc,0,0,0,0,rc.right,NCB_TITLEHEIGHT,rc.right,NCB_TITLEHEIGHT); //底栏区域 m_dibBanner.Draw(hdc,0,rc.bottom - NCB_BOTTOMHEIGHT,0,NCB_TITLEHEIGHT,rc.right, NCB_BOTTOMHEIGHT,rc.right,NCB_BOTTOMHEIGHT);


至此贴图窗口完成,看一下程序截图:






目前的这个程序可拖动,可调整大小,双击可最大化,系统栏图标按右键可弹出仿QQ的菜单,不过仅“打开主面板”和“关闭”命令有效。界面上的按钮只是贴图,并不会响应鼠标动作。下一步会实现界面按钮的三态和功能响应,添加其他功能,下一篇再说了。

补充说明:界面库是支持MFC的,程序中的贴图代码基本可以照搬到MFC的程序,只需要包含"ringdib.h"即可。不过需要先编译libsrc\freelib下的zlib,png库,想支持JPG还需编译JPG库。

程序下载地址:http://d.download.csdn.net/down/1974639/ringphone

 

分享到:
评论

相关推荐

    循序渐进实现仿QQ界面(一):

    序渐进实现仿QQ界面(一):园角矩形与双缓冲贴图窗口 - CSDN论坛 - CSDN.NET.mht

    循序渐进实现仿QQ界面

    ### 循序渐进实现仿QQ界面:关键技术点解析 #### 一、园角矩形与双缓冲贴图窗口 为了实现仿QQ界面中的园角矩形效果,开发者需要掌握如何利用Windows API来创建园角矩形区域。具体做法如下: 1. **使用...

    麦芽糊精检验表格(食品企业原辅料质量验收记录表).docx

    麦芽糊精检验表格(食品企业原辅料质量验收记录表).docx

    塑料原型制作服务市场报告:全球前13强生产商排名及市场份额.docx

    塑料原型制作服务市场报告:全球前13强生产商排名及市场份额.docx

    C++数据结构与STL容器总结

    C++数据结构与STL容器总结

    谷氨酸钠(味精)检验表格(食品企业原辅料质量验收记录表).docx

    谷氨酸钠(味精)检验表格(食品企业原辅料质量验收记录表).docx

    小程序/虚拟资源变现知识付费小程序/激励广告流量主

    已更新微信登录获取用户头像失败功能,增加登录更新账号信息功能。 主要功能 会员系统,用户登录/注册 购买记录 收藏记录 基本设置 后台控制 导航颜色 字体颜色 标题等设置 流量主广告开关 小程序广告显示隐藏 广告主审核过审核 资源管理 后台可以添加5种类型资源 灵活设置 激励广告解锁资源 vip专享资源 免费资源 积分购买资源 阅读全文资源 公告 会员公告系统 VIP系统 用户可以开通VIP 查看vip专属资源 签到 签到互动二奖励 分类 资源分类 友情连接 跳转小程序 盈利能力:激励视频广告+插屏广告+视频广告+横幅广告+格子广告 =收益神器

    [继电保护仿真]-三段式距离保护 基于matlab simulink仿真 支持三段式电流保护、三段式距离保护、零序电流保护、欠压保护、振荡闭锁、差动保护、变压器差动保护、变压器后备保护、母线保护、

    [继电保护仿真]--三段式距离保护 基于matlab simulink仿真 支持三段式电流保护、三段式距离保护、零序电流保护、欠压保护、振荡闭锁、差动保护、变压器差动保护、变压器后备保护、母线保护、自动重合闸、分布式电源自适应保护等仿真定制 ,继电保护仿真; 三段式距离保护; MATLAB Simulink仿真; 多种保护类型仿真定制,Matlab Simulink三段式距离保护仿真定制

    基于Flask的pythonweb开发的外卖平台毕设

    内含数据库 源码 流程图 效果图,绝对物超所值

    薄板动力学相空间非传统Hamilton变分原理及辛算法的研究与应用(可复现,有问题请联系博主)

    内容概要:本文主要讨论了将弹性薄板动力分析从传统的Lagrange体系转换到Hamilton体系的必要性和优势。通过引入非传统Hamilton变分原理,建立了薄板动力学在相空间中的正则方程及对应的辛算法——辛空间有限元-时间子域法。这种方法不仅可以提高计算精度与效率,而且克服了以往非辛算法中存在的诸多缺陷。此外,文章提供了具体的数学模型、边界和初始条件推导以及算例验证。 适用人群:适用于固体力学领域研究人员、机械工程专业的学生和技术人员,特别是关注弹性薄板振动特性分析的专业人士。 使用场景及目标:本方法适用于弹性薄板结构在不同边界条件下的动态响应分析。旨在为相关工程问题提供更高精确度的解决方案。 其他说明:该研究展示了新型算法相比于传统方法在稳定性和准确性方面的优越性。通过对两个特定实例的数据对比进一步证实了辛算法的有效性和可行性。

    基于时变参数字典与精细化二次选择的正交匹配追踪算法在轴承故障诊断中的应用(可复现,有问题请联系博主)

    内容概要:本文提出了一种基于时变参数字典和细化二次选择机制的正交匹配追踪(TPRSS-OMP)算法,用于滚动轴承的早期故障检测。传统的相关滤波方法对噪声敏感,固定参数原子难以适应时间变化的影响特征,而本文提出的改进方法克服了这些问题。首先通过分段时域相关滤波与K-means聚类确定拉普拉斯小波字典的时间变化参数范围,在求解稀疏系数过程中引入新的优化后的次级选择原则——考虑信号重建前后信封频谱峰度的变化,从而提高算法对背景噪音干扰下的故障冲击特征提取能力。实验结果表明,新算法能有效重构故障信号并精准提取故障脉冲特征,适用于实际工况下的滚动轴承监测任务。 适合人群:具有一定机械工程与振动信号处理基础知识的研究人员、研究生、工程师。 使用场景及目标:①工业设备中滚动轴承及其他旋转设备的早期故障预警系统构建;②从强背景噪声中精确提取故障冲击特征。 其他说明:论文提供仿真及真实数据验证,展示了改进后的正交匹配追踪方法相比现有技术在准确性方面的优越表现,特别强调对于复杂操作环境下的鲁棒性能提升。文中还讨论了未来需要解决的问题如K-means聚类方法可能受到大幅波动的影响以及复合故障情况下的扩展性研

    醪糟检验表格(食品企业原辅料质量验收记录表).docx

    醪糟检验表格(食品企业原辅料质量验收记录表).docx

    SBLC买断基本信息.docx

    SBLC买断基本信息.docx

    罗汉果检验表格(食品香辛料质量验收记录表)检验表格(食品香辛料质量验收记录表).docx

    罗汉果检验表格(食品香辛料质量验收记录表)检验表格(食品香辛料质量验收记录表).docx

    MySQL 的.ibd文件恢复数据

    100%能恢复数据,亲测亲调试优化了代码 工具概述 我们有一个用Go语言编写的工具,能够读取.ibd文件并将其转换为可执行的SQL语句,从而实现数据恢复。该工具的主要功 解析.ibd文件:读取并解析.ibd文件中的数据结构。 生成SQL脚本:将解析到的数据转换为SQL插入语句。 恢复数据:通过执行生成的SQL脚本,将数据重新导入数据库 https://blog.csdn.net/qq_24396737/article/details/146182892?spm=1001.2014.3001.5501

    船舶与海洋工程技术-带顶滚轮的船用通用导缆器标准规范(ISO 13733:2020)

    内容概要:本国际标准 (ISO 13733:2020) 详细规定了安装在船舶上以引导系泊绳从船内到外板的带有顶部滚轮的船用通用导缆器的标准和技术要求。具体涵盖四种类型的导缆器分类、额定尺寸、尺寸参数、制造材料、结构设计、制造与检测要求以及标记要求等内容,并明确了安全工作载荷(SWL)的定义和要求,还提供了有限元法(FEM)用于评估强度的分析条件。 适用人群:适用于从事船舶工程、海上技术设备制造和相关标准规范实施的专业技术人员和监管人员。 使用场景及目标:本标准用于指导船舶装备制造商和工程师进行正确的导缆器设计、选型、生产及其安装施工,并保障在各种实际操作条件下能可靠传递系泊负荷。 其他说明:标准修订了多项内容,增加了技术指南并调整了关键部件的设计尺寸,提高了产品的安全性。此外,对于涉及专利权的技术细节,请参照ISO官网的相关信息获取进一步帮助。

    2025年汽车租赁业务系统应该具备的功能

    本文为抛砖引玉:简单描述,如需根据自身业务详细设计,请随时联系

    基于51单片机的测量仪(电压,电平,频率) 1104-基于51单片机的测量仪(电压,电平,频率)原理图、流程图、物料清单、仿真图、源代码 功能介绍: 基于单片机的简易测量仪(测量电压、TTL电平01

    基于51单片机的测量仪(电压,电平,频率) 1104-基于51单片机的测量仪(电压,电平,频率)原理图、流程图、物料清单、仿真图、源代码 功能介绍: 基于单片机的简易测量仪(测量电压、TTL电平01,频率等) 设计一个简易的测量设备,用两支表笔(1个是GND,一个是输入信号)测可用于数字电路实验及测试中 功能要求如下: (1)测量直流信号的电压,电压范围0~5V; (2)测量信号的TTL电平,给出高低电平测量结果;(3)测量数字信号的频率,给出测量结果; (4)用LCD显示结果,使用按键切测量功能(5)显示学号及姓名的拼音字母 有哪些资料: 1、仿真工程文件 2、源代码工程文件 3、原理图工程文件 4、流程图 5、功能介绍 6、元件清单 ,基于51单片机的测量仪;电压测量;电平测量;频率测量;原理图;流程图;物料清单;仿真图;LCD显示;按键切换功能;学号姓名显示。,基于51单片机多功能测量仪:电压、电平、频率测量及显示系统

    基于YOLOv9的智慧渔业捕捞检测系统(Python源码+数据集) 智慧渔业捕捞一共355张,类别为:'fish' ,基于YOLOv9; 智慧渔业捕捞检测系统; Python源码; 数据集; 鱼('

    基于YOLOv9的智慧渔业捕捞检测系统(Python源码+数据集) 智慧渔业捕捞一共355张,类别为:'fish' ,基于YOLOv9; 智慧渔业捕捞检测系统; Python源码; 数据集; 鱼('fish'); 355张图片,基于YOLOv9的渔业智慧检测系统(Python+数据集)

    O型環槽部設計.zip

    O型環槽部設計.zip

Global site tag (gtag.js) - Google Analytics