MFC:解决PostMessage发送字符串造成数据错乱问题

Published

在VC6.0工程中,默认的字符集形式是多字节字符集(MBCS:Multi-Byte Character Set)。

在vs2015工程中,默认字符集编码是Unicode。

 

带你玩转 Visual Studio——带你理解多字节编码与 Unicode 码(very good)

https://wiki.jikexueyuan.com/project/visual-studio/14.html

编码

ANSI (多字节字符集)

  ANSI 在不同的操作系统下代表着不同的编码。在我们正常用的简体中文windows操作系统中,ANSI代表着GBK编码,而在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。

用多个(1-3个)字节来表示 1 个字符。

UNICODE:(宽字节字符集)

char* 转 CString

char* pData = "1234";
CString strData(pData);

debug 可以看出strData的值为 L”1234” , 这里有L说明当前项目编码是 UNICODE,下面我们将
编码改为 ANSI 。
修改编码一般就是使用vs修改项目属性 字符集就可以了
此时

CString strData("1234");

发现strData的值为 “1234” , 而不是 L”1234”

see:

https://www.jianshu.com/p/9804c28e21e8

 

LPARAM类型转化为CString类型

假如现在有一个类型为LPARAM的变量lParam,要将其转化为CString类型,可以:

①CString str((char*)lParam);    --构造函数

②CString str;
 str=(char*)lParam;  --运算符重载

③使用CString的格式化函数:
CString str;
str.format("%s", (char*)iParam);

④一个行不通的办法!但是仔细一看却和方法②相差无几。

CString str=(char*)lParam; --拷贝构造函数    (此时会编译不成功。提示:“初始化”: 无法从“char *”转换为“ATL::CStringT<BaseType,StringTraits>”)

原因是:CString类没有可以将char * 型的转化为CString型的拷贝构造函数。然而,CString的operate=有可以将char *型的转化为CString类的重载函数!

CString,int,LPARAM之间的转换

CString——————————>int

CString strNum(_T("100"));
int num;
num = _ttoi(strNum);
//num = atoi(strNum);

CString<——————————int

int i = 123;
CString str ;
str.Format(_T("%d"), i);

CString——————————>LPARAM

CString str=_T("444");
LPARAM lp=(LPARAM)str1.GetBuffer(256);
str.ReleaseBuffer();
int num1, num2, num3;
	CString str1,str2,str3;
    ::SendMessage(GetDlgItem(IDC_EDIT2)->m_hWnd, WM_GETTEXT, 10, (LPARAM)str1.GetBuffer(256));
	::SendMessage(GetDlgItem(IDC_EDIT3)->m_hWnd, WM_GETTEXT, 10, (LPARAM)str2.GetBuffer(256));
	

	num1 = _ttoi(str1);
	num2 = _ttoi(str2);
	num3 = num1 + num2;
	str3.Format(_T("%d"), num3);

	m_edit3.SendMessage(WM_SETTEXT,0, (LPARAM)str3.GetBuffer(0));

	str1.ReleaseBuffer();
	str2.ReleaseBuffer();
	str3.ReleaseBuffer();

 

update:

	::SendMessage( pInfo->hMainWnd, WM_USER_DOWNLOAD_END, TRUE, (LPARAM)strNote.GetBuffer(strNote.GetLength()+1) );

解决PostMessage发送字符串造成数据错乱问题

 

使用PostMessage来发送字符串数据到主界面,由于字符串是临时变量,而PostMessage是异步发送,有时候由于主界面接收到数据的时候,系统已经将字符串占用的内存释放了,造成获取的字符串可能出现乱码的现象!

    经过分析,主要是由于PostMessage是异步操作造成的。因为TMessage中的WParam是数值型,所以我们发送消息就只能发送字符串的起始地址,然后在接收端通过起始地址获得这个字符串的值。但是这样做会有一个隐形的问题,就是在栈上分配的内存,会在当前作用域结束后释放掉。

字符串前加 L 就变成宽字符 wchar_t 存储用2Byte存1个字符)了,例如,L‘看’,L"abc啊";或_T("sf飞")

 

解决SendMessage发送字符汉字显示为乱码的问题

如果你发送的字符串是char类型即ascii,而工程却用了unicode(wchar),导致字符串解析出问题

step 1:首先要看你的工程设置

alt+F7,配置属性 -> 常规 -> 项目默认值 -> 字符集

step 2:api后面带A(比如SendMessageA)就表示此函数是ascii版本的,W就为unicode版本的,否则的话就为当前工程的字符设置,比如设置了unicode,SendMessage则默认就是SendMessageW,即unicode版本。

如果其字符集为未设置,SendMessage就自动替换为SendMessageA

VS2008默认字符集为Unicode,SendMessage默认替换为SendMessageW

既然用windows api,那你的程序铁定在windows(至少2000以后)上跑,所以除非是别人的代码你不想改,否则就用unicode版的api,不然的话系统还是在幕后转换为unicode再调用,调用后再转回非unicode给你的

配套改用swprintf

或者用_stprintf通用

除非是简单示例,可以少敲些字符而且一目了然,否则统统用unicode版的

char 改成 TCHAR
sprintf 改成 _stprintf
字符串用TEXT括起来,比如"test",改成TEXT("test");

//连接成功,
sprintf(str,"%s : %d 连接成功\n",IpChar,Param.Port); 
}
//向list box发送LB_ADDSTRING显示数据
SendMessage(GetDlgItem(hDlg,IDC_LIST_RST),LB_ADDSTRING,NULL,(LPARAM)str); 

 

 

 

关于多字节字符集项目中 汉字显示为乱码的问题

用DWORD关键字

CString	sFileName	=	pInfo->pStringArray->ElementAt(i);
		::SendMessage( pInfo->hMainWnd, WM_USER_INSTALL_MESSAGE, PROG_NEWGROUPMSG, (DWORD)sFileName.GetBuffer(sFileName.GetLength()+1) );
		
 CString   str="ssss";
(LPARAM)(LPCTSTR)str
在传递自己定义消息的过程中。须要转换CString 变量。
 

在发送消息端使用例如以下方法:

 

SendMessage(WM_MESSAG_MINE,0,(LPARAM)strVal.AllocSysString());

----------------------------------------

在接收消息端使用:

BSTR b = (BSTR)lParam;
CString s(b);
SysFreeString(b);
AfxMessageBox(s);

 

 CString cstr1;
    cstr1.Format(_T("%d"), i);
    CString cstr2 = _T("Hello Test String!"); 
    pWnd->SendMessage(WM_TESTMESSAGE, (WPARAM)(LPCTSTR)cstr1,(LPARAM)(LPCTSTR)cstr2);

 

parallel algorithms in C++17 we can now use:

std::vector<std::string> foo;
std::for_each(
    std::execution::par_unseq,
    foo.begin(),
    foo.end(),
    [](auto&& item)
    {
        //do stuff with item
    });

to compute loops in parallel. The first parameter specifies the execution policy

http://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t

 

LPSTR lpszAscii = T2A((LPTSTR)lpszHostAddress);

 

https://www.shuzhiduo.com/A/ZOJPeVwP5v/

MFC与C#网络传输字符串时中文乱码

https://bbs.csdn.net/topics/390931152