MFC自绘-WzdList列表类

列表分为列表头和列表项两个部分。
从列表头开始自绘。

class CWzdListHeader : public CHeaderCtrl
{
    DECLARE_DYNAMIC(CWzdListHeader)

public:
    CWzdListHeader();
    virtual ~CWzdListHeader();

    // 添加字段
    void AddColumn(int nCol, LPCTSTR sName, int nFormat);

protected:
    afx_msg void OnPaint();
    LRESULT OnLayout(WPARAM wParam, LPARAM lParam);
    DECLARE_MESSAGE_MAP()
};

可以看到列表头自绘很简单,OnPaint里进行绘画,其中列表头的各个字段的显示属性在AddColumn函数中保存到一个multimap中,以便于绘画的时候一一对应。
AddColumn函数会在下面的InsertColumn中用到。

void CWzdListHeader::OnPaint()
{
    CPaintDC dc(this); // device context for painting

    CRect itemRect;
    CBrush colomnBrush;     // Column画刷
    CPen linePen;       // 分隔线画刷
    CPen* pOldPen;
    colomnBrush.CreateSolidBrush(COLOR_LISTHEAR);
    linePen.CreatePen(PS_SOLID, 1, COLOR_WHITE);
    pOldPen = dc.SelectObject(&linePen);

    // 画出所有字段
    int nItem = GetItemCount(); // 得到单元数量
    int i = 0;
    std::multimap<int, std::pair<LPCTSTR, int>>::iterator itor = g_columeMap.begin();
    while (itor != g_columeMap.end() && i < nItem)
    {
        // 画分隔线,填充背景
        GetItemRect(i, &itemRect);
        if (0 != i)
        {
            dc.MoveTo(CPoint(itemRect.left, itemRect.top));
            dc.LineTo(CPoint(itemRect.left, itemRect.bottom));
            itemRect.left += 1;
        }
        dc.FillRect(&itemRect,&colomnBrush);

        // 创建字体
        CFont textFont;
        CFont* pOldFont;
        dc.SetBkMode(TRANSPARENT);
        dc.SetTextColor(RGB(0,0,0));
        textFont.CreateFont(20,0,0,0,0,FALSE,FALSE,0,0,0,0,0,0, DEFAULT_TEXTFACE);
        pOldFont = dc.SelectObject(&textFont);

        // 画字
        TEXTMETRIC metric;
        int ofst = 0;
        dc.GetTextMetrics(&metric);
        ofst = itemRect.Height() - metric.tmHeight;
        itemRect.OffsetRect(0, ofst / 2);
        dc.DrawText(itor->second.first, &itemRect, itor->second.second);

        dc.SelectObject(pOldFont);
        textFont.DeleteObject();
        itor++;
        i++;
    }

    //画头部剩余部分
    CRect lastRect;
    GetClientRect(&lastRect);
    lastRect.left = itemRect.right + 1;
    dc.MoveTo(CPoint(itemRect.right, lastRect.top));
    dc.LineTo(CPoint(itemRect.right, itemRect.bottom));
    dc.FillRect(&lastRect, &colomnBrush);

    colomnBrush.DeleteObject();
    linePen.DeleteObject();
    dc.SelectObject(pOldPen);
}

然后就是列表项的自绘

class CWzdList : public CListCtrl
{
    DECLARE_DYNAMIC(CWzdList)

public:
    CWzdList();
    virtual ~CWzdList();

    int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1);

protected:
    CWzdListHeader m_listHeader;

    virtual void PreSubclassWindow();
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

    DECLARE_MESSAGE_MAP()
};

PreSubclassWindow和OnCreate都是用来在创建之前改变列表的风格,前者是绑定的时候调用,后者是动态创建的时候调用。

void CWzdList::PreSubclassWindow()
{

    SetWindowLong(this->m_hWnd, GWL_STYLE, GetStyle() | LVS_OWNERDRAWFIXED | LVS_REPORT);
    SetExtendedStyle(GetExtendedStyle()| LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
    CHeaderCtrl *pHeader = GetHeaderCtrl();
    m_listHeader.SubclassWindow(pHeader->GetSafeHwnd());

    CListCtrl::PreSubclassWindow();
}

int CWzdList::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CListCtrl::OnCreate(lpCreateStruct) == -1)
        return -1;

    SetWindowLong(this->m_hWnd, GWL_STYLE, GetStyle() | LVS_OWNERDRAWFIXED | LVS_REPORT);
    SetExtendedStyle(GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
    CHeaderCtrl *pHeader = GetHeaderCtrl();
    m_listHeader.SubclassWindow(pHeader->GetSafeHwnd());

    return 0;
}

同样添加了LVS_EX_FULLROWSELECT 属性后,可以在DrawItem种进行自绘。

void CWzdList::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    LV_COLUMN lvColumn, lvColumnPre ;
    ZeroMemory(&lvColumn, sizeof(lvColumn));
    ZeroMemory(&lvColumnPre, sizeof(lvColumnPre));
    lvColumn.mask = LVCF_WIDTH | LVCF_FMT;
    lvColumnPre.mask = LVCF_WIDTH | LVCF_FMT;

    // 获取DC和列表尺寸
    CDC* pDC;
    CRect rtClient;
    pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    GetClientRect(&rtClient);

    std::multimap<int, std::pair<LPCTSTR, int>>::iterator itor = g_columeMap.begin();
    for (int nCol = 0; GetColumn(nCol, &lvColumn); nCol++, itor++)
    {
        // 获取列表项尺寸,全部LVIR_BOUNDS
        CRect rcItem;
        GetSubItemRect(lpDrawItemStruct->itemID, nCol, LVIR_BOUNDS, rcItem);

        // 初始化列表项, 获取列表项文字
        LV_ITEM lvItem;
        WCHAR lpBuffer[256];
        ZeroMemory(&lvItem, sizeof(lvItem));
        lvItem.iItem = lpDrawItemStruct->itemID;
        lvItem.mask = LVIF_TEXT | LVIF_PARAM;
        lvItem.iSubItem = nCol;
        lvItem.pszText = lpBuffer;
        lvItem.cchTextMax = sizeof(lpBuffer);
        VERIFY(GetItem(&lvItem));

        // 画选中和不选中的Item
        if (lpDrawItemStruct->itemState & ODS_SELECTED)
        {
            pDC->FillSolidRect(&rcItem, COLOR_LISTITEM_SELECT);
        }
        else
        {
            pDC->FillSolidRect(rcItem, COLOR_LISTITEM_NORMAL);
        }

        // 创建字体
        CFont nFont;
        CFont* pOldFont;
        nFont.CreateFont(17,0,0,0,0,FALSE,FALSE,0,0,0,0,0,0, DEFAULT_TEXTFACE);
        pOldFont = pDC->SelectObject(&nFont);

        // 获取列表项尺寸,文字部分LVIR_LABEL
        GetSubItemRect(lpDrawItemStruct->itemID, nCol, LVIR_LABEL, rcItem);
        // 画字
        CString strText(lpBuffer);
        int uFormat = itor->second.second;
        pDC->SetTextColor(COLOR_BLACK);
        pDC->DrawText(strText, strText.GetLength(), &rcItem, uFormat);

    }
}

最后重写InsertColumn来储存插入的列表头关键字属性

int CWzdList::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat /*= LVCFMT_LEFT*/, int nWidth /*= -1*/, int nSubItem /*= -1*/)
{
    m_listHeader.AddColumn(nCol, lpszColumnHeading, nFormat);

    return CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat, nWidth, nSubItem);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MFC 自绘图片控件是一种在 Microsoft Foundation Class (MFC) 框架下开发的控件,用于实现自定义绘制图片的功能。通过这个控件,我们可以方便地将自定义绘制的图片显示在应用程序的界面上。 MFC 自绘图片控件的使用主要包括以下几个步骤: 首先,我们需要创建一个继承自 MFC 的 CWnd 的子,该子将扮演画图的窗口的角色。 然后,我们需要在该子中重写 OnPaint 函数,这个函数将实现绘制图片的逻辑。在这个函数中,我们可以使用 GDI+ 或者其他绘图技术,根据自己的需求来绘制介绍的图片。 接下来,我们需要在该子中添加一些其他的函数,用于加载图片资源、设置显示的图片、调整图片的尺寸等。这些函数将在控件的使用过程中被调用。 最后,在 MFC 应用程序的界面上,我们可以使用资源编辑器或者代码来创建和布置这个自绘图片控件的实例。通过调用相应的函数,我们可以加载图片资源,设置绘制的图片,以及实现其他一些操作。 MFC 自绘图片控件的好处是它可以根据自己的需求来绘制图片,使得应用程序的用户界面更加美观、个性化。同时,它也提供了一些方便的函数来加载图片资源、设置图片、调整图片的尺寸等,使得开发者在使用过程中更加方便。 总之,MFC 自绘图片控件是一种实现自定义绘制图片功能的控件,通过继承 MFC 的 CWnd 并重写相应的函数,我们可以实现自己想要的图片效果。这个控件的使用方法简单,同时也提供了一些方便的函数来帮助我们实现功能。 ### 回答2: MFC(Microsoft Foundation Classes)是一种基于C++编程语言的框架,用于开发Windows应用程序。在MFC中,自绘图片控件是指可以自定义绘制图片的控件。 自绘图片控件通常继承自MFC的CWnd或CStatic,通过重写控件的绘制函数来实现自定义绘制。 在自绘图片控件中,首先需要实现OnPaint函数来处理绘制事件。可以通过GDI(图形设备接口)函数来绘制图片,例如使用CDC的DrawBitmap函数绘制位图、使用DrawIcon函数绘制图标等。还可以使用GDI+库来实现更复杂的绘图效果,例如绘制自定义形状、应用渐变色等。 除了绘图函数,还可以重写控件的其他函数来处理其他事件,例如OnLButtonDown函数处理鼠标点击事件、OnMouseMove函数处理鼠标移动事件等。通过重写这些函数,可以实现控件的交互功能,例如点击图片时弹出对话框、拖拽图片等。 在使用自绘图片控件时,需要创建控件对象并添加到对应的对话框或窗口中。可以使用Create函数来创建控件,并调用ShowWindow函数来显示控件。 总之,自绘图片控件MFC框架中的一种特殊控件,可以通过重写绘制函数和其他事件处理函数,实现对图片的自定义绘制和交互功能。通过灵活运用GDI函数和GDI+库,可以实现各种各样的绘图效果,为应用程序增加更丰富的用户界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值