Windows编程 Windows下Unicode编码

我们知道在ascii编码,每个字符占用一个字节,这样能够表示的字符数远远不够表示世界所有语言的符号,所以Unicode编码就是出现了,当然Unicode也有8位 16位 32位的编码,UTF-8、UTF-16、UTF-32分别以char、char16_t、char32_t作为编码单位,本文讨论16位 即UTF-16,(注: char16_t 和 char32_t 是 C++ 11 标准新增的关键字。如果你的编译器不支持 C++ 11 标准,请改用 unsigned short 和 unsigned long。)

 

当然本文着重讨论Unicode在Windows中的应用,至于具体细节以及原理上的东西,本人才疏学浅,不配在此谈论此问题,呵呵。还请各位到Google去寻找大牛吧。。由于个人能力有限,文中难免有错误之处,还请各位多多批评和指正,多多包涵才是。

许久以前我在学习MFC的过程中,用GetDlgItemText获取Edit Control的值,其得到的值是CString,,我们看下该函数的原型:

int GetDlgItemText( HWND hDlg , int nID, LPTSTR lpStr, int nMaxCount) const;int GetDlgItemText( int nID, CString& rString) const;

CString编码方式为TCHAR,即在定义了UNICODE和_UNICODE(前者是Windows风格后者是C语言风格,效果形同,通常同时定义)时,是wchar_t型,没有定义时是char型。那么在项目设置为多字节编码时,很好处理,比如在网络编程过程中

sendto(_In_ SOCKET s,_In_reads_bytes_(len) const char FAR * buf,_In_ int len,_In_ int flags,_In_reads_bytes_(tolen) const struct sockaddr FAR * to,_In_ int tolen);

sendto第二个参数为待发送数据的缓冲区,char类型的指针,这时CString的存储类型就为char ,那么可以直接使用CString的值。

但是当项目的编码方式设置为Unicode时,这时CString的存储类型就为wchar_t,就需要将CString进行类型转换,CString有一个成员函数GetBuffer,这个函数是为一个CString对象重新获取其内部字符缓冲区的指针,返回的LPTSTR为非const的,从而允许直接修改CString中的内容。然后就可以强制转换为(char *)类型了。

但是在接收端你必须还要劳烦一次,呵呵  有点啰嗦了,这不是我的风格,代码如下:

wchar_t recvBuf[200];SOCKADDR_IN addrFrom;int len=sizeof(SOCKADDR);recvfrom(sock,(char *)recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);

或者在进行一下处理:

char *ip=inet_ntoa(addrFrom.sin_addr);wchar_t *wIp=new wchar_t;memset(wIp,0,sizeof(wchar_t*));MultiByteToWideChar(CP_ACP,0,ip,-1,wIp,16);//点分10进制格式地址最长也就15wsprintf(tempBuf,L,wIp,recvBuf);::PostMessageA(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);

参考:

关于MFC的CString就先说到这儿吧 !

接下来看下使用

TCHAR :

#ifndef _TCHAR_DEFINEDtypedef WCHAR TCHAR, *PTCHAR;typedef WCHAR TBYTE , *PTBYTE ;#define _TCHAR_DEFINED#endif /* !_TCHAR_DEFINED */#ifndef _MACtypedef wchar_t WCHAR; typedef unsigned

可以看出TCHAR 实质就是wchar_t(在Unicode编码下)。

_T("")是一个宏,定义于tchar.h下。

#define _T(x)__T(x)#define _TEXT(x) __T(x)

他的作用是让你的程序支持Unicode编码,因为Windows使用两种字符集ANSI和UNICODE,前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。

Windows NT的所有与字符有关的函数都提供两种方式的版本,而Windows 9x只支持ANSI方式。

如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。

L是表示字符串资源为Unicode的。比如:

wchar_tStr[] = L"Hello World!";    这个就是双字节存储字符了。

_T是一个适配的宏~ 当#ifdef _UNICODE的时候 ,_T就是L,没有#ifdef _UNICODE的时候,_T就是ANSI的。

LPTSTR lpStr = new TCHAR[32];TCHAR* szBuf = _T();

以上两句使得无论是在UNICODE编译条件下还是在ANSI编译条件下都是正确编译的。

_TEXT      //同样定义于tchar.h下

#define _T(x)__T(x)#define _TEXT(x) __T(x)

看出来了吧 _TEXT和_T一样的作用。

TEXT     //定义于winnt.h

#define TEXT(quote) __TEXT(quote) // r_winnt

#define __TEXT(quote) L##quote// r_winnt

呵呵 看到这儿,可能有些懵了吧,TEXT   和  _T功能一样?是的,功能一样,但是有了_T为什么还有TEXT呢,我们看他们定义的头文件,TEXT定义于winnt.h,以win开头的是Microsoft的头文件,根据宏内容,winnt.h是以UNICODE定义的,Tchar.h则是以_UNICODE定义的,是有区别的,至于Microsoft为什么这么做,应该是为了windows开发者能够方便统一吧!其实在winnt.h这个头文件中同样对TCHAR之类的类型进行了定义,有兴趣的童鞋可以去看看这两个问价的内容分。

TEXT   和  _T的区别解释的很不准确,欢迎大家指正,待本人理解在深刻一些在做修改吧 !

好吧,要回寝室了,今日就到这儿了,Unicode字符串的处理明日在叙!!!

继续。。。。

说完了使用 接下来说处理吧

先看_tcslen()这个函数 ,在tchar.h 这个头文件里面找到了其定义

#define _tcslenwcslen

仔细点还可以找到另一个定义

#define _tcslenstrlen

呵呵 ,我想大家已经明白其意思了吧!

在Unicode编码下会使用上面那个宏,当然多字节编码就会使用下面那个了。

的确,Microsoft这样一处理,我们使用起来就方便多了,很容易在项目里面实现统一。

使用和处理都说了 最后说一下转换吧!

有时候项目是采用多字节编码,但是一些windows函数不支持宽字节,比如上面说到了网络编程中的收发数据的函数,这时候就需要我们转换一下:

带着我的相机和电脑,远离繁华,走向空旷。

Windows编程 Windows下Unicode编码

相关文章:

你感兴趣的文章:

标签云: