.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名稱, 指定控制元件的類別,此部分不給也可以, 但是要防止碰到名稱一樣的控制元件,第二個是控制元件名稱, 以這個例子就是"列印", 程式碼如下
?
1
2
3
4
5
HWND wnd = FindWindow( NULL, "列印");
if(wnd)
{
//處理
}
II.對視窗做控制
在視窗的控制方面, 有兩種方式, 以下個別做說明
如果可以確定元件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的訊息有三種方式
Menu
Accelerator
Control
其中Accelerator不討論,這邊看menu以及Control的方式
.WM_COMMAND - Menu
實際測試了一下, 按鈕的話照menu方式直接送ID也有BN_CLICKED的效果,非按鈕的我就不確定了, 程式碼如下.
?
1
SendMessage(wnd, WM_COMMAND, IDOK, NULL);
參考程式碼頁面,照定義送的是menu元件的話, 則wParam的高位元會是0, 低位元是id, 其實等同IDOK(送高位元放0, 低位元IDOK), 如果怕判斷會出問題的話, 可以用MAKEWPARAM即可
?
1
2
3
4
5
6
7
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-defined notification code
低位元放Control identifier
lParam
Handle to the control window
此例已知控制視窗的wnd, 所以處理wParam即可
?
1
SendMessage(wnd, WM_COMMAND, MAKEWPARAM(IDOK,BN_CLICKED),0);
2.抓最底層目標元件
目前已取得目標視窗的HWND, 要在更進一步找視窗裡面的元件時, 需要使用FindWindowEX來處理, 使用方式一樣是由名稱找, 這邊範例指定class名稱, 名稱定義詳細可以看msdn, 這邊就不詳述了, 程式碼如下
?
1
2
3
HWND wndButton = FindWindowEx(wnd, NULL,"Button", "取消");;
SendMessage(wndButton, BM_CLICK, 0, 0);
III.實作程式碼
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);
}
}
}
http://arkkk.blogspot.tw/2011/11/findwindow-sendmessage.html