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