SOFTIST 编程方法筆記 目录

自描画列表控件列表VIEW(VC++)

下图是自描画报表形式列表控件的例子。做一个简单的列表控件的自描画,自描画内容包括:文字显示,图片显示,选择状态显示,焦点状态显示。列表VIEW实际上是封装列表控件,所以做法是一样的。在描画处理中可以使用任何描画功能,使画面的表现丰富多彩

1.使用资源编辑器,为对话框贴一个列表控件,并且设其属性为「自描画,LVS_REPORT」。准备一个位图IDB_BITMAP_LIST如下。

2.从CListCtrl派生一个CListCtrlOwner类。

3.用ClassWizard为刚刚贴的列表框定义一个CListCtrlOwner类型的变量m_listctrlCImageList 类型的变量m_imglstList在对话框派生类的OnInitDialog()中做文字列插入等适当处理。

m_imglstList.Create(IDB_BITMAP_LIST, 20, 1, (COLORREF)(0x00000000));
m_listctrl.SetImageList(&m_imglstList, LVSIL_SMALL);
m_listctrl.InsertColumn(0, _T("Field1"), LVCFMT_LEFT, 100);
m_listctrl.InsertColumn(1, _T("Field2"), LVCFMT_LEFT, 100);
m_listctrl.InsertColumn(2, _T("Field3"), LVCFMT_LEFT, 100);
for (int i = 0; i < 20; i ++)
{
    for (int j = 0; j < 3; j ++)
    {
        CString strText;
        strText.Format(_T("Data[%d,%d]"), i+1, j+1);
        if (j == 0)
            m_listctrl.InsertItem(i, strText);
        else
            m_listctrl.SetItemText(i,j,strText);
    }
    m_listctrl.SetItem(i, 0, LVIF_IMAGE, NULL, i%2, 0,0,0 );
}

4.重载和填写void CListCtrlOwner::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
函数。

void CListCtrlOwner::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    CRect rcItem(lpDrawItemStruct->rcItem);
    int nItem = lpDrawItemStruct->itemID;

    LV_ITEM lvi;
    lvi.mask = LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
    lvi.iItem = nItem;
    lvi.iSubItem = 0;
    lvi.stateMask = 0xFFFF;        
    GetItem(&lvi);
    //描画每一行的背景
    COLORREF clrTextSave;
    COLORREF clrBkSave;
    if (lvi.state & LVIS_SELECTED)
    {
        clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
        CBrush cb(::GetSysColor(COLOR_HIGHLIGHT));
        pDC->FillRect(rcItem, &cb);
    }
    else
    {
        if (nItem % 2)    //斑马线颜色
        {
            CBrush cb(::GetSysColor(COLOR_WINDOW));
            pDC->FillRect(rcItem, &cb);
        }
        else
        {
            CBrush cb((COLORREF)0x00f0f0f0);
            pDC->FillRect(rcItem, &cb);
        }
    }
    //描画位图
    CImageList* pImageList = GetImageList(LVSIL_SMALL);
    pImageList->Draw(pDC, lvi.iImage, rcItem.TopLeft(), ILD_TRANSPARENT);

    CRect rectItem(0, 0, 0, 0);
    CRect rectText;

    for (int j = 0; j < 3; j ++)
    {
        if (j == 0)
            GetItemRect(nItem, rectItem, LVIR_LABEL);
        else
        {
            rectItem.left = rectItem.right;
            rectItem.right += GetColumnWidth(j);
        }

        rectText = rectItem;
        rectText.right -= 4;

        CString strData = GetItemText(nItem, j);

        if ((lvi.state & LVIS_SELECTED))
            clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
        
        if (rectText.right >= rectText.left)
            pDC->DrawText(strData, rectText, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER);

        if ((lvi.state & LVIS_SELECTED))
            pDC->SetTextColor(clrTextSave);
    }
    
    if (lvi.state & LVIS_SELECTED)
        pDC->SetBkColor(clrBkSave);
    //描画焦点
    if ((lvi.state & LVIS_FOCUSED) != 0 && GetFocus() == this)
                pDC->DrawFocusRect(&rcItem);

}