VC入門學習---MFC傳輸自定義消息並響應自定義消息

發送自定義消息
                                    
說明:
以下用一個自創的對話框類(MyMessageDlg)向視圖類(MessageTestView)
發送自定義消息爲例,說明這兩種不同方法的自定義消息的
 
總結:
消息傳遞的方法一:使用ON_MESSAGE
使用ON_MESSAGE響應消息,必須配合定義消息#define WM_MY_MESSAGE (WM_USER+100)
對於發送消息者-MyMessageDlg,
在其MyMessageDlg.h中,定義#define WM_MY_MESSAGE (WM_USER+100)
在其MyMessageDlg.cpp中要先添加:#include "MainFrm.h"
因爲使用了CMainFrame*定義對象。
並且要有測試消息的函數:
void MyMessageDlg::OnButtonMsg() 
{
    // TODO: Add your control notification handler code here
    CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd;  //先通過獲取當前框架指針
    CView * active = pMF->GetActiveView();//才能獲取當前視類指針
    if(active != NULL)  //獲取了當前視類指針才能發送消息
    active->PostMessage(WM_MY_MESSAGE,0,0);   //使用PostMessage發送消息
}
對於消息的接受者-MessageTestView,
在其MessageTestView.h中,也要定義#define WM_MY_MESSAGE (WM_USER+100)
並定義消息映射函數-OnMyMessage()
protected:
 //{{AFX_MSG(CMessageTestView)
 afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); 
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
在其MessageTestView.cpp中,
先要聲明響應消息:
BEGIN_MESSAGE_MAP(CMessageTestView, CEditView)
 //{{AFX_MSG_MAP(CMessageTestView)
 ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
 //}}AFX_MSG_MAP
再添加消息響應的函數實現:
LRESULT CMessageTestView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
 MessageBox("OnMyMessage!");
 return 0;
}
 
消息傳遞的方法二:使用ON_REGISTERED_MESSAGE
使用ON_REGISTERED_MESSAGE註冊消息,必須配合
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
對於消息的發送者-MyMessageDlg,
在其MyMessageDlg.h中,只要
定義static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
就可以了。
在其MyMessageDlg.cpp中要先添加:#include "MainFrm.h"
因爲使用了CMainFrame*定義對象。
並且要有測試消息的函數:
void MyMessageDlg::OnButtonMsg() 
{
    // TODO: Add your control notification handler code here
    CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd;  //先通過獲取當前框架指針
    CView * active = pMF->GetActiveView();//才能獲取當前視類指針
    if(active != NULL)  //獲取了當前視類指針才能發送消息
    active->PostMessage(WM_MY_MESSAGE,0,0);   //使用PostMessage發送消息
}
對於消息的接收者-MessageTestView,
在其MessageTestView.h中不要定義
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
應該把這個定義放到MessageTestView.cpp中,要不會出現: redefinition
在其MessageTestView.h中只要定義消息映射函數
protected:
 //{{AFX_MSG(CMessageTestView)
 afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); 
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
在其MessageTestView.cpp中,先定義
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
接着註冊消息:
BEGIN_MESSAGE_MAP(CMessageTestView, CEditView)
 //{{AFX_MSG_MAP(CMessageTestView)
        ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage)
 //}}AFX_MSG_MAP
最後添加消息響應的函數實現:
LRESULT CMessageTestView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
 MessageBox("OnMyMessage!");
 return 0;
}
----------------------------------------------------------------
比較兩種方法,只是略有不同。但也要小心謹慎,以免出現接收不到消息的情況。
-------------------------------------------------------------------
其他注意事項:
發送消息的-MyMessageDlg.cpp前也要定義
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
接受消息的-MessageTestView.cpp前也要定義
static UINT WM_MY_MESSAGE=RegisterWindowMessage("Message");
RegisterWindowMessage("Message")中""的內容是什麼不重要,寫什麼都可以,單必須
發送者與接受者是一樣的內容,例如:"Message"
小心的使用消息傳送--傳送給多個View類時需要引起注意的一個問題
 
我的前一篇文章裏說的是關於《兩種自定義消息的發送與接收的方法實現》
可當我在一次使用消息傳送的時候也遇到一個讓人迷惑的問題,
好在最後解決了。
-------------------------------------------------------------
原來我對於一個消息的傳送也做過,使用的是
    CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd; // 通過獲取當前框架指針
    CView * active = pMF->GetActiveView();// 獲取當前視類指針
    if(active != NULL)  
    active->PostMessage(WM_MY_MESSAGE,0,0);   // 使用PostMessage發送消息
來發送我定義的消息的。
很順利的,我就在要接收的View類裏接收到了該消息。
可是當一個類中定義了2個自定義的消息,並要分別發送給兩個不同的View視圖類的時候,
如果還般照上面的代碼,就要出一些問題了。
爲什麼說是照搬就會出現問題呢?
請注意一個地方:
上面的代碼中,是如何得到View類的指針的。
對,就是使用的函數GetActiveView(),這個函數的作用是獲得"當前"視圖指針。
我之所以出問題,使得其中的一個View類不能接收到消息也就是這個原因。
------------------------------------------------------------
下面詳細說明我出錯的過程和解決過程。
來源:一個SDI被我用靜態切分的方式,且分成左右大小相等的兩個部分,並使這兩個部分分別指向自行創建的兩個新類:CMyLeftView和CMyRightView,它們的基類都是CEditView。所以說這兩個準備接收消息的視圖類除了名字,其他並沒有什麼不太一樣的地方。
一個對話框(CMyFindDialog類),其上有2個RADIO BUTTON控件,和一個確定按鈕,
這兩個RADIO BUTTON控件在選擇的時候,使其只能進行單選,他們也就分別對應於前面所說的左右兩個部分,選擇後,點擊確定按鈕,便表示向 哪個視圖發送消息。
做好了發送和接收部分,運行發現只能有一個消息被接收到,
void CMyFindDialog::OnButtonFind() 
{   MainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd;
    CView* active = pMF->GetActiveView();//獲取當前視類指針
    // 錯就錯在上一句得到的active是個 “不確定“ 的對象。
    if(m_selLeft == TRUE)
       {  if(active != NULL)  
              active->PostMessage(WM_MY_MESSAGE_LEFT,0,0);  
       }
     else if(m_selRight == TRUE)
      {  if(active != NULL)  
            active->PostMessage(WM_MY_MESSAGE_RIGHT,0,0);
      } 
     else
           MessageBox("MUST CHOOSE ONE!"); 
}
通過GetActiveView()得到的當前視類指針,那麼
如果你打開對話框之前,焦點(光標)在左邊,那麼就是左邊能接收到消息,右邊怎麼也接收不到。
如果你打開對話框之前,焦點(光標)在右邊,那麼就是右邊能接收到消息,左邊怎麼也接收不到。
程序運行後,焦點(光標)默認的是在左邊,這也就導致我總一爲是右邊的接收消息的部分有問題。
其實,如果在程序運行後,先把焦點(光標)改換到右邊,再打開對話框測試發送與接收,就成了
左邊收不到消息,右邊可以收到消息。(這還是在論壇中,別人的話提醒了,才找到了錯誤的所在。要不然還在考慮是不是接收部分出了問題。)
對於這樣一個向2個View類發送消息問題,就是要注意你所執行發送(PostMessage)的對象是誰!
正確的代碼如下:
void CMyFindDialog::OnButtonFind() 
{   CMainFrame* pMF=(CMainFrame*)AfxGetApp()->m_pMainWnd;
     CMyLeftView* pLV=(CMyLeftView*)pMF->m_wndSplitter.GetPane(0,0);
     CMyRightView* pRV=(CMyRightView*)pMF->m_wndSplitter.GetPane(0,1);
   // 對於我這個題,是通過切分對象m_wndSplitter的GetPane函數得到它實際並確定的
   // 視圖類指針的。
   // 如果你也是多個視圖類,但不是切分,而是別的,只要注意
   // 獲得的是個你確定視圖對象指針。
    if(m_selLeft == TRUE) 
     {  if(pLV != NULL)  
             pLV->PostMessage(WM_MY_MESSAGE_LEFT,0,0);  
     }
    else if(m_selRight == TRUE)
       {  if(pRV != NULL)  
               pRV->PostMessage(WM_MY_MESSAGE_RIGHT,0,0);
       } 
    else
           MessageBox("MUST CHOOSE ONE!"); 
}
總結:
當你需要發送消息給多個視圖對象的時候,要考慮你是向什麼樣的視圖對象發送消息。
如果你就是向多個視圖對象中當前的視圖對象發送消息,那麼我原本“出錯”的那個
方法對於你來說就是正確的。
但如果你不是向當前視圖對象發消息,而是有個明確的目標,那麼千萬要注意,通過
某種方法一定要得到確定的視圖指針,
那麼用  (View*)->PostMessage( , , )發送消息的時候,
接收方纔能接收的到你的消息。
如何在自定義消息中傳遞字符串呢(我有一種方法)?
 發送方:   
  CString   mystr   ;   
  char   *buf   ;   
  buf   =   (   char   *   )   new   char[   100   ]   ;   
  mystr   =   "謝謝wtzyb4446(不死鳥)   、stonespace(stonespace)   具體的在下面:”;   
  strcpy(   buf,   mystr   );   
  ::SendMessage(   pFrame->m_wndWorkspace.GetActiveView()->GetSafeHwnd(),   WM_USER_QUERY   ,   (WPARAM)buf,(LPARAM)mystr.GetLength());   
    
  接收方:   
  char   *   dd   ;   
  dd   =   (   char   *   )wParam   ;   
  int   num   =   (int)lParam   ;   
  for(   int   i   =   0   ;   i   <   num   ;   i   ++   )   
  {   
      str   +=   dd[   i   ];   
  }   
  delete   dd   ; 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章