2020-10-20

it2023-02-02  53

MFC(C++)根据控件的长度在字符串中添加换行符

问题 在静态文本控件上表示一串字符串(wchar_t数组),如果是连续的半角英文字母或者数字,不能自动换行,后面多余的字符会被隐藏掉;汉字或半角英文字母、数字有空格可以自动换行,不存在上述问题。

解决策 根据控件的长度,在字符串中添加换行符

GetClientRect–获取控件在屏幕上长度 GetTextExtentPoint32–获取字符串在屏幕上长度

方法 从第wchar_t[0]开始累加每个wchar_t的长度,直至大于或等于控件的长度,此时在当前wchar_t之前添加换行符,并从当前wchar_t重新开始重复之前操作。

问题 wchar_t的编码方式是utf-16,使用2个或者4个字节存储字符。一个wchar_t是2个字节,一般常用字符只有2个字节,1个wchar_t存储即可,一些特殊字符有四个字节(比如𩸽),需要2个wchar_t来存储。所以如果字符串中有四字节的字符的时候,按上述方法,有可能在存储4字节的2个wchar_t中间添加换行符,导致这个字符显示异常。

改进方法 从第一个字符开始累加每个字符的长度,直至大于或等于控件的长度,此时在当前字符之前添加换行符,并从当前字符重新开始重复之前操作。

累加每个字符的长度的时候,分俩种情况 1,4字节字符–累加相邻2个wchar_t的长度

GetTextExtentPoint32W(dc, pwszTemp, 2, &size);

2,2字节字符–累加1个wchar_t的长度

GetTextExtentPoint32W(dc, pwszTemp, 1 &size);

4字节字符的判断方法 字符的前16位范围是0xD800~0xDBFF

int utf16CodePoint = (int)wchar_t[x] if (utf16CodePoint >= 0xD800 && utf16CodePoint <= 0xDBFF) { // 4字节 }

【转】 code point: 指 Unicode 标准里“字符”的编号,目前 Unicode 使用了 0 ~ 0x10FFFF 的编码范围。 code unit: 指某种 Unicode 编码方式里编码一个 code point 需要的最少字节数,比如 UTF-8 需要最少一个字节,UTF-16 最少两个字节UCS-2 两个字节,UCS-4 和 UTF-32 四个字节,后面三个是定长编码。早期的时候,Unicode 只用到了 0~0xFFFF 范围的数字编码,这就是BMP 字符集,UCS-2 编码,很多语言就用 2 bytes 来表示 wchar_t 或者 char,典型的例子是 C/C++/Java。但后来 Unicode 组织胡搞瞎搞居然用到了超过这个范围的字,于是就出来 surrogate pair 的概念了。Surrogate pair 是专门用于 UTF-16 的,以向后兼容 UCS-2,做法是取 UCS-2 范围里的 0xD800~0xDBFF(称为 high urrogates) 和 0xDC00~0xDFFF(称为 low surrogates) 的 code point,一个 high surrogate 接一个 low surrogate 拼成四个字节表示超出BMP 的字符,两个 surrogate range 都是 1024 个 code point,所以 surrogate pair 可以表达 1024 x 1024 = 1048576 = 0x100000 个符,这就是 Unicode 的字符集范围上限是 0x10FFFF 的原因。

最新回复(0)