| CWnd::OnMeasureItem 
 說明: 當(dāng)控件被創(chuàng)建的時候,框架為自畫按鈕、組合框、列表框或菜單項調(diào)用這個成員函數(shù)。 重載這個函數(shù)并填充lpMeasureItemStruct指向的MEASUREITEMSTRUCT數(shù)據(jù)結(jié)構(gòu),然后返回;這將通知Windows控件的大小,并使Windows能夠正確地處理控件的用戶交互。 如果列表框或組合框是用LBS_OWNERDRAWVARIABLE或CBS_OWNERDRAWVARIA_BLE風(fēng)格創(chuàng)建的,則框架為控件中的每一個項調(diào)用這個函數(shù);否則這個函數(shù)只被調(diào)用一次。 在發(fā)送WM_INITDIALOG消息之前,Windows為用OWNERDRAWFIXED風(fēng)格創(chuàng)建的組合框和列表框的擁有者發(fā)出對 OnMeasureItem的調(diào)用。其結(jié)果是,當(dāng)擁有者接收到這個調(diào)用時,Windows還沒有確定在控件中使用的字體的高度和寬度;需要這些值的函數(shù)調(diào) 用和計算應(yīng)該發(fā)生在應(yīng)用程序或庫的主函數(shù)中。 如果要測量的的項是CMenu,CListBox或CComboBox對象,則將調(diào)用適當(dāng)?shù)念惖奶摵瘮?shù)MeasureItem。重載適當(dāng)?shù)目丶惖腗easureItem成員函數(shù)以計算并設(shè)置每個項的大小。 僅當(dāng)控件類是在運行時創(chuàng)建,或者它是用LBS_OWNERDRAWVARIABLE或CBS_OWNERDRAWVARIABLE風(fēng)格創(chuàng)建的時候,OnMeasureItem才會被調(diào)用。這是因為WM_MEASUREITEM消息時在控件創(chuàng)建過程的早期被發(fā)送的。 如果你使用DDX_Control,SubclassDlgItem或SubclassWindow進(jìn)行了子類化,則子類化過程通常發(fā)生在創(chuàng)建過程之后。 因此,在控件的OnChildNotify函數(shù)中無法處理WM_MEASUREITEM消息,這是MFC用來實現(xiàn) ON_WM_MEASUREITEM_REFLECT的機(jī)制。 注意 框架調(diào)用這個成員函數(shù)以允許你的應(yīng)用程序處理一個Windows消息。傳遞給你的成員函數(shù)的參數(shù)反映了接收到消息時框架接收到的參數(shù)。如果你調(diào)用了這個函數(shù)的基類實現(xiàn),則該實現(xiàn)將使用最初傳遞給消息的參數(shù)(而不是你提供給這個函數(shù)的參數(shù))。 僅僅WM_DRAWITEM還是不夠的,對于一些特殊的控件,如ListBox,系統(tǒng)在發(fā)送WM_DRAWITEM消息前,還發(fā)送WM_MEASUREITEM消息,需要你設(shè)置ListBox中每個項目的高度。 WM_DRAWITEM的映射函數(shù)原型如下: afx_msg void OnMeasureItem( int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct ); nIDCtl 該控件的ID,如果該元素為菜單,則nIDCtl為0 lpMeasureItemStruct指向MEASUREITEMSTRUCT結(jié)構(gòu)對象的指針,MEASUREITEMSTRUCT的結(jié)構(gòu)定義如下: 
 CtlType指定了控件的類型,其取值如表6所示: 類型值  ODT_COMBOBOX  ODT_LISTBOX  ODT_MENU  表6 CtlType的類型值與含義 CtlID 指定自繪控件的ID值,該成員不適用于菜單項 itemID表示菜單項ID,也可以表示可變高度的列表框或組合框中某項的索引值。該成員不適用于固定高度的列表框或組合框。 itemWidth 指定菜單項的寬度 itemHeight指定菜單項或者列表框中某項的的高度,最大值為255 itemData 對于菜單項,該成員的取值為由CMenu::AppendMenu、CMenu::InsertMenu、CMenu::ModifyMenu等函數(shù)傳遞給菜單的值。 對于列表框或這組合框,該成員的取值為由ComboBox::AddString、CComboBox::InsertString、CListBox::AddString或者CListBox::InsertString等函數(shù)傳遞給控件的值。 圖示出了OnMeasureItem的效果: 
 相應(yīng)的OnMeasureItem()實現(xiàn)如下: 
 同樣別忘了指定列表框的Owner draw屬性: 
 圖11 指定下拉框的Owner draw屬性 3.3.6 NM_CUSTOMDRAW 大家也許熟悉WM_NOTIFY,控件通過WM_NOTIFY向父窗口發(fā)送消息。在WM_NOTIFY消息體中,部分控件會發(fā)送NM_CUSTOMDRAW告訴父窗口自己需要繪圖。 可以反射NM_CUSTOMDRAW消息,如: ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) afx_msg void OnCustomDraw(NMHDR *pNMHDR, LRESULT *pResult); 參數(shù): pNMHDR 說到底只是一個指針,大多數(shù)情況下它指向一個NMHDR結(jié)構(gòu)對象,NMHDR結(jié)構(gòu)如下: 
 其中: hwndFrom 發(fā)送方控件的窗口句柄 idFrom 發(fā)送方控件的ID code 通知代碼 對于某些控件來說,pNMHDR則會解釋成其它內(nèi)容更豐富的結(jié)構(gòu)對象的指針,如:對于列表控件來說,pNMHDR常常指向一個NMCUSTOMDRAW對象,NMCUSTOMDRAW結(jié)構(gòu)如下: 
 hdr NMHDR對象 dwDrawStage 當(dāng)前繪制狀態(tài),其取值如表7所示: 類型值  CDDS_POSTERASE  CDDS_POSTPAINT  CDDS_PREERASE  CDDS_PREPAINT  CDDS_ITEM  CDDS_ITEMPOSTERASE  CDDS_ITEMPOSTPAINT  CDDS_ITEMPREERASE  CDDS_ITEMPREPAINT  CDDS_SUBITEM  表7 dwDrawStage的類型值與含義 hdc指定了繪制操作所使用的設(shè)備環(huán)境。 rc指定了將被繪制的矩形區(qū)域。 dwItemSpec 列表項的索引 uItemState 當(dāng)前列表項的狀態(tài),其取值如表8所示: 類型值  CDIS_CHECKED  CDIS_DEFAULT  CDIS_DISABLED  CDIS_FOCUS  CDIS_GRAYED  CDIS_SELECTED  CDIS_HOTLIGHT  CDIS_INDETERMINATE  CDIS_MARKED  表8 uItemState的類型值與含義 lItemlParam 當(dāng)前列表項的綁定數(shù)據(jù) pResult 指向狀態(tài)值的指針,指定系統(tǒng)后續(xù)操作,依賴于dwDrawStage: 當(dāng)dwDrawStage為CDDS_PREPAINT,pResult含義如表9所示: 類型值  CDRF_DODEFAULT  CDRF_NOTIFYITEMDRAW  CDRF_NOTIFYPOSTERASE  CDRF_NOTIFYPOSTPAINT  表9 pResult的類型值與含義(一) 當(dāng)dwDrawStage為CDDS_ITEMPREPAINT,pResult含義如表10所示: 類型值  CDRF_NEWFONT  CDRF_NOTIFYSUBITEMDRAW  CDRF_SKIPDEFAULT  表10 pResult的類型值與含義(二) 以下是一個利用NM_CUSTOMDRAW消息繪制出的多色列表框的例子: 
 圖12 利用NM_CUSTOMDRAW消息美化界面 對應(yīng)代碼如下: 
 注意到上例采取了3.1所推薦的第2種實現(xiàn)方法,派生了一個新類CCoolList。 3.4 使用MFC類的虛函數(shù)機(jī)制 修改Windows界面,除了從Windows消息機(jī)制下功夫,也可以從MFC類下功夫,這應(yīng)該得益于類的虛函數(shù)機(jī)制。為了防止諸如“面向?qū)ο蠹夹g(shù)”等術(shù)語在此泛濫,以下僅舉一段代碼作為例子: 
 這是MFC中viewcore.cpp中的源代碼,很多讀者總不明白OnDraw()和OnPaint()之間的關(guān)系,從以上的代碼中很容易看 出,CView的WM_PAINT消息響應(yīng)函數(shù)OnPaint()會自動調(diào)用CView::OnDraw()。而作為開發(fā)者的用戶,可以通過簡單的 OnDraw()的重載實現(xiàn)對WM_PAINT的處理。所以說,對MFC類的虛函數(shù)的重載是對消息機(jī)制的擴(kuò)展。 以下列出了與界面美化相關(guān)的虛函數(shù),參數(shù)說明略去: CButton::DrawItem CCheckListBox::DrawItem CComboBox::DrawItem CHeaderCtrl::DrawItem CListBox::DrawItem CMenu::DrawItem CStatusBar::DrawItem CStatusBarCtrl::DrawItem CTabCtrl::DrawItem virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct ); Owner draw元素自繪函數(shù) 很顯然,位圖菜單都是通過這個DrawItem畫出來的。限于篇幅,在此不再附以例程。 | 
|  |