我一直在尝试找到一种方法来重新映射我的键盘并发送 5 位十六进制 unicode 字符,方法如下所述:ahk Send 仅支持 4 位十六进制代码 {U+nnnn},我知道过去,autohotkey 本身不支持 unicode,因此需要一些功能才能做到这一点,也许这就是我的解决方案。
例:
#If GetKeyState("CapsLock","T")
+u::Send {U+1D4B0}
结果是 풰 而不是 U,풰 的代码是 {U+D4B0},这意味着 AHK 只读取最后 4 位数字。即使我需要制作新功能来实现它,我该如何修复它?
谢谢
-马克
0xFFFF 的 Unicode 值必须编码为两个代理项对:
+u:: SendInput ,{U+D835}{U+DCB0}
以下是将范围0x10000内的 Unicode 码位转换为0x10FFFF、代理项对的算法,转述自维基百科:
首先从码位中减去0x10000,得到范围0xFFFFF中的数字。
然后将数字右移 10 位并向其添加0xD800以获得高代理项。
取数字中最低的十位并向其添加0xDC00以获得低代理项
我从上面采用了 2501 的解决方案,并将其转换为工作 ahk 脚本。几个月来,我一直在断断续续地寻找这个解决方案!
+u:: FUNC_SEND_UNICODE( 0x1D4B0 )
FUNC_SEND_UNICODE(func_args)
{
/*
;commented out proof of concept code:
str := ""
u1 := Chr( 0xD835 )
u2 := Chr( 0xDCB0 )
str := u1 . u2
bk := clipboard
clipboard := str
send, ^v
sleep,200
clipboard := bk
*/
;bk == "clipboard [B]ac[K]up
bk := clipboard
;chunk of data that needs to be cut into
;two chunks.
ful := func_args + 0
/* commented out testing code, using original
sample input of stack overflow post
;msgbox,ful:[%ful%]
;for testing. Expecting input to be equal to
;the value in the post.
if(ful != 0x1D4B0 ){
msgbox,"[WHATTHEHECK]"
}
*/
;Subtract 0x10000 from ful, gets number
;in range(rng) 0x0 to 0xFFFFFF inclusive
rng := ful - 0x10000
if(rng > 0xFFFFF)
{
msgBox,[Step1 Resulted In Out Of Range]
}
;Do shifting and masking, then check to make
;sure the value is in the expected range:
big_shif := (rng >> 10)
lit_mask := (rng & 0x3FF)
if(big_shif > 0x3FF)
{
msgBox,[MATH_ERROR:big_shif]
}
if(lit_mask > 0x3FF)
{
msgBox,[MATH_ERROR:lit_mask]
}
big := big_shif + 0xD800
lit := lit_mask + 0xDC00
if(big < 0xD800 || big >= 0xDBFF){
msgBox, [HIGH_SURROGATE_OUT_OF_BOUNDS]
}
if(lit < 0xDC00 || lit >= 0xDFFF){
msgBox, [LOW_SURROGATE_OUT_OF_BOUNDS]
}
;Convert code points to actual characters:
u1 := Chr( big )
u2 := Chr( lit )
;concatentate those two characters to
;create our final surrogate output:
str := u1 . u2
;set it equal to clipboard, and send
;the clipboard. This is a hack.
;send,%str% works fine in google chrome,
;but fails in notepad++ for some reason.
;tried appending EOF, STX, ETX control codes
;along with output, but to no effect.
clipboard := str
send, ^v
;Must sleep before restoring clipboard,
;otherwise, the clipboard will get
;overwritten before ctrl+v has the chance
;to output the character. You'll end up just
;pasting whatever was originally on the
;clipboard.
sleep,200
clipboard := bk
return
}
2501 答案的实现。
- 侦听
;u
- 后跟一个结束字符(例如
;
或返回( - 等待一系列按键,如 1D4B0
- 输入在被
;
终止时结束 - 如果低于 65536,则直接发送所需的 Unicode 字符,否则计算代理项对
- 插入所需的 Unicode 字符
:?:`;u::
Input, keys, , `;
if (StrLen(keys) < 5)
Send {U+%keys%}
else {
keys := "0x" + keys
num := keys - 0x10000
w1 := Format("{:x}", (num >> 10) + 0xD800)
w2 := Format("{:x}", (num & 1023) + 0xDC00)
Send {U+%w1%}{U+%w2%}
}
return
供参考:
- 热字符串
- 输入
- 斯特伦
- 将字符串转换为数字
- 格式
- 按位运算
- 发送
从互联网上的某个地方: sendunicodechar(0x1D4B0)
SendUnicodeChar(charCode)
{
VarSetCapacity(ki, 28 * 2, 0)
EncodeInteger(&ki + 0, 1)
EncodeInteger(&ki + 6, charCode)
EncodeInteger(&ki + 8, 4)
EncodeInteger(&ki +28, 1)
EncodeInteger(&ki +34, charCode)
EncodeInteger(&ki +36, 4|2)
DllCall("SendInput", "UInt", 2, "UInt", &ki, "Int", 28)
}
EncodeInteger(ref, val)
{
DllCall("ntdllRtlFillMemoryUlong", "Uint", ref, "Uint", 4, "Uint", val)
}
编辑。 可能被否决了缺少来源的BC。我根本不知道我从哪里得到它了。但是当我几年前使用它时,它完美无缺。