通過api獲取句柄控制其他窗體(轉)


很多時候,編寫程序模擬鼠標和鍵盤操作可以方便的實現你需要的功能,而不需要對方程序為你開放接口。比如,操作飛信定時發送短信等。我之前開發過飛信耗子,用的是對飛信協議進行抓包,然后分析協議,進而模擬協議的執行,開發出了客戶端,與移動服務器進行通信,但是這有一些缺點。如果移動的服務器對接口進行變更,我所編寫的客戶端也要進行相應的升級。如果服務器的協議進行了更改,甚至個人編寫的這種第三方客戶端需要重寫。而我個人也沒有這個時間和精力,或者說沒有足夠的利益支撐我繼續去重構飛信耗子。因此,這款還算優秀的軟件,現在就束之高閣了,我自己也覺得遺憾。上周,某項目驗收,需要修改界面,但是零時找不到源碼了。我在兩三個小時內要解決這個問題,時間緊迫。我突然想起室友以前做過模擬鼠標鍵盤去發送飛信消息的小程序。於是我趕緊電話咨詢了一下。然后掌握了這個技巧,按時解決了問題。我覺得這個技巧還是很有用的,現總結如下:
首先,引入如下三個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;

 


還有其他的類型Flag,可以參考上一篇Blog查詢,也可以去查MSDN。第三個參數和第四個參數都是消息的具體內容。一般我們用的是最后一個參數。第三個參數填為IntPtr.Zero。

當然如果是鼠標的動作,那么最后一個參數就是null。

?
SendMessage(htextbox, WM_SETTEXT, IntPtr.Zero, name); //填寫文本框。
SendMessage(hbutton, WM_LBUTTONDOWN, IntPtr.Zero, null ); //鼠標按下按鈕。

 


OK,介紹完畢,收工。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM