说起来发现这个还是因为做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
结论: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();
}
结果为:
可以发现,得出的值每个都不一样,
但是为什么会这样呢?真是百思不得其解。
我迷茫了,不知道到底问题出在哪里,各位读者有知道的麻烦告知一下,就当做是指点一下新手了。呵呵
后记:
由于一直没有答案,我便开始考虑是不是我寻找的方向错了,后来我想,屏幕取色工具很可能会用到颜色转换。根据这个想法,我还真的找到了答案,还弄了一个屏幕取色的小程序。
至此,本研究终于有了成果,转换win32颜色到net的颜色,其实微软有个专门的类库来进行这些转换,代码如下:
int
win32Color
=
ColorTranslator.ToWin32(netColor);
//
从net的Color结果取得win32的色值
Color netColor
=
ColorTranslator.FromWin32(win32Color);
//
从win32的色值转换到net的Color结构
在我的屏幕取色工具中,使用net的方法是先截屏,然后对截的图使用net的GetPixel函数,获得颜色,使用ColorTranslator转换为win32的色值,接着为了对比,我又用了win32的api对桌面进行GetPixel,对比结果发现,都是同一色值!!那么为什么我的实验二会不同呢?
我仔细观察源代码,发现了这句极为可疑
IntPtr imgHDC
=
g.GetHdc();
//
获取图片的设备上下文
也许问题就出在这里,net从画板取得的DC很可能与win32的DC不一致,导致了结果不一致。但是这个结论我没有办法证明,不知谁可以解释一下?