Win32函数ToUnicode()/ToAscii()最多可以输出多少个字符?在给定虚拟键代码、扫描键代码和键盘状态的情况下,它能输出什么,肯定有一个合理的上限吧?
jtw3ybtb1#
在我的Windows 8机器上,USER32!ToAscii使用内部缓冲区调用USER32!ToUnicode,并将cchBuff设置为2。因为ToAscii的输出是LPWORD而不是LPSTR,所以我们不能从这个研究中假设ToUnicode的真实的极限,但我们知道ToAscii总是输出WORD。返回值告诉您这个WORD的0、1或2字节是否包含有用的数据。继续到ToUnicode,事情变得有点棘手。如果返回0,则没有写入任何内容。如果它返回1或-1,则写入了一个UCS-2代码点。然后我们就得到了奇怪的2 <= return表达式。我们可以尝试剖析MSDN文档:两个或多个字符被写入pwszBuff指定的缓冲区。最常见的原因是存储在键盘布局中的死键字符(重音或变音符号)无法与指定的虚拟键组合形成单个字符。但是,缓冲区包含的字符可能比返回值指定的多。发生这种情况时,任何额外的字符都是无效的,应该忽略。您可以将其解释为“写入了两个或多个字符,但其中只有两个有效”,但返回值应该记录为2而不是2 ≤ value。我认为这句话中有两件事,我们应该消除它所谓的“额外字符”:但是,缓冲区包含的字符可能比返回值指定的多。这只是意味着函数可能会在缓冲区中超出它实际返回的有效值。这一点得到以下方面的证实:发生这种情况时,任何额外的字符都是无效的,应该忽略。这就给我们留下了一个不幸的开场白:两个或多个字符被写入pwszBuff指定的缓冲区。我可以想象返回值为2,它可以像基本字符与diacritic组合一样简单,而diacritic并不作为预组合的代码点存在。“或更多”部分可以来自多个来源。如果基本字符被编码为代理对,那么任何附加的变音符号/组合字符都将使您超过2。在基本字符上也可以简单地存在多于一个的附加符号/组合字符。甚至可能有一个领先的LTR/RTL标记。我不知道是否有可能在同一时间结束所有3个条件,但我会发挥它的安全,并指定一个缓冲区的10个左右的WCHAR。这应该在你用“一次击键”就能在键盘上产生的范围之内。这绝不是一个最终的答案,但它可能是最好的,除非有人从微软的回应。
USER32!ToAscii
USER32!ToUnicode
cchBuff
ToAscii
LPWORD
LPSTR
ToUnicode
WORD
2 <= return
2
2 ≤ value
t5fffqht2#
在通常的死键情况下,我们可以为一个ToUnicode调用接收一个或两个WCHAR(如果键不能用死键组合,则返回两个WCHAR)。但Windows也支持连字:键盘术语中的连字意味着单个键输出两个或更多UTF-16码点。请注意,一些语言使用BMP(基本多语言平面)之外的脚本,并且需要完全通过代理对的连字(两个UTF-16代码点)来实现。如果我们想从实际的一面来看:使用连字的Windows系统键盘布局的Here is a list。208个系统布局中有51个有结扎线因此,正如我们从表中看到的-我们可以为一个ToUnicode()调用最多4WCHAR(对于一个按键)在实践中。如果我们想从理论的Angular 来看-我们可以看看Windows SDK中的kbd.h,其中定义了底层键盘布局结构:
WCHAR
kbd.h
/* * Macro for ligature with "n" characters */ #define TYPEDEF_LIGATURE(n) typedef struct _LIGATURE##n { \ BYTE VirtualKey; \ WORD ModificationNumber; \ WCHAR wch[n]; \ } LIGATURE##n, *KBD_LONG_POINTER PLIGATURE##n; /* * Table element types (for various numbers of ligatures), used * to facilitate static initializations of tables. * * LIGATURE1 and PLIGATURE1 are used as the generic type */ TYPEDEF_LIGATURE(1) // LIGATURE1, *PLIGATURE1; TYPEDEF_LIGATURE(2) // LIGATURE2, *PLIGATURE2; TYPEDEF_LIGATURE(3) // LIGATURE3, *PLIGATURE3; TYPEDEF_LIGATURE(4) // LIGATURE4, *PLIGATURE4; TYPEDEF_LIGATURE(5) // LIGATURE5, *PLIGATURE5; typedef struct tagKbdLayer { .... /* * Ligatures */ BYTE nLgMax; BYTE cbLgEntry; PLIGATURE1 pLigature; .... } KBDTABLES, *KBD_LONG_POINTER PKBDTABLES;
nLgMax
LIGATURE##n.wch[n]
pLigature
cbLgEntry
所以我们在nLgMax中有一个BYTE值-这意味着连字大小在理论上可以达到255**WCHAR(UTF-16码位)**。
BYTE
2条答案
按热度按时间jtw3ybtb1#
在我的Windows 8机器上,
USER32!ToAscii
使用内部缓冲区调用USER32!ToUnicode
,并将cchBuff
设置为2。因为ToAscii
的输出是LPWORD
而不是LPSTR
,所以我们不能从这个研究中假设ToUnicode
的真实的极限,但我们知道ToAscii
总是输出WORD
。返回值告诉您这个WORD
的0、1或2字节是否包含有用的数据。继续到
ToUnicode
,事情变得有点棘手。如果返回0,则没有写入任何内容。如果它返回1或-1,则写入了一个UCS-2代码点。然后我们就得到了奇怪的2 <= return
表达式。我们可以尝试剖析MSDN文档:两个或多个字符被写入pwszBuff指定的缓冲区。最常见的原因是存储在键盘布局中的死键字符(重音或变音符号)无法与指定的虚拟键组合形成单个字符。但是,缓冲区包含的字符可能比返回值指定的多。发生这种情况时,任何额外的字符都是无效的,应该忽略。
您可以将其解释为“写入了两个或多个字符,但其中只有两个有效”,但返回值应该记录为
2
而不是2 ≤ value
。我认为这句话中有两件事,我们应该消除它所谓的“额外字符”:
但是,缓冲区包含的字符可能比返回值指定的多。
这只是意味着函数可能会在缓冲区中超出它实际返回的有效值。这一点得到以下方面的证实:
发生这种情况时,任何额外的字符都是无效的,应该忽略。
这就给我们留下了一个不幸的开场白:
两个或多个字符被写入pwszBuff指定的缓冲区。
我可以想象返回值为2,它可以像基本字符与diacritic组合一样简单,而diacritic并不作为预组合的代码点存在。
“或更多”部分可以来自多个来源。如果基本字符被编码为代理对,那么任何附加的变音符号/组合字符都将使您超过2。在基本字符上也可以简单地存在多于一个的附加符号/组合字符。甚至可能有一个领先的LTR/RTL标记。
我不知道是否有可能在同一时间结束所有3个条件,但我会发挥它的安全,并指定一个缓冲区的10个左右的WCHAR。这应该在你用“一次击键”就能在键盘上产生的范围之内。
这绝不是一个最终的答案,但它可能是最好的,除非有人从微软的回应。
t5fffqht2#
在通常的死键情况下,我们可以为一个
ToUnicode
调用接收一个或两个WCHAR
(如果键不能用死键组合,则返回两个WCHAR
)。但Windows也支持连字:
键盘术语中的连字意味着单个键输出两个或更多UTF-16码点。请注意,一些语言使用BMP(基本多语言平面)之外的脚本,并且需要完全通过代理对的连字(两个UTF-16代码点)来实现。
如果我们想从实际的一面来看:使用连字的Windows系统键盘布局的Here is a list。
208个系统布局中有51个有结扎线
因此,正如我们从表中看到的-我们可以为一个ToUnicode()调用最多4
WCHAR
(对于一个按键)在实践中。如果我们想从理论的Angular 来看-我们可以看看Windows SDK中的
kbd.h
,其中定义了底层键盘布局结构:nLgMax
-是LIGATURE##n.wch[n]
数组的大小(影响每个pLigature
对象的大小)。cbLgEntry
是pLigature
对象的数量。所以我们在
nLgMax
中有一个BYTE
值-这意味着连字大小在理论上可以达到255**WCHAR
(UTF-16码位)**。