结合keybd_event和PostKeybdMessage来模拟快捷方式

时间:2012-07-04 14:27:47

标签: keyboard windows-mobile compact-framework keyboard-shortcuts windows-ce

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

使用keybd_event我可以很好地模拟快捷方式,但此功能只允许Virtual-Key Codes。因此,我想到了PostKeybdMessage函数,它允许我将任何字符发送到前台窗口。但是,如果我将两个调用结合起来,Windows将只打印字符而不是执行快捷方式。

以下是我的尝试:

  • 以静默方式发送CTRL键(KEYEVENTF_SILENT
  • KeyShiftAnyCtrlFlag添加到PostKeybdMessage来电
  • 使用缓冲区和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);
  }

}

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

1 个答案:

答案 0 :(得分: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上检查间谍。