【轉(zhuǎn)】MFC中用戶自定義類響應(yīng)自定義消息 2009-08-13 17:15:11| 分類: MFC學(xué)習(xí) | 標(biāo)簽: |字號大中小 訂閱
隨處可見。網(wǎng)上眾多的討論都是關(guān)于如何響應(yīng)并進(jìn)行用戶自定義消息映射的,;網(wǎng)上還有一些文章介紹如何在自定 義類中響應(yīng)Windows消息,,在本文中都簡略敘述。但是,,網(wǎng)上大部分的文章沒用透徹闡述如何在用戶自定義類中 響應(yīng)自定義消息這一通用方法,。 某個自定義消息,。 首先能夠響應(yīng)消息的類必須都從CCmdTarget類中派生,因?yàn)橹挥幸赃@個類中提供了消息的框架和處理機(jī)制,,而 CWnd類也派生與此類,。CWinApp類、CDocument類,、CDocTemplate類等都是CCmdTarget的派生類,,即子類;而 CFrameWnd類,、CView類、CDialog類等都是從CWnd中派生的,,其實(shí)也是CCmdTarget的子孫,,所以都能夠響應(yīng)消息 ,,但是響應(yīng)消息的種類不太相同。 那么,,如果自己定義的類要求響應(yīng)命令消息(就是WM_COMMAND,,也就是一些菜單、工具欄中的消息,,包括快捷鍵 ,,這類消息處理的機(jī)制與其他以WM_開頭的消息處理機(jī)制不同,它具有一條層次明確的消息流動路徑),,那么自 定義的類可以從CCmdTarget中派生,。由于CWnd窗體類派生于CCmdTarget父類,那么從CWnd中派生的類也可以理所 應(yīng)當(dāng)?shù)捻憫?yīng)命令消息,。這種命令消息無論是往已有的一些諸如CWinApp類中還是自定義的類中添加都是一件非常 容易的事情,,只需用向?qū)Ъ纯桑诖瞬辉贁⑹觥?/p> 如果用戶自定義的類要求響應(yīng)普通的Windows消息(也就是以WM_開頭,,除了WM_COMMAND以外的消息,,這類消息在 WM_USER以下的是系統(tǒng)消息,WM_USER以上的可以由用戶自己定義),,那就要求自定義的類必須從CWnd中派生,。這 是由于此類消息的處理機(jī)制決定的,這類消息沒有命令消息那條繁瑣的流動路徑,,而是消息發(fā)出者直接發(fā)給對應(yīng) CWnd的窗體句柄,,由CWnd負(fù)責(zé)消息的響應(yīng)。所以這類消息必須同一個CWnd類對應(yīng),,更精確的說必須與一個HWND類 型的窗體句柄相對應(yīng),。這樣得出一個重要的結(jié)論,就是從CCmdTarget中派生而沒有從CWnd派生的類沒有處理此類 消息的能力,。 綜上所述,,就是為什么命令消息可以放到大部分類中處理,包括CWinThread,、CWinApp,、CDocument、CView,、 CFrameWnd或是自定義的類中,,而普通Windows消息和用戶自定義的消息只能放到CFrameWnd和CView等派生與CWnd 中的類中處理。 由此可見,,我們自定義的類要想響應(yīng)自定義消息就只能從CWnd中派生(當(dāng)然不響應(yīng)任何消息的類可以從CObject 中派生),。先來看看如何自定義消息: 在.h中做的工作: 第一步要聲明消息: #define WM_MYMSG WM_USER+8 第二步要在類聲明中聲明消息映射: DECLARE_MESSAGE_MAP() 第三步要在類聲明中定義消息處理函數(shù): afx_msg LRESULT MyMsgHandler(WPARAM,LPARAM); 在.cpp中做的工作: 第四步要實(shí)現(xiàn)消息映射: BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 第五步要實(shí)現(xiàn)消息處理函數(shù)(當(dāng)然可以不實(shí)現(xiàn)): LRESULT CMainFrame::OnMyMsgHandler(WPARAM w,LPARAM l) 在引發(fā)或發(fā)出消息的地方只用寫上: ::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0); 到此,自定義消息完畢,這是好多網(wǎng)上文章都寫的東西,。大家會發(fā)現(xiàn)上面代碼是在CMainFrame類中實(shí)現(xiàn)的,,但是 如果要用自定義類,就沒有那么簡單了,。顯然把第四步與第五步的CMainFrame換成自定義的類名(這里我用 CMyTestObject來代表自定義類)是不能正常工作的,。原因在于在發(fā)送消息的SendMessage函數(shù)中的第一個參數(shù)是 要響應(yīng)消息對應(yīng)的HWND類型的窗體句柄,而CMyTestObject類中的m_hWnd中在沒有調(diào)用CWnd::Create之前是沒有 任何意義的,,也就是沒有調(diào)用CWnd::Create或CWnd::CreateEx函數(shù)時,,CWnd不對應(yīng)任何窗體,消息處理不能正常 運(yùn)作,。 所以,,又一個重要的結(jié)論,在自定義類能夠處理任何消息之前一定要確保m_hWnd關(guān)聯(lián)到一個窗體,,即便這個窗體 是不可見的,。那么有人說,在自定義類的構(gòu)造函數(shù)中調(diào)用Create函數(shù)就行了,,不錯,,當(dāng)然也可以在別處調(diào)用,只 要確保在消息發(fā)送之前,。但是,,Create的調(diào)用很有說法,要注意兩個地方,,第一個參數(shù)是類的名稱,,我建議最好 設(shè)為NULL;第五個參數(shù)是父窗體對象的指針,,這個函數(shù)指定的對象一定要存在,,我建議最好為整個程序的主窗體 。還有很多人問第六個參數(shù)的意義,,這個參數(shù)關(guān)系不大,,是子窗體ID,用于傳給父窗體記錄以便識別,。如下是我 的自定義類的構(gòu)造函數(shù): CMyTestObject::CMyTestObject() CMyTestObject::CMyTestObject(CWnd *pParent) 不能如下調(diào)用Create,因?yàn)榇藭rCMyTestObject不關(guān)聯(lián)任何窗體,,所以this中的m_hWnd無效: CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),this,1234); 這時上面四,、五兩步修改成: BEGIN_MESSAGE_MAP(CMyTestObject, CWnd) LRESULT CMyTestObject::OnMyMsgHandler(WPARAM w,LPARAM l) 在類外部發(fā)出消息: CMyTestObject *test=new CMyTestObject(); 在類內(nèi)部某個成員函數(shù)(方法)中發(fā)出消息: ::SendMessage(m_hWnd,WM_MYMSG,0,0); 最后一個問題便是容易產(chǎn)生警告錯誤的窗體回收,,自定義的類要顯式調(diào)用窗體銷毀,,析構(gòu)函數(shù)如下: CMyTestObject::~CMyTestObject()
|
|
來自: 成長中輝煌 > 《201404-展示》