2016-07-27 14 views
0

いくつかのキーを押すのを自動化するためにSendInput()関数を使いたいと思います。SendInput()が機能しないのはなぜですか?

マイコード:

#include "stdafx.h" 
#include <iostream> 
#include <string> 
#include <Windows.h> 

using std::cin; 
using std::cout; 
using std::string; 

void presskeys(string s){ 
    INPUT ip; 
    ip.ki.wScan = 0; 
    ip.ki.time = 0; 
    ip.ki.dwExtraInfo = 0; 
    HKL kbl = GetKeyboardLayout(0); 
    for (unsigned int i = 0; i < s.length(); ++i) { 
     ip.type = INPUT_KEYBOARD; 
     char c = s[i]; 
     int vk = VkKeyScanEx((WCHAR)c, kbl); 
     ip.ki.wVk = vk; 
     SendInput(1, &ip, sizeof(ip)); 
     ip.ki.dwFlags = KEYEVENTF_KEYUP; 
     SendInput(1, &ip, sizeof(ip)); 
    } 
} 
int main() 
{ 
    cout << "Enter a string!\n"; 
    string str; 
    cin >> str; 
    Sleep(5000); 
    presskeys(str); 
    cout << "Done!\n"; 
    return 0; 
} 

私がプログラムを起動してのみ発生する何のために、文字列を入力します。どこが間違っていたのですか?

+1

sendinputからの戻りコードをチェックし、GetLastErrorを呼び出します。 –

+0

この入力を受け取るのはどのアプリケーションですか? UIPIを研究する。 –

+0

@RemyLebeau "この機能は、UIPIによってブロックされた場合に失敗します。GetLastErrorと戻り値のどちらも、UIPIのブロックによって障害が発生したことを示していないことに注意してください。 [sendinput関数のmsdnの説明に従って](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v = vs.85).aspx) –

答えて

0

ANSI文字列を使用しているため、VkKeyScanExAを使用するか、std::wstringに切り替えてください。 ANSIとUNICODEを混在させたり、キャストを使用してコンパイラの警告を隠さないでください。

キーダウンを示すには、ip.ki.dwFlagsをゼロにリセットする必要があります。次に、KEYEVENTF_KEYUPに設定します。

また、caplockとshiftなどのキーの状態をチェックする必要があります。SendInputを使用すると、無意味です。最初のパラメータは複数の入力を一度に送信できるようにするためのものです。 Barmakは、あなたが不適切な方法で一緒にANSIとUNICODEを混合している、とあなたが正しく入力フラグを管理していない、言ったようにあなたにもkeybd_event

void presskeys(string s) 
{ 
    INPUT ip; 
    ip.type = INPUT_KEYBOARD; 
    ip.ki.wScan = 0; 
    ip.ki.time = 0; 
    ip.ki.dwExtraInfo = 0; 
    HKL kbl = GetKeyboardLayout(0); 
    for (unsigned int i = 0; i < s.length(); ++i) 
    { 
     char c = s[i]; 
     ip.ki.wVk = VkKeyScanExA(c, kbl); //<== don't mix ANSI with UNICODE 
     ip.ki.dwFlags = 0; //<= Add this to indicate key-down 
     SendInput(1, &ip, sizeof(ip)); 
     ip.ki.dwFlags = KEYEVENTF_KEYUP; 
     SendInput(1, &ip, sizeof(ip)); 
    } 
} 
2

を使用する場合があります。

文字列を送信する場合、スキャンコードまたは仮想キーを使用する代わりに、KEYEVENTF_UNICODEフラグを使用してUTF-16コードユニットを送信する方が適切です。

のすべての文字を単一のユニットとして一緒に送信されますとによって中断、またはと混合、ある他の入力イベントすることができないように、あなたはまた、複数で文字列全体のためINPUT構造体をSendInput()1時間を呼び出す必要がありますユーザーまたは他のアプリケーション/スレッドによって同時に生成されます。

my answer~Sending Two or more chars using SendInputを参照してください。例えば

#include "stdafx.h" 
#include <Windows.h> 

#include <iostream> 
#include <string> 
#include <vector> 

void presskeys(const std::wstring &str) 
{ 
    int len = str.length(); 
    if (len == 0) return; 

    std::vector<INPUT> in(len*2); 
    ZeroMemory(&in[0], in.size()*sizeof(INPUT)); 

    int i = 0, idx = 0; 
    while (i < len) 
    { 
     WORD ch = (WORD) str[i++]; 

     if ((ch < 0xD800) || (ch > 0xDFFF)) 
     { 
      in[idx].type = INPUT_KEYBOARD; 
      in[idx].ki.wScan = ch; 
      in[idx].ki.dwFlags = KEYEVENTF_UNICODE; 
      ++idx; 

      in[idx] = in[idx-1]; 
      in[idx].ki.dwFlags |= KEYEVENTF_KEYUP; 
      ++idx; 
     } 
     else 
     { 
      in[idx].type = INPUT_KEYBOARD; 
      in[idx].ki.wScan = ch; 
      in[idx].ki.dwFlags = KEYEVENTF_UNICODE; 
      ++idx; 

      in[idx].type = INPUT_KEYBOARD; 
      in[idx].ki.wScan = (WORD) str[i++]; 
      in[idx].ki.dwFlags = KEYEVENTF_UNICODE; 
      ++idx; 

      in[idx] = in[idx-2]; 
      in[idx].ki.dwFlags |= KEYEVENTF_KEYUP; 
      ++idx; 

      in[idx] = in[idx-2]; 
      in[idx].ki.dwFlags |= KEYEVENTF_KEYUP; 
      ++idx; 
     } 
    } 

    SendInput(in.size(), &in[0], sizeof(INPUT)); 
} 

int main() 
{ 
    std::wcout << L"Enter a string and press enter:\n"; 
    std::wstring str; 
    if (std::getline(std::wcin, str)) 
    { 
     presskeys(str); 
     std::wcout << L"Done!\n"; 
    } 
    return 0; 
} 
関連する問題