Jing 
 

   
作者:
標題: [自創] 如何模擬使用者按指定視窗的按鈕 取消高亮 | 上一主題 | 下一主題
Jing
目擊者



積分 83
發貼 239
性別  保密
註冊 2003-11-14
來自 風城
狀態 在線
[自創] 如何模擬使用者按指定視窗的按鈕

老實說, 是看了 ungear 兄發表的 "按鍵精靈3.52 VIP ",
http://www.eastshare.net/viewthread.php?tid=21600

摘錄如下
-------------------------------------------------------------------
<略>

錄製功能:不用掌握任何編程知識即可錄製腳本。忠實記錄您的動作,
               新手也可錄製優秀腳本
調試腳本:一步一步執行腳本,可以隨時暫停/繼續腳本,方便查找腳本錯誤
製作腳本:支持多種腳本功能語句,包括鍵盤按鍵動作、鼠標點擊動作、
               鼠標移動動作、控制動作、輸入字符串動作、延遲動作等
<略>
-------------------------------------------------------------------
突然心血來潮, 想寫一下程式.
順便讓頭腦休息一下. ^_^

基本上, 我只是寫了利用一個程式代替我去按指定程式的按鈕的範例,
要完成"按鍵精靈"的功能, 還有一大段距離.

如果我有寫錯的地方,還請先進提出批評與指教.

ok! 我們就開始吧.

如果你要操控某一個視窗, 你必須要有那個視窗的 Handle.

現在就以"小算盤"為例好了.
如果要找到小算盤, 你可以使用 FindWindow 這個 Win32 API, 得到小算盤的 Window Handle

        HWND targetWindow=::FindWindow(NULL, "小算盤");
        if(targetWindow == NULL){
                ::MessageBox(NULL,"請開啟小算盤","Info",MB_OK);
                return;
        }


然後,你就可以使用 SetWindowPos API 搭配 Handle 改變小算盤的位置
        ::SetWindowPos(targetWindow,0,x,y,-1,-1,SWP_NOZORDER|SWP_NOSIZE);

你也可以任意改變小算盤的標題
        ::SendMessage(targetWindow, WM_SETTEXT,  0, (LPARAM) "這是我個人使用的小算盤");

但是,要如何自動地移動滑鼠並且按到小算盤上的數字鍵,

你可能會想..... 送出 WM_MBUTTONDOWN 之類的訊息, 給小算盤...
像這樣

        ::SendMessage(targetWindow, WM_MBUTTONDOWN,0, MAKELPARAM(x,y));


很快的, 你會發現這程式不能執行 !!!
不是會當掉, 而是小算盤完全沒反應...

主要的原因是 WM_MBUTTONDOWN  是屬於 Notification(通知) 類型的訊息,
意思是: 事情已經發生了, 現在來通知你
而不是: 要你做什麼事情!!

所以要指定工作給小算盤, 要用特定的 Function.

移動滑鼠: 使用 SetCursorPos(x,y);
注意: 這裡的 x,y 是對應你螢幕的左上角, 而不是小算盤視窗.
所以一般為了省麻煩, 我們都會使用 ClientToScreen 幫我們做轉換.

下面的例子就是: 將游標到小算盤上空移動

---------------------------------------------
        POINT pt;  // 滑鼠座標點 (要模擬的滑鼠座標點)
        RECT rc;   
        ::GetClientRect(targetWindow, &rc); // 取得 小算盤 的 client window 寬高資訊
        // 移動滑鼠瀏覽小算盤
        for(int y=rc.top;y                 for(int x=rc.left;x                         pt.y=y;
                        pt.x=x;

                        // 將小算盤 client window 座標換算成 Root 視窗的位置(絕對位置)
                        ::ClientToScreen(targetWindow, &pt);

                        SetCursorPos(pt.x, pt.y); // 移動滑鼠到指定的絕對位置
                }
        }
        MessageBox(_T("滑鼠是否在小算盤的左下角"),_T("移動滑鼠資訊"),MB_OK);
---------------------------------------------


你可以試試看, 很有趣喔!

現在要在 5 號按鈕上,模擬使用者按鍵 !!

模擬使用者按鍵: 要使用 SendInput function
你可以利用 SendInput 幫你在指定的絕對座標,送 keyboard input 或 mouse input
甚至是其他硬體的 input.

而系統會幫你送到該座標上的視窗

現在, 我們 focus 在 mouse input. 所以就介紹如何模擬 mouse click.
SendInput 需要的資料為 滑鼠的位置 與 滑鼠的按鍵狀態(左鍵還是右鍵被按下)
所以我們有必要設定 MOUSEINPUT 資料

MOUSEINPUT mDown;
            mDown.mouseData=0;// 不處理 mouse wheel event, 所以這項沒用
            mDown.time=0;
            mDown.dwExtraInfo=0;

            // 指定滑鼠的位置
            mDown.dy=pt.y;
            mDown.dx=pt.x;
            mDown.dwFlags=MOUSEEVENTF_LEFTDOWN; // 設定左按鍵向下


然後...

               將滑鼠的資料複製到 INPUT 型態變數中.

             // 建構 inputMouseDown  事件
            INPUT inputMouseDown;
            inputMouseDown.type=INPUT_MOUSE; // 指定 input 為 mouse (input 可以是 keyboard)
            inputMouseDown.mi=mDown;// 指定 滑鼠屬性結構


最後...

             利用 SendInput 把資料送出去.

            INPUT event[1]={inputMouseDown};
            UINT num=SendInput(1,event,sizeof(INPUT));
            if(num==0){
                ShowError();
            }


但是,我們按滑鼠,滑鼠的按鈕都是 DOWN(按下)與 Up(彈起) 的組合. 所以通常我們要建造兩個滑鼠資訊給指定的位置.

            mDown.dwFlags=MOUSEEVENTF_LEFTDOWN; // 設定左按鍵向下
            mUP.dwFlags=MOUSEEVENTF_LEFTUP; // 設定左按鍵向上


聰明的你,應該知道如何設定吧!

所以整個完整的程式碼如下:

因為後面有點多,所以結論寫在這:

還是一句話: 如果我有寫錯的地方,還請先進提出批評與指教.

有興趣的人可以玩玩看!!



==========================================
void CSendMessageDemoDlg::OnBnClickedOk()
{
        HWND targetWindow=::FindWindow(NULL, "小算盤");
        if(targetWindow == NULL){
                ::MessageBox(NULL,"請開啟小算盤","Info",MB_OK);
                return;
        }
       
       
        WINDOWINFO wi;
        wi.cbSize=sizeof(WINDOWINFO);
        BOOL bOk=::GetWindowInfo(targetWindow,&wi);
        RECT  OldRec=wi.rcWindow;


       

        POINT pt;  // 滑鼠座標點 (要模擬的滑鼠座標點)
       
        RECT rc;   
        ::GetClientRect(targetWindow, &rc); // 取得  target window 的 client window 寬高資訊



       
        // 移動滑鼠瀏覽小算盤
        for(int y=rc.top;y                 for(int x=rc.left;x                         pt.y=y;
                        pt.x=x;
                        ::ClientToScreen(targetWindow, &pt); // 將小算盤 client window 座標換算成 Root 視窗的位置(絕對位置)
                        SetCursorPos(pt.x, pt.y); // 移動滑鼠到指定的絕對位置
                }
        }

        // 定義 mouse 按下的 event
            MOUSEINPUT mDown;
            mDown.mouseData=0;// 不處理 mouse wheel event, 所以這項沒用
            mDown.time=0;
            mDown.dwExtraInfo=0;


        MessageBox(_T("滑鼠是否在小算盤的左下角"),_T("移動滑鼠資訊"),MB_OK);

        // 連續按四次 5
                for(int i=0;i<4;i++){
                        pt.y=106; // 5 號按鈕位於相對小算盤 client window 位置為 y,x => (106,109)
                        pt.x=109;
                        ::ClientToScreen(targetWindow, &pt);


                        SetCursorPos(pt.x, pt.y);  // 移到 5 按鈕上空

                        // 模擬使用者 Clicked 滑鼠左鍵
                        // 設定 mouse 屬性
                        mDown.dy=pt.y;
                        mDown.dx=pt.x;
                        mDown.dwFlags=MOUSEEVENTF_LEFTDOWN; // 設定左按鍵向下

                        // 建構 inputMouseDown  事件
                        INPUT inputMouseDown;
                        inputMouseDown.type=INPUT_MOUSE; // 指定 input 為 mouse
                        inputMouseDown.mi=mDown;// 指定 滑鼠屬性結構

                        // 建構 inputMouseDown  事件
                        INPUT inputMouseUP;
                        inputMouseUP.type=INPUT_MOUSE; // 指定 input 為 mouse
                        inputMouseUP.mi=mDown;// 指定 滑鼠屬性結構
                        inputMouseUP.mi.dwFlags=MOUSEEVENTF_LEFTUP; // 設定左按鍵向上
            // 滑鼠左鍵 Clicked INPUT 事件設定完成

                        // 將 INPUT 事件送到 Root 視窗, 系統會根據視窗的位置, 送給目標視窗
                        INPUT event[2]={inputMouseDown,inputMouseUP};
                        UINT num=SendInput(2,event,sizeof(INPUT));
                        if(num==0){
                                ShowError();
                        }

                }

                MessageBox(_T("按下 5 共 4 次"),_T("模擬使用者按下按鈕"),MB_OK);
       
}


版權聲明:
基於知識無價的原則, 你可以任意修改,重製,散佈這份文章.
但須註明來自 Eastshare

by jing

[ Last edited by jing on 2004-9-22 at 00:21 ]



聖人不積,既以為人己愈有,既以與人己愈多。          道德經(節錄)
2004-9-22 12:09 AM #1
查看資料  搜索該用戶的全部文章  發短消息   編輯文章  向版主反應這個文章
Ramius
旁觀者




積分 30
發貼 208
性別  男
註冊 2003-9-7
狀態 離線
以前有個日本人寫了一個叫AutoMouse的程式,你可以請google大神幫你找找看…
2004-9-23 01:10 AM #2
查看資料  搜索該用戶的全部文章  發短消息   編輯文章  向版主反應這個文章
Jing
目擊者



積分 83
發貼 239
性別  保密
註冊 2003-11-14
來自 風城
狀態 在線
[quote="Ramius"]以前有個日本人寫了一個叫AutoMouse的程式,你可以請google大神幫你找找看… [/quote]


是的, 剛剛上去看了 Kakuya Yamamoto 的網站.
http://ryujin.kuis.kyoto-u.ac.jp/ylab/yamakaku/AutoMouse/

AutoMouse 軟體:

You can make a program by combining Mouse-operating-commands, such as `Click this picture', `Double-click this picture', etc. When you execute the program, the mouse moves automatically. Key inputs are also available.




他有提供 Source Code.
有興趣的朋友可以下載回來參考參考.


謝謝 Ramius 兄提供這個資訊.



by jing



聖人不積,既以為人己愈有,既以與人己愈多。          道德經(節錄)
2004-9-23 03:16 PM #3
查看資料  搜索該用戶的全部文章  發短消息   編輯文章  向版主反應這個文章

   

可打印版本 | 推薦給朋友 | 訂閱主題 | 收藏主題


論壇跳轉:


 

Processed in 0.137926 second(s), 7 queries, Gzip enabled
EastShare Forum  |