mfc中的訊息的應用 (轉)

worldblog發表於2008-01-06
mfc中的訊息的應用 (轉)[@more@]

 mfc中的訊息莫是相對於虛表來說到底有什麼優勢?有人說是空間上面有好處。既可以省下長長的虛擬函式表的。比如:
 用虛擬函式的話,window的基類會是
 class window
 {
 virtual OnSize() = 0;
 virtual OnMove() = 0;
 virtual OnContextMenu() = 0;
 ……等等
 }
 可想而知,每個由此繼承而來的子類將會負擔多麼大的虛擬函式表,光是自帶的就有數十個之多。當然不可取。
 
 可是除此之外,似乎有一種觀點是如果機器夠快的話就可以採用虛擬函式的方法了,哪隻不不過是ms在當年的無奈之舉。嗬嗬,真的是這樣嗎?非也!
 其一、如果有自定義的訊息怎麼辦?修改基類?
 其二、其實在視窗間互相傳遞訊息可以看成是互相的請求服務,此服務被請求窗體可以響應,也可以不響應。這種靈活性是虛擬函式方法所無法取得的——如果不支援的話,嗬嗬,對不起,編譯時便會報錯了。請求方對於被請求方的所有要求僅僅是其是CCmdTarget的子類即可。怎麼樣,正所謂便宜實惠量又足啊。可就是不太好理解,所以ms提供了許多宏來做這件事情。 
 
 下面看一個具體的例子。這是一個關於treectrl操作的例子。這是一棵表示公司組織的樹,上面的節點有
 公司
  ----人事科
  -----張三
  -----李四 
  ----採購 
 -----王二
 -----麻子
 
 即三類節點,公司、科室、員工
 
 當客戶右擊滑鼠時,對於不同的節點彈出的選單當然是不同的。 
 做法1、判斷三種節點的圖示,(假定用不同的圖示顯示不同節點)然後針對不同的情況彈出選單。這種方法對於顯然不妥,有點像經典的
 if ( obj.typeid == ...)
 do something
 else if ( obj.typeid == .. )
 do somthine else ...
 結果就是在treectrl的程式碼中充滿了這樣的判斷程式碼
 
 做法2、有class Company, class , class person,均從CCmdTarget繼承。當insert treeitem的時候,產生,將其指標和插入的item聯絡起來,方法可以採用SetItemData(物件的指標),這樣的話,處理彈出選單的方法就變為
 treectrl::OnContextMenu(...)
 {
 CCmdTarget* p = GetItemData(hSelItem);
 p->sendcommand(wm_contextmenu, point)
 }
 這樣就ok了。但是有一個缺點,佔用太多的記憶體了!每個item都有多出sizeof(CCmdTarget),有點過分。
 再改進——做法3
 class Company, office, person不變,
 但增加他們的工廠類
 
 class treeitemor
 {
 virtual CCmdTarget* CreateItem() = 0;
 }
 class Companyor
 {
 long m_ID;
 virtual CmdTarget* CreateItem(); //產生Company類
 }
 class office和person同上
 
 彈出選單變為
 treectrl::OnContextMenu(...)
 {
 treeItemor* ItemCreator = GetItemData(hSelItem);
 CCmdTarget *pCmd = ItemCreator->CreateItem();
 pCmd->SendCommand(WM_CONTEXTMENU, POINT);
 }
 
 呼!總算完了。最後請大家多提意見!

 

 
 


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

相關文章