首页 随笔 乐走天涯 程序资料 评论中心 Tag 论坛 其他资源 搜索 联系我 关于 RSS

第2节 自动启动/关闭程序


日期: 2000-07-03 14:00 | 联系我 | 关注我: Telegram, Twitter

  前言: 很多初学 windows 编程的朋友, 大多搞不清 WINAPI 函数的工作方式。 如果您要成为一名熟练的Windows 程序员,想通过程序员这个职业赚钱, Make more money, 那么就不得不熟悉 WINAPI。 自动模拟/测试程序的实现,对于 Windows 编程新手了解 windows 窗口机制很有帮助。

  自动启动/关闭程序有很多种方法。这里分别讲述其中两种。

  

1. 启动程序

  方法一:使用 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
);
  

2. 关闭程序

  方法一: 模拟鼠标点击[关闭]按钮

  要用到以下两个 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状态。参数说明如下:

  • 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函数可取得这个值。可用的值取决于特定的驱动程序

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:

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 ()); }<

  方法2:找到程序的窗口句柄(Windows Handle),给其发送WM_CLOSE事件。

  要用到以下几个 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的自动移动/点击。

标签: WINAPI | VC 源码

 文章评论

第 1 楼  发表于 2009-03-22 00:21 | HUANGSN 的所有评论
好,虽然现在才看见,但是觉得很难得。我一直在关注自动化测试方面的内容,终于找到了。学习学习,本人现在还是一个DELPHI开发的蔡鸟

共有评论 1 条, 显示 1 条。

发表你的评论
如果你想针对此文发表评论, 请填写下列表单:
姓名: * 必填 (Twitter 用户可输入以 @ 开头的用户名, Steemit 用户可输入 @@ 开头的用户名)
E-mail: 可选 (不会被公开。如果我回复了你的评论,你将会收到邮件通知)
反垃圾广告: 为了防止广告机器人自动发贴, 请计算下列表达式的值:
8 x 2 + 1 = * 必填
评论内容:
* 必填
你可以使用下列标签修饰文字:
[b] 文字 [/b]: 加粗文字
[quote] 文字 [/quote]: 引用文字

 

程序员小辉 建站于 1997 ◇ 做一名最好的开发者是我不变的理想。
Copyright © XiaoHui.com; 保留所有权利。