3

我想为我们的 Windows Mobile 应用程序的远程控制功能模拟快捷方式。应该支持任何可能的快捷方式(想想Ctrl+/Alt+ ä)。

有了keybd_event我可以很好地模拟快捷键,但这个功能只允许使用虚拟键代码。因此,我想到了PostKeybdMessage允许我将任何字符发送到前台窗口的功能。但是如果我结合这两个调用,Windows 将只打印字符而不是执行快捷方式。

这是我尝试过的:

  • 静默发送 CTRL 键 ( KEYEVENTF_SILENT)
  • KeyShiftAnyCtrlFlagPostKeybdMessage通话中添加
  • 玩了很多缓冲区和PostKeybdMessage调用标志(这很令人困惑)

我的问题是:

  • 可以PostKeybdMessage用来模拟快捷方式还是我只是在浪费时间?如果可以,我在代码示例中做错了什么?
  • 是否有发送特殊字符(变音符号、#、=、...)的技巧keybd_event
  • 还有其他方法可以模拟快捷方式吗?

简单的测试应用

public partial class ShortcutTest : Form
{
  private const int KEYEVENTF_KEYUP = 0x0002;
  private const int HWND_FOREGROUND = -1;

  private const uint KEY_STATE_DOWN = 0x0080;
  private const uint KEY_SHIFT_NO_CHARACTER = 0x00010000;
  private const uint KEY_SHIFT_ANY_CONTROL = 0x40000000;

  private const byte VK_CONTROL = 0x11; // Keys.ControlKey

  [DllImport("coredll.dll", SetLastError = true)]
  internal static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

  [DllImport("coredll.dll")]
  private static extern bool PostKeybdMessage(int hwnd, uint vKey, uint KeyStateFlags, uint cCharacters, uint[] pShiftStateBuffer, uint[] pCharacterBuffer);

  public ShortcutTest()
  {
    InitializeComponent();
  }

  private void timer1_Tick(object sender, EventArgs e)
  {
    timer1.Enabled = false;

    keybd_event((byte)Keys.ControlKey, 0, 0, 0);

    // this would work: keybd_event((byte)Keys.X, 0, 0, 0);

    // this won't work
    SendChar('x');

    //keybd_event((byte)Keys.X, 0, KEYEVENTF_KEYUP, 0);

    keybd_event((byte)Keys.ControlKey, 0, KEYEVENTF_KEYUP, 0);

    button1.Enabled = true;
  }

  private void button1_Click(object sender, EventArgs e)
  {
    timer1.Enabled = true;
    button1.Enabled = false;
  }

  public void SendChar(char ch)
  {
    uint[] input = new uint[] { (uint)ch };

    uint[] downStates = { KEY_STATE_DOWN | KEY_SHIFT_ANY_CONTROL };
    uint[] upStates = { KEY_SHIFT_NO_CHARACTER | KEY_SHIFT_ANY_CONTROL };

    PostKeybdMessage(HWND_FOREGROUND, 0, downStates[0], 1, downStates, input);

    // tested with KeyShiftDeadFlag and some others, with \0 char ...
    PostKeybdMessage(HWND_FOREGROUND, 0, upStates[0], 1, upStates, input);
  }

}

编辑:我只是查看了 OpenNETCF 的实现,SendKeys它们keybd_event只使用(例如,“+a”会失败)。

4

1 回答 1

0

您是否尝试过使用 SendInput?我实际上正在使用 c++,并使用以下代码:

INPUT input[4];
memset(input, 0, sizeof(INPUT)*4);
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = VK_MENU;

input[1].type = INPUT_KEYBOARD;
input[1].ki.wVk = L'a';

input[2].type = INPUT_KEYBOARD;
input[2].ki.wVk = VK_MENU;
input[2].ki.dwFlags = KEYEVENTF_KEYUP;

input[3].type = INPUT_KEYBOARD;
input[3].ki.wVk = L'a';
input[3].ki.dwFlags = KEYEVENTF_KEYUP;

SendInput(4, input, sizeof(INPUT));

生成看起来应该可以工作的消息,我在 WM6.5 上检查了间谍。

于 2012-07-07T13:31:59.413 回答