为什么SendInput Ctrl + V在Outlook中不起作用?

时间:2014-05-24 21:55:09

标签: delphi outlook delphi-xe hotkeys sendinput

我有一个程序使用系统范围的热键 Ctrl + Shift + 一个用户选择的键来粘贴使用发送输入here发送 Ctrl + V 组合的剪贴板中的文本。这适用于大多数程序。但是在新电子邮件的“收件人”字段的Outlook中,我尝试的每个密钥最终都会显示“将项目移动到文件夹”#34; Outlook对话框应该是 Ctrl + Shift + V 组合键。在Body字段中没有任何反应。有什么想法在这里发生了什么?请参阅下面的代码重现:

procedure TForm1.FormCreate(Sender: TObject);
begin
  If not RegisterHotkey( Handle, 1, MOD_SHIFT or  MOD_CONTROL, Ord('P') ) Then
    ShowMessage('Error');
end;

Procedure TForm1.WMHotkey( Var msg: TWMHotkey );
var
  KeyInputs: array of TInput;

  procedure KeybdInput(VKey: Byte; Flags: DWORD);
  begin
    SetLength(KeyInputs, Length(KeyInputs)+1);
    KeyInputs[high(KeyInputs)].Itype := INPUT_KEYBOARD;
    with  KeyInputs[high(KeyInputs)].ki do
    begin
      wVk := VKey;
      wScan := MapVirtualKey(wVk, 0);
      dwFlags := Flags;
    end;
  end;

Begin
  If (msg.HotKey > 0) And (msg.HotKey < 2) Then
  Begin
    Clipboard.AsText:= 'Some text';
    KeybdInput(VK_CONTROL, 0);                // Ctrl
    KeybdInput(Ord('V'), 0);
    KeybdInput(Ord('V'), KEYEVENTF_KEYUP);
    KeybdInput(VK_CONTROL, KEYEVENTF_KEYUP); // Ctrl
    SendInput(Length(KeyInputs), KeyInputs[0], SizeOf(KeyInputs[0]));
  end
End;

2 个答案:

答案 0 :(得分:2)

SendInput不会重置键盘的当前状态。因此,Outlook会看到热键的 Ctrl + Shift 。您必须模拟释放 Shift 键。

因此,如果我执行以下操作,它将在Outlook中运行:

var
  input: TInput;
begin
  // This releases the shift Key:
  input.Itype := INPUT_KEYBOARD;
  input.ki.wVk := VK_SHIFT;
  input.ki.wScan := 0;
  input.ki.dwFlags := KEYEVENTF_KEYUP;
  input.ki.time := 0;
  input.ki.dwExtraInfo := 0;
  SendInput(1, input, sizeof(input));

  // Send 'V'
  input.Itype := INPUT_KEYBOARD;
  input.ki.wVk := Ord('V');
  input.ki.wScan := Ord('V');
  input.ki.dwFlags := 0;
  input.ki.time := 0;
  input.ki.dwExtraInfo := 0;
  SendInput(1, input, sizeof(input));
  input.ki.dwFlags := KEYEVENTF_KEYUP;
  SendInput(1, input, sizeof(input));
end;

答案 1 :(得分:0)

Outlook会像这样吃掉键击。唯一的解决方法是安装键盘钩子(SetWindowsHookEx(WH_GETMESSAGE,...))。在你的钩子proc中,你可以使用FindControl()来找到Delphi控件。然后,您可以决定是将消息传递给该控件并将消息重置为WM_NULL,还是将其传递给Outlook。

为什么不使用Outlook对象模型来修改文本? Inspector.GetWordEditor返回Word的Document对象。