【问题标题】:SendInput showing data sent out of sequenceSendInput 显示乱序发送的数据
【发布时间】:2016-09-21 04:59:12
【问题描述】:

我正在通过向备忘录发送字符串来试验 SendInput。我将 SendInput 命令与对 Memo.Lines.Add('....') 的调用混合在一起。令我惊讶的是,所有的 Memo.Lines.Add 命令都在任何 SendInput 例程之前执行。为什么?如何让备忘录以正确的顺序显示信息?

我的代码如下所示:

procedure TForm1.Button1Click(Sender: TObject);
const
  AStr = '123 !@# 890 *() abc ABC';
var
  i: integer;
  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
  Memo1.SetFocus;
  Memo1.Lines.Add('AStr := ' + AStr);

  Memo1.Lines.Add('');
  Memo1.Lines.Add('Use:   KeybdInput(ord(AStr[i]),0)');
  SetLength(KeyInputs,0);
  for i := 1 to Length(AStr) do KeybdInput(ord(AStr[i]),0);
  SendInput(Length(KeyInputs), KeyInputs[0], SizeOf(KeyInputs[0]));

  Memo1.Lines.Add('');
  Memo1.Lines.Add('Use:   KeybdInput(vkKeyScan(AStr[i]),0)');
  SetLength(KeyInputs,0);
  for i := 1 to Length(AStr) do KeybdInput(vkKeyScan(AStr[i]),0);
  SendInput(Length(KeyInputs), KeyInputs[0], SizeOf(KeyInputs[0]));
end;

我希望结果如下所示:

但实际上是这样的:

【问题讨论】:

    标签: delphi sendinput memo


    【解决方案1】:

    您使用SendInput 发送的键盘输入会通过 Windows 消息传递系统并最终进入您的应用程序消息队列。在您从Button1Click() 退出之前,不会处理消息队列。

    When something gets added to a queue, it takes time for it to come out the front of the queue

    要按您期望的顺序查看事件,您需要在每个SendInput() 之后插入对Application.Processmessages() 的调用。不过,通常不建议致电Application.ProcessMessages()

    The Dark Side of Application.ProcessMessages in Delphi Applications

    【讨论】:

    • SendInput() 之后立即调用ProcessMessages() 并不能保证击键可用。正如 Raymond Chen 在this blog article 中解释的那样,来自SendInput() 的消息到达应用程序需要时间。击键必须经过几层队列和处理,因此当您调用 ProcessMessages()(它只处理应用程序已经收到的消息)时,它们可能仍然处于运行状态。
    • @RemyLebeau 感谢这篇有趣的文章解释了为什么它仍然会失败。在发布我的答案之前我确实尝试过,并且在我的机器上在它的负载条件下它工作,但我承认其他措施可能是必要的。
    • 也有可能,当击键在飞行中时,另一个应用程序可能会窃取输入焦点并因此接收击键,而不是最初发送它们的应用程序。正如 Raymond 所写的那样,SendInput() 与实际键盘注入到相同的队列中,您无法控制哪些目标将接收输入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 2021-01-02
    • 1970-01-01
    相关资源
    最近更新 更多