1、
在自動化測試中經常要模拟視窗按鈕的點選。
參考文章:http://blog.csdn.net/blackboyofsnp/article/details/3372719
有時我們需要這麼做, 手動模拟按鈕按下的事件, 讓程式做出與按鈕真的按下時一樣的響應.
設按鈕ID為ID_BTN_OK, 目前Dialog視窗. 實際上系統并不能區分按鈕是真的按下了(如用滑鼠點選), 還是一個我們自己用代碼模拟出的一種"假象". 它所需要知道的隻是哪個視窗(按鈕也是一種視窗)發生了哪一種事件, 然後在消息循環中處理它. 系統怎麼才 能知道這些呢? 當然靠的是消息(message), 我們 隻需按照Windows或者MFC的标準格式把相應的資訊傳給系統, 系統就會"上當"了. 向系統傳遞消息可以用SendMessage或PostMessage(可能還有其他很多函數哦), 但SendMessage執行後系統 會一直等待, 直到要發送的消息被處理掉. 而PostMessage可不管那麼多, 發送消息後立即傳回程式流程. 當 按鈕按下的響應函數中有很大一個循環時, 用SendMessage會出現許多問題, 尤其是要在程式初始化階段模拟時, 會導緻窗體無法完成初始化. 是以我們用PostMessage(). 它的原型為:
BOOL PostMessage( HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
這樣寫;
PostMessage(WM_COMMAND, MAKEWPARAM(ID_BTN_OK, BN_CLICKED), NULL);
這裡, WM_COMMAND是要發送的消息, MAKEWPARAM宏是為了組成一個WPARAM,WM_COMMAND消息的WPARAM的低字為控件ID,高字為識别碼, 最後一個參數LPARAM可為NULL.相關定義可檢視MSDN.
這樣我們就把必需的資訊格式化好發送給系統了. 當系統在消息循環中收到該消息時, 就知道哦, 你要引發控件ID_BTN_OK 的事件BN_CLICKED, 好的我幫你處理. 于是我們就驚喜地看到按鈕看起來真的按下去了, 并執行了和真正按下去時一樣的代碼.
看評論說不管用,我又試驗了一下。建立一個對話框工程,在對話框上添加一個按鈕,ID為IDC_BTN_TEST,單擊它,為它添加ON_BN_CLICKED消息響應函數:
void CtestDlg::OnBnClickedBtnTest()
{
AfxMessageBox(_T("OK"));
}
然後在對話框的OnInitDialog()函數的return TRUE前加上:
PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BTN_TEST, BN_CLICKED), NULL);
好了,再運作程式,會彈出個消息框 “OK”,說明模拟正确。
2、 C#調用迅雷的時候 自動模拟點選”下載下傳按鈕” 關閉彈出視窗
網上 關于 “不彈出《建立任務》的對話框的方法 在迅雷5.9貌似不适用了” 那麼我改了一下網上的“監聽方式”來進行模拟點選
#region Dll Import 需要導入的api 聲明。
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent,
IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd,
int Msg, IntPtr wParam, string lParam);
const int WM_GETTEXT = 0x000D;
const int WM_SETTEXT = 0x000C;
const int WM_CLICK = 0x00F5;
#endregion
//關消息的方法
private void ClosePopWindow(object obj)
{
//這些用spy++可以看到
string lpszParentClass = "#32770"; //整個視窗的類名
string lpszParentWindow = "建立新的下載下傳任務"; //視窗标題
string lpszClass_Submit = "Button"; //需要查找的Button的類名
string lpszName_Submit = "立即下載下傳"; //需要查找的Button的标題
IntPtr ParenthWnd = new IntPtr(0);
IntPtr EdithWnd = new IntPtr(0);
int i = 0;
while (true)
{
//查到窗體,得到整個窗體
ParenthWnd = FindWindow(lpszParentClass, lpszParentWindow);
//判斷這個窗體是否有效
if (!ParenthWnd.Equals(IntPtr.Zero))
{
//得到第一級子視窗
EdithWnd = FindWindowEx(ParenthWnd,
new IntPtr(0), "#32770", "");
//Console.WriteLine("第一級-"+EdithWnd.ToString());
//得到Button這個子窗體,并觸發它的Click事件
EdithWnd = FindWindowEx(EdithWnd,
new IntPtr(0), lpszClass_Submit, lpszName_Submit);
//Console.WriteLine("第二級-" + EdithWnd.ToString());
if (!EdithWnd.Equals(IntPtr.Zero))
{
SendMessage(EdithWnd, WM_CLICK, (IntPtr)0, "0");
}
return;
}
Thread.Sleep(1000);
i++;
// Console.WriteLine("第"+i.ToString()+"次檢查"); 5秒都沒顯示出來就推出循環
if (i > 15)
{
//break;
}
}
}
//需要導入如下類庫
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32;
//在迅雷送出前添加一個方法
ThreadPool.QueueUserWorkItem(new WaitCallback(ClosePopWindow));
3、
#include <iostream>
#include <fstream>
#include <math.h>
#include <cctype>
#include <string>
#include <windows.h>
using namespace std;
int main()
{
//cout << "Hello world!" << endl;
HWND hwnd = FindWindow( 0, "檔案視窗" );
//HWND hWnd2 = GetDlgItem( hwnd, 1001);
char* strs = new char[ 255 ];
HWND hWnd2 = ::FindWindowEx(hwnd,NULL,"Button",NULL);
while ( hWnd2 )
{
GetWindowText( hWnd2, strs, 255 );
cout << strs << endl;
/* if ( strcasecmp( strs, "确定" ) == 0 ) {
break;
}*/
hWnd2 = FindWindowEx( hwnd, hWnd2, "Button", NULL );
}
UINT nCtrlID = ::GetDlgCtrlID(hWnd2);
::PostMessage(hWnd2, WM_COMMAND, (WPARAM)(BN_CLICKED << 16 | nCtrlID), (LPARAM)hWnd2);
::PostMessage(hWnd2,WM_MOUSEMOVE, MK_LBUTTON, MAKELONG(0,0) );
::PostMessage(hWnd2,WM_LBUTTONDOWN,MK_LBUTTON,MAKELPARAM(0,0));
::PostMessage(hWnd2,WM_LBUTTONUP,MK_LBUTTON,MAKELPARAM(0,0));
return 0;
}
4、往編輯框中寫入檔案(可實作)
SetWindowText