windows 从Win32 ToUnicode()/ToAscii()输出的最大字符数

2guxujil  于 2023-05-08  发布在  Windows
关注(0)|答案(2)|浏览(147)

Win32函数ToUnicode()/ToAscii()最多可以输出多少个字符?
在给定虚拟键代码、扫描键代码和键盘状态的情况下,它能输出什么,肯定有一个合理的上限吧?

jtw3ybtb

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。这应该在你用“一次击键”就能在键盘上产生的范围之内。
这绝不是一个最终的答案,但它可能是最好的,除非有人从微软的回应。

t5fffqht

t5fffqht2#

在通常的死键情况下,我们可以为一个ToUnicode调用接收一个或两个WCHAR(如果键不能用死键组合,则返回两个WCHAR)。
但Windows也支持连字:
键盘术语中的连字意味着单个键输出两个或更多UTF-16码点。请注意,一些语言使用BMP(基本多语言平面)之外的脚本,并且需要完全通过代理对的连字(两个UTF-16代码点)来实现。
如果我们想从实际的一面来看:使用连字的Windows系统键盘布局的Here is a list
208个系统布局中有51个有结扎线
因此,正如我们从表中看到的-我们可以为一个ToUnicode()调用最多4WCHAR(对于一个按键)在实践中
如果我们想从理论的Angular 来看-我们可以看看Windows SDK中的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对象的大小)。
  • cbLgEntrypLigature对象的数量。

所以我们在nLgMax中有一个BYTE值-这意味着连字大小在理论上可以达到255**WCHAR(UTF-16码位)**。

相关问题