前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MFC的自定义控件之控件封装

MFC的自定义控件之控件封装

作者头像
包子388321
发布2020-06-16 19:22:31
1.7K0
发布2020-06-16 19:22:31
举报
文章被收录于专栏:包子的书架

MFC实现CListBox的继承实现自定义效果

目标 - 实现有背景颜色项的列表

思路

  • 需要知道CListBox的每个item的绘制方法
  • 需要知道CListBox的item的测量方法 查看源码找到关键的量重写的方法:

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);

开始实现

  • 自定义控件的操作步骤 参考https://cloud.tencent.com/developer/article/1646119这边MFC的定义控件步骤 再创建控件类的时候,父类要选择CListBox 有个不一样的是在界面上的控件,可以是CListBox,也可以是Custom Control,只需要在控件属性的class 写成我们自定义的类名。
代码

控件的头文件

代码语言:javascript
复制
class CColorListBox : public CListBox
{
    DECLARE_DYNAMIC(CColorListBox)

public:
    CColorListBox();
    virtual ~CColorListBox();

    BOOL InitControl(CWnd* pWnd);   //用来做初始化控件的方法

public:
    virtual BOOL PreCreateWindow(CREATESTRUCT &cs);
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);   //一定要复写的方法
    virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);  //一定要复写的方法
    BOOL RegisterWindowClass(HINSTANCE hInstance = NULL);

protected:
    DECLARE_MESSAGE_MAP()
};

控件的源文件

代码语言:javascript
复制
// ColorListBox.cpp : 实现文件
#include "stdafx.h"
#include "ColorListBox.h"
#include "CustomUIApp.h"


// CColorListBox

IMPLEMENT_DYNAMIC(CColorListBox, CListBox)

CColorListBox::CColorListBox()
{
    RegisterWindowClass();   //控件注册类
}

CColorListBox::~CColorListBox()
{
}


BEGIN_MESSAGE_MAP(CColorListBox, CListBox)
END_MESSAGE_MAP()

BOOL CColorListBox::RegisterWindowClass(HINSTANCE hInstance)
{
    LPCWSTR className = L"CColorListBox"; // 控件类名,必须和属性的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);
}

//初始化控件,设置对应的控件属性, 列表控件才能显示数据,该方法必须调用,才可以正常显示数据
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;
        //设置控件的属性  
    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);  //这边是计算
    dc.DrawText(
        sText, -1, &rect, nFormat);   //这边是绘制文字
    //设置字体颜色和背景颜色
    dc.SetTextColor(crOldTextColor);
    dc.SetBkColor(crOldBkColor);

    dc.Detach();
}

void CColorListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
    lpMIS->itemHeight = ::GetSystemMetrics(SM_CYMENUCHECK);
}

在对话框的调用:

代码语言:javascript
复制
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 属性页应返回 FALSE
}

void CSecondDlg::OnBnClickedAddData()
{
    m_colorlb.AddString(L"11111111");
    m_colorlb.AddString(L"22222222");
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MFC实现CListBox的继承实现自定义效果
    • 思路
    • 开始实现
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档