MFC 如何添加自定義消息


 

MFC 如何添加自定義消息

分類: MFC
MFC如何添加自定義消息
 
 
 
 
 

如果用戶自定義的類要求響應普通的Windows消息(也就是以WM_開頭,除了WM_COMMAND以外的消息,這類消息在WM_USER以下的是系統消息,WM_USER以上的可以由用戶自己定義),那就要求自定義的類必須從CWnd中派生。這是由於此類消息的處理機制決定的,這類消息沒有命令消息那條繁瑣的流動路徑,而是消息發出者直接發給對應

      CWnd的窗體句柄,由CWnd負責消息的響應。所以這類消息必須同一個CWnd類對應,更精確的說必須與一個HWND類型的窗體句柄相對應。這樣得出一個重要的結論,就是從CCmdTarget中派生而沒有從CWnd派生的類沒有處理此類消息的能力。

     綜上所述,就是為什么命令消息可以放到大部分類中處理,包括CWinThread、CWinApp、CDocument、CView、CFrameWnd或是自定義的類中,而普通Windows消息和用戶自定義的消息只能放到CFrameWnd和CView等派生與CWnd中的類中處理。

      由此可見,我們自定義的類要想響應自定義消息就只能從CWnd中派生(當然不響應任何消息的類可以從CObject中派生)。先來看看如何自定義消息:

在.h中做的工作:

第一步要聲明消息:

#define WM_MYMSG WM_USER+8

第二步要在類聲明中聲明消息映射:

DECLARE_MESSAGE_MAP()

第三步要在類聲明中定義消息處理函數:

afx_msg LRESULTMyMsgHandler(WPARAM,LPARAM);

在.cpp中做的工作:

第四步要實現消息映射:

BEGIN_MESSAGE_MAP(CMainFrame,CMDIFrameWnd)

ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)

END_MESSAGE_MAP()

第五步要實現消息處理函數(當然可以不實現):

LRESULTCMainFrame::OnMyMsgHandler(WPARAM w,LPARAM l)

{

AfxMessageBox("Hello,World!");

return 0;

}

在引發或發出消息的地方只用寫上:

::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0);

到此,自定義消息完畢,這是好多網上文章都寫的東西。大家會發現上面代碼是在CMainFrame類中實現的,但是如果要用自定義類,就沒有那么簡單了。顯然把第四步與第五步的CMainFrame換成自定義的類名(這里我用CMyTestObject來代表自定義類)是不能正常工作的。原因在於在發送消息的SendMessage函數中的第一個參數是

要響應消息對應的HWND類型的窗體句柄,而CMyTestObject類中的m_hWnd中在沒有調用CWnd::Create之前是沒有任何意義的,也就是沒有調用CWnd::Create或CWnd::CreateEx函數時,CWnd不對應任何窗體,消息處理不能正常運作。

所以,又一個重要的結論,在自定義類能夠處理任何消息之前一定要確保m_hWnd關聯到一個窗體,即便這個窗體是不可見的。那么有人說,在自定義類的構造函數中調用Create函數就行了,不錯,當然也可以在別處調用,只要確保在消息發送之前。但是,Create的調用很有說法,要注意兩個地方,第一個參數是類的名稱,我建議最好設為NULL;第五個參數是父窗體對象的指針,這個函數指定的對象一定要存在,我建議最好為整個程序的主窗體。還有很多人問第六個參數的意義,這個參數關系不大,是子窗體ID,用於傳給父窗體記錄以便識別。如下是我

的自定義類的構造函數:

CMyTestObject::CMyTestObject()

{

CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),::AfxGetMainWnd(),1234);

}   //一定要在生成主窗體后使用,在主窗體完成OnCreate消息的處理后

CMyTestObject::CMyTestObject(CWnd*pParent)

{

CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),pParent,1234);

}

不能如下調用Create,因為此時CMyTestObject不關聯任何窗體,所以this中的m_hWnd無效:

CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),this,1234);

這時上面四、五兩步修改成:

BEGIN_MESSAGE_MAP(CMyTestObject,CWnd)

ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)

END_MESSAGE_MAP()

LRESULTCMyTestObject::OnMyMsgHandler(WPARAM w,LPARAM l)

{

AfxMessageBox("My Messge Handler in MySelf-Custom Class!");

return 0;

}

在類外部發出消息:

CMyTestObject *test=newCMyTestObject();

::SendMessage(test->m_hWnd,WM_MYMSG,0,0);

在類內部某個成員函數(方法)中發出消息:

::SendMessage(m_hWnd,WM_MYMSG,0,0);

最后一個問題便是容易產生警告錯誤的窗體回收,自定義的類要顯式調用窗體銷毀,析構函數如下:

CMyTestObject::~CMyTestObject()

{

CWnd::DestroyWindow();

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM