另类讨论SendMessage和PostMessage区别

版权声明:自2019年5月13日开始,本网站的所有技术博客与简书文章同步。 https://blog.csdn.net/y601500359/article/details/90756945

前言

今天在使用MFC消息传递函数时遇到一个问题,困了了半天,最终终于还是找到了原因。

函数信息

先看看两个函数原型:

LRESULT SendMessage(
        HWND hWnd,
        UINT Msg,
        WPARAM wParam,
        LPARAM lParam
);
BOOL PostMessage(
        HWND hWnd,
        UINT Msg,
        WPARAM wParam,
        LPARAM lParam
);

两者的四个参数含义是一样的。
参数含义:
hWnd:其窗口程序将接收消息的窗口的句柄。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。

目的

我使用这个消息的目的是,在消息发送过程中,第三个参数wParam需要带上我需要的消息,就是一串字符串。

出现问题

我首先用的是PostMessage,毕竟它不堵塞线程,不至于引起程序卡死,在使用过程中,我发现一个问题,在我接收消息时,发现解析出来的参数始终是乱码,起初我一直以为之强转导致的问题,但其实在我使用PostMessage函数的函数中强转又是正常的。过程如下:

使用方式

//发送消息
void NotifyRequstQuery(const std::string& body)
{
	const char *cBody = body.c_str();
	PostMessage(WM_MYMESSAGE_ONQUREY, (WPARAM)cBody, 0);
}

//接收消息
afx_msg LRESULT OnMyMessageOnqurey(WPARAM wParam, LPARAM lParam)
{
	char *strBody = (char *)wParam;
	.....
	return 0;
}

测试

在接收消息函数中解析不到我想要的消息时,以为强转除了问题,所以我进行了如下测试:

void NotifyRequstQuery(const std::string& body)
{
	const char *cBody = body.c_str();
	WPARAM wParm = (WPARAM)cBody;
	const char *cResult = (const char *)wParm;

	z_pFrame->PostMessage(WM_MYMESSAGE_ONQUREY, (WPARAM)cBody, 0);
}

这时发现其实强转回来,是没问题的。

更换消息函数

这时我将PostMessage函数更换为SendMessage,这时发现接收消息函数接收到的参数正常。
本着思考的目的,查了很多两者间的区别,总结出来就是:前者不需要相应,直接返回;而后者必须要消息处理后才返回,否则处于线程等待。
那么究竟是什么原因导致这两者出现不同的参数情况呢。
这时候想起会不会是变量使用周期引起的。
然后我又进行了如下测试:

void NotifyRequstQuery(const std::string& body)
{
	//const char *cBody = body.c_str();
	const char *cBody = "This is a Test."
	z_pFrame->PostMessage(WM_MYMESSAGE_ONQUREY, (WPARAM)cBody, 0);
}

这是发现也能正常接收。很奇怪。但我现在不确定这种使用方式 const 常指针变量会不会生命周期不一样?
说实话,形参、常引用形参、常指针变量等等,这一些列烧脑玩意,很多人还真不一定不会出错,于是进行了如下测试:

#include <iostream>

std::string g_strTemp;
//返回指向常变量的常指针
const  char *TestStr1()
{
	const char *cTemp = "This is TestStr1.";
	return cTemp;
}
//返回常引用形参赋值常指针
const  char *TestStr2(const std::string &strTemp)
{
	const char *cTemp = strTemp.c_str();
	return cTemp;
}
//返回一般形参赋值常指针
const char *TestStr3(std::string strTmpe)
{
	const char *cTemp = strTmpe.c_str();
	return cTemp;
}
//局部变量传常变量实参
const char *TestStr4()
{
	const char *cTemp = "********5555********";

	return TestStr2(cTemp);
}
//全局变量传实参
const char *TestStr5()
{
	g_strTemp = "********6666********";
	return TestStr2(g_strTemp);
}

int main()
{
	const  char *cReturn1 = TestStr1();
	std::cout << cReturn1 << std::endl;

	g_strTemp = "********1111********";
	const char *cReturn2 = TestStr2(g_strTemp);
	std::cout << cReturn2 << std::endl;

	g_strTemp = "********2222********";
	cReturn2 = TestStr3(g_strTemp);
	std::cout << "MAIN:" << cReturn2 << std::endl;

	std::string strBody = "********3333********";
	const char *cReturn3 = TestStr2(strBody);
	std::cout << cReturn3 << std::endl;

	strBody = "********4444********";
	cReturn3 = TestStr3(strBody);
	std::cout << cReturn3  << std::endl;

	const char *cReturn4 = TestStr4();
	std::cout << cReturn4 << std::endl;

	const char *cReturn5 = TestStr5();
	std::cout << cReturn5 << std::endl;
	system("pause");
	return 0;
}

运行结果如图:
运行结果
通过结果我们得出如下结论:

  • 将常变量赋值给常指针变量作为成员变量,成员变量的生命周期直到程序结束。
  • 通过常引用参数赋值返回的变量周期跟传入的实参有关,实参改变,周期结束。

出错原因

由此说明,问题出在调用NotifyRequstQuery的地方,说明传入的实参有所改变,因为发消息接收消息处于不同的线程,所以说这完全是可能存在的情况,因为PostMessage不阻塞。

解决办法

1、在调用NotifyRequstQuery时传入的实参,定义为全局变量,但个人不推荐;
2、使用SendMessage代替PostMessage,但具体情况要根据实际而定。

猜你喜欢

转载自blog.csdn.net/y601500359/article/details/90756945