PAYATHON 2026

SendKeys.Send 如何模拟 AltGr 或右侧 Alt 键?

数据阿明

SendKeys 没有独立的 AltGr 修饰符

SendKeys.Send 的字符串语法没有指定 AltGr 或区分左右 Alt 的修饰符。它支持 +、^、%,分别表示 Shift、Ctrl 和 Alt。%b 表示 Alt+B,无法用它明确指定右侧 Alt。SendKeys 文档

对于使用 AltGr 输入符号的 Windows 键盘布局,可以先尝试 Ctrl+Alt。如果目标窗口当前的布局确实将 AltGr+B 映射为 {,只需做一个小改动:

case '{':
    return "^%b";

增加的 ^ 表示 Ctrl。这个组合请求的是 Ctrl+Alt+B,并非独立的右侧 Alt 按键事件。

为什么 Ctrl+Alt 可能有效

对于某些使用右侧 Alt 作为字符修饰键的布局,Windows 会在内部将其转换为 Ctrl+Alt。微软在 VkKeyScanExW 文档中说明了这种情况。VkKeyScanExW 文档

可以按以下顺序确认:

  1. 将焦点放到目标程序的文本编辑区域,确认当前启用的是预期的匈牙利语键盘布局。
  2. 手动按 AltGr+B,确认是否得到 {。
  3. 手动按 Ctrl+Alt+B,检查目标程序是否也得到 {。
  4. 如果两者都符合预期,再使用 SendKeys.Send("^%b")。

如果目标程序将 Ctrl+Alt+B 注册为快捷键,这种替代方式就不适用。原描述中的“激活粗体”只能说明出现了非预期操作,还无法确定具体是哪个快捷键或输入处理环节触发的。

只需要输入文本时,先尝试发送转义后的字符

如果程序的目标是输出 TextBox 中的文本,可以先移除手写的键盘组合映射,改为传入字符,并对 SendKeys 的特殊语法进行转义。例如:

SendKeys.Send("{{}");  // {
SendKeys.Send("{}}");  // }
SendKeys.Send("{+}");  // +

这会请求输入相应字符,实际结果仍需在目标键盘布局和应用中确认。SendKeys 文档也提醒,多种国际键盘布局下的行为可能不一致。字符转义与键盘布局说明

可以用下面的方法替换原来的 charToKeystroke:

private string charToKeystroke(char c)
{
    switch (c)
    {
        case '\n':
            return "{ENTER}";
        case '\r':
            return "";
        case '\t':
            return "{TAB}";
        case '+':
        case '^':
        case '%':
        case '~':
        case '(':
        case ')':
        case '[':
        case ']':
        case '{':
        case '}':
            return "{" + c + "}";
        default:
            return c.ToString();
    }
}

示例将 \n 转为 Enter,并忽略 \r,避免 Windows 的 \r\n 产生两次 Enter。如果输入可能包含单独的 \r,应先统一换行格式。

原代码中的 {PLUS}、{MINUS} 也应调整:输入文本加号时使用 {+},减号可以直接使用 -;需要数字小键盘按键时,对应名称是 {ADD} 和 {SUBTRACT}。空格直接返回 " " 即可。支持的按键名称

必须模拟右侧 Alt 时,使用 SendInput

如果目标程序需要辨别左右 Alt,应使用 Win32 SendInput 构造键盘事件。Windows 为右侧 Alt 定义了 VK_RMENU,值为 0xA5。实现时需要正确构造按下、释放以及扩展键相关信息,不能把 {VK_RMENU} 当作 SendKeys 字符串使用。Virtual-Key Codes、KEYBDINPUT 文档

如果只关心文字结果,也可以考虑 SendInput 的 KEYEVENTF_UNICODE:设置 wVk = 0,通过 wScan 提供 Unicode 字符。这种方式无需手写 AltGr 字符映射,但目标程序必须能处理相应的文本输入消息,不能保证所有应用都接受。Unicode 输入说明

使用时还要注意什么

  • SendKeys 将输入发送给当前活动应用。开始前切换焦点后,仍需确保文本编辑区域持续获得焦点。
  • 在 WinForms 点击事件中使用 Thread.Sleep 会阻塞界面线程。如果需要保留输入间隔,可以改用 async 事件处理程序与 await Task.Delay(...)。
  • SendWait 可以改变等待方式,但不会增加 AltGr 或右侧 Alt 的字符串语法。
  • 使用 SendInput 时,应检查成功插入的事件数。它还受到 UIPI 限制,不能向更高完整性级别的应用注入输入。SendInput 文档

原始代码在 case ' 附近已经损坏,需要先恢复合法的 C# 语法。上面的示例说明了可采用的改法,但没有在该匈牙利语布局和目标程序中实测。

备注:内容仅供参考。