屏幕取色器设计思路及源码

16年因工作需要,需要根据UI图获取指定位置的颜色,在网上下载了几个取色软件,操作不方便,遂自己花了些时间做了一个 。
你可能会觉得做个这样的软件很难,其实不难,UI界面加上一系列的优化,仅花了几个小时。
怎样去做?
首先,你得知道什么是Windows API,摘自百度百科:Windows API 就是Windows应用程序接口,是针对Microsoft Windows操作系统家族的系统编程接口
Windows API可以做很多事情,比如说模拟鼠标点击,修改内存数据等等。我们做屏幕取色器要做的就是使用它的屏幕截图和取色。
知道了该用什么去做,接下来就是程序的设计思路了。
软件大体设计:
出于用户体验(自己的体验)方面,我们的软件应该做到随叫随到,至少不要用了以后关掉又得重新打开,所以,我们把它放到桌面右下角的托盘中去,用快捷键唤出。
软件唤出后,如果以窗口的形式停在某个位置,而我们刚好要取那个位置的点,会造成干扰。所以,我们将取色窗口设计成一个跟随鼠标移动的小窗口。
用鼠标准确选取某一个坐标点的颜色值比较困难,因此,我们可以将鼠标方圆10个像素点的颜色用小方格的形式展示出来。鼠标点击软件上的小方格可精确选取某个坐标点的像素。
得到坐标值以后需要复制颜色值,我们设计为点击颜色值直接复制到剪切板
最终效果图如下:

软件启动后会最小化到右下角的托盘图标  
Ctrl+Alt+X:呼出软件取色界面  
Ctrl+Alt+C:隐藏软件取色界面  
Shift:呼出软件取色界面后,按住Shift键,取色界面将跟随鼠标移动,获取鼠标位置方圆10像素点的颜色代码  
Ctrl+Alt+S:复制颜色值到剪切板  
点击取色界面上的小方格,获取小方格处的颜色值  
点击取色界面上的颜色值文本,自动将颜色值复制到剪切板

设计好了,开始进入编码阶段。
题外话:这里我要说一下伪代码,伪代码在大家学习编程的时候都学过,可以理解为是一段代码描述。不过我们基本上不会去写伪代码,很多同志都是需求不明,代码先行。不管想没想清楚,先写,写出来有问题,改,最后发现不能这样写,删了重新写。我觉得伪代码可以起到一个整理设计的作用,很多时候你可能写着写着会发现,好像不能这么写。写伪代码可以帮你提前发现这一点。伪代码其实是一个很重要的东西,不过它在书上并没有多少篇幅导致被很多人忽视。(现在很多人甚至连注释都懒得写)

编码设计:

获取鼠标方圆10像素点的颜色,也就是横竖21个格子。
-定义一个21*21的二维数组,用来保存鼠标位置附近坐标的颜色值
屏幕坐标系大家应该都知道,左上角是0,0,横向是X轴,纵向是Y轴。
-获取鼠标当前位置的坐标(x,y)
-循环遍历,横坐标从x-10遍历到x+10,纵坐标从y-10遍历到y+10 {
-将坐标颜色值存储到二维数组中
-}
-将二维数组的颜色值绘制到软件上

(扯一下伪代码的作用)
写好伪代码,我们可以看到两个关键点,获取鼠标坐标,获取坐标位置的颜色代码。解决了这两个点,整个软件的核心就可以写出来了,这两个关键点的代码几乎是可以从百度上复制下来的。
我们再看一下这段伪代码,逻辑很简单,但是在真正写代码的时候,可能会是一段很长的代码,如果代码全写一个方法里,看上去会很复杂,后期维护也不方便。
从这段伪代码我们已经可以看出,第一句,定义一个二维数组,这肯定是个全局变量,因为我们肯定不止在这个地方会用到它。第二句,调用系统函数获取鼠标在屏幕上的位置,普通代码。然后进入循环,一段普通代码。最后这句,把数据放到屏幕上展示出来,这可以做一个方法,它和我们的逻辑没有多少的关联,假如我们不需要界面展示,这段代码可以不要。
代码写好后,可以直接把伪代码当成注释。很多同志都没有写注释的习惯,我建议还是多写点,你如果接手了一个基本上看不到注释的项目心里肯定把上一波写的人问候了N遍,反过来你写了一个这样的项目,接手的人也会在心里问候你。
回到刚刚的程序,我碰到了个问题,我发现直接从屏幕上取颜色是个很耗时的操作,导致软件一卡一卡的,怎么办呢?
我们在工作中一般是自己开发自己的模块,也经常会碰到一些问题,这时候我们会找同事帮忙,同事来了以后,点着代码跳来跳去给别人看,看了半天,把同事给看懵了。
但是如果我们能把自己代码的整体逻辑用伪代码写好,同事一看就知道你要做什么,也就不用跟着你的代码去理解你的需求了。这样会节约很多时间,而且你可能在写伪代码的过程中,自己就发现问题在哪了。
上面那个问题我猜测拿颜色值每次都会调用获取窗口句柄这些函数,现在我们有四百多个格子,假设取一次10毫秒,取400个点就要4秒,怎么办?改成100个格子?减少格子数是下下策。实在没办法了才去用这种方法。
我换种方式,我先把屏幕截下来保存到内存中,从内存中获取坐标处的颜色值。伪代码这样写

-定义一个21*21的二维数组,用来保存鼠标位置附近坐标的颜色值
-获取鼠标当前位置的坐标(x,y)
-截取屏幕图像保存到内存中
-循环遍历,横坐标从x-10遍历到x+10,纵坐标从y-10遍历到y+10 {
-将内存图像上坐标颜色值存储到二维数组中
-}
-将二维数组的颜色值绘制到软件上


试了一下,果然不卡了。
我们在工作上有时候会碰到一些难题,但是解决问题的方法不止一种,如果一个方案行不通,我们可以试图使用其他的方案,不要死磕在一个点上。
软件的核心算是写完了,接下来就是做界面了,界面不需要美观,但是也要自己用的舒服。
看上去这个软件是做的差不多了,其实是有很大问题的,比如说我们的伪代码里面并没有考虑到鼠标移到屏幕边缘,数组下标会小于0。
很多问题在写的时候没想到,所以没考虑到,所以在写完代码后,一定要多测试,尽可能的去找可能会让它崩溃的原因。
有些东西看着神奇,其实只要你自己敢去想,敢去做,它并没有想象中的那么困难。
不过要想把一个软件做好,需要花费很多时间和精力去设计。

这里开源了我屏幕取色器的项目源码,代码是VB的,用VB6.0精简版既可运行,附带可直接运行的exe文件。(虽然我主修Java,但Java做桌面应用真不方便)
github:https://github.com/lieyanfeimao/screencolor
码云:https://gitee.com/edadmin/screencolor

用到的WindowsAPI:
GetAsyncKeyState:判断按键是否被按下
BitBlt:对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。(截屏操作)
GetCursorPos:获取鼠标在屏幕的坐标
GetDC:获取设备句柄
getpixel:检索指定坐标点的像素的RGB颜色值
SetProcessDpiAwareness:设置DPI缩放模式
SetWindowPos:设置窗口置顶
GetDeviceCaps:获取系统设置的DPI,不同的DPI对应不同的屏幕缩放率

用到的API可以自己百度查看详细的解释

作者:玄翼猫  2019-10-25

猜你喜欢

转载自blog.csdn.net/xymmwap/article/details/102746380