之前經常看到同僚和各位網友說控件自繪,沒有相關需求,是以一直沒有了解過,現在終于忍不住,學習下這方面知識。
控件自繪的方式有兩種:1.将控件的自繪封裝成一個類,控件類中自己繪制2.直接在父視窗進行自繪。
首先學習下第一種方式,在vs2008下示例:
1、建立基于對話框的MFC程式OwnerDrawing,添加按鈕ID為IDC_BUTTON1。
2、項目名上右擊->添加->類,添加MFC類(選MFC類非C++類),派生于CButton 的名為CMyBtn的類。
3、給IDC_BUTTON1添加CMyBtn類型的變量m_btn。
4、将IDC_BUTTON1的Owner Draw屬性設定為true。
5、随便添加兩個.bmp位圖,ID為IDB_BITMAP1、IDB_BITMAP2。
6、CMyBtn類中重載CButton類的DrawItem()函數。
//聲明:
afx_msg void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//定義
void CMyBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 在此添加消息處理程式代碼和/或調用預設值
CDC ButtonDC;
CBitmap bitmapTrans;
BITMAP bmp;
CDC mem;
CRect rc; //得到用于繪制按鈕的DC
ButtonDC.Attach(lpDrawItemStruct->hDC); //準備用于向按鈕區域傳輸位圖
mem.CreateCompatibleDC(&ButtonDC); //擷取按鈕所占的矩形大小
rc=lpDrawItemStruct->rcItem; //擷取按鈕目前所處的狀态,根據不同的狀态繪制不同的按鈕
UINT state = lpDrawItemStruct->itemState; //如果按鈕已經得到焦點,繪制選中狀态下的按鈕
if(state&ODS_FOCUS)
{
bitmapTrans.LoadBitmap(IDB_BITMAP2);
bitmapTrans.GetBitmap(&bmp);
CBitmap *old=mem.SelectObject(&bitmapTrans); //向按鈕所在位置傳輸位圖
//使用StretcnBlt的目的是為了讓位圖随按鈕的大小而改變
ButtonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
mem.SelectObject(old);
bitmapTrans.DeleteObject();
}
else
{
bitmapTrans.LoadBitmap(IDB_BITMAP1);
CBitmap *old2 = mem.SelectObject(&bitmapTrans);
bitmapTrans.GetBitmap(&bmp);
CBitmap *old=mem.SelectObject(&bitmapTrans);
ButtonDC.StretchBlt(rc.left,rc.top,rc.right,rc.bottom,&mem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
mem.SelectObject(old2);
bitmapTrans.DeleteObject();
}
}
這樣,就實作了當IDC_BUTTON1沒有焦點時按鈕bmp為IDB_BITMAP1,有焦點時按鈕bmp為IDB_BITMAP2。