可以用一系列的api实现:::GetCursorPos,获取当前鼠标的位置::SetCursorPos,移动鼠标到某一位置mouse_event,鼠标动作,单击等,如mouse_event(MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP,0,0,0,0);是在当前位置单击一次应用的实例如下:#includevoid main(){::SetCursorPos(10,10);mouse_event(MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP,0,0,0,0);}实现把鼠标移动到x=10,y=10这个位置,然后单击一下。
控制台模拟鼠标、键盘操作模拟鼠标、键盘操作,能让命令行顿然强大,想想,制作批处理版屏幕键盘等都不在话下(已制作过,效果很不错)。虽然这也跟CUI无关。本教程教会你如何让命令行模拟鼠标、键盘的操作。
鼠标的击键操作,需要用到mouse_event这个API函数。
示例代码:
模拟左键单击:
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0); mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
注意到了,其实一次击键是由两部分组成的:按下与释放。所以模拟一次单击要有DOWN及UP两次。
其他键位的属性如下,更改以上代码即可实现:
MOUSEEVENTF_RIGHTDOWN、MOUSEEVENTF_RIGHTUP; MOUSEEVENTF_MIDDLEDOWN、MOUSEEVENTF_MIDDLEUP;
模拟鼠标移位需要用到SetCursorPos这个API函数。尽管mouse_event也能实现模拟移位的效果,但是个人认为用SetCursorPos可能要简单一点。
示例代码:
将鼠标移位到屏幕(120,100)处:
SetCursorPos(120,100);
模拟键盘击键,可以使用keybd_event这个API函数。这个API函数没有太多需要注意的地方,直接看示例代码:
模拟按下A键:
keybd_event(65,0,0,0); keybd_event(65,0,KEYEVENTF_KEYUP,0);
可以发现,跟mouse_event一样,也有按下和释放两个部分。65是A的ASCII码(也可称为扫描码),其他键位对应的码值可以查Winuser.h中“Virtual Keys, Standard Set”的部分。
//mouse.h //模拟鼠标的常见操作 #pragma once #include class MOUSE { private: //坐标变量 POINT point; public: //移动类函数 void Move(int x,int y); void RelativeMove(int cx,int cy); void SavePos(); void RestorePos(); //锁定启用类 void Lock(); void Unlock(); //动作类 void LBClick(); void LBDbClick(); void LBDown(); void LBUp(); void RBClick(); void RBDbClick(); void RBDown(); void RBUp(); void MBClick(); void MBDbClick(); void MBDown(); void MBUp(); void MBRoll(int ch); }; //移动鼠标到绝对位置(X坐标,Y坐标) void MOUSE::Move(int x,int y) { this->point.x=x; this->point.y=y; ::SetCursorPos(x,y); } //移动鼠标到相对位置(X位移,Y位移) void MOUSE::RelativeMove(int cx,int cy) { ::GetCursorPos(&this->point); this->point.x+=cx; this->point.y+=cy; ::SetCursorPos(this->point.x,this->point.y); } //保存当前位置() void MOUSE::SavePos() { ::GetCursorPos(&this->point); } //恢复鼠标位置() void MOUSE::RestorePos() { ::SetCursorPos(this->point.x,this->point.y); } //锁定鼠标() void MOUSE::Lock() { POINT pt; RECT rt; ::GetCursorPos(&pt); rt.left=rt.right=pt.x; rt.top=rt.bottom=pt.y; rt.right++; rt.bottom++; ::ClipCursor(&rt); } //解锁鼠标() void MOUSE::Unlock() { ::ClipCursor(NULL); } //左键单击() void MOUSE::LBClick() { this->SavePos(); ::mouse_event(MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP,this->point.x,this->point.y,0,0); } //左键双击() void MOUSE::LBDbClick() { this->SavePos(); ::mouse_event(MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP,this->point.x,this->point.y,0,0); ::mouse_event(MOUSEEVENTF_LEFTDOWN|MOUSEEVENTF_LEFTUP,this->point.x,this->point.y,0,0); } //左键按下() void MOUSE::LBDown() { this->SavePos(); ::mouse_event(MOUSEEVENTF_LEFTDOWN,this->point.x,this->point.y,0,0); } //左键抬起() void MOUSE::LBUp() { this->SavePos(); ::mouse_event(MOUSEEVENTF_LEFTUP,this->point.x,this->point.y,0,0); } //右键单击() void MOUSE::RBClick() { this->SavePos(); ::mouse_event(MOUSEEVENTF_RIGHTDOWN|MOUSEEVENTF_RIGHTUP,this->point.x,this->point.y,0,0); } //右键双击() void MOUSE::RBDbClick() { this->SavePos(); ::mouse_event(MOUSEEVENTF_RIGHTDOWN|MOUSEEVENTF_RIGHTUP,this->point.x,this->point.y,0,0); ::mouse_event(MOUSEEVENTF_RIGHTDOWN|MOUSEEVENTF_RIGHTUP,this->point.x,this->point.y,0,0); } //右键按下() void MOUSE::RBDown() { this->SavePos(); ::mouse_event(MOUSEEVENTF_RIGHTDOWN,this->point.x,this->point.y,0,0); } //右键抬起() void MOUSE::RBUp() { this->SavePos(); ::mouse_event(MOUSEEVENTF_RIGHTUP,this->point.x,this->point.y,0,0); } //中键单击() void MOUSE::MBClick() { this->SavePos(); ::mouse_event(MOUSEEVENTF_MIDDLEDOWN|MOUSEEVENTF_MIDDLEUP,this->point.x,this->point.y,0,0); } //中键双击() void MOUSE::MBDbClick() { this->SavePos(); ::mouse_event(MOUSEEVENTF_MIDDLEDOWN|MOUSEEVENTF_MIDDLEUP,this->point.x,this->point.y,0,0); ::mouse_event(MOUSEEVENTF_MIDDLEDOWN|MOUSEEVENTF_MIDDLEUP,this->point.x,this->point.y,0,0); } //中键按下() void MOUSE::MBDown() { this->SavePos(); ::mouse_event(MOUSEEVENTF_MIDDLEDOWN,this->point.x,this->point.y,0,0); } //中键抬起() void MOUSE::MBUp() { this->SavePos(); ::mouse_event(MOUSEEVENTF_MIDDLEUP,this->point.x,this->point.y,0,0); } //中键滚动(滚动位移) void MOUSE::MBRoll(int ch) { this->SavePos(); ::mouse_event(MOUSEEVENTF_WHEEL,this->point.x,this->point.y,ch,0); } / //keyboard.h //模拟键盘的常见操作 / #pragma once #include class KEYBOARD { public: void PressStr(char *str); void PressKey(BYTE bVk); void KeyDown(BYTE bVk); void KeyUp(BYTE bVk); }; //按键(虚拟键值) void KEYBOARD::PressKey(BYTE bVk) { ::keybd_event(bVk,0,0,0); ::keybd_event(bVk,0,KEYEVENTF_KEYUP,0); } //按下(虚拟键值) void KEYBOARD::KeyDown(BYTE bVk) { ::keybd_event(bVk,0,0,0); } //抬起(虚拟键值) void KEYBOARD::KeyUp(BYTE bVk) { ::keybd_event(bVk,0,KEYEVENTF_KEYUP,0); } //发送字符串(字符串) void KEYBOARD::PressStr(char *str) { for (unsigned i=0;i { if (str[i]>0x60 && str[i]<0x7B) this->PressKey(str[i]-0x20); else this->PressKey(str[i]); } }BOOL SetCursorPos( int X, // horizontal position int Y // vertical position ); 设置鼠标位置。鼠标指针在屏幕像素坐标系统中的X,Y位置 这个函数是用来设置Mouse位置的。可以用这个函数来移动mouse在屏幕上的移动。
另外一个函数功能比较强,即mouse_event() VOID mouse_event( DWORD dwFlags, DWORD dx, DWORD dy, DWORD dwData, DWORD dwExtraInfo ); 设置mouse状态。参数说明如下: dwFlags Long,下述标志的一个组合 : MOUSEEVENTF_ABSOLUTE dx和dy指定鼠标坐标系统中的一个绝对位置。在鼠标坐标系统中,屏幕在水平和垂直方向上均匀分割成65535×65535个单元 MOUSEEVENTF_MOVE 移动鼠标 MOUSEEVENTF_LEFTDOWN 模拟鼠标左键按下 MOUSEEVENTF_LEFTUP 模拟鼠标左键抬起 MOUSEEVENTF_RIGHTDOWN 模拟鼠标右键按下 MOUSEEVENTF_RIGHTUP 模拟鼠标右键按下 MOUSEEVENTF_MIDDLEDOWN 模拟鼠标中键按下 MOUSEEVENTF_MIDDLEUP 模拟鼠标中键按下 dx 根据是否指定了MOUSEEVENTF_ABSOLUTE标志,指定水平方向的绝对位置或相对运动 dy 根据是否指定了MOUSEEVENTF_ABSOLUTE标志,指定垂直方向的绝对位置或相对运动 dwData amount of wheel movement dwExtraInfo,通常未用的一个值。用GetMessageExtraInfo函数可取得这个值。可用的值取决于特定的驱动程序。 例如:将mouse移动到坐标(450,100) 可用函数: SetCursorPos(450,100) ; 或 mouse_event(MOUSEEVENTF_MOVE ,0,450,100,GetMessageExtraInfo()); 来实现 实现鼠标单击: mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,GetMessageExtraInfo()); mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,GetMessageExtraInfo ()); 那么,如何模拟mouse不断的移动和点击呢?这需要用定时器完成。 以C为例: 在初始化程序的时候,设置时钟: ... case WM_CREATE: ... SetTimer(1, 1000, NULL); break; 这样就设置了ID号为1 的时钟事件, 它每秒(1000毫秒)将产生一个 WM_TIMER事件。 然后我们在WM_TIMER事件中将入相关的处理: case WM_TIMER: { ... // mouse move code... // mouse click code... break; }
关于鼠标模拟程序应用不算少见,在游戏外挂或者一些操作频繁位置确定的程序上应用往往有奇效。比较旧的API是mouse_event,本人一开始也用这个在搞,不过后来才看到新的API在操作上更加统一,稍作改动便也能模拟键盘输入(两者往往要一起应用),所以就用新的API来做。对了,新的API名为SendInput。
下面就不说废话了,直接上代码,本代码是运行在MFC工程上的,如要需要在控制台或者其他工程上运行要包含必须的头文件。此外,本程序只能模拟一般的鼠标操作,对于一些防外挂的程序进行点击需要驱动级的模拟。
模拟鼠标各动作函数
void MouseMove(int x, int y)//鼠标移动到指定位置 { double fScreenWidth = ::GetSystemMetrics(SM_CXSCREEN) - 1;//获取屏幕分辨率宽度 double fScreenHeight = ::GetSystemMetrics(SM_CYSCREEN) - 1;//获取屏幕分辨率高度 double fx = x*(65535.0f / fScreenWidth); double fy = y*(65535.0f / fScreenHeight); INPUT Input = { 0 }; Input.type = INPUT_MOUSE; Input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; Input.mi.dx = fx; Input.mi.dy = fy; SendInput(1, &Input, sizeof(INPUT)); } void MouseLeftDown()//鼠标左键按下 { INPUT Input = { 0 }; Input.type = INPUT_MOUSE; Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; SendInput(1, &Input, sizeof(INPUT)); } void MouseLeftUp()//鼠标左键放开 { INPUT Input = { 0 }; Input.type = INPUT_MOUSE; Input.mi.dwFlags = MOUSEEVENTF_LEFTUP; SendInput(1, &Input, sizeof(INPUT)); } void MouseRightDown()//鼠标右键按下 { INPUT Input = { 0 }; Input.type = INPUT_MOUSE; Input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN; SendInput(1, &Input, sizeof(INPUT)); } void MouseRightUp()//鼠标右键放开 { INPUT Input = { 0 }; Input.type = INPUT_MOUSE; Input.mi.dwFlags = MOUSEEVENTF_RIGHTUP; SendInput(1, &Input, sizeof(INPUT)); } 各动作函数配合完成鼠标各种操作 //模拟鼠标拖动框选 ShowWindow(SW_SHOWMINIMIZED);//窗体最小化 POINT mypoint; GetCursorPos(&mypoint);//获取鼠标当前所在位置 MouseMove(800, 1000);//鼠标移动到指定位置 MouseLeftDown();//鼠标左键点下 MouseMove(10, 10);//鼠标拖动到指定位置 Sleep(10);//这里需要等待一下,不然拖动会没有效果 MouseLeftUp();//鼠标释放 MouseMove(mypoint.x, mypoint.y);//将鼠标放回所在的位置 //模拟鼠标右键按下并释放 ShowWindow(SW_SHOWMINIMIZED);//窗体最小化 MouseRightDown(); Sleep(10); MouseRightUp();