如何模拟点击一个非当前窗口的外部程序的按钮,打开一个对话框,在对话框中输入字符串,并模拟点击对话框的“打开”按钮?
yjyb 2007-08-31 01:34:52 实际工作中需要编写一个程序,自动点击一个非当前窗口的外部程序mtsatDealProgram的“打开文件”按钮,以打开一个对话框,在这个对话框的“文件名”文本框中自动输入文件名字符串,再点击对话框中的“打开”按钮。
一开始用api函数mouse_event、keybd_event和SendKeys类实现,但是这种方法要求外部程序mtsatDealProgram处于当前窗口状态,在实际应用时受到很多限制。
后来尝试用api函数SendMessage和PostMessage来实现这个功能,代码如下;public void Run(string _mtsatDealProgramPath,string _fileName)
{
//启动鼠标和键盘锁定
//this.EnableKeyBoardCapture();
//this.EnableMouseCapture();
//判断程序是否已经运行,如果没有则启动之
bool isRun = this.IsProgramAlreadyRunned();
if (!isRun)
{
this.RunProgram(_mtsatDealProgramPath);
//延迟两秒后继续执行
Thread.Sleep(2000);
}
//获得程序主窗体的句柄
int mtsatMainWindowHandle = GetProgramMainWindowHandle() ;
//使主窗体在所有窗体之前,为当前窗体
this.SetWindowToTopMost(mtsatMainWindowHandle);
//获取“打开文件”按钮控件的句柄
int buttonHandleOfOpenFile = this.GetButtonHandleOfOpenFile(mtsatMainWindowHandle);
//利用PostMessage函数将点击命令传递给“打开文件”按钮控件
//int lResult = SendMessage(buttonHandleOfOpenFile, BM_CLICK, 0, 0);
while (!PostMessage(buttonHandleOfOpenFile, BM_CLICK, 0, 0))
{
Thread.Sleep(100);
}
//延迟1.5秒后继续执行
Thread.Sleep(1500);
//获得“打开”对话框的句柄
int openFileDialogHandle = GetOpenFileDialogHandle(mtsatMainWindowHandle);
//获得输入文件名的文本框的句柄
int fileNameTextHandle = GetFileNameTextHandle(openFileDialogHandle);
//利用SendMessage函数把文件名传递给输入文件名的文本框
SendMessage(fileNameTextHandle, WM_SETTEXT, 0, _fileName);
//获得输入获得“打开”按钮的句柄
int openButtonHandle = GetOpenButtonHandle(openFileDialogHandle);
//利用SendMessage函数将点击命令传递给“打开”按钮
SendMessage(openButtonHandle, BM_CLICK, 0, 0);
//取消主窗体的顶层窗口状态
CancelWindowTopMost(mtsatMainWindowHandle);
//解除鼠标和键盘盘锁定
//this.DisableKeyBoardCapture();
//this.DisableMouseCapture();
}
但是同样有很多问题存在:
1、同样要求mtsatDealProgram处于当前窗口状态下,当mtsatDealProgram在非当前窗口状态下,有时候能正常运行,但更多时候在执行到
//利用PostMessage函数将点击命令传递给“打开文件”按钮控件
while (!PostMessage(buttonHandleOfOpenFile, BM_CLICK, 0, 0))
{
Thread.Sleep(100);
}
时就停住了,无法打开“打开”对话框,不知为何?
2、通过
//使主窗体在所有窗体之前,为当前窗体
this.SetWindowToTopMost(mtsatMainWindowHandle);
使程序运行时,mtsatDealProgram程序在当前窗口状态下,程序能正常运行。但是,只要过程中,人工移动鼠标,就会对程序造成影响,在执行到
//利用PostMessage函数将点击命令传递给“打开文件”按钮控件
while (!PostMessage(buttonHandleOfOpenFile, BM_CLICK, 0, 0))
{
Thread.Sleep(100);
}
时就停住了,无法打开“打开”对话框,这是什么原因那?
3、在将
while (!PostMessage(buttonHandleOfOpenFile, BM_CLICK, 0, 0))
{
Thread.Sleep(100);
}
处改用int lResult = SendMessage(buttonHandleOfOpenFile, BM_CLICK, 0, 0);
时,能够打开“打开”对话框,但程序无法执行下去,也即lResult无法获得返回值,只有手动将“打开”对话框关闭时,程序才能执行下去,但也就无法实现程序功能了。
4、//启动鼠标和键盘锁定
this.EnableKeyBoardCapture();
this.EnableMouseCapture();
执行这两句代码会造成1、2中问题,而且好像也没法锁死鼠标和键盘。EnableKeyBoardCapture()和EnableMouseCapture()这两个函数定义如下:
private bool EnableKeyBoardCapture()
{
KeyBoardHookProcedure = new HookProc(this.KeyBoardHookProc);
Process currentProcess = Process.GetCurrentProcess();
//安装全局键盘钩子
hhookKeyBoard = SetWindowsHookEx(WH_KEYBOARD, KeyBoardHookProcedure, currentProcess.MainModule.BaseAddress, 0);
if (hhookKeyBoard == 0)
return false;
return true;
}
private int KeyBoardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
//如果nCode<0,直接调用CallNextHookEx返回
if (nCode < 0)
//return CallNextHookEx(hhookKeyBoard, nCode, wParam, lParam);
return 1;
//函数将消息向下传递,下一个钩子处理将截获这一消息
//if (nCode != HC_ACTION)
//return CallNextHookEx(hhookKeyBoard, nCode, wParam, lParam);
return 1;
}
private bool EnableMouseCapture()
{
MouseHookProcedure = new HookProc(this.MouseHookProc);
Process currentProcess = Process.GetCurrentProcess();
//安装全局鼠标钩子
hhookMouse = SetWindowsHookEx(WH_MOUSE, MouseHookProcedure, currentProcess.MainModule.BaseAddress, 0);
if (hhookMouse == 0)
return false;
return true;
}
private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
//如果nCode<0,直接调用CallNextHookEx返回
if (nCode < 0)
//return CallNextHookEx(hhookMouse,nCode,wParam,lParam);
return 1;
//函数将消息向下传递,下一个钩子处理将截获这一消息
//if(nCode!= HC_ACTION)
// return CallNextHookEx(hhookMouse, nCode, wParam, lParam);
return 1;
}
5、要如何才能使外部程序mtsatDealProgram在处于非当前窗口状态时,实现自动打开的功能,不受其它事情(如有人在使用键盘、鼠标)的影响?
问题可能太多了,分不够另开贴给分,谢谢支持!