2016-07-27 59 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阻塞引起的。」 [每發送輸入函數的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

你還必須檢查關鍵狀態的鎖定和移位等。以這種方式使用SendInput毫無意義,第一個參數是允許一次發送多個輸入。你還不如用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

像Barmak說,你是在一個不恰當的方式混合ANSI和UNICODE在一起,你是不是正確管理輸入的標誌。

發送字符串字符時,最好通過KEYEVENTF_UNICODE標誌發送UTF-16代碼單元,而不是使用掃描代碼或虛擬鍵。

你也應該調用SendInput()一次INPUT結構對於整個字符串,使所有字符都被髮送在一起作爲一個單元,不能被打斷,或混雜,其他輸入事件是由用戶或其他應用程序/線程同時生成。

參見my answerSending 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; 
}