2016-09-21 5 views
2

Я экспериментирую с SendInput, отправив строки в памятку. Я смешиваю команды SendInput с вызовами Memo.Lines.Add ('....'). К моему удивлению, все команды Memo.Lines.Add выполняются перед любыми процедурами SendInput. Зачем? Как я могу получить памятку для отображения информации в правильном порядке?SendInput показывает данные, отправленные из последовательности

Мой код выглядит следующим образом:

procedure TForm1.Button1Click(Sender: TObject); 
const 
    AStr = '123 [email protected]# 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; 

И я ожидал, что результат выглядит следующим образом:

Но это на самом деле выглядит следующим образом:

ответ

3

Клавиатурные входы, которые y ou отправить с SendInput проходит через систему обмена сообщениями Windows и заканчивается в очереди сообщений приложений. Очередь сообщений не обрабатывается до выхода из Button1Click().

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

Чтобы увидеть события в том порядке, вы ожидаете, что вам нужно будет вставить вызовы Application.Processmessages() после каждого SendInput(). Вызов Application.ProcessMessages() как правило, не рекомендуется, хотя:

The Dark Side of Application.ProcessMessages in Delphi Applications

+2

Вызов 'ProcessMessages()' * немедленно * после 'SendInput()' не гарантирует нажатия клавиш будут доступны. Как поясняет Раймонд Чэнь в [этой статье в блоге] (https://blogs.msdn.microsoft.com/oldnewthing/20140213-00/?p=1773), для получения сообщений от 'SendInput()' требуется время для приложений. Клавиши должны проходить через несколько уровней очередей и обработки, поэтому они все равно могут находиться в полете, когда вы вызываете 'ProcessMessages()' (который обрабатывает сообщения, которые приложение уже имеет * уже получено). –

+0

@RemyLebeau Спасибо за интересную статью, объясняющую, почему она все равно может потерпеть неудачу. Я попытался, прежде чем я отправил свой ответ, и на моей машине в условиях нагрузки он работал, но я признаю, что могут потребоваться другие меры. –

+0

Также возможно, что при нажатии клавиш нажатие клавиш может вызвать кражу фокуса ввода и, таким образом, получить нажатие клавиш, а не приложение, которое отправило их для начала. Как пишет Раймонд, 'SendInput()' вводит в ту же очередь, что и фактическая клавиатура, у вас нет контроля над тем, какая цель (ы) получит вход. –

Смежные вопросы