.Introduction
在開發程式中, 當碰到底層功能沒開放出來的時候, 往往最後只能在外部控制介面來處理,舉個例子, 像是碰到比較特殊的硬體裝置, 而廠商沒提供driver的原始碼, sdk的功能不完整等等問題之類的, 在只有官方的控制用應用程式的情況下, 此時也就只能寫外部程式直接來控制,以下論述實作方式.
首先, 如下圖, 拿一個列印介面來當例子, 主要步驟有兩個部分, 首先要先取得視窗控制元件,在來世更進一步的做控制.
列印程式介面
I. Get Window HWND
要取得一個windows的控制權, 首先要取得該視窗的HWND, 實作上可以使用FindWindow函式, 詳細可以看msdn.
FindWindow:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633499%28v=vs.85%29.aspx
由函式的定義來看, 可以指定的參數有兩個, 一個是class名稱, 指定控制元件的類別,此部分不給也可以, 但是要防止碰到名稱一樣的控制元件,第二個是控制元件名稱, 以這個例子就是"列印", 程式碼如下
II.對視窗做控制
由函式的定義來看, 可以指定的參數有兩個, 一個是class名稱, 指定控制元件的類別,此部分不給也可以, 但是要防止碰到名稱一樣的控制元件,第二個是控制元件名稱, 以這個例子就是"列印", 程式碼如下
HWND wnd = FindWindow( NULL, "列印"); if(wnd) { //處理 }
II.對視窗做控制
在視窗的控制方面, 有兩種方式, 以下個別做說明
1.WM_COMMAND
- 如果可以確定元件id的話, 可以Send WM_COMMAND做處理
- 抓到最底層目標的原件, 直接送訊息
1.WM_COMMAND
在這邊特別說明一下 WM_COMMAND, 當我們在做視窗操作時, 像是按下按鈕, 下拉選單等等, 都會觸發WM_COMMAND, 如果知道操作對象的話,某種程度直接使用WM_COMMAND就可以處理了, 詳細可以看msdn
WM_COMMAND:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms647591%28v=vs.85%29.aspx
WM_COMMAND的訊息有三種方式
其中Accelerator不討論,這邊看menu以及Control的方式
.WM_COMMAND - Menu
實際測試了一下, 按鈕的話照menu方式直接送ID也有BN_CLICKED的效果,非按鈕的我就不確定了, 程式碼如下.
參考程式碼頁面,照定義送的是menu元件的話, 則wParam的高位元會是0, 低位元是id, 其實等同IDOK(送高位元放0, 低位元IDOK), 如果怕判斷會出問題的話, 可以用MAKEWPARAM即可
.WM_COMMAND - Control
Control的方式較複雜, 以下是msdn的定義
低位元放Control identifier
此例已知控制視窗的wnd, 所以處理wParam即可
2.抓最底層目標元件
目前已取得目標視窗的HWND, 要在更進一步找視窗裡面的元件時, 需要使用FindWindowEX來處理, 使用方式一樣是由名稱找, 這邊範例指定class名稱, 名稱定義詳細可以看msdn, 這邊就不詳述了, 程式碼如下
III.實作程式碼
WM_COMMAND:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms647591%28v=vs.85%29.aspx
WM_COMMAND的訊息有三種方式
- Menu
- Accelerator
- Control
其中Accelerator不討論,這邊看menu以及Control的方式
.WM_COMMAND - Menu
實際測試了一下, 按鈕的話照menu方式直接送ID也有BN_CLICKED的效果,非按鈕的我就不確定了, 程式碼如下.
SendMessage(wnd, WM_COMMAND, IDOK, NULL);
參考程式碼頁面,照定義送的是menu元件的話, 則wParam的高位元會是0, 低位元是id, 其實等同IDOK(送高位元放0, 低位元IDOK), 如果怕判斷會出問題的話, 可以用MAKEWPARAM即可
WPARAM MAKEWPARAM( WORD wLow, WORD wHigh ); WPARAM wParam = MAKEWPARAM( IDC_OK, 0); SendMessage(wnd, WM_COMMAND, MAKEWPARAM(IDOK,0),0);
.WM_COMMAND - Control
Control的方式較複雜, 以下是msdn的定義
- wParam
低位元放Control identifier
- lParam
此例已知控制視窗的wnd, 所以處理wParam即可
SendMessage(wnd, WM_COMMAND, MAKEWPARAM(IDOK,BN_CLICKED),0);
2.抓最底層目標元件
目前已取得目標視窗的HWND, 要在更進一步找視窗裡面的元件時, 需要使用FindWindowEX來處理, 使用方式一樣是由名稱找, 這邊範例指定class名稱, 名稱定義詳細可以看msdn, 這邊就不詳述了, 程式碼如下
HWND wndButton = FindWindowEx(wnd, NULL,"Button", "取消");; SendMessage(wndButton, BM_CLICK, 0, 0);
III.實作程式碼
void main() { HWND wnd = FindWindow( NULL, "列印"); if(wnd) { //方式1..知道元件ID的話可以用, //物件是按鈕的話,直接送ID也可以達到Click的效果 //另外, 如果真的不確定id, //IDOK(1)通常會是windows預設介面的"確定",IDCANCEL同 //menu方式 SendMessage(wnd, WM_COMMAND, IDOK, NULL); SendMessage(wnd, WM_COMMAND, MAKEWPARAM(IDOK,0),0); //Control方式 SendMessage(wnd, WM_COMMAND, MAKEWPARAM(IDOK,BN_CLICKED),0); //方式2, 進一步取得按鈕, 送出按下訊息 HWND wndButton = FindWindowEx(wnd, NULL,"Button", "取消");//"列印(&P)"); if(wndButton) { SendMessage(wndButton, BM_CLICK, 0, 0); } } }
沒有留言:
張貼留言