形形色色的自定義訊息(下) (轉)

gugu99發表於2007-08-15
形形色色的自定義訊息(下) (轉)[@more@]

  在前面,我們討論了自身類中訊息的傳遞方法和成組的訊息傳遞,接下來的問題就是如何向不同的類中傳遞訊息。其實在《解析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);
  AFX_MSG
  (3)在MESSAGE_MAP塊中新增ON_MESSAGE宏指令:
  BEGIN_MESSAGE_MAP(CMyView, CView)
  AFX_MSG_MAP(CMyView)
  .....
  ON_MESSAGE(WM_MSG, OnMyMsg)
  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()函式提供了附加的標誌B_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}”
使用::RegisterMessage()註冊該視窗訊息文字字串: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;
D dwRecipients = BSM_APPLICATIONS;
::BroadcastSystemMessage( BSF_IGNORECURRENTTASK,&dwRecipients,idHelloMsg,wParam,lParam );

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-958617/,如需轉載,請註明出處,否則將追究法律責任。

相關文章