You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MFC ListCtrl修改行高触发DrawItem断言错误,寻求解决方案

解决MFC ListCtrl使用OnMeasureItem后触发DrawItem断言错误的问题

问题根源

当你为ListCtrl设置LVS_OWNERDRAWVARIABLE样式(触发OnMeasureItem调用的前提)时,MFC要求必须重载DrawItem函数实现自绘逻辑。默认的CListCtrl::DrawItem仅包含ASSERT(FALSE),因此会触发错误。

解决步骤

1. 确认ListCtrl样式

确保你的ListCtrl是报表视图(LVS_REPORT),并且已开启LVS_OWNERDRAWVARIABLE样式:

// 在对话框OnInitDialog中添加
CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LISTCTRL);
pList->SetStyle(pList->GetStyle() | LVS_OWNERDRAWVARIABLE);
// 可选:添加全选样式
pList->SetExtendedStyle(pList->GetExtendedStyle() | LVS_EX_FULLROWSELECT);

2. 重载DrawItem函数

  • 在对话框类的头文件(.h)中声明:
afx_msg void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
  • 在消息映射文件(.cpp)中添加:
BEGIN_MESSAGE_MAP(ShipInfoDlg, CDialog)
    // 其他消息映射
    ON_WM_DRAWITEM()
END_MESSAGE_MAP()

3. 实现DrawItem的自绘逻辑

以下是适配报表视图的完整实现,支持行选中状态区分、多列文本绘制:

void ShipInfoDlg::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    if (lpDrawItemStruct->CtlID != IDC_LISTCTRL)
    {
        CDialog::DrawItem(lpDrawItemStruct);
        return;
    }

    CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LISTCTRL);
    ASSERT_VALID(pList);

    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    RECT rcItem = lpDrawItemStruct->rcItem;

    // 绘制背景
    if (lpDrawItemStruct->itemState & ODS_SELECTED)
    {
        pDC->FillSolidRect(&rcItem, GetSysColor(COLOR_HIGHLIGHT));
        pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
        pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
    }
    else
    {
        pDC->FillSolidRect(&rcItem, GetSysColor(COLOR_WINDOW));
        pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
        pDC->SetBkColor(GetSysColor(COLOR_WINDOW));
    }

    // 绘制每列文本
    int nRow = lpDrawItemStruct->itemID;
    int nColCount = pList->GetHeaderCtrl()->GetItemCount();
    RECT rcCol;

    for (int nCol = 0; nCol < nColCount; ++nCol)
    {
        pList->GetColumnRect(nCol, rcCol);
        rcCol.top = rcItem.top;
        rcCol.bottom = rcItem.bottom;

        CString strText;
        pList->GetItemText(nRow, nCol, strText);
        // 左对齐、垂直居中绘制文本
        pDC->DrawText(strText, &rcCol, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
    }

    // 绘制行分隔线(可选)
    pDC->MoveTo(rcItem.left, rcItem.bottom - 1);
    pDC->LineTo(rcItem.right, rcItem.bottom - 1);
}

4. 更简单的替代方案(固定行高)

如果不需要可变行高,仅需统一修改所有行的高度,可直接使用SetItemHeight,无需启用自绘:

CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LISTCTRL);
LOGFONT lf;
pList->GetFont()->GetLogFont(&lf);
int nHeight = (lf.lfHeight < 0) ? -lf.lfHeight + 10 : lf.lfHeight + 10;
pList->SetItemHeight(-1, nHeight); // -1表示设置所有行的高度

内容的提问来源于stack exchange,提问作者Hunni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 02:30:44