⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sendkey.pas

📁 这一系列是我平时收集的pascal深入核心编程
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit SendKey;

interface

uses Windows, Messages;

type
 // 错误种类
  TSKErr = (
    SKERR_NOERROR = 0, // 没有错误
    SKERR_MISSINGCLOSEBRACE = 1, // 找不到与左大括号匹配的右大括号
    SKERR_INVALIDKEY = 2,        // 所使用的特殊键无法辨别
    SKERR_MISSINGCLOSEPAREN = 3, // 找不到与左括号匹配的右括号
    SKERR_INVALIDCOUNT = 4,      // 指定了一个非法的重复次数
    SKERR_STRINGTOOLONG = 5,     // 传入字符串过长
    SKERR_CANTINSTALLHOOK = 6    // 无法安装回放钩子
           );

  // 发送一系列按键
function SendKeys(hWndQueueSyncTarget: HWND; pszKeys: PChar): TSKErr; stdcall;

implementation

var
  g_SKD: record
    asVirtKeys: array[0..1023] of SHORT; // 虚拟键值列表
    nVirtKeyNum: Integer; // 下一个被播放的按键
    nMaxVirtKeys: Integer; // 列表长度
    pszKeys: PChar; // 输入字串中下一个字符地址
    fNoTokensRetrievedYet: BOOL; // Flag that indicates playback beginning
    hhook: LongWord; // HHOOK, 回放钩子句柄
    hWndQueueSyncTarget: HWND; // 接受WM_QUEUESYNC通知的窗口
  end;

const
 // 自定义虚拟键值, 遇此键值'回放'WM_QUEUESYNC消息
  VK_QUEUESYNC = -1;

type
 // 特殊按键信息
  PSpecialKey = ^TSpecialKey;
  TSpecialKey = record
    sVirtKey: SHORT; // 键值
    szKeyName: PChar; // 键名
  end;

const
 // 特殊按键列表
  g_SpecialKeys: array[0..42] of TSpecialKey = (
    ( sVirtKey: VK_QUEUESYNC; szKeyName: 'QUEUESYNC' ),
    ( sVirtKey: VK_CAPITAL; szKeyName: 'CAPSLOCK' ),
    ( sVirtKey: VK_NUMLOCK; szKeyName: 'NUMLOCK' ),
    ( sVirtKey: VK_SCROLL; szKeyName: 'SCROLLOCK' ),
    ( sVirtKey: VK_ESCAPE; szKeyName: 'ESCAPE' ),
    ( sVirtKey: VK_ESCAPE; szKeyName: 'ESC' ),
    ( sVirtKey: VK_RETURN; szKeyName: 'ENTER' ),
    ( sVirtKey: VK_HELP; szKeyName: 'HELP' ),
    ( sVirtKey: VK_SNAPSHOT; szKeyName: 'PRTSC' ),
    ( sVirtKey: VK_TAB; szKeyName: 'TAB' ),
    ( sVirtKey: VK_CONTROL; szKeyName: 'BREAK' ),
    ( sVirtKey: VK_CLEAR; szKeyName: 'CLEAR' ),
    ( sVirtKey: VK_BACK; szKeyName: 'BACKSPACE' ),
    ( sVirtKey: VK_BACK; szKeyName: 'BS' ),
    ( sVirtKey: VK_BACK; szKeyName: 'BKSP' ),
    ( sVirtKey: VK_DELETE; szKeyName: 'DELETE' ),
    ( sVirtKey: VK_DELETE; szKeyName: 'DEL' ),
    ( sVirtKey: VK_INSERT; szKeyName: 'INSERT' ),
    ( sVirtKey: VK_LEFT; szKeyName: 'LEFT' ),
    ( sVirtKey: VK_RIGHT; szKeyName: 'RIGHT' ),
    ( sVirtKey: VK_UP; szKeyName: 'UP' ),
    ( sVirtKey: VK_DOWN; szKeyName: 'DOWN' ),
    ( sVirtKey: VK_PRIOR; szKeyName: 'PGUP' ),
    ( sVirtKey: VK_NEXT; szKeyName: 'PGDN' ),
    ( sVirtKey: VK_HOME; szKeyName: 'HOME' ),
    ( sVirtKey: VK_END; szKeyName: 'END' ),
    ( sVirtKey: VK_F1; szKeyName: 'F1' ),
    ( sVirtKey: VK_F2; szKeyName: 'F2' ),
    ( sVirtKey: VK_F3; szKeyName: 'F3' ),
    ( sVirtKey: VK_F4; szKeyName: 'F4' ),
    ( sVirtKey: VK_F5; szKeyName: 'F5' ),
    ( sVirtKey: VK_F6; szKeyName: 'F6' ),
    ( sVirtKey: VK_F7; szKeyName: 'F7' ),
    ( sVirtKey: VK_F8; szKeyName: 'F8' ),
    ( sVirtKey: VK_F9; szKeyName: 'F9' ),
    ( sVirtKey: VK_F10; szKeyName: 'F10' ),
    ( sVirtKey: VK_F11; szKeyName: 'F11' ),
    ( sVirtKey: VK_F12; szKeyName: 'F12' ),
    ( sVirtKey: VK_F13; szKeyName: 'F13' ),
    ( sVirtKey: VK_F14; szKeyName: 'F14' ),
    ( sVirtKey: VK_F15; szKeyName: 'F15' ),
    ( sVirtKey: VK_F16; szKeyName: 'F16' ),
    ( sVirtKey: 0; szKeyName: nil ) );

 // 字符(串)转成虚拟键值
function SendKeys_SpecialKeyToVirtKey(const pszSpecialKey: PChar): SHORT;
var
  psk: PSpecialKey;
begin
 // 遍历按键列表
  psk := @g_SpecialKeys[0];
  Result := psk.sVirtKey;
  while (Result <> 0) and (lstrcmpi(pszSpecialKey, psk.szKeyName) <> 0) do
  begin
    Inc(psk);
    Result := psk.sVirtKey;
  end;

  if (Result = 0) and (lstrlen(pszSpecialKey) = 1) then
  begin
   // 单个字符转成虚拟键值
    Result := VkKeyScan(pszSpecialKey^);
  end;
end;

 // 分析字符串得出重复次数
function PCharToInt(P: PChar): Integer;
begin
  Result := 0;
  while (P^ <> '}') do
  begin
    if (P^ < '0') or (P^ > '9') then
    begin
      Result := 0;
      Exit;
    end;

    Result := Result * 10 + Byte(P^) - $30;
    Inc(P);
  end;
end;

 // 在字符串S定位指定字符C
function SearchChar(S: PChar; C: Char): PChar;
begin
  while (S^ <> #0) and (S^ <> C) do Inc(S);
  if (S^ = C) then Result := S else Result := nil;
end;

 // 预处理下一个按键
function SendKeys_PreprocessKeys(): TSKErr;
var
  cChar: Char; // 当前字符
  szSpecialKey: array[0..15] of Char; // 特殊键名
  pEndOfToken: PChar; // 当前尾部
  sVirtKey: SHORT; // 虚拟键值
  nCount: Integer; // 重复次数
  nNumChars: Integer;
label
  Other;
begin
  sVirtKey := 0;
  nCount := 1;
  Result := SKERR_NOERROR;
  cChar := g_SKD.pszKeys^;
  Inc(g_SKD.pszKeys);
  
 // 当前字符
  case (cChar) of
    #0:  // 末尾
      begin
        Dec(g_SKD.pszKeys); // 调整指针指向#0
      end;

    '(': // 成组
      begin
       // 添加组内字符
        while (g_SKD.pszKeys^ <> #0) and (g_SKD.pszKeys^ <> ')') do
        begin
          Result := SendKeys_PreprocessKeys();
          if (Result <> SKERR_NOERROR) then Break; // 出错
        end;

       // 因#0跳出循环
        if (g_SKD.pszKeys^ = #0) then
          Result := SKERR_MISSINGCLOSEPAREN // 缺少右括号
        else
          Inc(g_SKD.pszKeys); // 跳过右括号
      end;

    '~': // 回车
      begin
        if (g_SKD.nMaxVirtKeys = High(g_SKD.asVirtKeys) + 1) then
        begin
          Result := SKERR_STRINGTOOLONG; // 字串太长
        end else
        begin
          g_SKD.asVirtKeys[g_SKD.nMaxVirtKeys] := VK_RETURN; // 添加回车
          Inc(g_SKD.nMaxVirtKeys);
        end;
      end;

    '+', // Shift
    '^', // Control
    '%': // Alt
      begin
        if (cChar = '+') then
          cChar := Char(VK_SHIFT)
        else
          if (cChar = '^') then
            cChar := Char(VK_CONTROL)
          else
            cChar := Char(VK_MENU);

       // 按下自己
        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(cChar);
          Inc(g_SKD.nMaxVirtKeys);
        end;

       // 中间按键
        Result := SendKeys_PreprocessKeys();
        if (Result <> SKERR_NOERROR) then Exit;

       // 释放自己
        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(cChar);
          Inc(g_SKD.nMaxVirtKeys);
        end;
      end;

    '{':
      begin
       // 可能是 "{}}", 也就是单个字符"}"
        if (g_SKD.pszKeys^ = '}') then
        begin
          sVirtKey := VkKeyScan('}');
          Inc(g_SKD.pszKeys);
        end;

       // 搜寻空格或者右花括号
        pEndOfToken := SearchChar(g_SKD.pszKeys, ' ');
        if (pEndOfToken = nil) then pEndOfToken := SearchChar(g_SKD.pszKeys, '}');

       // 没有找到
        if (pEndOfToken = nil) then
        begin
          Result := SKERR_MISSINGCLOSEBRACE; // 缺少花括号
          Exit;
        end;

        // 并非'{}}'
        if (sVirtKey = 0) then
        begin
         // 虚拟键串
          nNumChars := pEndOfToken - g_SKD.pszKeys;
          lstrcpyn(szSpecialKey, g_SKD.pszKeys, nNumChars + 1);
          szSpecialKey[nNumChars] := #0;

         // 虚拟键值 
          sVirtKey := SendKeys_SpecialKeyToVirtKey(szSpecialKey);
          if (sVirtKey = 0) then
          begin
            Result := SKERR_INVALIDKEY;
            Exit;
          end;
        end;

       // 计算重复次数
        if (pEndOfToken^ = ' ') then
        begin
          Inc(pEndOfToken);
          nCount := PCharToInt(pEndOfToken);
          if (nCount = 0) then
          begin
            Result := SKERR_INVALIDCOUNT; // 非法次数
            Exit;
          end;
        end;

       // 跳过右大括号
        g_SKD.pszKeys := SearchChar(pEndOfToken, '}');
        if (g_SKD.pszKeys = nil) then
        begin
          Result := SKERR_MISSINGCLOSEBRACE;
          Exit;
        end;
        Inc(g_SKD.pszKeys);

       // 自定义"键值"
        if (sVirtKey = VK_QUEUESYNC) then
        begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -