前言: 很多初学 windows 编程的朋友, 大多搞不清 WINAPI 函数的工作方式。 如果您要成为一名熟练的Windows 程序员,想通过程序员这个职业赚钱, Make more money, 那么就不得不熟悉 WINAPI。 自动模拟/测试程序的实现,对于 Windows 编程新手了解 windows 窗口机制很有帮助。
自动启动/关闭程序有很多种方法。这里分别讲述其中两种。
方法一:使用 WinExec()函数
WinExec The WinExec function runs the specified application. Note: This function is provided only for compatibility with 16-bit Windows. Applications should use the CreateProcess function. UINT WinExec( LPCSTR lpCmdLine, // command line 包含要执行的命令行 UINT uCmdShow // window style 定义了以怎样的形式启动程序的常数值 ); VB的声明: Declare Function WinExec Lib "kernel32" Alias "WinExec" (ByVal lpCmdLine As String, ByVal nCmdShow As Long) As Long参数说明:
LPCSTR lpCmdLine: 包含要执行的命令行。
系统将在以下范围查找应用程序:
1. 应用程序启动位置
2. 当前目录位置
3. Windows system目录
4. Windows 目录
5. path中设置的路径列表
UNIT uCmdShow: 定义了以怎样的形式启动程序的常数值。具体说明如下:
SW_HIDE 隐藏窗口,活动状态给另一个窗口
SW_MINIMIZE 最小化窗口,活动状态给另一个窗口
SW_RESTORE 用原来的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOW 用当前的大小和位置显示一个窗口,同时令其进入活动状态
SW_SHOWMAXIMIZED 最大化窗口,并将其激活
SW_SHOWMINIMIZED 最小化窗口,并将其激活
SW_SHOWMINNOACTIVE 最小化一个窗口,同时不改变活动窗口
SW_SHOWNA 用当前的大小和位置显示一个窗口,不改变活动窗口
SW_SHOWNOACTIVATE 用最近的大小和位置显示一个窗口,同时不改变活动窗口
SW_SHOWNORMAL 与SW_RESTORE相同
例如:启动当前目录下的abc.exe 程序:
WinExec( "abc.exe",SW_SHOW );
方法二:使用 CreateProcess, ShellExecuteEx函数
WinExec是一个兼容win16的函数。win32应用程序可使用 CreateProcess 函数,也可使用ShellExecute, ShellExecuteEx函数。具体说明可查阅有关帮助文档。
CreateProcess The CreateProcess function creates a new process and its primary thread. The new process runs the specified executable file in the security context of the calling process. If the calling process is impersonating another user, the new process uses the token for the calling process, not the impersonation token. To run the new process in the security context of the user represented by the impersonation token, use the CreateProcessAsUser or CreateProcessWithLogonW function. BOOL CreateProcess( LPCTSTR lpApplicationName, // name of executable module LPTSTR lpCommandLine, // command line string LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD BOOL bInheritHandles, // handle inheritance option DWORD dwCreationFlags, // creation flags LPVOID lpEnvironment, // new environment block LPCTSTR lpCurrentDirectory, // current directory name LPSTARTUPINFO lpStartupInfo, // startup information LPPROCESS_INFORMATION lpProcessInformation // process information ); ShellExecute Performs an operation on a specified file. HINSTANCE ShellExecute( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd );
方法一: 模拟鼠标点击[关闭]按钮
要用到以下两个 WinAPI 函数:mouse_event 和 SetCursorPos
mouse_event The mouse_event function synthesizes mouse motion and button clicks. Windows NT/2000/XP: This function has been superseded. Use SendInput instead. VOID mouse_event( DWORD dwFlags, // motion and click options DWORD dx, // horizontal position or change DWORD dy, // vertical position or change DWORD dwData, // wheel movement ULONG_PTR dwExtraInfo // application-defined information );mouse_event 设置mouse状态。参数说明如下:
SetCursorPos The SetCursorPos function moves the cursor to the specified screen coordinates. If the new coordinates are not within the screen rectangle set by the most recent ClipCursor function call, the system automatically adjusts the coordinates so that the cursor stays within the rectangle. BOOL SetCursorPos( int X, // horizontal position int Y // vertical position );设置鼠标位置。鼠标指针在屏幕像素坐标系统中的X,Y位置
例如确定程序的关闭按钮位于座标点(1015,682),则执行下面两段代码中的任意一段都可以实现关闭:
代码1:方法2:找到程序的窗口句柄(Windows Handle),给其发送WM_CLOSE事件。void CloseProgram() { SetCursorPos(1015,682);
mouse_event(MOUSEEVENTF_LEFTDOWN ,0,0,0,GetMessageExtraInfo()); mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,GetMessageExtraInfo ()); } 代码2: void CloseSpedia() { mouse_event(MOUSEEVENTF_MOVE,0,1015,682,GetMessageExtraInfo()); mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,GetMessageExtraInfo()); mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,GetMessageExtraInfo ()); }<
要用到以下几个 API 函数:
EnumWindows The EnumWindows function enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE. BOOL EnumWindows( WNDENUMPROC lpEnumFunc, // callback function LPARAM lParam // application-defined value );EnumWindows 枚举窗口列表中的所有 top-level 窗口
PostMessage The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message. To post a message in the message queue associate with a thread, use the PostThreadMessage function. BOOL PostMessage( HWND hWnd, // handle to destination window UINT Msg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter );PostMessage 将一条消息投递到指定窗口的消息队列
GetWindowText The GetWindowText function copies the text of the specified window's title bar (if it has one) into a buffer. If the specified window is a control, the text of the control is copied. However, GetWindowText cannot retrieve the text of a control in another application. int GetWindowText( HWND hWnd, // handle to window or control LPTSTR lpString, // text buffer int nMaxCount // maximum number of characters to copy );GetWindowText 取得一个窗体的标题(caption)文字
实现原理:
通过使用EnumWindows枚举窗口列表中的所有父窗口,在其回调函数中记录所有窗口的标题和句柄。判断若是要关闭的应用程序句柄,则使用PostMessage向其发送WM_CLOSE命令。具体代码如下(假设我我们要关闭的程序是画笔程序):
typedef struct { HWND hWnd; char cWinBuf[256]; }WINLIST; WINLIST gWinList[256]; int giCountWin,j;BOOL CALLBACK EnumWindowsProc( HWND hWnd, LPARAM lParam ) { char buffer[256]; GetWindowText(hWnd, buffer, 256); if ( strlen(buffer) ) { if (giCountWin < 256) { gWinList[ giCountWin].hWnd = hWnd; strcpy(gWinList[ giCountWin].cWinBuf,buffer); giCountWin ++; } } return TRUE; } void CloseProgram() { giCountWin = 0; EnumWindows( (WNDENUMPROC)EnumWindowsProc,0); for ( j = 0; j
好了,今天就说到这。这一节涉及到的 API 函数比较多。下节向大家讲述如何实现mouse的自动移动/点击。