VC6下完成內(nèi)部進(jìn)程通訊
發(fā)表時(shí)間:2024-01-04 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]Windows是一種面向?qū)ο蟮捏w系結(jié)構(gòu),Windows環(huán)境和應(yīng)用程序都是通過消息來交互的。Windows應(yīng)用程序開始執(zhí)行后,Windows為該程序創(chuàng)建一個(gè)“消息隊(duì)列(message queue)”,用以存放郵寄給該程序可能創(chuàng)建的各種不同窗口的消息。消息隊(duì)列中消息的結(jié)構(gòu)(MSG)為: type...
Windows是一種面向?qū)ο蟮捏w系結(jié)構(gòu),Windows環(huán)境和應(yīng)用程序都是通過消息來交互的。Windows應(yīng)用程序開始執(zhí)行后,Windows為該程序創(chuàng)建一個(gè)“消息隊(duì)列(message queue)”,用以存放郵寄給該程序可能創(chuàng)建的各種不同窗口的消息。消息隊(duì)列中消息的結(jié)構(gòu)(MSG)為:
typedef struct tagMSG{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
}MSG;
其中第一個(gè)成員變量是用以標(biāo)識接收消息的窗口的窗口句柄;第二個(gè)參數(shù)便是消息標(biāo)識號,如WM_PAINT;第三個(gè)和第四個(gè)參數(shù)的具體意義同message值有關(guān),均為消息參數(shù)。前四個(gè)參數(shù)是非常重要和經(jīng)常用到的,至于后兩個(gè)參數(shù)則分別表示郵寄消息的時(shí)間和光標(biāo)位置(屏幕坐標(biāo))。
把消息傳送到應(yīng)用程序有兩種方法:一種是由系統(tǒng)將消息“郵寄(post)”到應(yīng)用程序的“消息隊(duì)列”這是“進(jìn)隊(duì)消息”Win32 API有對應(yīng)的函數(shù):PostMessage(),此函數(shù)不等待該消息處理完就返回;而另一種則是由系統(tǒng)在直接調(diào)用窗口函數(shù)時(shí)將消息“發(fā)送(send)”給應(yīng)用程序的窗口函數(shù),屬于“不進(jìn)隊(duì)消息”對應(yīng)的函數(shù)是SendMessage()其必須等待該消息處理完后方可返回。消息是在消息循環(huán)中被處理的,下面這段代碼就是一個(gè)典型的消息循環(huán):
MSG msg; //定義消息名
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ; //翻譯消息
DispatchMessage (&msg) ; //撤去消息
}
return msg.wParam ;
消息循環(huán)以GetMessage調(diào)用開始,它從消息隊(duì)列中取出一個(gè)消息。該函數(shù)的四個(gè)參數(shù)可以有控制地獲取消息,第一個(gè)參數(shù)指定要接收消息的MSG結(jié)構(gòu)的地址,第二個(gè)參數(shù)表示窗口句柄,一般將其設(shè)置為空,表示要獲取該應(yīng)用程序創(chuàng)建的所有窗口的消息;第三、四參數(shù)用于指定消息范圍。后面三個(gè)參數(shù)被設(shè)置為默認(rèn)值,用于接收發(fā)送到屬于這個(gè)應(yīng)用程序的任何一個(gè)窗口的所有消息。在接收到除WM_QUIT之外的任何一個(gè)消息后,GetMessage()返回TRUE;如果GetMessage收到一個(gè)WM_QUIT消息,則返回FALSE以退出消息循環(huán),終止程序運(yùn)行。因此,在接收到WM_QUIT之前,帶有GetMessage()的消息循環(huán)可以一直循環(huán)下去。
當(dāng)除WM_QUIT的消息用GetMessage讀入后,首先要經(jīng)過函數(shù)TranslateMessage()對其進(jìn)行解釋,但對大多數(shù)消息來說并不起什么作用。這里起關(guān)鍵作用的是DispatchMessage()函數(shù),把由GetMessage獲取的Windows消息傳送給在MSG結(jié)構(gòu)中為窗口所指定的窗口過程。在消息處理函數(shù)處理完消息之后,代碼又循環(huán)到開始去接收另一個(gè)消息,這樣就完成了一個(gè)完整的消息循環(huán)。
本文將設(shè)計(jì)一個(gè)主控程序和一個(gè)底層工作程序,由主控程序通過消息來控制底層工作程序的工作狀態(tài)。這里首先對主控程序的設(shè)計(jì)過程進(jìn)行介紹:
首先創(chuàng)建一個(gè)單文檔工程,添加三個(gè)菜單“命令一”、“命令二”、“命令三”及與之對應(yīng)的命令響應(yīng)函數(shù):
OnSendComm1()
{
CString str="Receiver";
CWnd *pWnd=CWnd::FindWindow(NULL,str);
if(pWnd)
pWnd->SendMessage(WM_COMM,0,0);
}
OnSendComm2()
{
CString str="Receiver";
CWnd *pWnd=CWnd::FindWindow(NULL,str);
if(pWnd)
pWnd-〉SendMessage(WM_COMM,0,1);
}
OnSendComm3()
{
CString str="Receiver";
CWnd *pWnd=CWnd::FindWindow(NULL,str);
if(pWnd)
pWnd-〉SendMessage(WM_COMM,1,0);
}
這里,WM_COMM是自定義消息,用于在主控程序和底層通信程序之間進(jìn)行聯(lián)系,為了能夠使用該消息,必須首先添加預(yù)定義語句:
#define WM_COMM WM_USER + 100
上述幾個(gè)函數(shù)的結(jié)構(gòu)沒有什么區(qū)別,首先通過FindWindow()返回由str變量指定窗口標(biāo)題的應(yīng)用程序主窗口句柄并將其保存到pWnd。然后再通過該句柄調(diào)用SendMessage()函數(shù)并發(fā)送剛才定義的WM_COMM消息及其消息參數(shù)。如果函數(shù)被正確執(zhí)行,底層程序?qū)⑹盏絹戆l(fā)自主控程序的WM_COMM消息并可在消息響應(yīng)函數(shù)中完成對消息參數(shù)的判斷處理以及進(jìn)一步的操作。
最后,來介紹一下底層工作程序的實(shí)現(xiàn)過程。底層工作程序也是一個(gè)單文檔應(yīng)用程序(當(dāng)然,對于多文檔應(yīng)用程序也是一樣)。由于主控程序是通過對應(yīng)用程序主窗口標(biāo)題的捕獲來得到底層程序主窗口句柄的。因此需要在底層工作程序應(yīng)用類的初始化應(yīng)用函數(shù)InitInstance()中添加(在函數(shù)末尾添加)下面語句:
m_pMainWnd-〉SetWindowText("Receiver");
以設(shè)置底層工作程序的窗口標(biāo)題。同時(shí)還要在主框架類的頭文件MainFrm.h中添加與主控程序一樣的自定義消息定義:
#define WM_COMM WM_USER+100
由于底層程序需要接收并響應(yīng)主控程序發(fā)出的通知消息,因此還要在底層工作程序中添加對自定義消息WM_COMM的響應(yīng)處理:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code !
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_COMM,OnSendMsg)
END_MESSAGE_MAP()
……
void CMainFrame::OnSendMsg(WPARAM wParam, LPARAM lParam)
{
if(wParam==0 && lParam==0)
AfxMessageBox("主控程序發(fā)送命令一!");
if(wParam==0 && lParam==1)
AfxMessageBox("主控程序發(fā)送命令二!");
if(wParam==1 && lParam==0)
AfxMessageBox("主控程序發(fā)送命令三!");
}
此后就可以通過辨別消息的兩個(gè)消息參數(shù)來區(qū)分主控程序發(fā)送的是哪一個(gè)命令從而可以執(zhí)行相應(yīng)的操作。執(zhí)行主控程序和底層工作程序由于本程序采用的是SendMessage()所以當(dāng)主控程序發(fā)送消息給底層工作程序時(shí),底層工作程序彈出響應(yīng)的模式對話框,在沒有關(guān)閉對話框前此消息未處理完,SendMessage()也就沒有執(zhí)行完,所以主控程序呈阻塞狀態(tài),如改用PoseMessage()則不會發(fā)生阻塞,具體選用哪個(gè)函數(shù)還應(yīng)根據(jù)實(shí)際要求靈活掌握。
結(jié)論:
通過上面的實(shí)例可以看出利用消息進(jìn)行進(jìn)程間通信不失為一種便捷的方法,進(jìn)程間的數(shù)據(jù)交換量不大卻能完成相當(dāng)?shù)墓δ?上下層次有著明顯的接口,上層和底層只通過這個(gè)接口進(jìn)行通訊,因此只要對上下層程序制定好規(guī)范詳盡的協(xié)議便可編制出協(xié)調(diào)性很好的軟件控制系統(tǒng)。