很早以前寫了一個刷卡程序,功能是定時監控讀卡器,當發現有IC卡放到讀卡器上后,自動識別出卡號,然后帶著這個卡號搜索一個英文用戶名和卡號的對照表,最后把英文用戶名直接自動輸入到當前光標所在的位置。本來程序一直用得好好的,可是最近遇到了一個新問題——因為用戶名現在居然可以用中文了!所以這下麻煩大了……
原先實現英文的自動輸入,用的是keybd_event函數,直接模擬鍵盤事件。但是要輸入中文,貌似沒有輸入法還是不行,難道還要我先用keybd_event調出輸入法,然后輸入拼音?這個思路想想就很恐怖,所以趕緊就上網搜解決方案去了。可是搜了一圈下來,只有寥寥幾篇提到解決方案,雖然網上搜索結果眾多,但是基本上就是這幾個版本貼來貼去,浪費了我好多時間。
不幸的事情還在后頭,雖然有人提到SendInput函數可以輸入中文,但是語焉不詳,按照他提供的點滴的代碼,我死活就是沒有試出來。所以最后中文搜索的結果,除了認識了這個SendInput函數之外,沒有更多的收獲。后來不死心,換了英文搜索,還真找到了一個比較接近我需求的,老外寫的VB版本的SendInput的例子,試驗了以下,果然可以輸入中文。大喜之下,決定花點時間研究一下人家的源代碼,然后寫一個VC的版本。
摸索了兩天之后,發現實現中文自動輸入還真不難,因為SendInput確實支持,所以終于可以不用輸入法了,萬幸。特意整理了幾個函數,共享一下。
首先是,頭文件必須包含以下兩個:
#include <winable.h>
#include <atlconv.h>
前者是SendInput函數要用到,后者是字符串轉換的時候要用到。
void SendAscii(wchar_t data, BOOL shift)
{
INPUT input[2];
memset(input, 0, 2 * sizeof(INPUT));
if (shift)
{
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = VK_SHIFT;
SendInput(1, input, sizeof(INPUT));
}
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = data;
input[1].type = INPUT_KEYBOARD;
input[1].ki.wVk = data;
input[1].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(2, input, sizeof(INPUT));
if (shift)
{
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = VK_SHIFT;
input[0].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, input, sizeof(INPUT));
}
}
void SendUnicode(wchar_t data)
{
INPUT input[2];
memset(input, 0, 2 * sizeof(INPUT));
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = 0;
input[0].ki.wScan = data;
input[0].ki.dwFlags = 0x4;//KEYEVENTF_UNICODE;
input[1].type = INPUT_KEYBOARD;
input[1].ki.wVk = 0;
input[1].ki.wScan = data;
input[1].ki.dwFlags = KEYEVENTF_KEYUP | 0x4;//KEYEVENTF_UNICODE;
SendInput(2, input, sizeof(INPUT));
}
//為方便使用,下面這個函數包裝了前兩個函數。
void SendKeys(CString msg)
{
short vk;
BOOL shift;
USES_CONVERSION;
wchar_t* data = T2W(msg.GetBuffer(0));
int len = wcslen(data);
for(int i=0;i<len;i++)
{
if (data[i]>=0 && data[i]<256) //ascii字符
{
vk = VkKeyScanW(data[i]);
if (vk == -1)
{
SendUnicode(data[i]);
}
else
{
if (vk < 0)
{
vk = ~vk + 0x1;
}
shift = vk >> 8 & 0x1;
if (GetKeyState(VK_CAPITAL) & 0x1)
{
if (data[i]>='a' && data[i]<='z' || data[i]>='A' && data[i]<='Z')
{
shift = !shift;
}
}
SendAscii(vk & 0xFF, shift);
}
}
else //unicode字符
{
SendUnicode(data[i]);
}
}
}
直接調用SendKeys函數就可以在當前光標的位置自動輸入指定的字符串,下面的例子演示了如何自動打開記事本程序并輸入一段話:
void CSendInputDlg::OnTest()
{
ShellExecute(NULL, NULL, "notepad.exe", NULL, NULL, SW_SHOWNORMAL);
Sleep(500); //為了確保記事本程序打開完畢,稍等片刻
CWnd *pWnd = FindWindow(NULL, "無標題 - 記事本");
if (pWnd)
{
pWnd->SetForegroundWindow();
SendKeys("我是sway,我愛中國!\nI love China!\nEmail: \b\b");
}
}
不含病毒。www.avast.com |
留言列表