专栏首页包子的书架MFC的自定义控件之控件封装

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

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

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

思路

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

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

开始实现

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

代码

控件的头文件

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()
};

控件的源文件

// 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);
}

在对话框的调用:

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");
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MFC对话框模式下,控件的数据交互

    方法四:利用GetDlgItemText(ID,字符串变量)和SetDlgItemText(ID, 字符串);

    包子388321
  • 利用Android系统源码中giflib实现播放gif文件

    目前市场上流行的图片框架都是可以很好的处理gif图片,像glide是通过Java层来处理gif的展示,但是Java层来处gif的展示,始终会存在OOM的风险。今...

    包子388321
  • Java的JVM介绍以及java的值传递和引用传递

    面试的时候碰到的了一个java基础问题,竟然给问蒙了,回来之后感觉针对这个问题总结一下

    包子388321
  • [nodejs] nodejs开发个人博客(二)入口文件

    公共文件夹(common),控制器文件夹(controller),模型文件夹(model),视图文件夹(view),静态资源文件夹(static)

    陶士涵
  • 采用共享内存或文件映射的方式保存用户数据

        举个例子,假如一个网站提供给用户8种特权服务,用户可以选择性的开通其中一个或多个,而用户一般的操作行为是查看自己的特权以及查看好友的特权。这类数据的特点...

    王亚昌
  • 请关注个人数据如何被采集和使用。

    题图来源:spyfari | 斯派来app。 ---- 今天把《现实挖掘》Reality Mining,这本书读完了,有些感悟想分享下。 现在很多人都在使用mo...

    mixlab
  • 如何用AI技术预测下一个热点?

    想实现目标,需花费大量时间搜索信息,可历经辛苦,找到的却可能是快“凉”了的“热点”,怎么破?

    用户1386409
  • Css实现内容溢出添加横向滚动条

    任我行RQ
  • ①DS1302解析--电子时钟的时钟来源

    之前我们写的如何用单片机设计一款电子产品中说到的时钟芯片DS1302,它是我们DIY这个时钟的时间数据的来源。现在我们就来详细的解析DS1302芯片是如何给我产...

    单片机技术宅
  • 【Download error:TOO MANY REQUESTS】&【TypeError:excepted string or buffer】

        link_crawler('http://example.webscraping.com','/index')

    逆向小白

扫码关注云+社区

领取腾讯云代金券