最簡單的方法其實是先把要發(fā)送的內容先保存到剪貼板中去,然后在要發(fā)送的時候“粘貼”一下(Send一個 Ctrl+V)即可。不過這樣做有一些缺點: 1、由于使用了剪貼板,用戶在 Send 的過程中將不能正常使用 Ctrl+C 和 Ctrl+V 等剪貼板相關的功能; 2、有可能會在還沒執(zhí)行完“粘貼”操作之前剪貼板的內容就被修改了,結果發(fā)送了別的內容。
當然還有別的方法,先引用一下下面的內容:
我們通過鍵盤只能夠輸入鍵盤上有的字符,其實,按住 ALT 鍵,然后在數(shù)字鍵盤上按表示要輸入字符的十進制代碼值的鍵,等完成輸入后,釋放 ALT 鍵還可以輸入鍵盤上沒有的字符呢。
如
果鍵入的第一個數(shù)字是“0”,該值將被識別為當前輸入?yún)^(qū)域設置中的代碼點或字符值。例如,在當前的輸入?yún)^(qū)域設置為“英語(美國)”時(代碼頁
1252:Windows Latin-1),按住 ALT 鍵,然后在數(shù)字鍵盤上鍵入“0163”將產生英鎊符號 £
(U+00A3)。在當前輸入?yún)^(qū)域是 "Russia" (代碼頁 1251:Windows Cyrillic),相同的鍵順序會產生西里爾大寫字母
JE (U+0408)。
而如果鍵入的第一位數(shù)是“1”到“9”的任意數(shù),該值將被識別為系統(tǒng) OEM
代碼頁中的代碼點。根據(jù)在“控制面板”的“區(qū)域選項”中所指定的 Windows
系統(tǒng)區(qū)域設置,結果各有不同。例如,如果您的系統(tǒng)區(qū)域設置是“英語(美國)”,代碼頁為 437(MS-DOS 拉丁美洲),那么只要按住 ALT
鍵,然后在數(shù)字鍵盤上鍵入“163”,就可以輸入 ú(U+00FA, 帶重音符號的小寫拉丁字母 U)。如果系統(tǒng)區(qū)域設置是“希臘語”(OEM
代碼頁 737 MS-DOS 希臘),相同序列將產生希臘語小寫字母 MU (U+03BC)。
新建一個文本文件,輸入“中文”這兩個字并保存,然后用UltraEdit等十六進制編輯器打開并用十六進制視圖顯示,可看到如下內容:
00000000h: D6 D0 CE C4 ; 中文
可知中文這兩個字的十六進制分別是 0xD6D0、0xCEC4(即十進制的54992、52932),那么如果要輸入“中”字,則只要按住Alt鍵,逐個輸入其十進制數(shù)字54992即可。 這樣,要實現(xiàn)自己的 Send 函數(shù)就簡單了:
AHK腳本: ; GBK是GB2312的擴展,是向下兼容的,因此GB2312中的漢字的編碼與GBK中 ; 漢字的相同。另外,GBK中還包含繁體字的編碼,GBK中每個漢字仍然包含兩 ; 個字節(jié),第一個字節(jié)的范圍是0x81-0xFE(即129-254),第二個字節(jié)的范圍 ; 是0x40-0xFE(即64-254)。GBK中有碼位23940個,包含漢字21003個。
#NoEnv SetKeyDelay, 20 ; 如因速度過快導致發(fā)送不正常請嘗試修改此行的延遲數(shù)值 SendMode InputThenPlay ; 如因速度過快導致發(fā)送不正常請則注釋此行或改為其它模式 SetWorkingDir %A_ScriptDir%
string1 := "簡體中文字符發(fā)送測試" string2 := "繁體中文字符發(fā)送測試"
F10:: Loop, 100 { SendString( "Sending #" . A_Index . " " . string1 ) Send, {Enter} } Return
SendString( string ) { Len := StrLen(string) ; 得到字符串的長度,注意一個中文字符的長度是2,即占2個字節(jié) Keys := "" ; 將要發(fā)送的字符序列 Index := 1 ; 用于循環(huán) Loop { IsUnicodeChar := false Code2 := 0 ; 字符2的ASCII碼 Code1 := Asc( SubStr(string, Index, 1) ) ; 得到第一個字符的ASCII值 if(Code1 >= 129 && Code1 <= 254 && Index < Len) ; 判斷是否中文字符的第一個字符 { Code2 := Asc( SubStr(string, Index+1, 1) ) ; 得到第二個字符的ASCII值 if(Code2 >= 64 && Code2 <= 254) ; 若條件成立則說明是中文字符 { IsUnicodeChar := true Code1 <<= 8 ; 第一個字符應放到高8位上 Code1 += Code2 ; 第二個字符放在低8位上 } ++Index } if( IsUnicodeChar ) Keys .= "{ASC " . Code1 . "}" else { Keys .= "{ASC 0" . Code1 . "}" ; 如果非中文字符,則需要前綴一個0 if( Code2 > 0 ) Keys .= "{ASC 0" . Code2 . "}" } ++Index if(Index > Len) Break } Send % Keys }
SendByClipboard( string, BackupClipBoard = false ) { if(BackupClipBoard) ClipSaved := ClipboardAll ClipBoard := string Send ^v if(BackupClipBoard) { Clipboard := ClipSaved ClipSaved = } }
///////////////////////////////////////////////////////////////////////////////
AU3腳本(3.2.4.0 之后的版本) 由于AutoIt自從版本3.2.4.0+開始已不再提供ANSI版本,因此再寫個能在新版用的
測試版本:v3.3.0.0 在編寫的過程中,一開始是打算使用 StringToBinary/Binary/DllStructSetData 來生成一個Ansi字符串方便處理的,但因為AutoIt存在將字符串截斷的問題(這個問題也算是歷史悠久了),因此不得不使用API來進行轉換。 有意思的是,在AutoIt的更新日志里面卻說這個問題已經解決了:
Fixed #92: DllStruct data truncated with char[]/wchar[].
最后還是要抱怨一下默認情況下AutoIt的 Send 函數(shù)速度實在是太慢了,好在AutoHotkey的速度很理想,盡管Send這種功能我本來也很少用 :)
HotKeySet("{F10}", "SendTest")
While 1 Sleep(100) WEnd
Func SendTest() Local $string = "A中文字符串A" $begin = TimerInit()
For $i = 1 To 10 _Send( $string ) Send("{Enter}") Next $dif = TimerDiff($begin) MsgBox(0,"Time passed", $dif) EndFunc
; 函數(shù): _Send ; 用途:發(fā)送字符串 ; 參數(shù):$string,待轉換的字符串,既可以是字符串字面值常量也可以是一個指向包含 ; Unicode 字符數(shù)組的 DllStruct 元素的指針 ; $bSendKeys,是否發(fā)送字符串,為 false 時只返回待發(fā)送的 Keys(請參考返回 ; 值的說明) 而不發(fā)送字符串 ; 返回值:使用 Send 函數(shù)時傳遞給它的第一個參數(shù)(Keys),形如 {Asc nn1}{Asc nn2} Func _Send( Const $string, $bSendKeys = true ) Local $szKeys = "" ; 待發(fā)送的按鍵序列 Local $nLen = StringLen($string) ; 字符串的長度 ; 字符串的 Unicode 編碼數(shù)組 Local $UnicodeStringASCIIArray = StringToASCIIArray( $string ) ; 因須將 $string 轉換為多字節(jié)版本,下面計算足夠用以保存轉換成后數(shù)據(jù)的空間大小 Local $nAnsiBufferSize = ($nLen+1) * 2 ; 用以保存轉換后的結果 Local $pAnsiStringStruct = DllStructCreate("ubyte[" & $nAnsiBufferSize & "]") ; 將 $string 轉換為多字節(jié)版本 Local $nBytesWritten = WideCharToMultiByte( $string, DllStructGetPtr($pAnsiStringStruct) ) If $nBytesWritten <= 0 Then $pAnsiStringStruct = 0 Return SetError(@error, 0, "") EndIf
Local $AnsiIndex = 1 ; Ansi 字符串元素的索引 Local $value ; 要傳給 Send 函數(shù)的數(shù)值,用以構成 {Asc $value} For $i = 0 To $nLen-1 $value = DllStructGetData($pAnsiStringStruct, 1, $AnsiIndex) If $UnicodeStringASCIIArray[$i] > 255 Then ; 大于255的字符說明是Unicode字符 $AnsiIndex += 1 $value = $value * 256 + DllStructGetData($pAnsiStringStruct, 1, $AnsiIndex) ElseIf $value > 0 Then $value = "0" & $value EndIf $szKeys &= "{Asc " & $value & "}" $AnsiIndex += 1 Next If $bSendKeys Then Send($szKeys) $pAnsiStringStruct = 0 Return $szKeys EndFunc ;==>_Send
Func SendByClipboard( Const $string, $BackupClipBoard = false ) If $BackupClipBoard Then Local $bak = ClipGet() EndIf ClipPut($string) Send("^v") If $BackupClipBoard Then ClipPut($bak) EndFunc
; 函數(shù): WideCharToMultiByte ; 用途:將 Unicode 字符串轉換為多字節(jié)字符串 ; 參數(shù):$UnicodeString,待轉換的字符串,既可以是字符串字面值常量也可以是一個指 ; 向包含 Unicode 字符數(shù)組的 DllStruct 元素的指針 ; $pMultiByte,用以保存轉換結果的地址,指向一個char/byte數(shù)組的 DllStruct ; 元素的指針 ; $iCodePage,代碼頁 ; 返回值:寫入到 $pMultiByte的字節(jié)數(shù) Func WideCharToMultiByte($UnicodeString, $pMultiByte, $iCodePage = 0) Local $aResult, $ParamType = "wstr" If IsPtr($UnicodeString) Then $ParamType = "ptr" $aResult = DllCall("Kernel32.dll", "int", "WideCharToMultiByte", "int", $iCodePage, "int", 0, _ $ParamType, $UnicodeString, "int", -1, "int", 0, "int", 0, "int", 0, "int", 0) If @error Then Return SetError(@error, 0, 0) $aResult = DllCall("Kernel32.dll", "int", "WideCharToMultiByte", "int", $iCodePage, "int", 0, _ $ParamType, $UnicodeString, "int", -1, "ptr", $pMultiByte, "int", $aResult[0], "int", 0, "int", 0) If @error Then Return SetError(@error, 1, 0) Return $aResult[0] EndFunc ;==>WideCharToMultiByte
///////////////////////////////////////////////////////////////////////////////
AU3腳本(3.2.4.0 之前的版本) (注意,最新版本(3.2.4.0+)已不再提供ANSI版本!因此請注意你的AutoIt版本): #cs 運行腳本時需用 AutoIt3A.exe 將 AutoIt 目錄下的AutoIt3A.exe重命名為AutoIt3.exe即可(建議先備份AutoIt3.exe) 編譯腳本時需用 Aut2exeA.exe #ce Run("notepad") WinWaitActive("[CLASS:Notepad]")
_SendRaw("簡體中文And繁體中文")
Func _SendRaw($Keys) Local $KeysInUnicode = "" Local $len = StringLen($Keys) Local $char1 Local $code1 Local $char2 Local $code2 Local $index = 1 While True $code2 = 0 $char1 = StringMid($Keys, $index, 1) $code1 = Asc($char1) If $code1 >= 129 And $code1 <= 254 And $index < $len Then $char2 = StringMid($Keys, $index+1, 1) $code2 = Asc($char2) If $code2 >= 64 And $code2 <= 254 Then $code1 *= 256 $code1 += $code2 EndIf $index += 1 EndIf If $code1 <= 255 Then $code1 = "0" & $code1 $KeysInUnicode &= "{ASC " & $code1 & "}" If $code2 > 0 And $code2 < 64 Then $code2 = "0" & $code2 $KeysInUnicode &= "{ASC " & $code2 & "}" EndIf $index += 1 If $index > $len Then ExitLoop WEnd Send($KeysInUnicode) EndFunc
|