📄 sendkey.pas
字号:
// 此键值将会导致向hwndQueueSyncTarget'回放'WM_QUEUESYNC消息
if (g_SKD.nMaxVirtKeys = High(g_SKD.asVirtKeys) + 1) then
begin
Result := SKERR_STRINGTOOLONG;
Exit;
end else
begin
g_SKD.asVirtKeys[g_SKD.nMaxVirtKeys] := Byte(VK_QUEUESYNC);
Inc(g_SKD.nMaxVirtKeys);
end;
end else
goto Other;
end;
else // 普通按键
begin
// 并非由上一分支跳入
Other: if (cChar <> '{') then
begin
sVirtKey := VkKeyScan(cChar);
end;
// 按下Shift
if (HiByte(sVirtKey) and 1) <> 0 then
begin
if (g_SKD.nMaxVirtKeys = High(g_SKD.asVirtKeys) + 1) then
begin
Result := SKERR_STRINGTOOLONG;
Exit;
end else
begin
g_SKD.asVirtKeys[g_SKD.nMaxVirtKeys] := Byte(VK_SHIFT);
Inc(g_SKD.nMaxVirtKeys);
end;
end;
// 添加按键
while (nCount > 0) do
begin
Dec(nCount);
if (g_SKD.nMaxVirtKeys = High(g_SKD.asVirtKeys) + 1) then
begin
Result := SKERR_STRINGTOOLONG;
Exit;
end else
begin
g_SKD.asVirtKeys[g_SKD.nMaxVirtKeys] := Byte(LOBYTE(sVirtKey));
Inc(g_SKD.nMaxVirtKeys);
end;
end;
// 放开Shift
if (HiByte(sVirtKey) and 1) <> 0 then
begin
if (g_SKD.nMaxVirtKeys = High(g_SKD.asVirtKeys) + 1) then
begin
Result := SKERR_STRINGTOOLONG;
Exit;
end else
begin
g_SKD.asVirtKeys[g_SKD.nMaxVirtKeys] := Byte(LOBYTE(VK_SHIFT));
Inc(g_SKD.nMaxVirtKeys);
end;
end;
end;
end; // END: case (cChar) of
end;
// 字符串 -> 虚拟键值表
function SendKeys_InitPreprocessKeys(pszPassedKeys: PChar): TSKErr; stdcall;
begin
g_SKD.nMaxVirtKeys := 0;
g_SKD.nVirtKeyNum := 0;
g_SKD.pszKeys := pszPassedKeys;
Result := SKERR_NOERROR;
// 转入虚拟键值表
while (g_SKD.pszKeys^ <> #0) do
begin
Result := SendKeys_PreprocessKeys();
if (Result <> SKERR_NOERROR) then Break;
end;
end;
// 取下一个要回放的按键
function SendKeys_GetToken(psVirtKey: PSmallint; pfPressDown, pfSysKey: PBOOL): BOOL;
const
{$J+}
sVirtKey: SHORT = 0;
fKeyIsDown: BOOL = FALSE;
fKeyPressWhileAltDown: BOOL = FALSE;
fShiftDown: BOOL = FALSE;
fControlDown: BOOL = FALSE;
fAltDown: BOOL = FALSE;
{$J-}
begin
// 初始化
if (psVirtKey = nil) then
begin
sVirtKey := 0;
fKeyIsDown := FALSE;
fShiftDown := FALSE;
fControlDown := FALSE;
fAltDown := FALSE;
g_SKD.nVirtKeyNum := 0;
Result := TRUE;
Exit;
end;
// 确定不是功能键
if (sVirtKey <> VK_SHIFT) and (sVirtKey <> VK_CONTROL) and (sVirtKey <> VK_MENU) then
begin
// 如果上次重放的键是按下, 现在则抬起
if (sVirtKey <> 0) and (fKeyIsDown) then
begin
psVirtKey^ := sVirtKey; // 键值相同
sVirtKey := 0;
pfPressDown^ := FALSE; // 释放按键
pfSysKey^ := fAltDown and not fControlDown; // Is it a SYS key?
fKeyPressWhileAltDown := TRUE;
Result := TRUE;
Exit;
end;
end;
// 回放完毕
if (g_SKD.nVirtKeyNum = g_SKD.nMaxVirtKeys) then
begin
Result := FALSE;
Exit;
end;
// 当前按键
psVirtKey^ := g_SKD.asVirtKeys[g_SKD.nVirtKeyNum];
Inc(g_SKD.nVirtKeyNum);
sVirtKey := psVirtKey^;
case (sVirtKey) of
VK_SHIFT:
begin
fShiftDown := not fShiftDown;
pfPressDown^ := fShiftDown;
end;
VK_CONTROL:
begin
fControlDown := not fControlDown;
pfPressDown^ := fControlDown;
end;
VK_MENU:
begin
fAltDown := not fAltDown;
pfPressDown^ := fAltDown;
if (fAltDown) then
fKeyPressWhileAltDown := FALSE;
end;
VK_QUEUESYNC:
begin
sVirtKey := 0;
end;
else
begin
pfPressDown^ := TRUE;
fKeyIsDown := TRUE;
fKeyPressWhileAltDown := TRUE;
end;
end;
// 是否系统按键
if (sVirtKey = VK_MENU) and (not fAltDown) then
pfSysKey^ := not fKeyPressWhileAltDown and not fControlDown
else
pfSysKey^ := fAltDown and not fControlDown;
Result := TRUE;
end;
// 回放钩子回调函数
function SendKeys_JrnlPlayBackHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
const
{$J+}
sVirtKey: SHORT = 0;
fKeyDown: BOOL = FALSE;
fSysKey: BOOL = FALSE;
{$J-}
var
pEvent: PEventMsg;
begin
// 安装钩子后首次调用
if (g_SKD.fNoTokensRetrievedYet) then
begin
SendKeys_GetToken(@sVirtKey, @fKeyDown, @fSysKey);
g_SKD.fNoTokensRetrievedYet := FALSE;
end;
case (nCode) of
HC_SKIP:
begin
// 取出下一个按键准备回放
if (SendKeys_GetToken(@sVirtKey, @fKeyDown, @fSysKey) = FALSE) then
begin
// 播放完毕则卸载钩子
UnhookWindowsHookEx(g_SKD.hhook);
g_SKD.hhook := 0;
end;
end;
HC_GETNEXT:
begin
// 拷贝按键消息至PEventMsg处
pEvent := PEventMsg(lParam);
pEvent.time := GetTickCount();
if (sVirtKey = VK_QUEUESYNC) then
begin
PostMessage(g_SKD.hwndQueueSyncTarget, WM_QUEUESYNC, 0, 0);
pEvent.hwnd := g_SKD.hwndQueueSyncTarget;
pEvent.message := WM_QUEUESYNC;
pEvent.paramL := 0;
pEvent.paramH := 0;
end else
begin
if (fSysKey = FALSE) then
begin
if fKeyDown then
pEvent.message := WM_KEYDOWN
else
pEvent.message := WM_KEYUP;
end else
begin
if fKeyDown then
pEvent.message := WM_SYSKEYDOWN
else
pEvent.message := WM_SYSKEYUP;
end;
// 虚拟键
pEvent.paramL := sVirtKey;
// 扫描码
pEvent.paramH := MapVirtualKey(sVirtKey, 0);
end;
end;
end;
// 立刻处理
Result := 0;
end;
// 发送一系列按键
function SendKeys(hWndQueueSyncTarget: HWND; pszKeys: PChar): TSKErr; stdcall;
var
abKeyState: TKeyboardState;
begin
// 转成虚拟键列表
Result := SendKeys_InitPreprocessKeys(pszKeys);
if (Result <> SKERR_NOERROR) then Exit;
// 初始化
SendKeys_GetToken(nil, nil, nil);
g_SKD.fNoTokensRetrievedYet := TRUE;
g_SKD.hwndQueueSyncTarget := hwndQueueSyncTarget;
// 安装钩子
g_SKD.hhook := SetWindowsHookEx(WH_JOURNALPLAYBACK, @SendKeys_JrnlPlayBackHook, HInstance, 0);
if (g_SKD.hhook = 0) then
begin
Result := SKERR_CANTINSTALLHOOK;
Exit;
end;
// 抬起按键
GetKeyboardState(abKeyState);
abKeyState[VK_CONTROL] := abKeyState[VK_CONTROL] and $7f;
abKeyState[VK_MENU] := abKeyState[VK_MENU] and $7f;
abKeyState[VK_SHIFT] := abKeyState[VK_SHIFT] and $7f;
abKeyState[VK_CAPITAL] := abKeyState[VK_CAPITAL] and $7e;
abKeyState[VK_NUMLOCK] := abKeyState[VK_NUMLOCK] and $7e;
SetKeyboardState(abKeyState);
// 返回成功
Result := SKERR_NOERROR;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -