[kaze's test] プログラミングメモ →目次

リスト コントロールとリスト ビューのオーナー描画(VC++)

リスト コントロールとリスト ビューのオーナー描画のメモです。簡単な描画をします。描画処理の内容としては、文字列、絵、選択されている行、フォーカスになっている行。リスト ビューは、リスト コントロールをカプセルしているので、やり方は同じだと思います。



1.リソースエディターで、ダイアログにリスト コントロールを貼り付け、プロパティを「オーナー描画、LVS_REPORT」にして、下記のようなシンプルなビットマップIDB_BITMAP_LISTを用意します。

2.CListCtrlクラスからCListCtrlOwnerクラスを派生します。

3.ClassWizardで、リスト コントロールをCListCtrlOwnerクラス型の変数m_listctrlを、CImageList 型の変数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);
}