前言

看過 朋友的網誌,決定補充這二個東西。事實上 keybd_event 和 mouse_event 算是最簡單的外掛函式之一,

然而在 Win32 API 與 MFC 裡面仍使用 SendMessage, PostMessage 之方式進行,

當然這些方式都有好有壞。keybd_event 與 mouse_event 是不管視窗是誰,

反正只要指定point 進去就開始點了,操作上比較簡單;

然而 SendMessage, PostMessage 方式卻要先取得 control of window -> HWND,

但相對的,這種方式就比較穩,誤點機率相對顯得非常小。

mouse_event

SetCursorPos 是設定目前滑鼠位置。通常在用 mouse_event 的時候,會用用 SetCursorPos 到指定位置上面去再進行點擊的動作。如要點 100,100 這個點,便使用  SetCursorPos(100,100);

至於 mouse_event 函式原始如下

VOID mouse_event(      

    DWORD dwFlags
    DWORD dx,
    DWORD dy,
    DWORD dwData,
    ULONG_PTR dwExtraInfo
);

1. dwFlags

為滑鼠的事件,主要有下列之值:

MOUSEEVENTF_ABSOLUTE // 是否採用絕對座標
MOUSEEVENTF_MOVE // 移動
MOUSEEVENTF_LEFTDOWN // 左下
MOUSEEVENTF_LEFTUP // 左上
MOUSEEVENTF_RIGHTDOWN // 右下
MOUSEEVENTF_RIGHTUP // 右上
MOUSEEVENTF_MIDDLEDOWN // 中下
MOUSEEVENTF_MIDDLEUP // 中上
MOUSEEVENTF_WHEEL // 滾輪

2. dx, dy

這部份之設定主要是給 MOUSEEVENTF_MOVE 事件用的,主要設定要移多少點的 dx 與 dy,dx > 0 代表向右跑,dy > 0 代表向下跑,其它資訊用不到通常都設0

3. dwData

這部份的設定主要是給 MOUSEEVENTF_WHEEL 用的,主要設定每次滾動的時候會變動多少位移量,其它資訊用不到通常都設0。如果 dwData < 0 ,則相當於往下拉; dwData >0,則相當於往上拉。

4. dwExtraInfo

事件額外資訊,這部份通常都設0。

5. 常用組合

int x, y, dx, dy, dwData;

左鍵一下:
SetCursorPos(x, y); // 先設要點的位置
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

右鍵一下:
SetCursorPos(x, y); // 先設要點的位置
mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);

左鍵二下:
事實上就是二次的左鍵一下,所以每次只要點一下的時候,點完後記得要 Sleep(),不然可能會被誤判為快點二下。

移動相對位置:
mouse_event(MOUSEEVENTF_MOVE, dx, dy, 0, 0);
這裡注意,如果加上 MOUSEEVENTF_ABSOULT 的話,其 dx, dy 指的就不是相對位置,而是絕對位置。

滾動滾輪
mouse_event(MOUSEEVENTF_WHEEL, 0, 0, dwData, 0);

以上是 mouse_event

keybd_event

事實上這組函式可以說已經被 SendInput 取代,其它可以取代它的還有 KeybdEvent,但這裡不對它們做介紹。

接下來的 keybd_event 對於虛擬碼、掃描碼沒概念的話很難說下去,這篇文章也不打算說,請進修相關知識。

同時若不使用 SendMesage, 只用 keybd_event , 事實上並不好操作,因為還要點進該視窗/控制,取得 active 主控權。

先看 keybd_event 原型

VOID keybd_event(      
    BYTE bVk,
    BYTE bScan,
    DWORD dwFlags,
    PTR dwExtraInfo
);

1. bVk

這裡的 bVk 指的便是虛擬碼,windows.h 底下的虛擬碼之 macro 設 1~254,其中包含英文與數字,這裡只舉出幾項做代表

VK_BACK -> backspace, 08
VK_TAB -> Tab, 09
VK_RETURN -> Enter, 0D, 這個很常記錯
VK_CONTROL -> Ctrl, 11
VK_SHIFT -> Shift, 10
VK_MENU -> ALT, 12, 這也很常記錯
VK_F1 -> 70, 相關的一直到 VK_F24, 都是連號
VK_LEFT -> 25, 方向鍵 ←
VK_UP -> 26, 方向鍵 ↑
VK_RIGHT -> 27, 方向鍵 →
VK_DOWN -> 28, 方向鍵 ↓
VK_SNAPSHOT -> 2C, PRINT SCREEN
VK_INSERT -> 2D, Ins
VK_DELETE -> 2E, Del

其它的有興趣請上 MSDN 查。值得注意的是,30h~39h 仍為數字鍵,而41h~5Ah 為英文字母,這和原本 ASCII 的定義一樣。

2. bscan

指定硬體掃描碼,事實上按下、彈起每個鍵的時候,送出去的 scan code 都不一樣,如 左邊的ALT,按下時是送38h, 彈起是送出B8h,而右邊的 alt 送的 scanf code 又都不同,這部份有興趣可去找 scan code。

3. dwFlags

其它指定可接受的函式之操作。只有二個值或其組合:KEYEVENTF_EXTENDEDKEY, KEYEVENTF_KEYUP。

4. dwExtraInfo

這個通常設成0。

5. 範例

假設現在您正使用 IE 看此 blog, 那麼有很多常用的快捷鍵,如 ALT + F 呼叫檔案選單;F11 全螢幕化。於這下面這個例子是 SHOW 出 Ctrl + F (呼叫檔案選單)快速鍵;至於要送字元給視窗、EditBox,我覺得用 keybd_event 並不合適。

#include <windows.h>
#define X 800
#define Y 200
int main()
{
          // 先去按一下 mouse 取得視窗控制權, 
          // 假設 X, Y 座標仍在視窗內
          SetCursorPos(X, Y);
          Sleep(200);
          mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
          mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
          keybd_event(VK_MENU, 0,  0, 0);
          keybd_event('F', 0, 0, 0);

          // 最後記得要放掉, 不然結束 ALT 就一直按著
          keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
          keybd_event('F', 0, KEYEVENTF_KEYUP, 0);
          return 0;
}

arrow
arrow
    全站熱搜

    edisonx 發表在 痞客邦 留言(0) 人氣()