Windows消息映射及消息發送(SendMess、PostMess)實現

  最近在看linux系統書籍看到消息調度方面,便動手封裝一個類似MFC簡易的消息發送框架(參考實例,沒有窗口句柄)。

  關於框架設計的幾點介紹:
    1.設計採用了自動釋放消息節點方式(增加虛析構函數在內部做相關釋放判斷,即使用完不釋放節點也沒關係);
    2.設計採用了雙向鏈表方式做消息綁定節點(爲了方便起見,沒有采用環形雙向鏈表);
    3.SendMess採用直接調用消息函數方式;
    4.PostMess按照我的想法多個線程同時發送一個消息,那麼這個消息調用次數進行疊加一直調用完成爲止。

  函數定義如下:

//第一個參數 消息ID,第二個參數 消息函數
#define  Test_AddOnMess(id,pthis)   AddMess(id,*pthis);//消息映射宏
void AddMess(int id,LRESULT (* pn)(WPARAM,LPARAM));

LRESULT TestMess(WPARAM wp,LPARAM lp);//測試消息函數
//第一個參數 消息ID,第二個參數 指定附加的消息,第三個參數 指定附加的消息
int Test_SendMess(UINT mess,WPARAM wp,LPARAM lp);//SendMess函數
//第一個參數 消息ID,第二個參數 指定附加的消息,第三個參數 指定附加的消息
int Test_PostMess(UINT mess,WPARAM wp,LPARAM lp);//PostMess函數

typedef struct Test_Mess //消息數據結構體
{
	int id;//消息ID
	volatile int MessRun;//運行狀態
	volatile int messNum;//運行次數
	LRESULT (* pn)(WPARAM wp,LPARAM lp);//消息函數
	Test_Mess *prev,*next; //鏈表節點
}*pTest_Mess;

typedef struct Test_Run//消息執行結構體
{
	pTest_Mess test_Mess,test_Messhead;
	Test_Run()
	{
		test_Mess = test_Messhead = 0;
	}
	virtual ~Test_Run()
	{
		while (0 != test_Messhead)
		{
			pTest_Mess dele;
			dele = test_Messhead->next;
			while (0 != test_Messhead->MessRun)//如果消息還沒執行完成,等待執行完成爲止
				;
			delete test_Messhead;
			test_Messhead = dele;
		}
	}
};
Test_Run testrun;

  代碼實現如下:

void AddMess(int id,LRESULT (* pn)(WPARAM,LPARAM))//消息綁定函數實現
{
	if (0 > id || 0 == pn)
	{
		return ;
	}
	testrun.test_Mess = testrun.test_Messhead;
	if (0 != testrun.test_Mess)//檢查是否ID號相同
	{
		while (id != testrun.test_Mess->id && 0 != testrun.test_Mess->next)
			testrun.test_Mess = testrun.test_Mess->next;
		if (id == testrun.test_Mess->id)
		{
			return ;
		}
	}
	if (0 == testrun.test_Mess)
	{
		testrun.test_Mess = new Test_Mess;
		testrun.test_Mess->next = 0;
		testrun.test_Mess->prev = 0;
		testrun.test_Messhead = testrun.test_Mess;
	}
	else
	{
		while (0 != testrun.test_Mess->next)
			testrun.test_Mess = testrun.test_Mess->next;
		testrun.test_Mess->next = new Test_Mess;
		testrun.test_Mess->next->next = 0;
		testrun.test_Mess->next->prev = testrun.test_Mess;
	}
	while (0 != testrun.test_Mess->next)
		testrun.test_Mess = testrun.test_Mess->next;
	testrun.test_Mess->id = id;
	testrun.test_Mess->MessRun = 0;
	testrun.test_Mess->pn = pn;
	testrun.test_Mess->messNum = 0;
}


LRESULT TestMess(WPARAM wp,LPARAM lp)//測試消息函數實現
{
	return 0;
}

int Test_SendMess(UINT mess,WPARAM wp,LPARAM lp)//SendMess函數實現
{
	pTest_Mess test_mess = testrun.test_Messhead;
	if (0 == test_mess)
	{
		return -2;
	}
	while (mess != test_mess->id && 0 != test_mess->next)
		test_mess = test_mess->next;
	if (mess != test_mess->id)
	{
		return -1;
	}
	test_mess->MessRun = 1;//這個參數的作用類似於鎖,如果不執行完成 那麼就達不到析構條件
	//因爲是Send方式直接啓動
	test_mess->pn(wp,lp);
	test_mess->MessRun = 0;
	return mess;//返回消息ID表示成功
}


int Test_PostMess(UINT mess,WPARAM wp,LPARAM lp)//PostMess函數實現
{
	pTest_Mess test_mess = testrun.test_Messhead;
	if (0 == test_mess)
	{
		return -2;
	}
	while (mess != test_mess->id && 0 != test_mess->next)
		test_mess = test_mess->next;
	if (mess != test_mess->id)
	{
		return -1;
	}
	test_mess->MessRun = 1;
	test_mess->messNum++;//post的設計爲多個線程同時發送一個消息,那麼消息進行疊加一直執行完成所有消息爲止
	while (0 < test_mess->messNum)
	{
		test_mess->pn(wp,lp);
		test_mess->messNum--;
	}
	test_mess->MessRun = 0;
	return mess;
}

  使用方式:

Test_AddOnMess(1,TestMess);//類似於MFC ON_Message 宏
Test_AddOnMess(2,TestMess);
Test_AddOnMess(3,TestMess);

Test_SendMess(2,2,3);
Test_PostMess(3,5,6);
發佈了97 篇原創文章 · 獲贊 218 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章