CMyListCtrl

1. MyListCtrl.h

#pragma once
#include <vector>
#include "resource.h"
// CMyListCtrl
#ifdef DLL_IMPLEMENT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API  __declspec(dllimport)
#endif

typedef unsigned int    UINT;
#define ID_LIST_SET_FONT 1001
#define ID_LIST_SAVE_ALL 1002

class DLL_API CMyListCtrl : public CListCtrl
{
    struct SColumn
    {
        UINT index, order, width;
        TCHAR name[128];
    };
    std::vector<SColumn> m_vecColumn;
    COLORREF m_clrFore, m_clrBack;
    CFont m_font;
    CString m_strCfgFileName;
    int m_nSortCol;//排序列的索引,-1表示无排序列
    bool m_bAscent;//true:升序  false:降序
    CImageList m_imgList;//列表头的排序图标

    DECLARE_DYNAMIC(CMyListCtrl)

public:
    CMyListCtrl();
    virtual ~CMyListCtrl();

protected:
    DECLARE_MESSAGE_MAP()
public:
    // 用配置文件填充列
    void FillColumn(LPCTSTR szConfigFileName);
private:

    // 保存颜色信息到ini文件
    void WriteColorInfoINI(const CString& strCfgFileName)
    {
        ::WritePrivateProfileStruct(_T("COLOR"), _T("color_fore"), &m_clrFore, sizeof(m_clrFore), strCfgFileName);
    }

    // 从ini配置文件获取颜色信息
    void GetColorInfoINI(const CString& strCfgFileName)
    {
        ::GetPrivateProfileStruct(_T("COLOR"), _T("color_fore"), &m_clrFore, sizeof(m_clrFore), strCfgFileName);
    }

    // 保存字体信息到ini配置文件
    void WriteFontInfoINI(const CString& strCfgFileName)
    {
        LOGFONT lf;
        GetFont()->GetLogFont(&lf);
        ::WritePrivateProfileStruct(_T("FONT"), _T("lf"), &lf, sizeof(lf), strCfgFileName);
    }

    // 从ini配置文件中获取字体信息
    void GetFontInfoINI(const CString& strCfgFileName)
    {
        LOGFONT lf;
        if (::GetPrivateProfileStruct(_T("FONT"), _T("lf"), &lf, sizeof(lf), strCfgFileName))
        {
            m_font.DeleteObject();
            m_font.CreateFontIndirect(&lf);
        }
        else
        {
            m_font.DeleteObject();
            m_font.CreateFont(20, 0, 0, 0, 400, 0, 0, 0, GB2312_CHARSET,
                OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_ROMAN, _T("微软雅黑"));
        }
    }

    // 保存列信息到ini文件
    void WriteColumnInfoINI(const CString& strCfgFileName)
    {
        CHeaderCtrl* pHeader = GetHeaderCtrl();
        if (NULL == pHeader)
            return;
        int nCount = pHeader->GetItemCount();
        if (0 == nCount)
            return;
        int* pOrder = new int[nCount];
        GetColumnOrderArray(pOrder, nCount);
        CString strSection, strOrder, strColumnWidth;
        for (int i = 0; i < nCount; ++i)
        {
            strSection.Format(_T("%d"), i);
            strOrder.Format(_T("%d"), pOrder[i]);
            strColumnWidth.Format(_T("%d"), GetColumnWidth(i));
            ::WritePrivateProfileString(strSection, _T("Order"), strOrder, strCfgFileName);
            ::WritePrivateProfileString(strSection, _T("Width"), strColumnWidth, strCfgFileName);
        }
        delete[] pOrder;

    }

    static int CALLBACK pfnSort(LPARAM lp1, LPARAM lp2, LPARAM lpSort);

    virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
public:
    afx_msg void OnSetFont();
    afx_msg void OnSaveAll();
    afx_msg void OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult);
    // 初始化一些变量,像m_imgList
    void InitListCtrl();
};
View Code

2. MyListCtrl.cpp

// MyListCtrl.cpp : 实现文件
//

#include "stdafx.h"
#define DLL_IMPLEMENT
#include "MyListCtrl.h"


// CMyListCtrl

IMPLEMENT_DYNAMIC(CMyListCtrl, CListCtrl)

CMyListCtrl::CMyListCtrl()
{
    //m_nSortCol = -1;
    //m_bAscent = true;
}

CMyListCtrl::~CMyListCtrl()
{
}


BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
    ON_COMMAND(ID_LIST_SET_FONT, OnSetFont)
    ON_COMMAND(ID_LIST_SAVE_ALL, OnSaveAll)
    ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, &CMyListCtrl::OnLvnColumnclick)
END_MESSAGE_MAP()



// CMyListCtrl 消息处理程序




// 用配置文件填充列
void CMyListCtrl::FillColumn(LPCTSTR szConfigFileName)
{
    m_strCfgFileName = szConfigFileName;
    CString strSection; 
    TCHAR szName[512] = { 0 };
    for (UINT i = 0; true; ++i)
    {
        SColumn sC;
        strSection.Format(_T("%d"), i);
        sC.order = ::GetPrivateProfileInt(strSection, _T("Order"), -1, m_strCfgFileName);
        if (-1 == sC.order)
            break;
        sC.width = ::GetPrivateProfileInt(strSection, _T("Width"), -1, m_strCfgFileName);
        ::GetPrivateProfileString(strSection, _T("ColumnName"), _T("-1"), sC.name, sizeof(sC.name)/sizeof(sC.name[0]), m_strCfgFileName);
        m_vecColumn.push_back(sC);
    }
    //插入列
    for (UINT i = 0; i < m_vecColumn.size(); ++i)
    {
        auto& c = m_vecColumn.at(i);
        InsertColumn(i, c.name, 0, c.width);
    }
    //按order排序
    UINT nCount = m_vecColumn.size();
    if (0 == nCount) return;
    int* arrOrder = new int[nCount];
    for (UINT i = 0; i < nCount; ++i)
    {
        arrOrder[i] = m_vecColumn[i].order;
    }
    SetColumnOrderArray(nCount, arrOrder);
    delete[] arrOrder;

    //获取字体,设置字体
    GetFontInfoINI(m_strCfgFileName);
    SetFont(&m_font);
}


BOOL CMyListCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    // TODO:  在此添加专用代码和/或调用基类
    if (0 == wParam && ((NMHDR*)lParam)->code == NM_RCLICK)
    {
        POINT pt;
        GetCursorPos(&pt);
        CMenu menu;
        menu.CreatePopupMenu();
        menu.AppendMenu(MF_STRING, ID_LIST_SET_FONT, _T("字体..."));
        menu.AppendMenu(MF_STRING, ID_LIST_SAVE_ALL, _T("保存所有设置"));
        menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
    }

    return CListCtrl::OnNotify(wParam, lParam, pResult);
}


void CMyListCtrl::OnSetFont()
{
    LOGFONT lf;
    GetFont()->GetLogFont(&lf);
    CFontDialog dlg(&lf, CF_SCREENFONTS, NULL, this);
    if (IDOK == dlg.DoModal())
    {
        m_font.DeleteObject();
        m_font.CreateFontIndirect(&dlg.m_lf);
        SetFont(&m_font);
    }
}
void CMyListCtrl::OnSaveAll()
{
    WriteFontInfoINI(m_strCfgFileName);
    WriteColumnInfoINI(m_strCfgFileName);
}


void CMyListCtrl::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
{
    //LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    //// TODO:  在此添加控件通知处理程序代码
    //*pResult = 0;

    //当点击不同的列表头时显示对应的排序图标
    NM_LISTVIEW* p = (NM_LISTVIEW*)pNMHDR;
    int nSub = p->iSubItem;//点击的列的索引
    CHeaderCtrl* pHeader = GetHeaderCtrl();

/* 方法1:用自己的图标或位图
    //pHeader->SetImageList(&m_imgList);
    HDITEM hdi = { HDI_IMAGE | HDI_FORMAT };
    if (nSub != m_nSortCol)
    {//点击不同列时,删除旧的列图标
        if (m_nSortCol > -1)
        {
            HDITEM hdi = { HDI_FORMAT };
            pHeader->GetItem(m_nSortCol, &hdi);
            hdi.fmt &= ~HDF_IMAGE ;//移除排序图标,win7下有问题,去不掉,加上 HDITEM hdi = { HDI_FORMAT };解决,看来开关mask很重要
            pHeader->SetItem(m_nSortCol, &hdi);
        }
        m_nSortCol = nSub;
    }
    else
    {//点击相同列时,显示相反排序图标
        m_bAscent = !m_bAscent;
    }
    pHeader->GetItem(nSub, &hdi);
    hdi.fmt |= HDF_IMAGE | HDF_BITMAP_ON_RIGHT;
    hdi.iImage = m_bAscent;
    pHeader->SetItem(nSub, &hdi);
*/
    //方法2:用系统提供的排序图标
    HDITEM hdi = { HDI_FORMAT };
    if (nSub != m_nSortCol)
    {//点击不同列时,删除旧的列图标
        if (m_nSortCol > -1)
        {
            pHeader->GetItem(m_nSortCol, &hdi);
            hdi.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
            pHeader->SetItem(m_nSortCol, &hdi);
        }
        m_nSortCol = nSub;
    }
    else
    {//点击相同列时,显示相反排序图标
        m_bAscent = !m_bAscent;
    }
    pHeader->GetItem(nSub, &hdi);
    hdi.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
    hdi.fmt |= (m_bAscent ? HDF_SORTUP : HDF_SORTDOWN);
    pHeader->SetItem(nSub, &hdi);



    //排序前,要将所有列表项的索引保存到关联数据中
    int i = GetItemCount();
    while(i--)
    {
        SetItemData(i, i);
    }
    SortItems(pfnSort, (DWORD)this); // 排序第二个参数是比较函数的第三个参数


    *pResult = 0;
}

int CALLBACK CMyListCtrl::pfnSort(LPARAM lp1, LPARAM lp2, LPARAM lpSort)
{
    CMyListCtrl* p = (CMyListCtrl*)lpSort;
    CString s1 = p->GetItemText(lp1, p->m_nSortCol);
    CString s2 = p->GetItemText(lp2, p->m_nSortCol);
    if (p->m_bAscent)
        return s2 < s1;
    else
        return s1 < s2;
}

// 初始化一些变量,像m_imgList
void CMyListCtrl::InitListCtrl()
{
    m_imgList.Create(16, 16, ILC_COLOR32 | ILC_MASK, 2, 4);
    CBitmap b1, b2;
    b1.LoadBitmap(IDB_ASCENT);
    b2.LoadBitmap(IDB_DESCENT);
    m_imgList.Add(&b2, RGB(255, 255, 255));
    m_imgList.Add(&b1, RGB(255, 255, 255));

    CHeaderCtrl* pHeader = GetHeaderCtrl();
    pHeader->SetImageList(&m_imgList);

    m_nSortCol = -1;
    m_bAscent = false;
}
View Code

 列配置文件 SetListing.ini

[0]
order=0
width=193
columnName=column1
[1]
order=1
width=193
columnName=column2
[2]
order=2
width=235
columnName=column3
...

在OnInitDialog中,添加

//成员变量 CMyListCtrl m_list;
    CRect rect;
    GetClientRect(rect);
    rect.bottom -= 70;
    m_list.Create(WS_VISIBLE | WS_CHILD | LVS_REPORT, rect, this, 10001);
    m_list.SetExtendedStyle(m_list.GetExStyle() | LVS_EX_FULLROWSELECT //| LVS_EX_GRIDLINES 
        | LVS_EX_HEADERDRAGDROP);
    m_list.InitListCtrl();
    CString strCfgPath = myFunctions::GetExeDir() + _T("\\SetListing.ini");
    m_list.FillColumn(strCfgPath.GetString());
    //m_list.InsertColumn(0, _T("jjj"), 0, 100);
    //m_list.InsertColumn(1, _T("jjj1"), 0, 100);
    //m_list.InsertColumn(2, _T("jjj2"), 0, 100);
    m_list.InsertItem(0, _T("123"));
    m_list.SetItemText(0, 1, _T("ss1"));
    m_list.SetItemText(0, 2, _T("dd1"));
    m_list.InsertItem(1, _T("222"));
    m_list.SetItemText(1, 1, _T("ss2"));
    m_list.SetItemText(1, 2, _T("dd2"));

 

 

系统默认的排序图标:

 

自己画的图标或位图:

 

posted @ 2019-12-07 15:10  htj10  阅读(280)  评论(0编辑  收藏  举报
TOP