MFC實(shí)現(xiàn)CListBox的繼承實(shí)現(xiàn)自定義效果
目標(biāo) - 實(shí)現(xiàn)有背景顏色項(xiàng)的列表
思路
- 需要知道CListBox的每個(gè)item的繪制方法
- 需要知道CListBox的item的測(cè)量方法
查看源碼找到關(guān)鍵的量重寫(xiě)的方法:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
開(kāi)始實(shí)現(xiàn)
- 自定義控件的操作步驟
參考http://m.itdecent.cn/p/e2fe069cfe35這邊MFC的定義控件步驟
再創(chuàng)建控件類(lèi)的時(shí)候,父類(lèi)要選擇CListBox
有個(gè)不一樣的是在界面上的控件,可以是CListBox,也可以是Custom Control,只需要在控件屬性的class
寫(xiě)成我們自定義的類(lèi)名。
代碼
控件的頭文件
class CColorListBox : public CListBox
{
DECLARE_DYNAMIC(CColorListBox)
public:
CColorListBox();
virtual ~CColorListBox();
BOOL InitControl(CWnd* pWnd); //用來(lái)做初始化控件的方法
public:
virtual BOOL PreCreateWindow(CREATESTRUCT &cs);
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); //一定要復(fù)寫(xiě)的方法
virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); //一定要復(fù)寫(xiě)的方法
BOOL RegisterWindowClass(HINSTANCE hInstance = NULL);
protected:
DECLARE_MESSAGE_MAP()
};
控件的源文件
// ColorListBox.cpp : 實(shí)現(xiàn)文件
#include "stdafx.h"
#include "ColorListBox.h"
#include "CustomUIApp.h"
// CColorListBox
IMPLEMENT_DYNAMIC(CColorListBox, CListBox)
CColorListBox::CColorListBox()
{
RegisterWindowClass(); //控件注冊(cè)類(lèi)
}
CColorListBox::~CColorListBox()
{
}
BEGIN_MESSAGE_MAP(CColorListBox, CListBox)
END_MESSAGE_MAP()
BOOL CColorListBox::RegisterWindowClass(HINSTANCE hInstance)
{
LPCWSTR className = L"CColorListBox"; // 控件類(lèi)名,必須和屬性的class一致
WNDCLASS windowclass;
if (hInstance)
hInstance = AfxGetInstanceHandle();
if (!(::GetClassInfo(hInstance, className, &windowclass)))
{
windowclass.style = CS_DBLCLKS;
windowclass.lpfnWndProc = ::DefWindowProc;
windowclass.cbClsExtra = windowclass.cbWndExtra = 0;
windowclass.hInstance = hInstance;
windowclass.hIcon = NULL;
windowclass.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
windowclass.hbrBackground = ::GetSysColorBrush(COLOR_WINDOW);
windowclass.lpszMenuName = NULL;
windowclass.lpszClassName = className;
}
return AfxRegisterClass(&windowclass);
}
//初始化控件,設(shè)置對(duì)應(yīng)的控件屬性, 列表控件才能顯示數(shù)據(jù),該方法必須調(diào)用,才可以正常顯示數(shù)據(jù)
BOOL CColorListBox::InitControl(CWnd* pWnd)
{
if (pWnd == NULL) return false;
CRect rect;
GetWindowRect(&rect);
pWnd->ScreenToClient(&rect);
UINT id = GetDlgCtrlID();
BOOL ret = DestroyWindow();
if (ret == FALSE) return false;
//設(shè)置控件的屬性
ret = Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | LBS_OWNERDRAWVARIABLE | LBS_HASSTRINGS | LBS_NOTIFY, rect, pWnd, id);
return ret;
}
BOOL CColorListBox::PreCreateWindow(CREATESTRUCT &cs)
{
if (!CListBox::PreCreateWindow(cs))
return FALSE;
cs.style &= ~(LBS_SORT | LBS_OWNERDRAWVARIABLE);
cs.style |= LBS_OWNERDRAWFIXED;
return TRUE;
}
void CColorListBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
ASSERT(lpDIS->CtlType == ODT_LISTBOX);
LPCTSTR lpszText = (LPCTSTR)lpDIS->itemData;
CDC dc;
dc.Attach(lpDIS->hDC);
COLORREF crOldTextColor = dc.GetTextColor();
COLORREF crOldBkColor = dc.GetBkColor();
// If this item is selected, set the background color
// and the text color to appropriate values. Also, erase
// rect by filling it with the background color.
if ((lpDIS->itemAction | ODA_SELECT) &&
(lpDIS->itemState & ODS_SELECTED))
{
dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
dc.FillSolidRect(&lpDIS->rcItem,
::GetSysColor(COLOR_HIGHLIGHT));
}
else
{
if (lpDIS->itemID % 2)
dc.FillSolidRect(&lpDIS->rcItem, RGB(128, 128, 128));
else
dc.FillSolidRect(&lpDIS->rcItem, RGB(255, 128, 255));
}
// If this item has the focus, draw a red frame around the
// item's rect.
if ((lpDIS->itemAction | ODA_FOCUS) &&
(lpDIS->itemState & ODS_FOCUS))
{
CBrush br(RGB(0, 0, 128));
dc.FrameRect(&lpDIS->rcItem, &br);
}
lpDIS->rcItem.left += 5;
// Draw the text.
CString sText;
GetText(lpDIS->itemID, sText);
CRect rect = lpDIS->rcItem;
// Setup the text format.
UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
if (GetStyle() & LBS_USETABSTOPS)
nFormat |= DT_EXPANDTABS;
dc.DrawText(
sText, -1, &rect, nFormat | DT_CALCRECT); //這邊是計(jì)算
dc.DrawText(
sText, -1, &rect, nFormat); //這邊是繪制文字
//設(shè)置字體顏色和背景顏色
dc.SetTextColor(crOldTextColor);
dc.SetBkColor(crOldBkColor);
dc.Detach();
}
void CColorListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
lpMIS->itemHeight = ::GetSystemMetrics(SM_CYMENUCHECK);
}
在對(duì)話框的調(diào)用:
BOOL CSecondDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
BOOL ret = m_colorlb.InitControl(this);
// TODO: 在此添加額外的初始化
return TRUE; // return TRUE unless you set the focus to a control
// 異常: OCX 屬性頁(yè)應(yīng)返回 FALSE
}
void CSecondDlg::OnBnClickedAddData()
{
m_colorlb.AddString(L"11111111");
m_colorlb.AddString(L"22222222");
}