本篇讲述如何进行界面调色。界面调色一般有两种方法,调色板和HSL色彩变换。调色板局限于256色,这里不采用,因此用HSL色彩变换实现。首先要了解一下什么是HSL色彩空间,完整且详尽的知识请到维基百科去看,链接地址:http://zh.wikipedia.org/wiki/HSL%E5%92%8CHSV%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4,这里简单讲一下(摘自维基百科):
HSL 和 HSV(也叫做 HSB)是对RGB 色彩空间中点的两种有关系的表示,它们尝试描述比 RGB 更准确的感知颜色联系,并仍保持在计算上简单。HSL 表示 hue(色相)、saturation(饱和度)、lightness(亮度),HSV 表示 hue、 saturation、value 而 HSB 表示 hue、saturation、brightness(明度)。如下图:

HSL 和 HSV 二者都把颜色描述在圆柱体内的点,这个圆柱的中心轴取值为自底部的黑色到顶部的白色而在它们中间是的灰色,绕这个轴的角度对应于“色相”,到这个轴的距离对应于“饱和度”,而沿着这个轴的距离对应于“亮度”,“value”或“明度”。
把RGB颜色转换到HSL色系,进行调色就很简单了,改变色彩只要转个角度,改变亮度就是沿轴升降进行“切片”,饱和度就是改变到中心轴的距离,3点定位到一个颜色,再转回RGB颜色就完成了界面调色。对需要调色的贴图进行这么一个变换,再重新贴图刷新一下界面就完成了调色功能。
并不是所有图片都需要调色,象标题栏右边的沙滩图案,如果调色就很难看了,会象照片的负片效果,因此用户头像,底纹图案,文字,图标都不需要调色,只需要把背景图案,按钮的高亮和按下状态图片,菜单背景和高亮图案进行色彩变换就行了。系统按钮需要局部调色,把最小化和最大化,还原按钮的高亮和按下状态的背景进行调色,因此准备了另外一张图片,一共5张图片需要调色:




最后一张图片是调色后透明绘制到系统按钮源图象上,实现了局部调色。
HSL色彩变换的实现是通过挂接图象库的滤镜插件类实现,实现原理请看RingSDK的帮助文档,调用代码极其简单,m_dibBkg.GETFILTER(dibFilterEFFECT)->AdjustHSL(h,s,l);就完成了背景的调色。图象库实现了两个滤镜插件类,dibFilterALPHA和dibFilterEFFECT,实现图象的各种ALPHA混合效果和亮度对比度,色度调整等。这里把关键的调色代码贴出来,其中m_rdib->Data()为已加载的32位色图象数据:
C/C++ code
//调整色调,参数范围:-180~180(度),=0不作调整
//调整饱和度,参数范围0~200(建议,最大值可>200),=100不作调整
//调整亮度,亮度参数范围0~200(建议,最大值可>200),=100不作调整
BOOL dibFilterEFFECT::AdjustHSL(int degHue,int perSaturation,int perLuminosity)
{
if(!m_rdib->Data())
return FALSE;
if(perSaturation < 0 || perLuminosity < 0)
return FALSE;
if(degHue == 0 && perSaturation == 100 && perLuminosity == 100)
return TRUE; //未作调整,直接返回
LPBYTE pRed, pGrn, pBlu,pBuf=(LPBYTE)m_rdib->Data();
UINT loop = m_rdib->Width() * m_rdib->Height();
COLORREF *cr = (COLORREF*)m_rdib->Data();
pRed=pBuf++;pGrn=pBuf++;pBlu=pBuf;
float H,S,L;
for (UINT i=0;i<loop;i++)
{
RGBtoHSL(*pRed,*pGrn,*pBlu,&H,&S,&L);
H += degHue;
S = (S*perSaturation/100.0f);
L = (L*perLuminosity/100.0f);
*cr = HSLtoRGB(H,S,L);
pRed+=4;
pGrn+=4;
pBlu+=4;
cr ++;
}
return TRUE;
}
void dibFilterEFFECT::RGBtoHSL(BYTE R,BYTE G,BYTE B,float* H,float* S,float* L)
{
BYTE minval = min(R,min(G,B));
BYTE maxval = max(R,max(G,B));
float mdiff = float(maxval) - float(minval);
float msum = float(maxval) + float(minval);
*L = msum / 510.0f;
if (maxval == minval)
{
*S = 0.0f;
*H = 0.0f;
}
else
{
float rnorm = (maxval - R) / mdiff;
float gnorm = (maxval - G) / mdiff;
float bnorm = (maxval - B) / mdiff;
*S = (*L <= 0.5f) ? (mdiff / msum) : (mdiff / (510.0f - msum));
if(R == maxval)
*H = 60.0f * (6.0f + bnorm - gnorm);
if(G == maxval)
*H = 60.0f * (2.0f + rnorm - bnorm);
if(B == maxval)
*H = 60.0f * (4.0f + gnorm - rnorm);
if (*H > 360.0f)
*H -= 360.0f;
}
}
COLORREF dibFilterEFFECT::HSLtoRGB(float H,float S,float L)
{
BYTE r,g,b;
L = min(1,L);
S = min(1,S);
if(S == 0.0)
{
r = g = b = (BYTE)(255 * L);
}
else
{
float rm1, rm2;
if (L <= 0.5f)
rm2 = L + L * S;
else
rm2 = L + S - L * S;
rm1 = 2.0f * L - rm2;
r = HueToRGB(rm1, rm2, H + 120.0f);
g = HueToRGB(rm1, rm2, H);
b = HueToRGB(rm1, rm2, H - 120.0f);
}
return RGB(r,g,b);
}
BYTE dibFilterEFFECT::HueToRGB(float rm1,float rm2,float rh)
{
while(rh > 360.0f)
rh -= 360.0f;
while(rh < 0.0f)
rh += 360.f;
if(rh < 60.0f)
rm1 = rm1 + (rm2 - rm1) * rh / 60.0f;
else if(rh < 180.0f)
rm1 = rm2;
else if(rh < 240.0f)
rm1 = rm1 + (rm2 - rm1) * (240.0f - rh) / 60.0f;
float n = rm1*255;
int m = min((int)n,255);
m = max(0,m);
return (BYTE)m;
}
实现了界面调色功能,接下来就得实现调色的设置界面,QQ2009的调色设置是预置了8种基色,可以选择一种基色,也可以对HSL分别调色,但是这8种基色是随着底纹和皮肤的选择变动的,皮肤的选择影响可选择的底纹和基色,一开始没怎么搞懂,后来下了一个QQ2009的主题包,结果是一个自定义格式的打包文件,没办法解开看里面图片,就没研究了,再下了一个2008版的主题包,可以看到所用的图片,大致清楚其为什么这么做了,里面的底纹图片是BMP格式,用紫红做透明色,由于没有ALPHA混合通道,这样的图片透明绘制到背景,边缘是有锯齿的,除非背景颜色跟图象边缘颜色相近才看不出来,因此选择的皮肤会限定底纹图片和背景颜色,选择底纹会同时变动背景颜色,再调色则对背景和底纹一起调色,底纹图案尽量采用RGB色差不大的图案,使调色效果不会太明显,这样整个界面调色底纹图案就没有了锯齿,变化也不怎么看得出来,是一种比较巧妙的做法。当然这是QQ以前版本的做法,2009应该已经改进了。这里演示的界面调色功能由于底纹图案是采用了带ALPHA通道的PNG格式图片,因此不存在这样的限制,同时为了简单起见,代码易于理解,就不学QQ的做法了,取消皮肤的设定,调色和底纹的选择互不影响,不做联动。在资源里预置了5张底纹图片可供选择,有兴趣的可以自己加。这里只是为简单起见而将底纹加到了资源里面,实际为了实现换肤并可扩展应该是自己实现一个换肤的配置文件和资源包,这里就不演示了。
现在实现调色的设置界面,首先响应“更改外观”按钮的弹起事件(WM_LBUTTONUP消息里面),弹出设置窗口,这个窗口是资源里面调色和底纹对话框的大小,不可拖动和调整大小,需要在失去焦点时自动隐藏,因此需要在其WM_ACTIVATE消息里面判断一下,如果是WA_INACTIVE状态就发送一个退出消息把自己关闭。加载调色和底纹两个对话框,显示一个,把另一个隐藏,调色和底纹的选择看起来应该是TAB控件,不过得自绘,这里用图片控件模拟TAB反而简单,反正只有两个选择,判断一下鼠标位置,换个图片,切换一下两个对话框的显示状态,看代码就知道了。
这里主要讲解一下调色对话框上4个Slider控件的自绘。控件自绘需要先子类化,RingSDK界面库已经封装好了,继承相应的控件类,子类化是自动的,可以重载其RingdowProc函数,即控件的窗口过程,想做什么都可以,给了你最大的自由度,未处理的消息返回DefaultProc或基类的RingdowProc就可以。自绘的Slider控件是继承自RingTrackBar,只要响应其WM_PRINTCLIENT和WM_PAINT消息,把背景图案和滑块图案画上去就OK了,代码很简单:
C/C++ code
LRESULT RingTrackBarEx::RingdowProc(HWND hWnd,RINGPARAMS param)
{
switch(param.uMsg)
{
case WM_PRINTCLIENT:
case WM_PAINT:
{
RECT rc,rcc;
HDC hdc,hMemDC;
PAINTSTRUCT ps;
GetWindowRect(m_hWnd,&rc);
OffsetRect(&rc,-rc.left,-rc.top);
hdc = param.wParam?(HDC)param.wParam:BeginPaint(hWnd,&ps);
FillRect(hdc,&rc,m_brush);
hMemDC = CreateCompatibleDC(hdc);
SelectObject(hMemDC,m_hbmLine);
GetChannelRect(&rcc);
StretchBlt(hdc,rcc.left,(rc.bottom - m_sizeLine.cy)/2,rcc.right-rcc.left,m_sizeLine.cy,
hMemDC,0,0,m_sizeLine.cx,m_sizeLine.cy,SRCCOPY);
SelectObject(hMemDC,m_hbmThumb);
GetThumbRect(&rc);
BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hMemDC,0,0,SRCCOPY);
DeleteDC(hMemDC);
if(param.wParam == 0)
EndPaint(hWnd, &ps);
return 0;
}
}
return DefaultProc(param);
}
因为调色函数AdjustHSL的参数关系,设置调整色调的控件调整范围值为-180 ~ 180,初始值为0,饱和度和亮度的范围都是0 ~ 200,初始值为100。关于透明度的调整,怎么使窗口半透明网上介绍文章有很多,这里就不罗嗦了,界面库对此做了封装,调用SetLayeredAlpha就可以了,不过范围值是设成了25 ~ 255,不能0 ~ 255,全透明的话窗口就不能操作了。
调整色调的图片是展开的HSL色环,如下图:

注意因为默认的背景是兰色,因此兰色是在图案的中间,如果默认背景是别的颜色,就需要循环平移这些色彩,使背景色处在中间位置,否则拖动滑块调色,实际的效果跟滑块所在的颜色就对不上号了。
底纹图案的选择很简单,重新加载选择的图案就OK,看代码就知道了。
至此完成了界面调色功能,界面中间部分因为以后会有控件遮盖,因此不需要调色。现在看看程序的截图:

最后说一下怎么做带ALPHA通道的PNG图片和加到程序里面:
首先找一张自己满意的图片,调整到高度95,QQ标题栏的高度,宽度随意,只要图案不怎么变形就可以,然后加一个蒙板,如图,按一下图中的按纽:

要使图片透明,需要去除背景,如果是新建图片并复制了图象过来,把背景层删掉,如果是直接打开的图片,需要复制一层然后把背景层删掉。加了蒙板后选择渐变工具,从右往左一拉,然后把图片保存为PNG格式就可以了,如图:

做完PNG图片还要做一张31*31的预览BMP图片,按资源里的格式做就可以了,把PNG加入为“PNG”类型的资源,ID值必须与resource.h里IDP_SEA等5张预置图片的ID值连续,预览图片的ID值必须与IDB_TATOO1~IDB_TATOO5的值连续,在wnduioption.cpp里面找到gszTatooInfo的初始化代码,把图片说明加到里面,编译一下程序就OK了。
现在这个仿QQ界面的程序已经完成了标题栏部分的功能,接下来要完成客户区和底栏部分的功能,留待下一篇再讲了。
程序代码下载地址:http://download.csdn.net/source/1995651
分享到:
相关推荐
### 循序渐进实现仿QQ界面:关键技术点解析 #### 一、园角矩形与双缓冲贴图窗口 为了实现仿QQ界面中的园角矩形效果,开发者需要掌握如何利用Windows API来创建园角矩形区域。具体做法如下: 1. **使用...
基于openocd开源工具实现的C#桌面应用工具
精品-2025人工智能神经网络基本原理解析.pdf
施耐德ATV312变频器通过MCGS RTU通讯实现双机监控与控制的触摸屏集成解决方案,无PLC的施耐德ATV312变频器通讯示例:触摸屏控制监控两台变频器,功能多且省成本,改进型可调整步长 P&O MPPT(二区MPPT复现),光储系统MPPT 直流负载供电的单级离网光伏系统中,降压转器将太阳能光伏阵列和直流负载连接起来,同时确保最大功率点跟踪(MPPT) 和电池充电控制的良好运行。 在MPPT方面,提出了一种改进的自适应步长扰动观测(P&O)方法,以达到不同天气条件下太阳能光伏阵列的实际最大功率点(MPP),同时减少稳态振荡和功率损耗。 此外,电池充电控制侧使用三级充电控制器 (TSCC) 为铅酸电池站充电。 ,改进型P&O; 复现二区MPPT; 光储系统MPPT; 最大功率点跟踪(MPPT); 步长扰动观测; 降压转换器; 太阳能光伏阵列; 电池充电控制; 三级充电控制器(TSCC); 铅酸电池站。,改进型P&O MPPT技术,光储系统高效能量管理
redis学习脑图笔记
大学生创业项目源码
Spring Boot企业员工管理系统(包含万字论文+MYSQL)
对应博客地址:https://blog.csdn.net/u011561335/article/details/146312389
相关文章:https://blog.csdn.net/liu_23yanfeng/article/details/146319189
从春晚看科技技术-陈雄 - 公开版本.pptx
在计算机上安装制造装备物联及生产管理ERP系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,制造装备物联及生产管理ERP系统的有效运用可以帮助管理人员准确快速地处理信息。 制造装备物联及生产管理ERP系统在对开发工具的选择上也很慎重,为了便于开发实现,选择的开发工具为Eclipse,选择的数据库工具为Mysql。以此搭建开发环境实现制造装备物联及生产管理ERP系统的功能。其中管理员管理用户,新闻公告。 制造装备物联及生产管理ERP系统是一款运用软件开发技术设计实现的应用系统,在信息处理上可以达到快速的目的,不管是针对数据添加,数据维护和统计,以及数据查询等处理要求,制造装备物联及生产管理ERP系统都可以轻松应对。 关键词:制造装备物联及生产管理ERP系统;SpringBoot框架,系统分析,数据库设计
传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代,问卷信息因为其管理内容繁杂,管理数量繁多导致手工进行处理不能满足广大用户的需求,因此就应运而生出相应的问卷调查系统。 本问卷调查系统分为管理员还有用户两个权限,管理员可以管理用户的基本信息内容,可以管理新闻资讯信息以及新闻资讯的租赁信息,能够与用户进行相互交流等操作,用户可以查看问卷信息,可以查看新闻资讯以及查看管理员回复信息等操作。 该问卷调查系统采用的是WEB应用程序开发中最受欢迎的B/S三层结构模式,使用占用空间小但功能齐全的MySQL数据库进行数据的存储操作,系统开发技术使用到了JSP技术。该问卷调查系统能够解决许多传统手工操作的难题,比如数据查询耽误时间长,数据管理步骤繁琐等问题。总的来说,问卷调查系统性能稳定,功能较全,投入运行使用性价比很高。 关键词:问卷调查系统;MySQL数据库;SSM技术
VID20250317191237.mp4
西门子S7-1511 PLC PID控制阀门开度与模拟量转换——博途WinCC监控画面程序实践,西门子S7-1511 PLC PID控制阀门开度与模拟量转换——博途WinCC监控画面程序实践,matlab验证码识别系统,基于数字图像处理实现。 经过对图像的预处理、二值化、区域剪裁、数字定位、模板匹配法识别数字。 有gui界面和测试图像数据集。 ,核心关键词:Matlab验证码识别系统; 数字图像处理; 图像预处理; 二值化; 区域剪裁; 数字定位; 模板匹配法识别; GUI界面; 测试图像数据集。,基于Matlab的数字图像处理验证码识别系统
内容概要:本文提供了详细的 VMware 虚拟机安装指南,涵盖软件选择(Pro 和 Player 版区别)、安装步骤(适用于 Windows 和 Linux 主机系统)、虚拟机创建以及操作系统安装指导。详细介绍了配置虚拟机的各项关键设置,如资源分配、硬件参数定制、安装 VMware Tools 提升虚拟机性能和稳定性。并且列出了快照、克隆等高级功能的具体应用,还包括共享文件夹配置和几种常见错误的排除解决方案。 适合人群:初次接触虚拟化的用户和对虚拟环境搭建有一定兴趣的技术爱好者。 使用场景及目标:帮助用户快速部署自己的虚拟机,并掌握虚拟环境中常见的配置技巧,能够针对具体应用场景灵活地调整虚拟机的相关参数,提高工作效率,满足测试、学习、开发的需求。 其他说明:提供了一些安装过程可能遇到的问题及对应解决方案,在创建和维护过程中给予指导性的意见来确保用户的使用体验尽可能顺畅无阻,并给出了部分性能优化建议。
Matlab开发初学者视频教程,零基础入门,非常适合初学者。
质子交换膜燃料电池(PEMFC)Simulink模型:静态与动态模型分析及参数计算,基于Simulink的质子交换膜燃料电池模型:静态和动态模拟,计算输出和效率,cst仿真超表面 极化复用 ,核心关键词: 1. CST仿真 2. 超表面 3. 极化复用 以上信息以分号隔开,即为“CST仿真;超表面;极化复用”。,CST仿真超表面极化复用技术
PEMFC的Simulink静态与动态模型:输出电压、功率、效率等多维度性能计算指南,质子交换膜燃料电池Simulink模型:涵盖静态与动态特性,全面计算输出性能与效率,附参考公式与文献指南,C#运动控制系统源码。 雷赛运动控制卡控制系统。 像高川控制卡、高川控制器、或者固高运动控制卡以及正运动控制器、正运动控制卡可以用这个框架,自己替一下库文件等代码就可以。 功能丰富,注释多,非常适合新手学习,也可以做框架。 ,核心关键词:C#运动控制系统源码; 雷赛运动控制卡控制系统; 高川控制卡/高川控制器/固高运动控制卡; 正运动控制器/正运动控制卡; 功能丰富; 注释多; 新手学习; 框架。,C#雷赛运动控制系统源码框架:通用控制卡编程指南
xilinx RFSOC 相关论文和资料