2014-07-25 25 views
1

我正在寫一個delphi應用程序(myApp)將鍵盤筆畫輸入到外部應用程序(extApp)。爲什麼PostMessage與外部應用程序的行爲不同於鍵盤

當extApp在Windows 7中啓動時,我按{tab} {tab} {down}我在列表框中選擇了適當的項目。向下箭頭選擇TListBox中的第二項(WinSpy ++告訴我它是一個TListBox)。

爲什麼myApp使用此代碼不具有與鍵盤相同的功能?此代碼將選擇一個TListBox(的{標籤}結果{選項卡},然後不動列表框選擇!

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; 

是否有不同的方法,我可以向下箭頭鍵行程發到我的外部應用程序,將?模仿物理鍵盤

+0

您是否嘗試過在sendxxx命令之間添加一些小的延遲? – Graymatter

+0

是的。我在PostMessage之間添加了一個Sleep(500) – Paul

+0

您沒有在消息的lParam參數中設置任何適當的狀態標誌。至少應該設置掃描碼位,以前的鍵狀態和轉換狀態。 –

回答

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; 
+0

這種方法的缺點是你失去了像原始代碼那樣針對特定窗口的能力。 –

+0

@Remy:確實。好處是它實際上發送了密鑰。 :-) –

+0

謝謝。這是我正在尋找的。猜猜我的解決方案並不是簡單的方法! – Paul

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()相反,像肯·懷特建議(雖然你失去了鍵盤輸入定向到的能力特定的窗口,它會一直到前臺窗口 - 但是,然後,真正的鍵盤輸入也是如此)。

+0

謝謝Remy畢竟看起來像是SendInput。 – Paul

相關問題