欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
WTL自畫(huà)按鈕的實(shí)現
WTL自畫(huà)按鈕的實(shí)現 2003-01-14··Bjarne··yesky



  一.思路:

  Windows 為控件提供了自畫(huà)(owner draw)的能力,程序員可以通過(guò)這一機制實(shí)現非??岬目丶庥^(guān)。WTL(Windows Template Library)提供了一個(gè)CownerDraw模板,用來(lái)對控件的自畫(huà)操作提供支持。

  COwnerDraw 的聲明為如下形式:

template <class T>
class CownerDraw



 ……                       

};

從上面的代碼可以看出,它沒(méi)有從任何基類(lèi)或模板派生,它并不是一個(gè)窗口類(lèi)。它只為參數T(T必須是一個(gè)支持自畫(huà)的控件類(lèi))提供自畫(huà)支持。除了自畫(huà)以外,我們也許還想讓按鈕具有ToolTip功能,或者看起來(lái)象一個(gè)位圖按鈕,最好還能在位圖的背景下顯示文字,或者上面顯示位圖下面顯示文字。這些功能我們都可以通過(guò)自畫(huà)操作來(lái)實(shí)現,但是那樣會(huì )很麻煩,利用WTL提供的CbitmapButtonImpl模板,我們只需要簡(jiǎn)單地繼承再加上自畫(huà)能力就可以實(shí)現上述功能?,F在看一看自畫(huà)按鈕的聲明:

class CownerDrawButton : public CbitmapButtonImpl<CownerDrawButton>,

public CownerDraw<CownerDrawButton>

……

  它采用多繼承的方式從兩個(gè)模板派生,從而不但具有了自畫(huà)的能力,而且也是一個(gè)位圖按鈕。

  二、COwnerDraw 模板

  CownerDraw模板提供了一組消息映射宏和相應的響應函數。如:

  BEGIN_MSG_MAP(COwnerDraw< T >)

    MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)

    ……

 ALT_MSG_MAP(1)

    MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)

  ……

  END_MSG_MAP()

因為CownerDrawButton從兩個(gè)基類(lèi)派生,在響應WM_DRAWITEM消息時(shí),它需要把消息鏈接到CownerDraw模板,在響應其它消息(如WM_CREATE)時(shí),需要把消息鏈接到CBitmapButtonImpl模板。ATL(注意是ATL而不WTL,WTL構建在A(yíng)TL之上)不知道哪一個(gè)消息要對應到哪個(gè)父類(lèi)的處理函數,如果兩個(gè)父類(lèi)都響應相同的消息,那么崎義就會(huì )產(chǎn)生,所以這一操作必須由程序員來(lái)完成。

使用基類(lèi)鏈接(base classchaining)機制用CHAIN_M(jìn)SG_M(jìn)AP宏,雖然可以將消息導向父類(lèi),但是如果父類(lèi)派生了多個(gè)子類(lèi),而每個(gè)子類(lèi)對相同的消息又有不同的處理要求時(shí), CHAIN_MSG_MAP就無(wú)能為力了。所以ATL又提供了另一個(gè)機制:消息分割(Alternate messagemaps),消息分割可以在父類(lèi)的消息映射中,將相同的消息分割放置在不同的區域,CownerDraw模板就是采用了這一機制。

  在CownerDraw模板的消息映射表里,消息映射被分為兩個(gè)區域,0號和1號區域。子類(lèi)要鏈接到不同區域,需要使用CHAIN_MSG_MAP_ALT宏。CownerDrawButton需要響應CownerDraw的1號區域中的OCM_DRAWITEM消息,就可以在它自己的消息映射表中加入這樣一條宏:CHAIN_MSG_MAP_ALT(COwnerDraw<CownerDrawButton>,1)

  而其余的消息,它希望由CbitmapButtonImpl模板來(lái)處理,仍然可以使用CHAIN_MSG_MAP做基類(lèi)鏈接(后面我會(huì )提到,實(shí)際上不能用CHAIN_MSG_MAP簡(jiǎn)單地做基類(lèi)鏈接)。

CownerDraw模板的這兩個(gè)消息映射區域唯一的不同是1號區域的消息是以OCM開(kāi)頭的。這就涉及到了ATL的消息反射(MessageReflection)機制。所謂消息反射,就是指窗口類(lèi)在收到消息時(shí)可以將消息反傳回去給發(fā)出消息的窗口類(lèi)。比如對于一個(gè)自畫(huà)樣式的按鈕,它會(huì )發(fā)出WM_DRAWITEM消息通知父窗口,而父窗口并不處理這個(gè)消息而是將它反傳回去,讓按鈕自己處理。顯而易見(jiàn),這種機制更符合面向對象的要求,減少了按鈕和父窗口之間的依賴(lài)關(guān)系。

  被父窗口返回的消息代號都是以OCM開(kāi)頭,當我們在父窗口的消息映射表中加入一條REFLECT_NOTIFICATIONS()宏時(shí),父窗口就能夠將支持消息反射的控件所發(fā)出的消息反傳回去,如果控件類(lèi)或其父類(lèi)(前提是已經(jīng)做了基類(lèi)鏈接)的消息映射表中有相應消息的反射處理宏,那么控件就會(huì )在自己或父類(lèi)的消息響應函數中處理這條消息。下面讓我們來(lái)看一看消息分割及反射的具體實(shí)現方法。首先在CownerDrawButton的消息映射表中加入如下宏:

CHAIN_MSG_MAP_ALT(COwnerDraw<CownerDrawButton>,1)

然后在框架類(lèi)的消息映射表中加入REFLECT_NOTIFICATIONS()宏,這樣就完成了消息映射。但是需要注意的是,REFLECT_NOTIFICATIONS必須放在消息映射表的最后,否則所有通知消息都將被返回,窗口本身得不任何通知消息,如果你在REFLECT_NOTIFICATIONS宏后面添加一條COMMAND_HANDLER(IDC_BUTTON1, BN_CLICKED,OnClickedButton1) ,那么OnClickedButton1是永遠也不會(huì )被觸發(fā)的。當按鈕發(fā)出WM_DRAWITEM消息時(shí),框架類(lèi)接到后,先檢查自己的消息映射表里是否有相對應的消息處理函數,如果沒(méi)有那么REFLECT_NOTIFICATIONS就將消息反回給按鈕,按鈕在消息映射表中找到MESSAGE_HANDLER(OCM_DRAWITEM,OnDrawItem)這一項,宏會(huì )將消息映射到OnDrawItem函數,通過(guò)調用OnDrawItem函數,完成繪制工作。CownerDraw模板已經(jīng)為我們實(shí)現了OnDrawItem函數,這個(gè)函數很簡(jiǎn)單,代碼如下:

LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)

{

T* pT = static_cast<T*>(this);

pT->SetMsgHandled(TRUE);

pT->DrawItem((LPDRAWITEMSTRUCT)lParam);

bHandled = pT->IsMsgHandled();

return (LRESULT)TRUE;

}

OnDrawItem函數通過(guò)static_cast運算符(靜態(tài)強制轉換)將基類(lèi)指針轉換到派生類(lèi)指針,然后調用派生的成員函數DrawItem來(lái)完成繪制任務(wù)。DrawItem是實(shí)現自畫(huà)的關(guān)鍵所在,CownerDraw并沒(méi)有提供DrawItem的實(shí)現,因為它沒(méi)有辦法知道派生類(lèi)的具體繪制要求,所以DrawItem必須由派生類(lèi)去實(shí)現。CownerDraw模板只提供了一個(gè)接口,如果你在派生類(lèi)中不提供DrawItem的實(shí)現,那么在調試的時(shí)候,將引發(fā)一ATL assert。

  三、CBitmapButtonImpl模板

CbitmapButtonImpl為位圖按鈕提供了支持,使我們不必了解太多實(shí)現細節,就可以做漂亮的位圖按鈕。它還提供了對ToolTip的支持。我們還可以通過(guò)重載DoPaint函數來(lái)實(shí)現個(gè)性化。CbitmapButtonImpl定義了一個(gè)重要的成員變量m_ImageList,這個(gè)成員主要用于位圖或圖標的管理和繪制。我們將在例程中看到它的使用方法。

  四、COwnerDrawButton 類(lèi)

前面曾經(jīng)說(shuō)過(guò),CownerDrawButton類(lèi)可以通過(guò)基類(lèi)鏈接的機制,將消息導向其基類(lèi),但是如果簡(jiǎn)單地使用CHAIN_MSG_MAP(CbitmapButtonImpl<CownerDrawButton>)宏,就會(huì )出現問(wèn)題。因為我們實(shí)現是的“自畫(huà)”按鈕,所有的繪制工作都應該在DrawItem函數里完成,但是CbitmapButtonImpl并不知道這種情況,所以它仍然響應WM_PAINT、WM_PRINTCLIENT和WM_ERASEBKGND以及其它有關(guān)繪制操作的消息,并調用DoPaint等函數進(jìn)行繪制工作,可想而知這會(huì )造成極大的混亂。因此我們必須屏蔽掉CownerDrawButton對這些消息的響應??截怌bitmapButtonImpl的所有消息映射表項到CownerDrawButton的消息消息映射表中,然后刪除這三行:

MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)

MESSAGE_HANDLER(WM_PAINT, OnPaint)

MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)

再添加CHAIN_MSG_MAP_ALT(COwnerDraw<COwnerDrawButton>,1)這一項,這樣窗口默認的繪制消息就不會(huì )被觸發(fā),問(wèn)題也得到了解決。但是不要忘記,CownerDrawButton也是一個(gè)位圖按鈕,而CbitmapButtonImpl是在DoPaint函數中實(shí)現位圖的顯示,如果不響應WM_PAINT或者WM_PAINTCLIENT消息,DoPaint是不會(huì )被調用的。顯然如果CownerDrawButton的m_ImageList成員包含圖片的話(huà),我們就需要自己在DrawItem函數里實(shí)現位圖的顯示,當然我們也可以在需要顯示位圖的時(shí)候簡(jiǎn)單地調用DoPaint函數,只要為它傳遞一個(gè)CDCHandle,DoPaint就會(huì )非常好地完成任務(wù),實(shí)際上我就是這么做的。不過(guò)要想實(shí)現圖1所顯示的按鈕,CbitmapButtonImpl提供的DoPaint函數是沒(méi)有辦法辦到的。為CownerDrawButton聲明一個(gè)成員變量m_uBmpPosStyle,當m_ImageList包含圖像時(shí),這個(gè)變量就被設置,用于存儲圖像的具體位置。圖像的位置被聲明為五個(gè)無(wú)符號的整型常量如下所示:

unsigned int const IMAGEPOS_TOP   = 1 ;

unsigned int const IMAGEPOS_BOTTOM = 2 ;

unsigned int const IMAGEPOS_LEFT  = 3 ;

unsigned int const IMAGEPOS_RIGHT  = 4 ;

unsigned int const IMAGEPOS_CENTER  = 5 ;

只有當m_ImageList包含圖像,圖像的擴展樣式不是自動(dòng)尺寸(BMPBTN_AUTOSIZE),并且圖像尺寸小于按鈕客戶(hù)區域時(shí),這些樣式才有效。還要聲明一個(gè)CRect類(lèi)型的成員變量m_ClientRect,用于記錄客戶(hù)區域的尺寸,每當我們顯示完位圖之后,就對m_ClientRect區域進(jìn)行裁剪,以便于文本的排布。為了應用這些樣式,以及對m_ClientRect成員進(jìn)行修改,必須對DoPaint進(jìn)行重載。把CbitmapButtonImpl模板的DoPaint源碼拷貝到CownerDrawButton的DoPaint中,然后此基礎上進(jìn)行修改。修改后的DoPaint函數對位圖尺寸和客戶(hù)區域進(jìn)行比較,如果圖片尺寸小于客戶(hù)區域,則再根據m_uBmpPosStyle設置的樣式繪制位圖,最后對m_ClientRect進(jìn)行裁剪,以便于文本布局。在DrawItem函數中,通過(guò)對m_ImageList 是否包含圖片及是否設置主圖進(jìn)行判斷,來(lái)決定是否調用DoPaint進(jìn)行圖片的顯示。如果沒(méi)有圖片則執行缺省的繪制,并在客戶(hù)區域中央顯示文本。

  為了便于位圖資源的導入,CownerDrawButton提供了一個(gè)LoadImageFromID函數,原型為:

BOOL LoadImageFromID(UINT IDBitmap ,UINT IDMask, const IMGINFOS & imgno);

  其第三個(gè)參數是一個(gè)自定義類(lèi)型的結構,包含了按鈕的圖像列表成員中包含的各個(gè)圖像的狀態(tài)信息、圖像的尺寸、圖像類(lèi)型標志、圖像列表中初始圖像個(gè)數和最大圖像個(gè)數等。結構的聲明及函數實(shí)現如下:

typedef struct _imageinfo{

int Normal ;

int Pushed ;

int Hover ;

int Disabled ;

int cx;

int cy;

UINT flags;

int cInitial;

int cGrow;

}IMAGELISTINFOSTRUCT;

typedef IMAGELISTINFOSTRUCT IMGINFOS;

file://Load bitmap from resource Id

BOOL LoadImageFromID(UINT IDBitmap ,UINT IDMask, const IMGINFOS & imgno)

{

if(!m_ImageList.Create( imgno.cx,imgno.cy,imgno.flags ,imgno.cInitial,imgno.cGrow))

return FALSE;

CBitmap m_Mask,m_bbmp;

if(!m_bbmp.LoadBitmap(IDBitmap))

return FALSE;

if(!m_Mask.LoadBitmap(IDMask))

return FALSE;

if((m_ImageList.Add(m_bbmp,m_Mask) == -1))

return FALSE;

SetImages(imgno.Normal,imgno.Pushed ,imgno.Hover,imgno.Disabled);

return TRUE;

}

  五、例程

啟動(dòng)VC++6.0,創(chuàng )建一個(gè)基于WTL對話(huà)框的應用程序,工程名為OwnerDrawDemo創(chuàng )建完成后,打開(kāi)ClassView,選擇CmainDlg,單擊鼠標右鍵,選擇Add Member Variable為CmainDlg類(lèi)添加一個(gè)CownerDrawButton成員變量。打開(kāi)ResourceView,在對話(huà)框資源模板上添加一個(gè)按鈕,調整到合適尺寸,ID為IDC_BUTTON1,Caption 為Help。導入一幅位圖和一幅相應的Mask圖,修改ID分別為:IDB_BUTTON、IDB_M(jìn)ASK。

  打開(kāi)FileView,打開(kāi)OwnerDrawDemo.cpp在其頂部依次添加#include <atlctrlx.h>、

  #include <atlgdi.h> 和 #include <atlmisc.h>。打開(kāi)maindlg.h文件,在OnInitDialog函數中添加如下代碼:

DWORD style =  BMPBTN_AUTO3D_SINGLE|BMPBTN_SHAREIMAGELISTS|

 BMPBTN_HOVER;

 IMGINFOS imgis = {0,1,1,-1,30,30,ILC_COLOR24|ILC_MASK,0,2};

 if(m_Button.LoadImageFromID(IDB_BUTTON,IDB_MASK,imgis))

 {

   m_Button.SetBitmapButtonExtendedStyle(style);

   m_Button.SetBitmapPosStyle(IMAGEPOS_TOP);

 }

 m_Button.SubclassWindow(GetDlgItem(IDC_BUTTON1));

 m_Button.SetToolTipText(_T("WTL_OwnerDrawButton!"));

  現在就可以按F7構建或者Ctrl + F5執行了。

  程序在Windows2000 + VC++6.0 +WTL 7.0 環(huán)境下編譯通過(guò),在Windows98、Windows 2000及WindowsXP下運行通過(guò)。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
VC知識庫文章 - MFC程序員的WTL指南: Part V - 高級對話(huà)框用戶(hù)界面類(lèi)
WM_DRAWITEM與DrawItem()的討論
白喬原創(chuàng ):VC之美化界面篇
CListCtrl自繪
MFC 自繪
MFC按鈕自繪消息分析
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久