为什么外部应用程序的PostMessage与键盘不同

时间:2014-07-25 19:29:25

标签: delphi windows-7

我正在编写delphi应用程序(myApp)以将键盘笔划输入到外部应用程序(extApp)。

当在Windows 7中启动extApp并按{tab} {tab} {down}时,我会在列表框中选择相应的项目。向下箭头选择TListBox中的第二项(WinSpy ++告诉我它是TListBox)。

为什么使用此代码的myApp不具备与键盘相同的功能?此代码将选择TListBox({tab} {tab}的结果,然后不移动ListBox选择!

    procedure TfrmMain.run;
    begin
      setForegroundWindow(extApp);
      sendTab(extApp);
      sendTab(extApp);
      sendDown(extApp);
    end

    procedure TfrmMain.sendTab(h: HWND);
    begin
      PostMessage(h, WM_KEYDOWN, VK_TAB, 0);
      PostMessage(h, WM_KEYUP,   VK_TAB, 0);
    end;
    procedure TfrmMain.sendDown(h:HWND);
    begin
      PostMessage(h, WM_KEYDOWN, VK_DOWN, 0);
      PostMessage(h, WM_KEYUP,   VK_DOWN  , 0);
    end;

我可以通过不同的方式向我的外部应用程序发送一个向下箭头键击来模仿物理键盘吗?

2 个答案:

答案 0 :(得分:3)

这样做的正确方法是使用SendInput。这样的事情应该让你开始:

var
  Inputs: array of TInput;
  ScanCode: Word;
begin
  ScanCode := MapVirtualKey(VK_TAB, 0);

  SetLength(Inputs, 2);
  Inputs[0].iType := INPUT_KEYBOARD;
  Inputs[0].ki.wVk := VK_TAB;
  Inputs[0].ki.wScan := ScanCode;

  Inputs[1].iType := INPUT_KEYBOARD;
  Inputs[1].ki.wVk := VK_TAB;
  Inputs[1].ki.wScan := ScanCode;
  Inputs[i].ki.dwFlags := KEYEVENTF_KEYUP;

  SendInput(2, Inputs[0], SizeOf(Inputs[0]));
end;

答案 1 :(得分:1)

您没有在消息的lParam参数中设置任何适当的状态标志。您至少应该设置扫描代码,先前的键状态和转换状态的位,例如:

procedure TfrmMain.sendTab(h: HWND);
var
  ScanCode: UINT:
begin
  ScanCode := MapVirtualKey(VK_TAB, 0) shl 16;
  PostMessage(h, WM_KEYDOWN, VK_TAB, ScanCode);
  Sleep(50);
  PostMessage(h, WM_KEYUP,   VK_TAB, ScanCode or $C0000001);
end;

procedure TfrmMain.sendDown(h:HWND);
var
  ScanCode: UINT:
begin
  ScanCode := MapVirtualKey(VK_DOWN, 0) shl 16;
  PostMessage(h, WM_KEYDOWN, VK_DOWN, ScanCode);
  Sleep(50);
  PostMessage(h, WM_KEYUP,   VK_DOWN, ScanCode or $C0000001);
end;

话虽如此,you can't simulate keyboard input with PostMessage,所以请使用SendInput(),就像Ken White建议的那样(虽然你失去了将键盘输入定向到特定窗口的能力,但它总是会转到前台窗口 - 但是,真正的键盘输入也是如此。