很多時候,編寫程式模擬滑鼠和鍵盤操作可以方便的實現你需要的功能,而不需要對方程式為你開放介面。比如,操作飛信定時傳送簡訊等。我之前開發過飛信耗子,用的是對飛信協議進行抓包,然後分析協議,進而模擬協議的執行,開發出了客戶端,與移動伺服器進行通訊,但是這有一些缺點。如果移動的伺服器對介面進行變更,我所編寫的客戶端也要進行相應的公升級。如果伺服器的協議進行了更改,甚至個人編寫的這種第三方客戶端需要重寫。而我個人也沒有這個時間和精力,或者說沒有足夠的利益支撐我繼續去重構飛信耗子。因此,這款還算優秀的軟體,現在就束之高閣了,我自己也覺得遺憾。上週,某專案驗收,需要修改介面,但是零時找不到原始碼了。我在兩三個小時內要解決這個問題,時間緊迫。我突然想起室友以前做過模擬滑鼠鍵盤去傳送飛信訊息的小程式。於是我趕緊**諮詢了一下。然後掌握了這個技巧,按時解決了問題。我覺得這個技巧還是很有用的,現總結如下:
首先,引入如下三個api介面:
[dllimport(
"user32.dll"
)]
public
static
extern
intptr findwindow(
string
lpclassname,
string
lpwindowname);
[dllimport(
"user32.dll"
, entrypoint =
"sendmessage"
)]
private
static
extern
int
sendmessage(intptr hwnd,
int
msg, intptr wparam,
string
lparam);
[dllimport(
"user32.dll "
)]
public
static
extern
intptr findwindowex(intptr parent, intptr childe,
string
strclass,
string
frmtext);
第乙個與第三個是用於查詢視窗控制代碼的,凡執行於windows上的視窗,都具有控制代碼。視窗上的文字框,按鈕之類的,也有其控制代碼(可看作子視窗控制代碼)。這些控制代碼的型別可以通過
spy++進行查詢。比如c語言編寫的程式中,文字框的控制代碼型別一般為「edit」,c#寫的程式則不是,可以具體去查。第二個介面則是用於向視窗傳送各種訊息,比如向文字框傳送
字串,或者向按鈕傳送按下與彈起的訊息等。詳細解釋如下:
intptr hwnd = findwindow(
null
,
"無標題 - 記事本"
);
這是用於查詢作業系統中開啟的視窗中標題名為無標題 - 記事本的視窗。第乙個引數是此視窗的型別。這兩個引數知道一
個即可,另乙個可以填null。但是如果是用視窗型別查詢,則可能只能得到其中的乙個視窗。因此通過標題進行查詢是非常方便的。
intptr htextbox = findwindowex(hwnd, intptr.zero,
"edit"
,
null
);
這個函式用於獲得視窗中子視窗的控制代碼,子視窗指的其實就是視窗中的各種控制項。第乙個引數是父視窗的控制代碼,第二個引數指示獲得的是同一型別中的第幾個子視窗。填
intptr.zero則表示獲得第乙個子視窗。第三個引數表示你需要找的子視窗的型別,第四個引數一般為null。如果乙個視窗中有兩個文字框,那麼可以用如下操作獲得第二個文字框
的控制代碼。
intptr htextbox = findwindowex(hwnd, intptr.zero,
"edit"
,
null
);
intptr htextbox2 = findwindowex(hwnd, htextbox,
"edit"
,
null
);
//填上次獲得的控制代碼,可以得到下乙個的控制代碼。
這裡只是先將第二個引數填為intptr.zero,獲取第乙個edit型別的文字框,然後第二次呼叫時,再將第二引數填為第乙個文字框的控制代碼,那麼執行返回的就是下乙個文字框的控制代碼
了。因此htextbox2得到的就是第二文字框的控制代碼。
在可以自由獲得各種視窗及其上控制項的控制代碼後,我們就可以向其傳送各種訊息進行滑鼠和鍵盤的模擬了。比如:
sendmessage(htextbox, wm_settext, intptr.zero, name);
這句是為文字框填寫相應的字串name。
intptr hbutton = findwindowex(hwnd, intptr.zero,
"button"
,
null
);
sendmessage(hbutton, wm_lbuttondown, intptr.zero,
null
);
sendmessage(hbutton, wm_lbuttonup, intptr.zero,
null
);
這三句是獲得了視窗的乙個button,然後傳送按下,彈起訊息給它,模擬了點選滑鼠的動作。
sendmessage函式的第乙個引數是視窗控制代碼,或者視窗中控制項的控制代碼,第二個引數是訊息的型別flag,這些值是在api的一些標頭檔案中定義好的。你要是在c#中用,就自己去定義他們,比如
constint wm_settext =0x000c;constint wm_lbuttondown =0x0201;
constint wm_lbuttonup =0x0202;
constint wm_close =0x0010;
當然如果是滑鼠的動作,那麼最後乙個引數就是null。
sendmessage(htextbox, wm_settext, intptr.zero, name);
//填寫文字框。
sendmessage(hbutton, wm_lbuttondown, intptr.zero,
null
);
//滑鼠按下按鈕。
滑鼠獲取窗體控制代碼
通過滑鼠座標獲取窗體控制代碼 cpoint lppoint getcursorpos lppoint 得到當前座標 hwnd hwnd 定義窗體控制代碼 hwnd windowfrompoint lppoint char formtitle max path char classname max p...
Delphi 通過程式窗體控制代碼獲取程式路徑
引用psapi varh hwnd pid cardinal phandle thandle buf array 0.max path of char begin h getforegroundwindow 獲取當前啟用的窗體控制代碼 getwindowthreadprocessid h,pid 通...
獲取視窗控制代碼(內部窗體)
要找到某個cwnd物件的hwnd,用getsafehwnd 在視窗類中,可以直接訪問 m hwnd 在視窗類外,可以用afxgetmainwnd m hwnd獲得。想得到乙個控制項的的控制代碼 getdlgitem id xx m hwnd 得到檢視的控制代碼 afxgetmainwnd getac...