项目中要处理一些欧洲的杂志,西欧字体的显示全部是乱码,升级了richedit宽字符版本,但是仍然无效,richedit2.0只能在unicode环境下才能正常工作。这个项目前前后后很多人接手,后来没人敢接了,里面代码也杂乱无章,不知为什么当初他们没用unicode,现在太庞大了,改成unicode显得很不现实(大概有一二十万行代码),也只好硬着头皮手动去改。
1. Find & Replace
微软的IDE还是不错的,Find & Replace 结合正则表达式,替换每个" "加上_T(""),省了很多手动查找的工夫。
// 所有字符串
/("[^"]*"/) ----> _T(/1)
// 前后无括号的字符串
/([^(]/)/("[^"]*"/) ----> /1_T(/2)
// 所有char、char * 声明
char -----> TCHAR
char * -----> TCHAR *
2. String Function
C库中所有多字节处理函数都要改成mb/wc格式的(_t开头的), 能同时处理宽字节和多字节的字符串,msdn上都有一一对应。
3. CString
对CString印象一直很不好,效率是一方面, 在底层实现上也是很不雅,STL感觉好些。下面是CString封装的数据块:
struct CStringData
{
long nRefs; // reference count
int nDataLength; // length of data (including terminator)
int nAllocLength; // length of allocation
// TCHAR data[nAllocLength]
TCHAR* data() // TCHAR* to managed data
{ return (TCHAR*)(this+1); }
};
工程中使用大量CString的GetBuffer(), 其实它返回的就是这个TCHAR* data,而工程中很多底层模块是用多字节实现的,这些已经不可能改成unicode的了, 还是需要用到char * 类型的buffer, 只好将GetBuffer()获取的宽字节buffer转变一下,用WideCharToMultiByte和
MultiByteToWideChar可以简单实现,为了方便期间,写了个CString的委托类,也是个智能指针,将buffer自由转换,自动释放buffer。
// StringW
class StringW
{
public:
// constructors
StringW():m_nLength(0) {
m_pData = new wchar_t[1];
m_pData[0] = 0;
}
StringW(LPCWSTR lpsz) {
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
m_nLength = nSrcLen;
m_pData = new wchar_t[m_nLength+1];
m_pData[m_nLength] = 0;
memcpy(m_pData,lpsz,nSrcLen * sizeof(wchar_t));
}
StringW(LPCSTR lpsz) {
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
if (nSrcLen)
{
m_nLength = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nSrcLen, NULL,
0);
m_pData = new wchar_t[m_nLength+1];
m_pData[m_nLength] = 0;
::MultiByteToWideChar(CP_ACP, 0, lpsz, nSrcLen, m_pData,
m_nLength+1);
}
else {
m_pData = new wchar_t[1];
m_pData[0] = 0;
}
}
StringW(CString& strSrc) {
int nSrcLen = strSrc.GetLength();
if (m_nLength) {
LPTSTR lpsz = strSrc.GetBuffer(nSrcLen);
#ifndef _UNICODE
m_nLength = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nSrcLen, NULL,
0);
m_pData = new wchar_t[m_nLength+1];
m_pData[m_nLength] = 0;
::MultiByteToWideChar(CP_ACP, 0, lpsz, nSrcLen, m_pData,
m_nLength+1);
#else
m_nLength = nSrcLen;
m_pData = new wchar_t[m_nLength+1];
m_pData[m_nLength] = 0;
memcpy(m_pData,lpsz,nSrcLen * sizeof(wchar_t));
#endif
} else {
m_pData = new wchar_t[1];
m_pData[0] = 0;
}
}
// attributes and member functions
inline wchar_t * GetBuffer() { return m_pData; }
inline int GetLength() { return m_nLength; }
operator wchar_t* () const {
return m_pData;
}
operator LPCWSTR() const {
return m_pData;
}
friend CString operator+(const CString& string, const StringW& stringW) {
ASSERT((LPCWSTR)stringW!=NULL);
CString s(string);
s += (LPCWSTR)stringW;
return s;
}
public:
~StringW()
{
if (m_pData) {
delete [] m_pData;
m_pData = NULL;
m_nLength = 0;
}
}
private:
wchar_t * m_pData;
int m_nLength;
};
// StringA
class StringA
{
public:
// constructors
StringA():m_nLength(0) {
m_pData = new char[1];
m_pData[0] = 0;
}
StringA(LPCWSTR lpsz) {
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
if (nSrcLen)
{
m_nLength = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nSrcLen, NULL,
0, NULL, NULL);
m_pData = new char[m_nLength+1];
m_pData[m_nLength] = 0;
::WideCharToMultiByte(CP_ACP, 0, lpsz, nSrcLen, m_pData,
m_nLength+1, NULL, NULL);
}
else {
m_pData = new char[1];
m_pData[0] = 0;
}
}
StringA(LPCSTR lpsz) {
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
m_nLength = nSrcLen;
m_pData = new char[m_nLength+1];
m_pData[m_nLength] = 0;
memcpy(m_pData,lpsz,nSrcLen);
}
StringA(CString& strSrc) {
int nSrcLen = strSrc.GetLength();
if (m_nLength) {
LPTSTR lpsz = strSrc.GetBuffer(nSrcLen);
#ifndef _UNICODE
m_nLength = nSrcLen;
m_pData = new char[m_nLength+1];
m_pData[m_nLength] = 0;
memcpy(m_pData,lpsz,nSrcLen);
#else
m_nLength = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nSrcLen, NULL,
0, NULL, NULL);
m_pData = new char[m_nLength+1];
m_pData[m_nLength] = 0;
::WideCharToMultiByte(CP_ACP, 0, lpsz, nSrcLen, m_pData,
m_nLength+1, NULL, NULL);
#endif
} else {
m_pData = new char[1];
m_pData[0] = 0;
}
}
// attributes and member functions
inline char * GetBuffer() { return m_pData; }
inline int GetLength() { return m_nLength; }
operator char* () const {
return m_pData;
}
operator LPCSTR() const {
return m_pData;
}
friend CString operator+(const CString& string, const StringA& stringA) {
ASSERT((LPCSTR)stringA!=NULL);
CString s(string);
s += (LPCSTR)stringA;
return s;
}
public:
~StringA()
{
if (m_pData) {
delete [] m_pData;
m_pData = NULL;
m_nLength = 0;
}
}
private:
char * m_pData;
int m_nLength;
};
在用到需要字节转换的时候,调用一下就行了。
StringA strA(L"宽字节");
DWORD dwBytesWritten;
if ( ! ::WriteFile(hFile, strA, strA.GetLength(), &dwBytesWritten, NULL) )
return ::GetLastError();
先行这样处理,还要接着改,遇到什么问题再添加上。
2024

被折叠的 条评论
为什么被折叠?



