关于Unicode和多字节字符集

时间:2022-08-09 22:16:40
一个MFC对话框程序,将它的字符集设置成多字节字符集,::SetWindowTextW( m_hwnd, L"测试字符集ABC" )为什么也可以正常显示出来?还有一个问题:设置成多字节字符条件下,中文和日文能够同时正确显示吗?

14 个解决方案

#1


::SetWindowText是一个宏,根据是否定义UNICODE选择SetWindowTextA或SetWindowTextW。
程序中使用SetWindowTextA和SetWindowTextW都可。
SetWindowTextA("");
SetWindowTextW(L"");
或者
SetWindowText(_T(""));
用_T("")能根据是否定义UNICODE选择是""还是L“”。

#2


API有两套,支持多字节和Unicode
如果想显示多种语言,建议用Unicode字符

#3


没有回答我的问题啊

#4


如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

#5


引用 4 楼 BeanJoy 的回复:
如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

#6


引用 4 楼 BeanJoy 的回复:
如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

对于第一个问题:如果使用多字节版本的api,windows会在内部转换成unicode版本。但是我现在工程是设置成了多字节版本,调用的是unicode版本的API,为什么还能正确显示呢?

#7


SetWindowTextA的内部也是将字符串转换为Unicode后调用SetWindowTextW。(参考《windows核心编程》)
无论你用的是什么字符集,在显示的时候,最终调用的都是SetWindowTextW,因为整个widnows操作系统内部用的都是Unicode字符集。
至于你将工程设置为多字节字符集还是Unicode字符集,影响的仅仅只是SetWindowText的意义,在多字节字符集下,SetWindowText=SetWindowTextA,在Unicode字符集下,SetWindowText=SetWindowTextW

#8


简单来说SetWindowTextA内部的代码是这样的

SetWindowTextA(HWND hWnd,char* lpString)
{
      wchar_t *pwsz = 转换(lpString);
      return  SetWindowTextW(hWnd, pwsz);
}


所以无论你用的是什么字符集,无论调用SetWindowTextA还是SetWindowTextW
最终将字符显示到窗口上的还是SetWindowTextW这个函数

#9


引用 6 楼 hideforever 的回复:
Quote: 引用 4 楼 BeanJoy 的回复:

如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

对于第一个问题:如果使用多字节版本的api,windows会在内部转换成unicode版本。但是我现在工程是设置成了多字节版本,调用的是unicode版本的API,为什么还能正确显示呢?


工程设置成多字节版本并不影响windows api的执行。若设置成UNICODE,只是预先定义了宏UNICODE,代码中调用SetWindowText时,预编译时,会将代码中所有的SetWindowText替换成SetWindowTextW,_T("")替换成L""而已。你在代码中还是可以直接调用SetWindowTextA或SetWindowTextW的。
工程是多字节还是UNICODE只是在编译阶段起作用。

#10


举个例子,用MessageBox来显示一段文字

多字节字符集下显示一段日文,在日文操作系统上显示日文,中文系统乱码

多字节字符集下显示一段中文,在中文操作系统上显示中文,日文系统乱码

unicode符集下显示一段日文,在日文操作系统上显示日文,中文系统也显示日文

unicode符集下显示一段中文,在日文操作系统上显示中文,中文系统也显示中文

#11


多谢各位的解答,以前的概念都是混淆的,现在清楚了

#12


引用 8 楼 CharlesSimonyi 的回复:
简单来说SetWindowTextA内部的代码是这样的

SetWindowTextA(HWND hWnd,char* lpString)
{
      wchar_t *pwsz = 转换(lpString);
      return  SetWindowTextW(hWnd, pwsz);
}


所以无论你用的是什么字符集,无论调用SetWindowTextA还是SetWindowTextW
最终将字符显示到窗口上的还是SetWindowTextW这个函数

有一点不明白:既然归根结底都是调用SetWindowTextW,那还要SetWindowTextA干什么呢?

#13


由于多字节字符集的存在,为了保持对多字节字符集的兼容性,所以才有SetWindowTextA这样的函数存在。
多字节字符集也有它的好处,Unicode出现之前用的就是多字节字符集,现在还不能把多字节字符集彻底抹杀掉,还在用,所有要保持兼容。

#14


引用 13 楼 CharlesSimonyi 的回复:
由于多字节字符集的存在,为了保持对多字节字符集的兼容性,所以才有SetWindowTextA这样的函数存在。
多字节字符集也有它的好处,Unicode出现之前用的就是多字节字符集,现在还不能把多字节字符集彻底抹杀掉,还在用,所有要保持兼容。

多谢Charles的解释,可惜已经结贴没有分了

#1


::SetWindowText是一个宏,根据是否定义UNICODE选择SetWindowTextA或SetWindowTextW。
程序中使用SetWindowTextA和SetWindowTextW都可。
SetWindowTextA("");
SetWindowTextW(L"");
或者
SetWindowText(_T(""));
用_T("")能根据是否定义UNICODE选择是""还是L“”。

#2


API有两套,支持多字节和Unicode
如果想显示多种语言,建议用Unicode字符

#3


没有回答我的问题啊

#4


如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

#5


引用 4 楼 BeanJoy 的回复:
如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

#6


引用 4 楼 BeanJoy 的回复:
如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

对于第一个问题:如果使用多字节版本的api,windows会在内部转换成unicode版本。但是我现在工程是设置成了多字节版本,调用的是unicode版本的API,为什么还能正确显示呢?

#7


SetWindowTextA的内部也是将字符串转换为Unicode后调用SetWindowTextW。(参考《windows核心编程》)
无论你用的是什么字符集,在显示的时候,最终调用的都是SetWindowTextW,因为整个widnows操作系统内部用的都是Unicode字符集。
至于你将工程设置为多字节字符集还是Unicode字符集,影响的仅仅只是SetWindowText的意义,在多字节字符集下,SetWindowText=SetWindowTextA,在Unicode字符集下,SetWindowText=SetWindowTextW

#8


简单来说SetWindowTextA内部的代码是这样的

SetWindowTextA(HWND hWnd,char* lpString)
{
      wchar_t *pwsz = 转换(lpString);
      return  SetWindowTextW(hWnd, pwsz);
}


所以无论你用的是什么字符集,无论调用SetWindowTextA还是SetWindowTextW
最终将字符显示到窗口上的还是SetWindowTextW这个函数

#9


引用 6 楼 hideforever 的回复:
Quote: 引用 4 楼 BeanJoy 的回复:

如2楼版主所说,windows api支持多字节和unicode。
实际windows在实现时,如果你调用的是多字节版本的api,则windows内部会先将相应的字符转换成unicode,然后再调用unicode版本的api。
比如你调用的是::SetWindowTextA(m_hwnd, "测试字符集ABC"),则windows会先将"测试字符集ABC"转换成unicode字符串,然后调用::SetWindowTextW。
你第二个问题是不行的。
多字节的显示是需要在某个代码页下而言的,一般我们用的简体中文的代码页为936,也就是我们常说的GBK。
在GBK环境中某个字符显示正常,那么拿到日文操作系统上,他们的代码页不为936,可能显示乱码。
UNICODE字符是最全的,包含了世界上所有的字符,代码中用UNICODE才能使你的程序无论在什么环境下都能显示正确。

对于第一个问题:如果使用多字节版本的api,windows会在内部转换成unicode版本。但是我现在工程是设置成了多字节版本,调用的是unicode版本的API,为什么还能正确显示呢?


工程设置成多字节版本并不影响windows api的执行。若设置成UNICODE,只是预先定义了宏UNICODE,代码中调用SetWindowText时,预编译时,会将代码中所有的SetWindowText替换成SetWindowTextW,_T("")替换成L""而已。你在代码中还是可以直接调用SetWindowTextA或SetWindowTextW的。
工程是多字节还是UNICODE只是在编译阶段起作用。

#10


举个例子,用MessageBox来显示一段文字

多字节字符集下显示一段日文,在日文操作系统上显示日文,中文系统乱码

多字节字符集下显示一段中文,在中文操作系统上显示中文,日文系统乱码

unicode符集下显示一段日文,在日文操作系统上显示日文,中文系统也显示日文

unicode符集下显示一段中文,在日文操作系统上显示中文,中文系统也显示中文

#11


多谢各位的解答,以前的概念都是混淆的,现在清楚了

#12


引用 8 楼 CharlesSimonyi 的回复:
简单来说SetWindowTextA内部的代码是这样的

SetWindowTextA(HWND hWnd,char* lpString)
{
      wchar_t *pwsz = 转换(lpString);
      return  SetWindowTextW(hWnd, pwsz);
}


所以无论你用的是什么字符集,无论调用SetWindowTextA还是SetWindowTextW
最终将字符显示到窗口上的还是SetWindowTextW这个函数

有一点不明白:既然归根结底都是调用SetWindowTextW,那还要SetWindowTextA干什么呢?

#13


由于多字节字符集的存在,为了保持对多字节字符集的兼容性,所以才有SetWindowTextA这样的函数存在。
多字节字符集也有它的好处,Unicode出现之前用的就是多字节字符集,现在还不能把多字节字符集彻底抹杀掉,还在用,所有要保持兼容。

#14


引用 13 楼 CharlesSimonyi 的回复:
由于多字节字符集的存在,为了保持对多字节字符集的兼容性,所以才有SetWindowTextA这样的函数存在。
多字节字符集也有它的好处,Unicode出现之前用的就是多字节字符集,现在还不能把多字节字符集彻底抹杀掉,还在用,所有要保持兼容。

多谢Charles的解释,可惜已经结贴没有分了