您的位置:首页 > 其它

农场工具程序设计(一)

2009-11-22 09:20 155 查看
首先声明:本人设计和开发这个程序没有任何商业目的,完全是用于学习交流!程序的主要设计思路为模拟鼠标操作,没有截取任何商业信息,无病毒、无木马!没有损害他人利益,只是一个替代用户手工操作的工具!使用者也请勿用用于商业用途以及损害他人利益之用!在使用过程中,如腾讯公司警告你不能使用此工具,请暂停使用!谢谢合作!

农场工具主要是模拟鼠标事件来完成各项操作,其中还包含了对图像的识别来判断果实成熟状态以及出现的错误情况的处理。下面来分别介绍各项工具的设计思路和过程:
1、获取光标位置
由于整个程序主要用来模拟鼠标事件,所以必须清楚每一个事件过程中光标所处的位置。获取光标位置可以直接采用Cursor来完成,添加一个Timer,用于时刻显示光标的位置,如下代码:
private void timer1_Tick(object sender, EventArgs e)
{
CursorPoslabelX.Text = "当前光标位置:X=" + Cursor.Position.X + ",Y=" + Cursor.Position.Y;
}
2、设置窗体坐标
由于农场的窗体大小一定,农场中各个工具的位置相对于农场窗体也是一定,所以只需要确定农场窗体在屏幕中的位置,即可找到各个工具的位置。在此以设置农场窗体左上角坐标为例,如下图所示:

在全局变量中定义窗体左上角的坐标变量,如下:
private int BorderLeft, BorderTop;//农场左上角坐标
然后添加一个按钮,设置其Name和Text属性都为“设置农场窗体左上角坐标”,为其Click事件添加如下代码:
private void 设置农场窗体左上角坐标_Click(object sender, EventArgs e)
{
BorderLeft = int.Parse(leftTextBox.Text);
BorderTop = int.Parse(topLextBox.Text);
}
3、定义鼠标单击事件函数
在鼠标模拟过程中主要通过鼠标的单击来完成,所以可以定义一个鼠标单击函数,如下:
private void OnClickEvent(int x, int y)
{
SetCursorPos(x, y);
mouse_event(MouseEventFlag.LeftDown | MouseEventFlag.LeftUp, x, y, 0, (UIntPtr)0);
}
在此用到设置光标位置函数SetCursorPos和鼠标事件函数mouse_event,所以需要在全局变量中声明这两个Windows API中的函数,如下:
[DllImport("user32.dll")]
private extern static bool SetCursorPos(int x, int y);

[DllImport("user32.dll")]
private static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo);
enum MouseEventFlag : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
VirtualDesk = 0x4000,
Absolute = 0x8000
}
通过鼠标单击函数OnClickEvent即可实现在任何地方点击了,但是要判断果实是否成熟或者是否需要除草,可以通过获取图像,然后对图像进行识别,如果图像识别结果为果实则摘取,如果为草则除草。
4、获取图像
获取屏幕图像需要引用系统中的BitBlt函数和CreateDC函数,其声明如下: [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, //目标设备的句柄
int nXDest, // 目标对象的左上角的X坐标
int nYDest, // 目标对象的左上角的Y坐标
int nWidth, // 目标对象的矩形的宽度
int nHeight, // 目标对象的矩形的长度
IntPtr hdcSrc, // 源设备的句柄
int nXSrc, // 源对象的左上角的X坐标
int nYSrc, // 源对象的左上角的X坐标
System.Int32 dwRop // 光栅的操作值
);
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern IntPtr CreateDC(
string lpszDriver, // 驱动名称
string lpszDevice, // 设备名称
string lpszOutput, // 无用,可以设定位"NULL"
IntPtr lpInitData // 任意的打印机数据
);
然后定义一个获取图像的函数GetScreenImage,如下:
private Bitmap GetScreenImage(Point point01, Point point02, bool full)
{
//创建显示器的DC
IntPtr dc1 = CreateDC("DISPLAY", null, null, (IntPtr)null);
//由一个指定设备的句柄创建一个新的Graphics对象
Graphics g1 = Graphics.FromHdc(dc1);
Bitmap MyImage;
int width, height;
if (full)
{
width = Screen.PrimaryScreen.Bounds.Width;
height = Screen.PrimaryScreen.Bounds.Height;
}
else
{
width = point02.X - point01.X;
height = point02.Y - point01.Y;
}

//根据指定的宽度和高度创建一个与之相同大小的Bitmap对象
MyImage = new Bitmap(width, height, g1);

//获得屏幕的句柄
Graphics g2 = Graphics.FromImage(MyImage);
//获得位图的句柄
IntPtr dc3 = g1.GetHdc();
//把当前屏幕捕获到位图对象中
IntPtr dc2 = g2.GetHdc();
//把当前屏幕拷贝到位图中
BitBlt(dc2, 0,0, width, height, dc3, point01.X, point01.Y, 13369376);
//释放屏幕句柄
g1.ReleaseHdc(dc3);
//释放位图句柄
g2.ReleaseHdc(dc2);

return MyImage;
}
该函数实现的功能为获取屏幕中以点Point1为左上角坐标、以点Point2为右下角坐标的图像。
5、识别摘取状态
识别摘取状态在此并没有设计特殊的算法,只是用简单的RGB来识别其摘取状态,定义函数,其代码如下:
private int JudgeType2(Bitmap image, int interval)
{
Color myColor = image.GetPixel(0, 0);
int R = (int)myColor.R;
int G = (int)myColor.G;
int B = (int)myColor.B;
//判断为摘取
if (Math.Abs(R - 230) <= interval)
{
if (Math.Abs(G - 200) <= interval)
{
if (Math.Abs(B - 150) <= 2 * interval)
{
return 1;
}
}
}
//判断为草
if (Math.Abs(R - 124) <= interval)
{
if (Math.Abs(G - 176) <= 2 * interval)
{
if (Math.Abs(B - 63) <= 2 * interval)
{
return 2;
}
}
}
//判断为灰色
if (Math.Abs(R - 165) <= 15)
{
if (Math.Abs(G - 165) <= 15)
{
if (Math.Abs(B - 165) <= 15)
{
return 3;
}
}
}
//判断为白色
if ((R == G) && (G == B) && (R >= 240))
{
return 4;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: