最近刚换一工作,开发工具使用VS2008,于是我得从前一个公司熟悉的VC6编程环境转换到vs2008,,首当其重视是unicode编码的注意事项。查了下windows核心编程,总结了一下多字节和宽字节之间的一些相互转换。
最近写一个接口,接口字符串参数全都都是用char*形式传入的,所以在我的unicode编译环境下,首先得把传入的多字节参数转换成宽字节
int WriteIniFile(const char* szFileName)
{
CONST TCHAR* pFileFullName = NULL;
#ifdef UNICODE //传入的参数进行多字节到宽字节的转换
wchar_t* pWStr;
int unicodeLen = MultiByteToWideChar(CP_ACP, 0, szFileName, -1, NULL, 0);
pWStr = new wchar_t[unicodeLen+1];
memset(pWStr,0,(unicodeLen+1)*sizeof(wchar_t));
::MultiByteToWideChar( CP_ACP, 0, szFileName, -1, (LPWSTR)pWStr, unicodeLen);
pFileFullName = pWStr;
#else
pFileFullName = szFileName;
#endif
/*。。。。。后面代码与转换无关,省略。。。。。。。*/
<pre name="code" class="cpp">#ifdef UNICODE
<span> </span>SAFE_DEL_PTR(pFileFullName)
#endif
}
在使用COPY_DATA消息的时候,发送方编译环境是宽字节,接收方这边是多字节,接受到的消息转换为字符串就只有第一个字符。
考虑到发送消息方和接收消息方可能编译环境会改变,所以在接收方这边修改代码如下:
BOOL CMainTestDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
if (pCopyDataStruct->dwData == 0xff01)
{
TCHAR recvData[MAX_PATH] = {0} ;
CString sCopyData;
if(IsTextUnicode(pCopyDataStruct->lpData, pCopyDataStruct->cbData, NULL)) //消息为UNICODE编码
{
#ifndef UNICODE
char* pElementText;
int iTextLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pCopyDataStruct->lpData, -1, NULL, 0, NULL, NULL);
pElementText = new char[iTextLen+1];
memset((void*)pElementText, 0, sizeof(char)*(iTextLen+1));
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pCopyDataStruct->lpData, -1, pElementText, iTextLen, NULL, NULL);
sCopyData.Format("%s",pElementText);
delete []pElementText;
#else
sCopyData.Format(_T("%s"),pCopyDataStruct->lpData);
#endif
}
else //消息为ANSI编码
{
#ifdef UNICODE
int unicodeLen = ::MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pCopyDataStruct->lpData, -1, NULL, 0);
wchar_t * pUnicode;
pUnicode = new wchar_t[unicodeLen+1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pCopyDataStruct->lpData, -1, (LPWSTR)pUnicode, unicodeLen);
sCopyData.Format(_T("%s"), pUnicode);
delete []pUnicode;
#else
sCopyData.Format("%s",pCopyDataStruct->lpData);
#endif
}
MessageBox(sCopyData);
}
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
考虑到转换占代码行数太多,于是打算将转换写成几个函数,刚好在查阅多字节和宽字节转换的时候百度到一个哥们封装的函数
以下代码转自 http://www.cnblogs.com/gakusei/articles/1585211.html
1. ANSI to Unicode
wstring ANSIToUnicode( const string& str )
{
int len = 0;
len = str.length();
int unicodeLen = ::MultiByteToWideChar( CP_ACP,
0,
str.c_str(),
-1,
NULL,
0 );
wchar_t * pUnicode;
pUnicode = new wchar_t[unicodeLen+1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
::MultiByteToWideChar( CP_ACP,
0,
str.c_str(),
-1,
(LPWSTR)pUnicode,
unicodeLen );
wstring rt;
rt = ( wchar_t* )pUnicode;
delete pUnicode;
return rt;
}
2. Unicode to ANSI
string UnicodeToANSI( const wstring& str )
{
char* pElementText;
int iTextLen;
// wide char to multi char
iTextLen = WideCharToMultiByte( CP_ACP,
0,
str.c_str(),
-1,
NULL,
0,
NULL,
NULL );
pElementText = new char[iTextLen + 1];
memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
::WideCharToMultiByte( CP_ACP,
0,
str.c_str(),
-1,
pElementText,
iTextLen,
NULL,
NULL );
string strText;
strText = pElementText;
delete[] pElementText;
return strText;
}
3. UTF-8 to Unicode
wstring UTF8ToUnicode( const string& str )
{
int len = 0;
len = str.length();
int unicodeLen = ::MultiByteToWideChar( CP_UTF8,
0,
str.c_str(),
-1,
NULL,
0 );
wchar_t * pUnicode;
pUnicode = new wchar_t[unicodeLen+1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
::MultiByteToWideChar( CP_UTF8,
0,
str.c_str(),
-1,
(LPWSTR)pUnicode,
unicodeLen );
wstring rt;
rt = ( wchar_t* )pUnicode;
delete pUnicode;
return rt;
}
4. Unicode to UTF-8
string UnicodeToUTF8( const wstring& str )
{
char* pElementText;
int iTextLen;
// wide char to multi char
iTextLen = WideCharToMultiByte( CP_UTF8,
0,
str.c_str(),
-1,
NULL,
0,
NULL,
NULL );
pElementText = new char[iTextLen + 1];
memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
::WideCharToMultiByte( CP_UTF8,
0,
str.c_str(),
-1,
pElementText,
iTextLen,
NULL,
NULL );
string strText;
strText = pElementText;
delete[] pElementText;
return strText;
}