MFC版本

今天遇到奇怪的现象,日文系统下在控件上按下Ctrl+C,再粘贴出来得到乱码,非得切换到日文输入法再进行粘贴不可.经过代码分析,得出结论是剪切板SetClipboardData()时自动内存转换惹的祸.这家伙默认状态下并不能识别双字节的字符.
所以修改的思路是,先统统转成宽字符,再按照宽字符进行拷贝.

之前的代码:

BOOL	CopyStringToClipBoard( HWND hOwner, CString strSource ) { 	if( ::OpenClipboard(hOwner) ) 	{ 		HANDLE clipbuffer ; 		char *buffer ; 		::EmptyClipboard() ; 		clipbuffer = ::GlobalAlloc( GMEM_DDESHARE,strSource.GetLength()+1 ) ; 		buffer = (char*)::GlobalLock(clipbuffer) ; 		strcpy( buffer, LPCSTR(strSource) ) ; 		::GlobalUnlock(clipbuffer) ; 		::SetClipboardData(CF_TEXT, clipbuffer) ; 		::CloseClipboard() ; 	}  	return FALSE ; } 

修改之后的代码:

BOOL	CopyStringToClipBoard( HWND hOwner, CString strSource ) { 	if( ::OpenClipboard(hOwner) ) 	{ 		int buff_size = strSource.GetLength() ; 		CStringW strWide = CStringW(strSource); 		int nLen = strWide.GetLength(); 		HANDLE clipbuffer ; 		char* buffer; 		::EmptyClipboard() ; 		clipbuffer = ::GlobalAlloc( GMEM_DDESHARE, (nLen + 1) * 2 ) ; 		buffer = (char*)::GlobalLock(clipbuffer) ; 		memset(buffer, 0, (nLen + 1) * 2); 		memcpy_s(buffer, nLen * 2, strWide.GetBuffer(0), nLen* 2 ); 		strWide.ReleaseBuffer(); 		::GlobalUnlock(clipbuffer) ; 		::SetClipboardData(CF_UNICODETEXT, clipbuffer) ; 		::CloseClipboard() ; 	}  	return FALSE ; }  

///

C++  SDK UNICODE版本

TCHAR g_szCode[0x200]= { 0 }; if(OpenClipboard(NULL)) 				{ 					EmptyClipboard(); 					// 此处用_tcslen得到字符串的实际长度 没有计算最后的结尾符号\0\0 但是剪切板以及_tcscpy_s函数规定字符串最后是以\0\0结尾                                         //所以这里加1预留出新字符串结尾符号的空间 					SIZE_T nSize = _tcslen(g_szCode) + 1;			 					// 申请内存的空间大小 这里是字节来计算 所以需要把字符串实际长度 * 每个字符所占用的空间  UNICODE是2个字节 所以TCHAR就代表2 					HGLOBAL hClip=GlobalAlloc(GMEM_DDESHARE, nSize * sizeof(TCHAR)); 					PTSTR pszBuf=(PTSTR)GlobalLock(hClip); 					// 这里是以字符数量来复制的 nSize是pszBuf中字符数量的大小 g_szCode的字符数量比nSize小1一个字符 用于_tcscpy_s函数最后需要追加\0\0 					// 由于_tcscpy_s会自动在新字符串上追加结尾符号\0\0 所以这里nSize的大小必须比g_szCode大1 且nSize是pszBuf的实际空间大小                                         _tcscpy_s(pszBuf, nSize, g_szCode); 					GlobalUnlock(hClip);    					SetClipboardData(CF_UNICODETEXT, hClip); 					CloseClipboard(); 				}
注意:如果这里的_tcscpy_s字符没有设置正确 这句代码很可能不会报错 但是在后边的SetClipboardData会报错 这样的错误不容易查找