外部用户有一个需求,在Windows系统下利用一个小工具完成机器的识别和鉴定,也就是常见的获取并生成设备唯一性序列码,类似实现windows一机一码激活的功能,为日后系统授权做技术储备。
收到任务后分析,从交互体验方面考虑以cmd窗口给用户提示设备信息过于敷衍不适合,要以图形化的界面形式给用户呈现设备的序列码信息;从技术实现角度考虑,要获取硬件信息c或者c++语言对底层支撑比较友好,是不二之选(其它语言咱也不熟悉^^)。基于这两个方面的考虑,可选择的开发工具还是不少,比如:QT、VS系列等,由于仅仅实现一个小功能,QT的发布策略实在是过于臃肿,而VS仅提供一个exe文件就能完成所有功能,没有理由不选它。
没想到,十多年前用的vc6.0现在已经发展到一系列工具,2010/2013/2015版本众多,眼花缭乱,这次因为有安装包就没有过多犹豫的选择了vs2010,也没想到进化中的vs给了我当头一棒,看似简单的功能想要实现却累到肝痛~~仅以本文纪念下曾经的利器,想说懂你有点难。也希望在痛苦额定摸索过程中,把1、2个点的解决方案进行透彻的总结,达到看了就会,拿来就能用的目的。如果恰好你也有类似的需求,希望能不走弯路直接解决问题,留出时间享受生活。
机器序列码的原理比较简单,就是获取设备多种硬件信息,通过某种加密或抗扰算法结合成为一串不可逆且唯一的数据,作为区分的依据以此来映射和对应到某台机器。类似的算法网络上很多,基本通过主板、网卡、cpu信息,辅助以MD5、base64等算法就能实现,不算难点就不在这里多费口舌。
这次重点讲述在不同分辨率下,图片的自适应和button控件实现贴图功能。实质是一样的,就是在性能指标越来越高的机器面前,如何把软件颜值尽可能的调到最优,吸引和留住到用户。
问题描述:
buttoncontrol控件表面,加载一张bmp图片,自测加载以及控件按压功能无误,表现十分完美,还原度视觉效果都不错。没费多大功夫,本以为这就成了,换到测试同学手里一番操作,就成了这个样子相当尴尬。
仔细一问是分辨率调整到2560*1600,而开发机器的分辨率最高设置到1680*1650,当时就想用户哪有这么高配的设备,据理力争后谁也说服不了谁。收到用户的反馈真有一批次高配的设备需要生成序列码,而且分辨率设置为2560*1600。逃是逃不了的,继续乖乖的解决吧。带着明确的问题去寻找答案,也没当回事,结果还是太年轻痛苦的序幕拉开了。
网络上大部分的答案分为两类,锁定控件大小和bmp图片根据控件尺寸自适应。思路都看懂了但含糊不清的描述和支离破碎的代码以及复杂的MFC消息机制没有一个能解决实际问题,一个下午过去了丝毫没有进展,痛定思痛只能另寻出路。图示都是堵死的路,支离破碎的优秀代码代表~~~
重新整理思路,思索故障现场有三张图片,两个控件,在不同的分辨率下产生不一致的拉伸比率造成,减少变量的个数应该可以减少拉伸比率的差异,相对来说更好控制。带着这个思路,自然而然的将背景图与控件的bmp贴图合一处理,一张图片在同一个比率下拉伸,不会产生不一致的现象,也就能解决button控件在贴图的效果下,拉伸比例不一致产生的控件和图片尺寸不一致的故障。剩下就只有一个难点需要解决,那就是button控件透明化,隐藏在背景图按钮位置的下方,否则button的默认背景图会覆盖在地图之上,完全看不到背景图的按钮图标效果。如图示
这个解决过程也破费一番功夫,中间查阅多个帖子都是一知半解,没有一个完整可靠地处理线索,最终结合多个帖子总算是解决了控件透明化的功能。这个大坑省略几百字直接敲黑板说答案,总共三个步骤完成:
步骤一,在rc资源中添加一个MFC消息,定制化消息融入MFC消息体系中的一环。鼠标落在控件实体上,右击添加消息的控件,在弹出对话框选择消息Tab蓝,找到WM_CTLCOLOR消息,以系统默认函数名称OnCtlColor进行“确定”。
步骤二,在OnCtlColor函数中做处理,因为这个函数作用域范围是系统全局处理入口,程序加载运行所有控件的绘制消息都会进入这个函数并处理。本需求只对指定的button控件才做处理,所以需要对控件对应的ID做限制和判断,其它控件退出不做额外处理。经过筛选后,成功将button控件透明化,漂亮的背景按钮图标清晰的显示出来。如图示
处理代码示例
关键处理有两处,分别是:
- SetBkMode(TRANSPARENT) // 设置背景为透明,使得控件和背景图颜色一样
- SRCCOPY,复制来源的图像,即背景图,达到将控件本身透明化处理的效果
步骤三,如果只看到步骤二其实你还是不能解决控件透明化问题,因为这时的OnCtlColor消息无法被MFC监测并转发到用户程序模块处理,猜测消息会在MFC逻辑内部被丢弃。因为你没有告诉MFC消息控制中心,这个消息需要在用户态去做额外的处理~
解决办法是需要在button控件属性中设置Owner Draw 为 TRUE,消息就会递交到OnCtlColor处理函数,你就能按照步骤二的处理去实现控件透明化功能。
Owner Draw实质就是开启控件绘制机制,在系统显示效果的基础上,提供给用户定制化控件显示效果的途径,根据需要做调整和美化,拉满效果。
回顾总结一下,vs2010是十多年前的技术工具,强大且完备,同时内部控制逻辑复杂难懂,一旦缺少某个环节的知识点,就无法想象程序执行的结果,当然也有没有静下心来去识别原理和机制,只从简单解决问题的目标去寻找快捷答案。
也不能套用现在的开发工具去理解vs的强大之处,可能是我不太懂你,还得继续舔你^^