菜鸟变凤凰,KingDZ 变菜鸟,每日一个C#小实例之---C#取色器

今天首先给大家带来的实例是C#取色器,目前互联网上各种版本的取色器多不胜数,其中好用的软件更是多如牛毛,今天我们就简单的讲解一个C#版本的取色器,诞生的过程,整个过程中,我会不断的完善我们的取色器,争取做一个可发布版本的取色器,也正好趁这个机会开发一个适合自己在实际编程中方便的取色去,哈哈,开始吧。
大家可以去其他网站上面找相应的软件,互联网上面也有很多很好的开源代码。博取众家之长,不断学习。
哦,对了,顺表告诉大家一句,我的开发环境是Window7+VS2010呵呵。
当然了,我们这次首先还是基于API接口开发,当然大家有更好的建议,欢迎告诉我,我喜欢更高的效率。哈哈。
首先我们要得到颜色,首先要做的就是得到屏幕上面某点的坐标了。哈哈
简单。上节课也实现了,这节课我们采用新的办法
Point p = new Point(MousePosition.X, MousePosition.Y); lblX.Text = p.X.ToString(); lblY.Text = p.Y.ToString();
好了,得到鼠标的坐标了。对了,我把这个放在
tm_Tick
里面了,这个是时间控件的Tick事件哦。
首先为了下面的代码方便,我们需要首先了解一下什么是 IntPtr
C#中的IntPtr类型称为“平台特定的整数类型”,它们用于本机资源,如窗口句柄。
IntPtr 类型被设计成整数,其大小适用于特定平台。即是说,此类型的实例在 32 位硬件和操作
系统中将是 32 位,在 64 位硬件和操作系统上将是 64 位。
具体的用法,还有其中的奥妙,我想大家还是需要去了解一下。
http://msdn.microsoft.com/zh-cn/library/system.intptr.aspx
好了,我们来实现我们的取色器代码吧。
首先我们先用最简单的原理实现一个版本的取色器,我们实现的是移动鼠标显示桌面任意点的颜色。版本1当然是最简单的实现啦。
2KingDZ 变菜鸟,每日一个C#小实例之---C#取色器菜鸟变凤凰
首先我们依然是调用API接口,
[DllImport("User32")] public static extern IntPtr GetDC(IntPtr h); [DllImport("gdi32")] public static extern uint GetPixel(IntPtr h, Point p);
GetDC的说明,请参照官网
http://msdn.microsoft.com/en-us/library/dd144871(v=vs.85).aspx
GetPixel  该函数检索指定坐标点的像素的RGB颜色值。
http://msdn.microsoft.com/en-us/library/dd144909%28v=vs.85%29.aspx
建议英文好的童鞋可以好好看看上面的说明,对你绝对有好处滴。哈哈。
好了,说简单一些上面的两个函数,一个是取屏幕,另一个就是得到坐标点像素。
我们继续吧。
IntPtr h = GetDC(new IntPtr(0)); //取屏幕,0代表着全屏
uint color = GetPixel(h, p); //取颜色喽 uint red = (color & 0xFF); //转换红色 uint green = (color & 0xFF00) / 256; //转换绿色 uint blue = (color & 0xFF0000) / 65536;//转换蓝色
上面的颜色转换使我们在编程中,经常用到的技巧,建议大家记住。
txtRGB.Text = string.Format("{0},{1},{2}", red, green, blue); txtT.Text = color.ToString(); txtL.Text = "#" + red.ToString("x").PadLeft(2, '0') + green.ToString("x").PadLeft(2, '0') + blue.ToString("x").PadLeft(2, '0'); picColor.BackColor = Color.FromArgb((int)red,(int)green,(int)blue);
好了,最上面的代码也已完成了,呵呵,OK,简易版本的完成了。我们下面实现一个相对比较复杂的。大家觉得怎么样,这个只要一打开就可以会得到颜色了,但是可控制性不好。下面我们自己想办法控制,啥时间去颜色,啥时间不取颜色。
我们改变更一种写法来实现我们想要的效果。
首先声明几个坐标点。分别是,窗口起始左边,Window左下角和右下角。为什么出现这几个坐标呢,拜托。假如你想取到你取色器那个位置下面的坐标呢?你还取得到吗?覆盖着呢。
好了。开始
public Point formLoad, formLeft, formRight;
当然了,我们也需要一个及时取色的Timer
Timer tm; 首先在构造函数里面初始化数据。
Rectangle rect = Screen.PrimaryScreen.WorkingArea; formLeft = new Point(0, rect.Height - this.Height); formRight = new Point(rect.Width - this.Width, rect.Height - this.Height);
Screen.PrimaryScreen.WorkingArea得到屏幕工作区域,记住不包括任务栏啊,哈哈,怎么取到任务栏的颜色,你自己想办法吧。 下面我们还需要几个API来实现。
[DllImport("gdi32")] private static extern IntPtr CreateDC( string lpszDriver, // 驱动名称 string lpszDevice, // 设备名称 string lpszOutput, // 无用,可以设定位"NULL" IntPtr lpInitData // 任意的打印机数据 );
上面这个API可以到http://msdn.microsoft.com/en-us/library/dd183490%28v=vs.85%29.aspx查找资料。
[DllImport("gdi32.dll")] private static extern bool BitBlt( IntPtr hdcDest, // 目标设备的句柄 int nXDest, // 目标对象的左上角的X坐标 int nYDest, // 目标对象的左上角的X坐标 int nWidth, // 目标对象的矩形的宽度 int nHeight, // 目标对象的矩形的长度 IntPtr hdcSrc, // 源设备的句柄 int nXSrc, // 源对象的左上角的X坐标 int nYSrc, // 源对象的左上角的X坐标 int dwRop // 光栅的操作值 );
http://msdn.microsoft.com/en-us/library/dd183370%28v=vs.85%29.aspx上面的API解释在这个地方。
当然,除了用API,还有其他的办法吗?当然有的,一会我们介绍。
22KingDZ 变菜鸟,每日一个C#小实例之---C#取色器菜鸟变凤凰
btnGetColor_Click
该事件是按钮的单击事件,我们需要在里面定位我们的取色窗体。
formLoad = this.Location; this.Location = formLeft; this.TopMost = true;
我像上面的代码很好理解吧。
tm = new Timer(); tm.Interval = 1; tm.Tick += new EventHandler(tm_Tick); tm.Enabled = true;
好了计时器也在这里开始工作了。我们首先实现计时器的代码。
首先创建显示器的DC
IntPtr hdlDisplay = CreateDC("display",null,null,IntPtr.Zero);
从指定设备的句柄创建新的 Graphics 对象
Graphics g= Graphics.FromHdc(hdlDisplay);
创建只有一个象素大小的 Bitmap 对象
Bitmap bmp = new Bitmap(1, 1, g);
从指定 Image 对象创建新的 Graphics 对象
Graphics gimg = Graphics.FromImage(bmp);
获得屏幕的句柄与获得位图的句柄
IntPtr hdlScreen = g.GetHdc(); IntPtr hdlBmp = gimg.GetHdc();
把当前屏幕中鼠标指针所在位置的一个象素拷贝到位图中
BitBlt(hdlBmp, 0, 0, 1, 1, hdlScreen, MousePosition.X, MousePosition.Y, 13369376);
释放屏幕句柄和释放位图句柄
g.ReleaseHdc(hdlScreen); gimg.ReleaseHdc(hdlBmp);
好了,到这取色的流程得到了,当然你也可以这么实现,下面的就不需要句柄了、
获得当前屏幕的
Screen screen = Screen.PrimaryScreen; Rectangle rc = screen.Bounds; int iWidth = rc.Width; int iHeight = rc.Height;
创建一个和屏幕一样大的Bitmap
Image myImage = new Bitmap(iWidth, iHeight);
从一个继承自Image类的对象中创建Graphics对象
Graphics g = Graphics.FromImage(myImage);
复制全屏幕。得到全屏幕了,你想去像素也就简单多了。
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(iWidth, iHeight));
好了,接着我们上面描述继续开发,我们需要的窗体,这里有一个技巧就是,用一个基本完全透明的窗体覆盖住Window剩下的我们好操作。
GetColors getColors = new GetColors(); getColors.Tag = this; getColors.ShowDialog();
在这个新窗体中,我们在Load事件中简单的写两句即可。
this.MaximizedBounds = Screen.PrimaryScreen.Bounds; this.WindowState = FormWindowState.Maximized; this.FormBorderStyle = FormBorderStyle.None; this.Opacity = 0.01;
最后的这个就是透明度了,哈哈,你可以改成 1 试试 窗体单击关闭
private void GetColors_Click(object sender, EventArgs e) { this.Close(); }
当然更多的操作,比如窗体的鼠标,窗体的其他一些美工,都要靠自己了,你也可以,用其他的办法给窗体定位,或者,取指定窗体的颜色。
private void GetColors_MouseMove(object sender, MouseEventArgs e) { MainForm Mymainform = (MainForm)this.Tag; if (e.X > Mymainform.Left && e.X < Mymainform.Left + Mymainform.Width && e.Y > Mymainform.Top && e.Y < Mymainform.Top + Mymainform.Width) { Mymainform.Location=Mymainform.Location == Mymainform.formLeft ? Mymainform.formRight:Mymainform.formLeft; } }
当然这个方法就是解决咱们前面遇到的取色窗体覆盖的问题啦。哈哈,点不到,点不到....... 单击关闭透明窗体
tm.Enabled = false; this.Location = formLoad; this.TopMost = false;
释放资源,得到颜色 picColor.BackColor = bmp.GetPixel(0, 0); txtARGB.Text = "0x" + picColor.BackColor.ToArgb().ToString("x").ToUpper(); txtRGB.Text = picColor.BackColor.R.ToString().ToLower() + "," + picColor.BackColor.G.ToString().ToLower() + "," + picColor.BackColor.B.ToString().ToLower(); txtL.Text = "#" + picColor.BackColor.R.ToString("x").PadLeft(2, '0') + picColor.BackColor.G.ToString("x").PadLeft(2, '0') + picColor.BackColor.B.ToString("x").PadLeft(2, '0'); g.Dispose(); gimg.Dispose(); bmp.Dispose();
哈哈,好了,一个取色器做好了。
剩下的大家自己可以扩展了,可以按Ctrl去颜色,也可以取到颜色放到剪贴板中,总之呢,最难解决的就是拿到像素点颜色了,我们都已经拿到了,还有什么难的呢?
代码下载
GetColor.rar
Tags:  cf菜鸟变高手 韩剧菜鸟变凤凰 菜鸟变黑客 菜鸟变凤凰国语 菜鸟变凤凰

延伸阅读

最新评论

发表评论