说起来发现这个还是因为做qq外挂
当时发现从屏幕上GetPixel一个点,然后将这个颜色SetPixel到一个BitMap上,但是很奇迹地发现两者居然不同
后来干脆先全屏截图,两种方法再取同样一个点,发现真的不一样。
翻查一些资料才知道,原来net中色值还包括一个透明度,而api的却是没有这个透明度
api中的色值最多只有六位,而net多了一个透明度变成八位了
然后我做了一个实验来求出他们之间的差值
请看:
int ret = Color.Red.ToArgb() - 0xFF0000;//值为-16777216
int r = Color.FromArgb(0xFF0000 - 16777216).R;//值为255
int ret1 = Color.Green.ToArgb()-0x00FF00;//值为-16809728 这个不知道为什么会这样
int g = Color.FromArgb(0x00FF00 - 16777216).G;//值为255
int ret2 = Color.Blue.ToArgb() - 0x0000FF;//值为-16777216
int b = Color.FromArgb(0x0000FF - 16777216).B;//值为255
int ret3 = Color.FromArgb(123, 123, 123).ToArgb() - 0x7B7b7B;//值为-16777216
//以上如果忽略掉绿色的那个值,可得出公式
//
// net的色值=api的色值-16777216
//
//下面同样会验证对于绿色这个公式也是适合的
//-----------------------------------------------------
//以下验证这个公式算出来的net色值分离r g b是否正确
//事实证明是正确的 呵呵
int tempr = Color.FromArgb(0x7BFF7B - 16777216).R;//值为123
int tempg = Color.FromArgb(0x7BFF7B - 16777216).G;//值为255
int tempb = Color.FromArgb(0x7BFF7B - 16777216).B;//值为123
//这里验证对于绿色也是适合的
int tempr1 = Color.FromArgb(0x00FF00 - 16777216).R;//值为0
int tempg1 = Color.FromArgb(0x00FF00 - 16777216).G;//值为255
int tempb1 = Color.FromArgb(0x00FF00 - 16777216).B;//值为0
int r = Color.FromArgb(0xFF0000 - 16777216).R;//值为255
int ret1 = Color.Green.ToArgb()-0x00FF00;//值为-16809728 这个不知道为什么会这样
int g = Color.FromArgb(0x00FF00 - 16777216).G;//值为255
int ret2 = Color.Blue.ToArgb() - 0x0000FF;//值为-16777216
int b = Color.FromArgb(0x0000FF - 16777216).B;//值为255
int ret3 = Color.FromArgb(123, 123, 123).ToArgb() - 0x7B7b7B;//值为-16777216
//以上如果忽略掉绿色的那个值,可得出公式
//
// net的色值=api的色值-16777216
//
//下面同样会验证对于绿色这个公式也是适合的
//-----------------------------------------------------
//以下验证这个公式算出来的net色值分离r g b是否正确
//事实证明是正确的 呵呵
int tempr = Color.FromArgb(0x7BFF7B - 16777216).R;//值为123
int tempg = Color.FromArgb(0x7BFF7B - 16777216).G;//值为255
int tempb = Color.FromArgb(0x7BFF7B - 16777216).B;//值为123
//这里验证对于绿色也是适合的
int tempr1 = Color.FromArgb(0x00FF00 - 16777216).R;//值为0
int tempg1 = Color.FromArgb(0x00FF00 - 16777216).G;//值为255
int tempb1 = Color.FromArgb(0x00FF00 - 16777216).B;//值为0
结论:net的色值=api的色值-16777216
至此,貌似得出了一个强大的结论,但是在我进一步的实验中,结果却并非如此
且看:
class Program
{
static void Main(string[] args)
{
Thread.Sleep(1000);//延迟片刻截图
//截全屏
Bitmap img = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
Graphics g = Graphics.FromImage(img);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.AllScreens[0].Bounds.Size);
IntPtr imgHDC = g.GetHdc();//获取图片的设备上下文
for (int x = 0; x < Screen.AllScreens[0].Bounds.Width/100; x++)
for (int y = 0; y < Screen.AllScreens[0].Bounds.Height/100; y++)
{
int netColor = img.GetPixel(x, y).ToArgb();
int apiColor = Win32Api.GetPixel(imgHDC, x, y);
int sub = netColor - apiColor;
Console.WriteLine("当前比较的点为:{0},{1}",x.ToString(),y.ToString());
Console.WriteLine("net色值为:{0}",netColor.ToString());
Console.WriteLine("api色值为:{0}", apiColor.ToString());
Console.WriteLine("差值为:{0}", sub.ToString());
Console.WriteLine("------------------------------------");
}
Console.ReadKey();
}
{
static void Main(string[] args)
{
Thread.Sleep(1000);//延迟片刻截图
//截全屏
Bitmap img = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
Graphics g = Graphics.FromImage(img);
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.AllScreens[0].Bounds.Size);
IntPtr imgHDC = g.GetHdc();//获取图片的设备上下文
for (int x = 0; x < Screen.AllScreens[0].Bounds.Width/100; x++)
for (int y = 0; y < Screen.AllScreens[0].Bounds.Height/100; y++)
{
int netColor = img.GetPixel(x, y).ToArgb();
int apiColor = Win32Api.GetPixel(imgHDC, x, y);
int sub = netColor - apiColor;
Console.WriteLine("当前比较的点为:{0},{1}",x.ToString(),y.ToString());
Console.WriteLine("net色值为:{0}",netColor.ToString());
Console.WriteLine("api色值为:{0}", apiColor.ToString());
Console.WriteLine("差值为:{0}", sub.ToString());
Console.WriteLine("------------------------------------");
}
Console.ReadKey();
}
结果为:
可以发现,得出的值每个都不一样,
但是为什么会这样呢?真是百思不得其解。
我迷茫了,不知道到底问题出在哪里,各位读者有知道的麻烦告知一下,就当做是指点一下新手了。呵呵
后记:
由于一直没有答案,我便开始考虑是不是我寻找的方向错了,后来我想,屏幕取色工具很可能会用到颜色转换。根据这个想法,我还真的找到了答案,还弄了一个屏幕取色的小程序。
至此,本研究终于有了成果,转换win32颜色到net的颜色,其实微软有个专门的类库来进行这些转换,代码如下:


在我的屏幕取色工具中,使用net的方法是先截屏,然后对截的图使用net的GetPixel函数,获得颜色,使用ColorTranslator转换为win32的色值,接着为了对比,我又用了win32的api对桌面进行GetPixel,对比结果发现,都是同一色值!!那么为什么我的实验二会不同呢?
我仔细观察源代码,发现了这句极为可疑
IntPtr imgHDC = g.GetHdc();//获取图片的设备上下文
也许问题就出在这里,net从画板取得的DC很可能与win32的DC不一致,导致了结果不一致。但是这个结论我没有办法证明,不知谁可以解释一下?