本帖最后由 lswandym_888 于 2014-09-01 10:04:32 编辑

解决方案 »

  1.   

    Using Check Box in List Control
      

  2.   

    // CheckBoxListCtrl.cpp : 实现文件
    //#include "stdafx.h"
    #include "Annex.h"
    #include "CheckBoxListCtrl.h"
    // CCheckBoxListCtrlIMPLEMENT_DYNAMIC(CCheckBoxListCtrl, CBCGPListCtrl)CCheckBoxListCtrl::CCheckBoxListCtrl()
    : m_blInited(FALSE)
    , m_check(FALSE)
    {
    m_OddItemBkColor = 0xF7F7F7;//奇数行背景颜色
    m_EvenItemBkColor = 0xFCFCFC;//偶数行背景颜色 0xFFFFFF
    m_HoverItemBkColor = 0xFF;//热点行背景颜色
    m_SelectItemBkColor = GetSysColor(COLOR_HIGHLIGHT);//选中行背景颜色
    m_OddItemTextColor = GetSysColor(COLOR_BTNTEXT);//奇数行文本颜色
    m_EvenItemTextColor = GetSysColor(COLOR_BTNTEXT);//偶数行文本颜色
    m_HoverItemTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT);//热点行文本颜色
    m_SelectItemTextColor = GetSysColor(COLOR_BTNTEXT);//选中行文本颜色
    m_nHoverIndex = -1;
    m_bTracking = FALSE;
    }CCheckBoxListCtrl::~CCheckBoxListCtrl()
    {
    }
    BEGIN_MESSAGE_MAP(CCheckBoxListCtrl, CBCGPListCtrl)
    ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CCheckBoxListCtrl::OnLvnColumnclick)
    ON_NOTIFY_REFLECT(NM_CLICK, &CCheckBoxListCtrl::OnNMClick)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CCheckBoxListCtrl::OnNMCustomdraw)
    ON_WM_MOUSEMOVE()
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    END_MESSAGE_MAP()void CCheckBoxListCtrl::SetOddItemBkColor(COLORREF color, BOOL bDraw)//设置奇数行背景颜色
    {
    m_OddItemBkColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }
    void CCheckBoxListCtrl::SetEvenItemBkColor(COLORREF color, BOOL bDraw)//设置偶数行背景颜色
    {
    m_EvenItemBkColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }
    void CCheckBoxListCtrl::SetHoverItemBkColor(COLORREF color, BOOL bDraw)//设置热点行背景颜色
    {
    m_HoverItemBkColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }
    void CCheckBoxListCtrl::SetSelectItemBkColor(COLORREF color, BOOL bDraw)//设置选中行背景颜色
    {
    m_SelectItemBkColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }
    void CCheckBoxListCtrl::SetOddItemTextColor(COLORREF color, BOOL bDraw)//设置奇数行文本颜色
    {
    m_OddItemTextColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }
    void CCheckBoxListCtrl::SetEvenItemTextColor(COLORREF color, BOOL bDraw)//设置偶数行文本颜色
    {
    m_EvenItemTextColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }
    void CCheckBoxListCtrl::SetHoverItemTextColor(COLORREF color, BOOL bDraw)//设置热点行文本颜色
    {
    m_HoverItemTextColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }
    void CCheckBoxListCtrl::SetSelectItemTextColor(COLORREF color, BOOL bDraw)//设置选中行文本颜色
    {
    m_SelectItemTextColor = color;
    if (bDraw)
    InvalidateRect(NULL);
    }BOOL CCheckBoxListCtrl::Init()
    {
    if (m_blInited)
    return TRUE; VERIFY(m_checkImgList.Create(IDB_CHECKBOXES, 16, 4, RGB(255, 0, 255)));
    SetColCheck(); m_blInited = TRUE; return TRUE;
    }void CCheckBoxListCtrl::SetColCheck()
    {
    this->GetHeaderCtrl().SetImageList(&m_checkImgList);//
    HDITEM hdItem;
    hdItem.mask = HDI_IMAGE | HDI_FORMAT;
    VERIFY(this->GetHeaderCtrl().GetItem(0, &hdItem));
    hdItem.iImage = 1;
    hdItem.fmt |= HDF_IMAGE;
    VERIFY(this->GetHeaderCtrl().SetItem(0, &hdItem));
    }// CCheckBoxListCtrl 消息处理程序void CCheckBoxListCtrl::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    if (pNMLV->iSubItem == 0)
    {
    int sum = GetItemCount();
    if (sum > 0)
    {
    for (int x = 0; x < sum; x++)
    SetCheck(x, !m_check);
    m_check = !m_check;
    HDITEM hdItem;
    hdItem.mask = HDI_IMAGE | HDI_FORMAT;
    VERIFY(this->GetHeaderCtrl().GetItem(0, &hdItem));
    if (m_check)
    hdItem.iImage = 2;
    else
    hdItem.iImage = 1;
    hdItem.fmt |= HDF_IMAGE;
    VERIFY(this->GetHeaderCtrl().SetItem(0, &hdItem));
    }
    }
    *pResult = 0;
    }void CCheckBoxListCtrl::ScanItemsSetHeadSate(int curItem)
    {
    int checkItem = 0;
    int nCount = GetItemCount();
    for (int nItem = 0; nItem < nCount; nItem++)
    if (ListView_GetCheckState(GetSafeHwnd(), nItem))//GetCheck(nItem)
    checkItem++;
    //因为此时单击行还未完成状态更新,所以作特殊处理
    if (!ListView_GetCheckState(GetSafeHwnd(), curItem))
    checkItem++;
    else
    checkItem--;
    /////////////////////////////////////////////////
    HDITEM hdItem;
    hdItem.mask = HDI_IMAGE | HDI_FORMAT;
    VERIFY(this->GetHeaderCtrl().GetItem(0, &hdItem));
    if (checkItem == 0)
    {
    m_check = FALSE;
    hdItem.iImage = 1;
    }
    else
    if (checkItem == nCount)
    {
    m_check = TRUE;
    hdItem.iImage = 2;
    }
    else
    if (checkItem>0 && checkItem<nCount)
    hdItem.iImage = 3;
    hdItem.fmt |= HDF_IMAGE;
    VERIFY(this->GetHeaderCtrl().SetItem(0, &hdItem));
    }void CCheckBoxListCtrl::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

    DWORD dwPos = GetMessagePos();
    CPoint point(LOWORD(dwPos), HIWORD(dwPos));
    ScreenToClient(&point);
    UINT nFlag;
    int nItem = HitTest(point, &nFlag);
    if (nFlag == LVHT_ONITEMSTATEICON)
    ScanItemsSetHeadSate(pNMItemActivate->iItem); *pResult = 0;
    }void CCheckBoxListCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMLVCUSTOMDRAW pNMCD = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
    *pResult = 0; int nItemIndex = pNMCD->nmcd.dwItemSpec;
    if (pNMCD->nmcd.dwDrawStage == CDDS_PREPAINT)
    {
    *pResult = CDRF_NOTIFYITEMDRAW;
    }
    else
    {
    if (nItemIndex == m_nHoverIndex)
    { //热点行
    pNMCD->clrTextBk = m_HoverItemBkColor;
    pNMCD->clrText = m_HoverItemTextColor;
    }
    else
    if (GetItemState(nItemIndex, LVIS_SELECTED) == LVIS_SELECTED)
    { //选中行
    pNMCD->clrTextBk = m_SelectItemBkColor;
    pNMCD->clrText = pNMCD->clrFace = m_SelectItemTextColor;
    ::SetTextColor(pNMCD->nmcd.hdc, m_SelectItemTextColor);
    }
    else
    if (nItemIndex % 2 == 0)
    {//偶数行 比如 0、2、4、6
    pNMCD->clrTextBk = m_EvenItemBkColor;
    pNMCD->clrText = m_EvenItemTextColor;
    }
    else
    { //奇数行 比如 1、3、5、7
    pNMCD->clrTextBk = m_OddItemBkColor;
    pNMCD->clrText = m_OddItemTextColor;
    }
    *pResult = CDRF_NEWFONT;
    }
    }
    void CCheckBoxListCtrl::OnMouseMove(UINT nFlags, CPoint point)
    {
    int nIndex = HitTest(point);
    if (nIndex != m_nHoverIndex)
    {
    int nOldIndex = m_nHoverIndex;
    m_nHoverIndex = nIndex;
    CRect rc;
    if (nOldIndex != -1)
    {
    GetItemRect(nOldIndex, &rc, LVIR_BOUNDS);
    InvalidateRect(&rc);
    }
    if (m_nHoverIndex != -1)
    {
    GetItemRect(m_nHoverIndex, &rc, LVIR_BOUNDS);
    InvalidateRect(&rc);
    }
    }
    //=====================================================
    if (!m_bTracking)
    {
    TRACKMOUSEEVENT   tme;
    tme.cbSize = sizeof(tme);
    tme.hwndTrack = m_hWnd;
    tme.dwFlags = TME_LEAVE;//   |   TME_HOVER; 
    tme.dwHoverTime = 1;
    m_bTracking = _TrackMouseEvent(&tme);
    } CBCGPListCtrl::OnMouseMove(nFlags, point);
    }LRESULT CCheckBoxListCtrl::OnMouseLeave(WPARAM wParam, LPARAM lParam)
    {
    m_bTracking = FALSE; if (m_nHoverIndex != -1){
    CRect rc;
    GetItemRect(m_nHoverIndex, &rc, LVIR_BOUNDS);
    m_nHoverIndex = -1;
    InvalidateRect(&rc);
    }
    return 0;
    }
    #pragma once
    // CCheckBoxListCtrlclass CCheckBoxListCtrl : public CBCGPListCtrl
    {
    DECLARE_DYNAMIC(CCheckBoxListCtrl)public:
    CCheckBoxListCtrl();
    virtual ~CCheckBoxListCtrl();
    BOOL Init();
    void SetColCheck();//初始化第1列的复选框图标
    public:
    //设置奇数行背景颜色
    void SetOddItemBkColor(COLORREF color, BOOL bDraw = TRUE);
    //设置偶数行背景颜色
    void SetEvenItemBkColor(COLORREF color, BOOL bDraw = TRUE);
    //设置热点行背景颜色
    void SetHoverItemBkColor(COLORREF color, BOOL bDraw = TRUE);
    //设置选中行背景颜色
    void SetSelectItemBkColor(COLORREF color, BOOL bDraw = TRUE);
    //设置奇数行文本颜色
    void SetOddItemTextColor(COLORREF color, BOOL bDraw = TRUE);
    //设置偶数行文本颜色
    void SetEvenItemTextColor(COLORREF color, BOOL bDraw = TRUE);
    //设置热点行文本颜色
    void SetHoverItemTextColor(COLORREF color, BOOL bDraw = TRUE);
    //设置选中行文本颜色
    void SetSelectItemTextColor(COLORREF color, BOOL bDraw = TRUE);
    protected:
    BOOL m_bTracking;
    int m_nHoverIndex;//当前热点项目索引
    COLORREF m_OddItemBkColor;//奇数行背景颜色
    COLORREF m_EvenItemBkColor;//偶数行背景颜色
    COLORREF m_HoverItemBkColor;//热点行背景颜色
    COLORREF m_SelectItemBkColor;//选中行背景颜色
    COLORREF m_OddItemTextColor;//奇数行文本颜色
    COLORREF m_EvenItemTextColor;//偶数行文本颜色
    COLORREF m_HoverItemTextColor;//热点行文本颜色
    COLORREF m_SelectItemTextColor;//选中行文本颜色
    protected:
    DECLARE_MESSAGE_MAP()
    private:
    BOOL m_blInited;
    CImageList m_checkImgList;
    BOOL m_check;
    void ScanItemsSetHeadSate(int curItem);
    public:
    afx_msg void OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnNMClick(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
    };
    附带了隔行换色的功能,三态复选框部份自己剥离来即可。