List Control DEMO

 

The code

In CXListCtrl class derived from CListCtrl, I implemented NM_CUSTOMDRAW message because I wanted selected subitems to be drawn, NM_CLICK message to select subitem by mouse, and LVN_KEYDOWN to select subitem by keyboard.

  • int m_sel_row; to keep track of selected row
  • int m_sel_col; to keep track of selected column
  • BOOL m_bCustomDraw; e.g., to switch off custom draw
  • int m_nNumberOfRows; number of rows in ListCtrl
  • int m_nNumberOfCols; number of columns in ListCtrl

XListCtrl.h

//{{AFX_MSG(CXListCtrl)

  afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult);

afx_msg void custom_draw_funtion(NMHDR *pNMHDR, LRESULT *pResult);

XListCtrl.cpp

BEGIN_MESSAGE_MAP(CXListCtrl, CListCtrl)
    //{{AFX_MSG_MAP(CXListCtrl)
    ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
    ON_NOTIFY_REFLECT(LVN_KEYDOWN, OnKeydown)
    //}}AFX_MSG_MAP
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW,custom_draw_funtion)
END_MESSAGE_MAP()
void CXListCtrl::custom_draw_funtion(NMHDR *pNMHDR, LRESULT *pResult)
{
    NMLVCUSTOMDRAW* nmcd=(NMLVCUSTOMDRAW*)pNMHDR;
    *pResult=CDRF_DODEFAULT;

    int row; 
    int col;
    switch(nmcd->nmcd.dwDrawStage)
    {
        case CDDS_PREPAINT:
            if(m_bCustomDraw) 
                *pResult=CDRF_NOTIFYITEMDRAW; 
            // else CDRF_DODEFAULT which tell windows to paint itself
            return;

        case CDDS_ITEMPREPAINT:
            *pResult=CDRF_NOTIFYSUBITEMDRAW;
            return;

        case CDDS_SUBITEM|CDDS_ITEMPREPAINT:
        {
            *pResult=0;
            row=nmcd->nmcd.dwItemSpec;
            col=nmcd->iSubItem;

            CString str=GetItemText(row,col);

            CRect rect;
            CDC*pDC=CDC::FromHandle(nmcd->nmcd.hdc);

            if(col>0)
                GetSubItemRect(row,col,LVIR_BOUNDS,rect);
            else
                GetItemRect(row,&rect,LVIR_LABEL);

            UINT uCode=DT_LEFT;

            if(row==m_sel_row && col==m_sel_col)
            {
                COLORREF kolor=0xaa00aa;

                if(GetFocus()==this)
                    kolor=0x0000ff;

                CBrushbrush(kolor);
                pDC->FillRect(&rect,&brush);
            }
            rect.OffsetRect(5,0);
            pDC->DrawText(str,&rect,uCode);

            *pResult=CDRF_SKIPDEFAULT;

            break;
        }
    }
}
void CXListCtrl::invalidate_grid(int row, int col)
{   //I add this function to reduce flickering
    CRect r;

    if(col==0)
        GetItemRect(row,&r,LVIR_LABEL);
    else
        GetSubItemRect(row,col,LVIR_BOUNDS,r);

    InvalidateRect(&r);
}
void CXListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NMITEMACTIVATE* nm=(NMITEMACTIVATE*)pNMHDR;

    invalidate_grid(m_sel_row,m_sel_col);//to clear old selection
    m_sel_row=nm->iItem;
    m_sel_col=nm->iSubItem;
    invalidate_grid(m_sel_row,m_sel_col);

    *pResult = 0;
}
void CXListCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult) 
{
    NMLVKEYDOWN* nmkd = (NMLVKEYDOWN*)pNMHDR;

    switch(nmkd->wVKey)
    {
        case VK_LEFT:
            m_sel_col--;
            if(m_sel_col<0)
                m_sel_col=0;
            invalidate_grid(m_sel_row,m_sel_col+1);
            break;
        case VK_RIGHT:
            m_sel_col++;
            if(m_sel_col>m_nNumberOfCols-1)
                m_sel_col=m_nNumberOfCols-1;
            invalidate_grid(m_sel_row,m_sel_col-1);
            break;

        case VK_UP:
            m_sel_row--;
            if(m_sel_row<0)
                m_sel_row=0;
            invalidate_grid(m_sel_row+1,m_sel_col);
            break;

        case VK_DOWN: 
            m_sel_row++;
            if(m_sel_row>m_nNumberOfRows-1)
                m_sel_row=m_nNumberOfRows-1;
            invalidate_grid(m_sel_row-1,m_sel_col);
            break;
        case VK_PRIOR:
            invalidate_grid(m_sel_row,m_sel_col);
            m_sel_row=0;
            break;
        case VK_NEXT:
            invalidate_grid(m_sel_row,m_sel_col);
            m_sel_row=m_nNumberOfRows-1;
            break;
        case VK_HOME:
            invalidate_grid(m_sel_row,m_sel_col);
            m_sel_col=0;

            if(GetKeyState(VK_CONTROL)<0)
                m_sel_row=0;

            SetItemState(m_sel_row,LVIS_FOCUSED,LVIS_FOCUSED);
            *pResult = CDRF_SKIPDEFAULT;
            invalidate_grid(m_sel_row,m_sel_col);
            return;
            break;
        case VK_END:
            invalidate_grid(m_sel_row,m_sel_col);
            m_sel_col=m_nNumberOfCols-1;
            if(GetKeyState(VK_CONTROL)<0)
                m_sel_row=m_nNumberOfRows-1;

            SetItemState(m_sel_row,LVIS_FOCUSED,LVIS_FOCUSED);

            *pResult=CDRF_SKIPDEFAULT;
            invalidate_grid(m_sel_row,m_sel_col);
            return;
    }
    *pResult = 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值