MFC的自定義控件之控件封裝

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");
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,365評(píng)論 25 708
  • 定義實(shí)例 一個(gè)實(shí)例本質(zhì)上是一個(gè)字典,里面包含的是:“方法名”-“函數(shù)”對(duì)。 定義類(lèi) 栗子 最后一句locals()...
    Rim99閱讀 332評(píng)論 0 0
  • 作者:南鄉(xiāng)子江淮郎 心系楊梅水,平添萬(wàn)古情。 明新?lián)]筆墨,布院訴門(mén)庭①。 道觀遺香火,龍山樹(shù)玉屏②。 可憐白馬廟,...
    廣聰閱讀 812評(píng)論 0 0
  • 是不是有時(shí)候按照吸引力法則的步驟,去下訂單,觀想,靜坐,冥想,寫(xiě)感恩日記,做豐盛交換等,確實(shí)也感覺(jué)到幸福了。但當(dāng)負(fù)...
    Martin王閱讀 1,040評(píng)論 0 0

友情鏈接更多精彩內(nèi)容