內部進程間通訊和數據交換有多種方式:消息、共享內存、匿名(命名)管道、郵槽、Windows套接字等多種技術。其中利用消息機制實現IPC雖然同其他方法相比有交換的數據量小、攜帶的信息少等缺點,但由於其實現方便、應用靈活而廣泛應用於無須大量、頻繁數據交換的內部進程通訊系統之中,尤其是對於在上層主控軟件與底層工作軟件之間的命令與響應上更能充分顯示其良好的性能。本文就通過編制一個主控軟件和一個受其操作的底層工作軟件來闡述如何用VC++6.0通過消息來實現內部進程通信。
一、Windows消息機制
Windows是一種面向對象的體系結構,Windows環境和應用程序都是通過消息來交互的。Windows應用程序開始執行後,Windows為該程序創建一個"消息隊列(message queue)",用以存放郵寄給該程序可能創建的各種不同窗口的消息。消息隊列中消息的結構(MSG)為:
typedef struct tagMSG{
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWord time;
POINT pt;
}MSG;
其中第一個成員變量是用以標識接收消息的窗口的窗口句柄;第二個參數便是消息標識號,如WM_PAINT;第三個和第四個參數的具體意義同message值有關,均為消息參數。前四個參數是非常重要和經常用到的,至於後兩個參數則分別表示郵寄消息的時間和光標位置(屏幕坐標)。把消息傳送到應用程序有兩種方法:一種是由系統將消息"郵寄(post)"到應用程序的"消息隊列"這是"進隊消息"Win32 API有對應的函數:
PostMessage(),此函數不等待該消息處理完就返回;而另一種則是由系統在直接調用窗口函數時將消息"發送(send)"給應用程序的窗口函數,屬於"不進隊消息"對應的函數是SendMessage()其必須等待該消息處理完後方可返回。
二、主控程序的實現
(1)新建一工程文件:Sender,選取MFC AppWizard(exe)。
(2)第二步選取Single document(單文檔)。
(3)其余幾步均為確省值。
(4)添加三個菜單"命令一"、"命令二"、"命令三"及與之對應的函數:
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);
}
(5)在SenderVIEw.h中添加自定義消息:#define WM_COMM WM_USER+100編譯完成即可。
三、底層工作程序的實現
(1)新建工程Receiver、仍是單文檔。
(2)在CReceiverApp類的InitInstance()函數末尾添加:
m_pMainWnd->SetWindowText("Receiver");
用以指定底層工作程序的窗口標題,以便主控程序能根據標題獲取到此窗口的窗口句柄。
(3)在MainFrm.h中添加自定義消息:#define WM_COMM WM_USER+100。
(4)添加自定義消息WM_COMM的消息映射:
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()
(5)完成消息響應函數OnSendMsg()
void CMainFrame::OnSendMsg(WPARAM wParam, LPARAM lParam)
{
if(wParam==0 && lParam==0)
AfxMessageBox("主控程序發送命令一!");
if(wParam==0 && lParam==1)
AfxMessageBox("主控程序發送命令二!");
if(wParam==1 && lParam==0)
AfxMessageBox("主控程序發送命令三!");
}
我們便可以通過辨別消息的兩個消息參數來區分主控程序發送的是哪一個命令從而可以執行相應的操作。執行主控程序和底層工作程序由於本程序采用的是SendMessage()所以當主控程序發送消息給底層工作程序時,底層工作程序彈出響應的模式對話框,在沒有關閉對話框前此消息未處理完,SendMessage()也就沒有執行完,所以主控程序呈阻塞狀態,如改用PoseMessage()則不會發生阻塞,具體選用哪個函數還應根據實際要求靈活掌握。
結論: 通過上面的實例可以看出利用消息進行進程間通信不失為一種便捷的方法,進程間的數據交換量不大卻能完成相當的功能,上下層次有著明顯的接口,上層和底層只通過這個接口進行通訊,因此只要對上下層程序制定好規范詳盡的協議便可編制出協調性很好的軟件控制系統。