另類討論SendMessage和PostMessage區別

前言

今天在使用MFC消息傳遞函數時遇到一個問題,困了了半天,最終終於仍是找到了緣由。ios

函數信息

先看看兩個函數原型:web

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

二者的四個參數含義是同樣的。
參數含義:
hWnd:其窗口程序將接收消息的窗口的句柄。
Msg:指定被髮送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。svg

目的

我使用這個消息的目的是,在消息發送過程當中,第三個參數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;
}

測試

在接收消息函數中解析不到我想要的消息時,覺得強轉除了問題,因此我進行了以下測試:spa

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 常指針變量會不會生命週期不同?
說實話,形參、常引用形參、常指針變量等等,這一些列燒腦玩意,不少人還真不必定不會出錯,因而進行了以下測試:code

#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;
}

運行結果如圖:
運行結果
經過結果咱們得出以下結論:xml

  • 將常變量賦值給常指針變量做爲成員變量,成員變量的生命週期直到程序結束。
  • 經過常引用參數賦值返回的變量週期跟傳入的實參有關,實參改變,週期結束。

出錯緣由

由此說明,問題出在調用NotifyRequstQuery的地方,說明傳入的實參有所改變,由於發消息接收消息處於不一樣的線程,因此說這徹底是可能存在的狀況,由於PostMessage不阻塞。

解決辦法

一、在調用NotifyRequstQuery時傳入的實參,定義爲全局變量,但我的不推薦;
二、使用SendMessage代替PostMessage,但具體狀況要根據實際而定。

相關文章
相關標籤/搜索