最簡單的方法其實是先把要發(fā)送的內(nèi)容先保存到剪貼板中去,然后在要發(fā)送的時候“粘貼”一下(Send一個 Ctrl+V)即可。不過這樣做有一些缺點:
1、由于使用了剪貼板,用戶在 Send 的過程中將不能正常使用 Ctrl+C 和 Ctrl+V 等剪貼板相關(guān)的功能;
2、有可能會在還沒執(zhí)行完“粘貼”操作之前剪貼板的內(nèi)容就被修改了,結(jié)果發(fā)送了別的內(nèi)容。
當(dāng)然還有別的方法,先引用一下下面的內(nèi)容:
我們通過鍵盤只能夠輸入鍵盤上有的字符,其實,按住 ALT 鍵,然后在數(shù)字鍵盤上按表示要輸入字符的十進制代碼值的鍵,等完成輸入后,釋放 ALT 鍵還可以輸入鍵盤上沒有的字符呢。
如果鍵入的第一個數(shù)字是“0”,該值將被識別為當(dāng)前輸入?yún)^(qū)域設(shè)置中的代碼點或字符值。例如,在當(dāng)前的輸入?yún)^(qū)域設(shè)置為“英語(美國)”時(代碼頁1252:Windows Latin-1),按住 ALT 鍵,然后在數(shù)字鍵盤上鍵入“0163”將產(chǎn)生英鎊符號 £(U+00A3)。在當(dāng)前輸入?yún)^(qū)域是 "Russia" (代碼頁 1251:Windows Cyrillic),相同的鍵順序會產(chǎn)生西里爾大寫字母JE (U+0408)。
而如果鍵入的第一位數(shù)是“1”到“9”的任意數(shù),該值將被識別為系統(tǒng) OEM代碼頁中的代碼點。根據(jù)在“控制面板”的“區(qū)域選項”中所指定的 Windows系統(tǒng)區(qū)域設(shè)置,結(jié)果各有不同。例如,如果您的系統(tǒng)區(qū)域設(shè)置是“英語(美國)”,代碼頁為 437(MS-DOS 拉丁美洲),那么只要按住 ALT鍵,然后在數(shù)字鍵盤上鍵入“163”,就可以輸入 ú(U+00FA, 帶重音符號的小寫拉丁字母 U)。如果系統(tǒng)區(qū)域設(shè)置是“希臘語”(OEM代碼頁 737 MS-DOS 希臘),相同序列將產(chǎn)生希臘語小寫字母 MU (U+03BC)。
新建一個文本文件,輸入“中文”這兩個字并保存,然后用UltraEdit等十六進制編輯器打開并用十六進制視圖顯示,可看到如下內(nèi)容:
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 ; 如因速度過快導(dǎo)致發(fā)送不正常請嘗試修改此行的延遲數(shù)值
SendMode InputThenPlay ; 如因速度過快導(dǎo)致發(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 ; 第一個字符應(yīng)放到高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來進行轉(zhuǎn)換。
有意思的是,在AutoIt的更新日志里面卻說這個問題已經(jīng)解決了:
Fixed #92: DllStruct data truncated with char[]/wchar[].
最后還是要抱怨一下默認(rèn)情況下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,待轉(zhuǎn)換的字符串,既可以是字符串字面值常量也可以是一個指向包含
; 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 轉(zhuǎn)換為多字節(jié)版本,下面計算足夠用以保存轉(zhuǎn)換成后數(shù)據(jù)的空間大小
Local $nAnsiBufferSize = ($nLen+1) * 2
; 用以保存轉(zhuǎn)換后的結(jié)果
Local $pAnsiStringStruct = DllStructCreate("ubyte[" & $nAnsiBufferSize & "]")
; 將 $string 轉(zhuǎn)換為多字節(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ù)值,用以構(gòu)成 {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 字符串轉(zhuǎn)換為多字節(jié)字符串
; 參數(shù):$UnicodeString,待轉(zhuǎn)換的字符串,既可以是字符串字面值常量也可以是一個指
; 向包含 Unicode 字符數(shù)組的 DllStruct 元素的指針
; $pMultiByte,用以保存轉(zhuǎn)換結(jié)果的地址,指向一個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
聯(lián)系客服