• 另类讨论SendMessage和PostMessage区别


    前言

    今天在使用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,但具体情况要根据实际而定。

  • 相关阅读:
    python笔记第十一天 模块补充
    python笔记第十天 模块
    python笔记第九天 装饰器
    python笔记第八天 迭代器与生成器
    python笔记第七天 文件操作
    python笔记第六天 函数和函数的内置方法
    C语言----指针形参(指向指针的指针形参)
    NEON使用方法
    ARM NEON指令集总结
    三维变换矩阵左乘和右乘分析
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049089.html
Copyright © 2020-2023  润新知