形形色色的自定義消息(下)

 在前面,我們討論了自身類中消息的傳遞方法和成組的消息傳遞,接下來的問題就是如何向不同的類中傳遞消息。其實在《解析VC++6中的指針 》中,我們討論瞭如何在不同的類中獲取其他類的指針的方法,,我們借用這種獲取指針的方法就可以輕鬆的隨心所欲的在各個類中傳遞消息了。
  首先,定義消息的方式和我們在上面所說的是一樣的(例如在框架類中向視圖類發送消息):
  (1)在視圖類.cpp中定義消息值: #define WM_MSG  (WM_USER+101)
  (2)首先在AFX_MSG塊中加入消息聲明:在CMyView.h中,找到如下部分,並加入消息聲明:
     protected:    
      // {{AFX_MSG(CMyView)
      ......
      afx_msg LRESULT OnMyMsg(WPARAM wParam,LPARAM lParam);
      file://}}AFX_MSG
   (3)在MESSAGE_MAP塊中添加ON_MESSAGE宏指令:
      BEGIN_MESSAGE_MAP(CMyView, CView)
       file://{{AFX_MSG_MAP(CMyView)
        .....
       ON_MESSAGE(WM_MSG, OnMyMsg)
       file://}}AFX_MSG_MAP
      END_MESSAGE_MAP()
   (4)添加消息函數體:
     LPESULT CMyView::OnMyMsg(WPARAM wParam, LPARAM lParam)
     {
       AfxMessageBox("消息已經收到!");
       return 0;
     }
   (5)在主框架中加入測試函數
    void CMainFrame::OnTestMsg()
    {
      CView * pView = GetActiveView();//獲取當前視類指針
      if(pView!=NULL) pView->PostMessage(WM_MSG,0,0);
    }
   這裏,我們看到了,只要我們有辦法獲得發送消息的目標類的指針,我們就可以任意的發送消息,參考我在《解析VC++6中的指針 》一文中的方法,Let's go!

   與其他應用程序通信
   前面我們講的消息傳遞都是基於同一個應用程序的,但是在某些情況下我們可能需要向其他的應用程序發送消息,這時候我們可以採用SendMessage()函數向目標應用程序的某個窗口的句柄發送消息。其中的技巧在於獲取該窗口的句柄。同時使用RegisterWindowMessage()函數創建一個唯一的消息,並且兩個應用程序相互都瞭解這條消息的含義。同時還會用到BrodcastSystemMessage()函數,它可以向系統中的每個應用程序的主窗口發送消息。這樣便可以避免出現獲取另一個應用程序窗口句柄的問題。BroadcastSystemMessage()函數提供了附加的標誌BSF_LPARAMPOINTER,可以將寫入參數lParam的指針轉化爲可以被目標程序用來訪問程序空間的指針,但是這個標誌可能尚未進行文檔標準化。
   方法如下:
   首先註冊自己的窗口消息。不過我們這次不用WM_USER+1的技術,註冊窗口消息的好處是不必費心考慮WM_USER加上某個數之後,所表示的消息標識符是否超出工程的允許範圍。本例在兩個工程中都使用文本字符串來註冊消息。由於這個文本字符串在整個系統中應當是唯一的,因此將使用一種稱爲GUID的COM技術來命名消息。GUID名字生成器程序可以在MFC的BIN目錄下找到,其可執行文件名爲GUIDGEN.EXE。該程序將生成在應用程序已知範圍內認爲是唯一的文本字符串,這對應用程序來說當然是最好不過的。
1) 註冊一個唯一的窗口消息
使用GUIDGEN.EXE生成一個GUID。
在應用程序中把GUID定義爲窗口消息文本字符串:#define HELLO_MSG “{6047CCB1-E4E7-11d1-9B7E-00AA003D8695}”
使用::RegisterWindowsMessage()註冊該窗口消息文本字符串:idHelloMsg = ::RegisterWindowMessage( HELLO_MSG );
保存消息標識符idHelloMsg,便於以後使用。
2) 向其他應用程序發送消息
使用::RegisterWindowsMessage()返回的消息標識符發送消息,可使用以下代碼:
::SendMessage(hWnd, idHelloMsg,wParam,lParam);
以上代碼假定事先可以通過某種方式獲取目標應用程序的某個窗口的句柄。一個指向CWnd類的指針不能在程序範圍之外而發揮作用。但是可以在CWnd 類中封裝已獲取的窗口句柄,並如下所示來發送消息:
CWnd wnd;
wnd.Attach( hWnd );
wnd.SendMessage( idHelloMsg,wParam,lParam );
3) 接收已註冊的窗口消息
爲接收已註冊的窗口消息,需要在接收窗口類,一般爲CMainFrame中手工添加ON_REGISTERED_MESSAGE消息宏到消息映射中:
BEGIN_MESSAGE_MAP( CMainFrame, CMDIFrameWnd )
// {{AFX_MSG_MAP( CMainFrame )
// }}AFX_MSG_MAP
ON_REGISTERED_MESSAGE( idHelloMsg,OnHelloMsg )
END_MESSAGE_MAP()
有關已註冊消息的消息處理函數的代碼如下:
LRESULT CMainFrame::OnHelloMsg( WPARAM wParam,LPARAM lParam )
{
// process message
return 0;
}
該實例到目前爲止,一直假定事先可以通過某種方式取得目標應用程序的某個窗口的句柄。但這是一個困難的任務。簡單的方法是向每個應用程序廣播一條消息,並且希望目標程序正在監聽。由於在系統中註冊了一條唯一的消息,因此只有目標程序會響應這條消息。應用程序廣播的消息可能是它自己的窗口句柄,於是接收程序可以使用::SendMessage()來發送應答,也可能是用窗口句柄來結束循環。
4) 廣播窗口消息
使用下面的代碼廣播窗口消息:
WPARAM wParam = xxx;
LPARAM lParam = xxx;
DWORD dwRecipients = BSM_APPLICATIONS;
::BroadcastSystemMessage( BSF_IGNORECURRENTTASK,&dwRecipients,idHelloMsg,wParam,lParam );  
 更多分享請關注:軟信網-編程-http://www.iis365.net.cn

發佈了13 篇原創文章 · 獲贊 5 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章