在AHK脚本中使用Send发送中文Word文件下载.docx
《在AHK脚本中使用Send发送中文Word文件下载.docx》由会员分享,可在线阅读,更多相关《在AHK脚本中使用Send发送中文Word文件下载.docx(8页珍藏版)》请在冰豆网上搜索。
![在AHK脚本中使用Send发送中文Word文件下载.docx](https://file1.bdocx.com/fileroot1/2022-11/25/6f5516aa-bc5c-4f38-8a45-6e74b0d57815/6f5516aa-bc5c-4f38-8a45-6e74b0d578151.gif)
9&
的任意数,该值将被识别为系统OEM
代码页中的代码点。
根据在&
控制面板&
的&
区域选项&
中所指定的Windows
系统区域设置,结果各有不同。
例如,如果您的系统区域设置是&
,代码页为437(MS-DOS拉丁美洲),那么只要按住ALT
键,然后在数字键盘上键入&
163&
,就可以输入&
#250;
(U+00FA,带重音符号的小写拉丁字母U)。
如果系统区域设置是&
希腊语&
(OEM
代码页737MS-DOS希腊),相同序列将产生希腊语小写字母MU(U+03BC)。
新建一个文本文件,输入&
中文&
这两个字并保存,然后用UltraEdit等十六进制编辑器打开并用十六进制视图显示,可看到如下内容:
00000000h:
D6D0CEC4;
中文可知中文这两个字的十六进制分别是0xD6D0、0xCEC4(即十进制的54992、52932),那么如果要输入&
中&
字,则只要按住Alt键,逐个输入其十进制数字54992即可。
这样,要实现自己的Send函数就简单了:
AHK脚本:
;
GBK是GB2312的扩展,是向下兼容的,因此GB2312中的汉字的编码与GBK中
汉字的相同。
另外,GBK中还包含繁体字的编码,GBK中每个汉字仍然包含两
个字节,第一个字节的范围是0x81-0xFE(即129-254),第二个字节的范围
是0x40-0xFE(即64-254)。
GBK中有码位23940个,包含汉字21003个。
#NoEnv
SetKeyDelay,20;
如因速度过快导致发送不正常请尝试修改此行的延迟数值
SendModeInputThenPlay;
如因速度过快导致发送不正常请则注释此行或改为其它模式
SetWorkingDir%A_ScriptDir%string1:
="
简体中文字符发送测试"
string2:
繁體中文字符發送測試"
F10:
:
Loop,100
{
SendString("
Sending#"
.A_Index."
"
.string1)
Send,{Enter}
}
ReturnSendString(string)
{
Len:
=StrLen(string);
得到字符串的长度,注意一个中文字符的长度是2,即占2个字节
Keys:
"
;
将要发送的字符序列
Index:
=1;
用于循环
Loop
IsUnicodeChar:
=false
Code2:
=0;
字符2的ASCII码
Code1:
=Asc(SubStr(string,Index,1));
得到第一个字符的ASCII值
if(Code1&
gt;
=129&
amp;
&
Code1&
lt;
=254&
Index&
Len);
判断是否中文字符的第一个字符
=Asc(SubStr(string,Index+1,1));
得到第二个字符的ASCII值
if(Code2&
=64&
Code2&
=254);
若条件成立则说明是中文字符
=true
=8;
第一个字符应放到高8位上
Code1+=Code2;
第二个字符放在低8位上
++Index
if(IsUnicodeChar)
Keys.="
{ASC"
.Code1."
}"
else
{ASC0"
如果非中文字符,则需要前缀一个0
if(Code2&
0)
.Code2."
if(Index&
Len)
Break
Send%Keys
}SendByClipboard(string,BackupClipBoard=false)
if(BackupClipBoard)
ClipSaved:
=ClipboardAll
ClipBoard:
=string
Send^v
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:
DllStructdatatruncatedwithchar[]/wchar[].最后还是要抱怨一下默认情况下AutoIt的Send函数速度实在是太慢了,好在AutoHotkey的速度很理想,尽管Send这种功能我本来也很少用:
)HotKeySet("
{F10}"
"
SendTest"
)While1
Sleep(100)
WEndFuncSendTest()
Local$string="
A中文字符串A"
$begin=TimerInit()For$i=1To10
_Send($string)
Send("
{Enter}"
)
Next
$dif=TimerDiff($begin)
MsgBox(0,"
Timepassed"
$dif)
EndFunc;
函数:
_Send
用途:
发送字符串
参数:
$string,待转换的字符串,既可以是字符串字面值常量也可以是一个指向包含
Unicode字符数组的DllStruct元素的指针
$bSendKeys,是否发送字符串,为false时只返回待发送的Keys(请参考返回
值的说明)而不发送字符串
返回值:
使用Send函数时传递给它的第一个参数(Keys),形如{Ascnn1}{Ascnn2}
Func_Send(Const$string,$bSendKeys=true)
Local$szKeys="
待发送的按键序列
Local$nLen=StringLen($string);
字符串的长度
字符串的Unicode编码数组
Local$UnicodeStringASCIIArray=StringToASCIIArray($string)
因须将$string转换为多字节版本,下面计算足够用以保存转换成后数据的空间大小
Local$nAnsiBufferSize=($nLen+1)*2
用以保存转换后的结果
Local$pAnsiStringStruct=DllStructCreate("
ubyte["
&
$nAnsiBufferSize&
]"
将$string转换为多字节版本
Local$nBytesWritten=WideCharToMultiByte($string,DllStructGetPtr($pAnsiStringStruct))
If$nBytesWritten&
=0Then
$pAnsiStringStruct=0
ReturnSetError(@error,0,"
EndIfLocal$AnsiIndex=1;
Ansi字符串元素的索引
Local$value;
要传给Send函数的数值,用以构成{Asc$value}
For$i=0To$nLen-1
$value=DllStructGetData($pAnsiStringStruct,1,$AnsiIndex)
If$UnicodeStringASCIIArray[$i]&
255Then;
大于255的字符说明是Unicode字符
$AnsiIndex+=1
$value=$value*256+DllStructGetData($pAnsiStringStruct,1,$AnsiIndex)
ElseIf$value&
0Then
$value="
0"
$value
EndIf
$szKeys&
{Asc"
$value&
If$bSendKeysThenSend($szKeys)
Return$szKeys
EndFunc;
==&
_SendFuncSendByClipboard(Const$string,$BackupClipBoard=false)
If$BackupClipBoardThen
Local$bak=ClipGet()
ClipPut($string)
^v"
If$BackupClipBoardThenClipPut($bak)
WideCharToMultiByte
将Unicode字符串转换为多字节字符串
$UnicodeString,待转换的字符串,既可以是字符串字面值常量也可以是一个指
向包含Unicode字符数组的DllStruct元素的指针
$pMultiByte,用以保存转换结果的地址,指向一个char/byte数组的DllStruct
元素的指针
$iCodePage,代码页
写入到$pMultiByte的字节数
FuncWideCharToMultiByte($UnicodeString,$pMultiByte,$iCodePage=0)
Local$aResult,$ParamType="
wstr"
IfIsPtr($UnicodeString)Then$ParamType="
ptr"
$aResult=DllCall("
Kernel32.dll"
int"
WideCharToMultiByte"
$iCodePage,"
0,_
$ParamType,$UnicodeString,"
-1,"
0,"
0)
If@errorThenReturnSetError(@error,0,0)
$pMultiByte,"
$aResult[0],"
If@errorThenReturnSetError(@error,1,0)
Return$aResult[0]
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
WhileTrue
$code2=0
$char1=StringMid($Keys,$index,1)
$code1=Asc($char1)
If$code1&
=129And$code1&
=254And$index&
$lenThen
$char2=StringMid($Keys,$index+1,1)
$code2=Asc($char2)
If$code2&
=64And$code2&
=254Then
$code1*=256
$code1+=$code2
$index+=1
=255Then$code1="
$code1
$KeysInUnicode&
$code1&
0And$code2&
64Then
$code2="
$code2
$code2&
If$index&
$lenThenExitLoop
WEnd
Send($KeysInUnicode)
EndFunc