前言
看過 朋友的網誌,決定補充這二個東西。事實上 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;
}