您的位置:首页 > 编程语言 > C#

关于C# windows发送消息

2008-07-11 09:49 344 查看

关于C# windows发送消息

2007年11月19日 星期一 下午 04:15
今天终于又有一点心得啦..这一切都源于我喜欢的一个游戏.由于在玩游戏,所以用按键精灵做了个外挂,使用后发现游戏中是针对按键精灵处理过的,当使用它一定的时间后,后隐去人物的红和蓝,让自己不能加血,够狠的!!于是今天上午想能不能用C#来做一个类似的东西呢,过程如下:一、获取指定坐标的颜色 在游戏中,怪物的血是显示在一个固定的地方的,所以,只要这个点没有血,那么表示当前没有怪可攻击,意思就是可以找怪了,但是这个坐标是多少我都不知道。于是,我在游戏中截了下屏,并保存了图片,把它设为桌面背景色,哈哈,我真是太聪明啦~~在程序中BUTTON下写一行:lbpoint.Text = Cursor.Position.X.ToString() + "," + Cursor.Position.Y.ToString();把鼠标放到血是最左边,也就是怪物血最少的那里,按了下空格,嘿嘿,坐标出来了:293, 35,当然是不是一次完成的,多几下就差不多了。现在坐标出来了,怎么取它的色呢?经过一阵“摆渡”,原来windows的一个API可以实现这样的功能,OK,那就用它吧,代码如下:[DllImport("gdi32.dll")]
static public extern uint GetPixel(IntPtr hDC, int XPos, int YPos); [DllImport("gdi32.dll")]
static public extern IntPtr CreateDC(string driverName, string deviceName, string output, IntPtr lpinitData); [DllImport("gdi32.dll")]
static public extern bool DeleteDC(IntPtr DC); static public byte GetRValue(uint color)
{
return (byte)color;
} static public byte GetGValue(uint color)
{
return ((byte)(((short)(color)) >> 8));
} static public byte GetBValue(uint color)
{
return ((byte)((color) >> 16));
} static public byte GetAValue(uint color)
{
return ((byte)((color) >> 24));
} static public Color GetColorOfScreen(Point screenPoint)
{
IntPtr displayDC = CreateDC("DISPLAY", null, null, IntPtr.Zero);
uint colorref = GetPixel(displayDC, screenPoint.X, screenPoint.Y);
DeleteDC(displayDC);
byte Red = GetRValue(colorref);
byte Green = GetGValue(colorref);
byte Blue = GetBValue(colorref);
return Color.FromArgb(Red, Green, Blue);
}我现在只要调用GetColorOfScreen这个方法就可以得到相应坐标点的色了,作了下测试,OK!游戏中怪的血条色为:(255, 162, 2, 5)可以Color redColor = Color.FromArgb(255, 162, 2, 5);这可构造出色。二、获取游戏窗口如果按逻辑的顺序的话,这一步应该放在第一的,这里也是应用的API[DllImport("user32.dll")]
static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);IntPtr 这个东西,其实说白了就是窗口的句柄,同时,我用进程名称要获取这个游戏窗口,如下:Process[] pros = Process.GetProcessesByName(txtProName.Text.Trim());
if (pros.Length != 0)
{
IntPtr pGame = pros[0].MainWindowHandle; SetActiveWindow(pGame);
SetForegroundWindow(pGame);
Thread.Sleep(2000); BeginGame();
}
else
{
MessageBox.Show("找不到相应的窗口");
}三、开始游戏先是定义一个色表示为怪物的血条Color redColor = Color.FromArgb(255, 162, 2, 5);再定义一个点,并获取它的色:Point p = new Point(293, 35);
Color gameColor = GetColorOfScreen(p);当这两个色相同时,那么就打怪:不相等时,再找怪方法是这样的:private void BeginGame()
{
Color redColor = Color.FromArgb(255, 162, 2, 5);//(255, 255, 123, 104); Point p = new Point(293, 35);
Color gameColor = GetColorOfScreen(p); if (gameColor == redColor)
{
Fight(); BeginGame();
}
else
{
FindMonster(); BeginGame();
}
}四、找怪核心: SendKeys.SendWait("{Tab}");向指定的窗口发送消息,SendKeys还有一个方法Send,有什么区别呢,自己试了就知道了,输出到文本文件里看就明白了,这里表示按了一下Tab这个键,关于其它键的用法如下:键 代码
BACKSPACE {BACKSPACE}、{BS} 或 {BKSP}
BREAK {BREAK}
CAPS LOCK {CAPSLOCK}
DEL 或 DELETE {DELETE} 或 {DEL}
DOWN ARROW(下箭头键) {DOWN}
END {END}
ENTER {ENTER} 或 ~
ESC {ESC}
HELP {HELP}
HOME {HOME}
INS 或 INSERT {INSERT} 或 {INS}
LEFT ARROW(左箭头键) {LEFT}
NUM LOCK {NUMLOCK}
PAGE DOWN {PGDN}
PAGE UP {PGUP}
PRINT SCREEN {PRTSC}(保留,以备将来使用)
RIGHT ARROW(右箭头键) {RIGHT}
SCROLL LOCK {SCROLLLOCK}
TAB {TAB}
UP ARROW(上箭头键) {UP}
F1 {F1}
F2 {F2}
F3 {F3}
F4 {F4}
F5 {F5}
F6 {F6}
F7 {F7}
F8 {F8}
F9 {F9}
F10 {F10}
F11 {F11}
F12 {F12}
F13 {F13}
F14 {F14}
F15 {F15}
F16 {F16}
数字键盘加号 {ADD}
数字键盘减号 {SUBTRACT}
数字键盘乘号 {MULTIPLY}
数字键盘除号 {DIVIDE}

若要指定与 SHIFT、CTRL 和 ALT 键的任意组合一起使用的键,请在这些键代码之前加上以下一个或多个代码:

键 代码
SHIFT + (SHIFT="+")
CTRL ^ (CTRL="^") 如果输入
ALT % 如果是一般的数据和字母,就只要写进去就可以了,如:SendKeys.SendWait("A");五、打怪找怪都做好了,那打怪就好办了,我想(事实不是这样的)把攻击键放到3这个位置,SendKeys.SendWait("3");
SendKeys.SendWait("3");
SendKeys.Flush();OK。这样就差不多了,再加个线程进去,不然,怎么停止呢~~,完整的代码如下(主要部分):Thread th = null;//开始挂机private void btStart_Click(object sender, EventArgs e)
{
th = new Thread(new ThreadStart(StartGame));
th.Start(); btStart.Enabled = false;
btStop.Enabled = true;
}//停止挂机 private void btStop_Click(object sender, EventArgs e)
{
th.Abort(); btStart.Enabled = true;
btStop.Enabled = false;
} private void StartGame()
{
Process[] pros = Process.GetProcessesByName(txtProName.Text.Trim());//在窗体上输入游戏进程名
if (pros.Length != 0)
{
IntPtr pGame = pros[0].MainWindowHandle; SetActiveWindow(pGame);
SetForegroundWindow(pGame);
Thread.Sleep(2000); BeginGame();
}
else
{
MessageBox.Show("找不到相应的窗口");
}
} private void BeginGame()
{
Color redColor = Color.FromArgb(255, 162, 2, 5);//(255, 255, 123, 104); Point p = new Point(293, 35);
Color gameColor = GetColorOfScreen(p); if (gameColor == redColor)
{
Fight(); BeginGame();
}
else
{
FindMonster(); BeginGame();
}
} private void Fight()
{
SendKeys.SendWait("3");
SendKeys.SendWait("3");
SendKeys.Flush(); Thread.Sleep(2000);
} private void FindMonster()
{
SendKeys.SendWait("{Tab}");
Thread.Sleep(2000);
}到这里为止,我认为就差不多了,测试:把游戏图片设为桌面背景,打开一个记事本,在窗体中输入notepad,点开始挂机,找到记事本,OK由于桌面那张图片是有怪物的,输入33 OK再把记事本最大化,找不到怪物血条了,输入tab OK。。哈哈,,说明测试成功!!但是,问题也出来了,进入游戏后,找怪都可以正常,就是不能按3这个键,,不知道为什么,我在自己写的窗体上都可以的~~~于是,再做了个窗体;protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
lbMessage.Text=KeyData.ToString();
return base.ProcessCmdKey(ref msg, keyData);
}这样,窗体上输入的按键都会显示到控件是去,然后用刚刚那个窗口,输入这个程的名称,点开始挂机,在没有怪血条的时候是输入的Tab,OK。但有怪的时候是输入的D3而不是3,啊。。这是怎么回事呢,于是我把打怪那一行改为:SendKeys.SendWait("D3");但是由于下午上班了,没时间测试,晚上回去再试试吧。后记:我还用鼠标点示来实现触发打怪,取到攻击技能的坐标,[Flags]
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
}
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")]
static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo);SetCursorPos(418, 744);
Thread.Sleep(1000);
mouse_event(MouseEventFlag.RightDown, 418, 744, 0, UIntPtr.Zero);
mouse_event(MouseEventFlag.RightUp, 418, 744, 0, UIntPtr.Zero);MouseEventFlag 这个枚举基本上所有的鼠标事件都有了,不错,可以做很多事啦,但在游戏中还是不行,我怀疑是游戏处理了这种消息的发送的,不让这种模拟的消息传入,那样的话,做外挂可以麻烦了,不过。今天还是有不少的体会的,因为我一开始什么都不懂,到后来还是学到点东西啦~[DllImport("user32.dll")]表示调用Windows的一个DLL,它是Windows自带的,不过要对它有所了解才能用它,我们用的时候只要定义好它的方法就行了,实现交给它自身去处理,就是extern
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: