65.9K
CodeProject 正在变化。 阅读更多。
Home

带工具提示、编辑、颜色、列隐藏、排序等功能的 MFC 列表控件。

starIconstarIconstarIconstarIconstarIcon

5.00/5 (28投票s)

2018年12月14日

MIT

5分钟阅读

viewsIcon

58370

downloadIcon

2623

带工具提示、编辑、颜色、排序、超链接、列隐藏等功能的自绘列表控件。

用于 MFC 应用程序的列表控件

目录

引言

IListExMFC CMFCListCtrl 类的自绘扩展,具有许多功能

安装

控件的使用很简单

  1. ListEx.hCListEx 添加到您的项目中
  2. 声明 IListExPtr 变量:IListExPtr myList { CreateListEx() };

IListExPtr 是指向 IListEx 类的指针,封装在 std::unique_ptr 中。此包装器主要用于方便,因此您不必担心对象的生命周期,它将自动销毁。这就是为什么调用工厂函数 CreateListEx() 来正确初始化指针的原因。

控件使用自己的命名空间 LISTEX。因此,在声明前是否使用命名空间前缀取决于您

LISTEX::

或在源文件开头定义命名空间

using namespace LISTEX;

Create

手动

Create 是创建列表控件的主要方法。它将 LISTEXCREATE 结构作为参数。

下面是 控件 创建的一个简单示例

IListExPtr myList { CreateListEx() };
.
.
LISTEXCREATE lcs;
lcs.pParent = this;
lcs.uID = ID_MY_LIST;
lcs.rect = CRect(0, 0, 500, 300);

myList->Create(lcs);

在对话框中

要在对话框中创建控件,您可以使用 Create 方法手动完成。

但大多数情况下,您更喜欢通过从 Visual Studio 中的 工具箱 拖放标准 列表控件对话框 模板上。
要使用后一种方法,请遵循以下步骤

  1. 将工具箱中的标准 列表控件 放置到对话框模板上。为其指定适当的 ID (IDC_LISTEX) 并使其达到所需大小。
  2. 在您的对话框类中声明 IListExPtr 成员变量:IListExPtr m_myList { CreateListEx() };
  3. 在您的 OnInitDialog 方法中调用 m_myList->CreateDialogCtrl(IDC_LISTEX, this); 函数。

工具提示

要为给定单元格设置工具提示,只需编写

myList->SetCellTooltip(0, 1, L"Tooltip text", L"Tooltip caption:");

这将为单元格 (0, 1) 设置工具提示,文本为:Tooltip text,标题为 Tooltip caption

排序

要启用排序,请将 LISTEXCREATE::fSortable 标志设置为 true。在这种情况下,当您单击标题时,列表将根据单击的列进行排序。默认情况下,IListEx 执行词典排序。

要设置您自己的排序例程,请使用 SetSortable 方法。

编辑单元格

默认情况下,列表控件以只读模式工作。要启用单元格编辑,请调用 SetColumnEditable 方法,并传入您希望其单元格可编辑的列 ID。

数据对齐

经典的 MFC 列表控件只允许同时设置标题和列文本的对齐方式。
ListEx 允许分别为标题和数据设置对齐方式。InsertColumn() 方法中的 iDataAlign 参数正是负责此功能的。

公共方法

IListEx 类还具有一组附加的公共方法,可帮助您在许多不同方面自定义控件。

隐藏列

void HideColumn(int iIndex, bool fHide);

根据 iIndex 隐藏或显示列。

设置单元格颜色

SetCellColor(int iItem, int iSubitem, COLORREF clrBk, COLORREF clrText = -1);

设置给定单元格的背景和文本颜色。

设置单元格数据

void SetCellData(int iItem, int iSubitem, ULONGLONG ullData);

设置与给定单元格关联的任意应用程序定义数据。

设置单元格工具提示

void SetCellTooltip(int iItem, int iSubitem, std::wstring_view wstrTooltip, std::wstring_view wstrCaption = L"");

设置给定单元格的工具提示和标题。

设置列可编辑

void SetColumnEditable(int iColumn, bool fEditable);

启用或禁用给定列的编辑模式。

设置标题列图标

void SetHdrColumnIcon(int iColumn, int iIconIndex, bool fClick = false);

设置给定 iColumn 的标题图像列表中的图标索引。要从列中删除图标,请将 iIconIndex 设置为 -1
标志 fClick 表示图标是可点击的。有关更多信息,请参见 LISTEX_MSG_HDRICONCLICK 消息。

设置标题高度

void SetHdrHeight(DWORD dwHeight);

设置可排序

void SetSortable(bool fSortable, PFNLVCOMPARE pfnCompare = nullptr, EListExSortMode enSortMode = EListExSortMode::SORT_LEX)

参数

bool fSortable
启用或禁用排序

PFNLVCOMPARE pfnCompare
回调函数指针,类型为 int (CALLBACK *PFNLVCOMPARE)(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),用于设置您自己的比较函数。如果为 nullptrIListEx 将执行默认排序。
比较函数必须是类的静态成员或非任何类的独立函数。有关更多信息,请参见官方 MSDN 文档

EListExSortMode enSortMode
列表的默认排序模式。

结构体

LISTEXCREATE

struct LISTEXCREATE {
    LISTEXCOLORS stColor { };             //All control's colors.
    CRect        rect;                    //Initial rect.
    CWnd*        pParent { };             //Parent window.
    LOGFONTW*    pListLogFont { };        //List font.
    LOGFONTW*    pHdrLogFont { };         //Header font.
    UINT         uID { };                 //List control ID.
    DWORD        dwStyle { };             //Control's styles. Zero for default.
    DWORD        dwListGridWidth { 1 };   //Width of the list grid.
    DWORD        dwHdrHeight { };         //Header height.
    bool         fDialogCtrl { false };   //If it's a list within dialog.
    bool         fSortable { false };     //Is list sortable, by clicking on the header column?
    bool         fLinkUnderline { true }; //Links are displayed underlined or not.
    bool         fTooltipBaloon { true }; //Baloon type tooltip for cells.
    bool         fLinkTooltip { true };   //Show links' toolips.
    bool         fHighLatency { false };  //Do not redraw window until scrolling completes.
};

LISTEXCOLORS

struct LISTEXCOLORS
{
    COLORREF clrListText { GetSysColor(COLOR_WINDOWTEXT) };       //List text color.
    COLORREF clrListTextLink { RGB(0, 0, 200) };                  //List hyperlink text color.
    COLORREF clrListTextSel { GetSysColor(COLOR_HIGHLIGHTTEXT) }; //Selected item text color.
    COLORREF clrListTextLinkSel { RGB(250, 250, 250) };           //List hyperlink text color in selected cell.
    COLORREF clrListTextCellTt { GetSysColor(COLOR_WINDOWTEXT) }; //Text color of a cell that has tooltip.
    COLORREF clrListBkRow1 { GetSysColor(COLOR_WINDOW) };         //List Bk color of the odd rows.
    COLORREF clrListBkRow2 { GetSysColor(COLOR_WINDOW) };         //List Bk color of the even rows.
    COLORREF clrListBkSel { GetSysColor(COLOR_HIGHLIGHT) };       //Selected item bk color.
    COLORREF clrListBkCellTt { RGB(170, 170, 230) };              //Bk color of a cell that has tooltip.
    COLORREF clrListGrid { RGB(220, 220, 220) };                  //List grid color.
    COLORREF clrTooltipText { GetSysColor(COLOR_INFOTEXT) };      //Tooltip window text color.
    COLORREF clrTooltipBk { GetSysColor(COLOR_INFOBK) };          //Tooltip window bk color.
    COLORREF clrHdrText { GetSysColor(COLOR_WINDOWTEXT) };        //List header text color.
    COLORREF clrHdrBk { GetSysColor(COLOR_WINDOW) };              //List header bk color.
    COLORREF clrHdrHglInact { GetSysColor(COLOR_GRADIENTINACTIVECAPTION) };//Header highlight inactive.
    COLORREF clrHdrHglAct { GetSysColor(COLOR_GRADIENTACTIVECAPTION) };    //Header highlight active.
    COLORREF clrNWABk { GetSysColor(COLOR_WINDOW) };              //Bk of Non Working Area.
};

此结构也用于 SetColor 方法。

LISTEXCOLOR

struct LISTEXCOLOR
{
    COLORREF clrBk { };
    COLORREF clrText { };
};
using PLISTEXCOLOR = LISTEXCOLOR*;

LISTEXHDRICON

struct LISTEXHDRICON
{
    POINT pt { };              //Point of the top-left corner.
    int   iIconIndex { };      //Icon index in the header's image list.
    bool  fClickable { true }; //Is icon sending LISTEX_MSG_HDRICONCLICK message when clicked.
};

EListExSortMode

枚举显示列表列的排序类型。

enum class EListExSortMode : short
{
    SORT_LEX, SORT_NUMERIC
};

通知消息

这些消息以 WM_NOTIFY 窗口消息的形式发送到父窗口。
lParam 将包含指向 NMHDR 标准 Windows 结构的指针。NMHDR::code 可以是下面描述的 LISTEX_MSG_... 消息之一。

LISTEX_MSG_GETCOLOR

在虚拟模式下,发送到父窗口以检索单元格的颜色。期望响应中包含指向 LISTEXCOLOR 结构的指针,或者不包含任何内容以使用默认值。

void CListDlg::OnListExGetColor(NMHDR* pNMHDR, LRESULT* /*pResult*/)
{
    const auto pNMI = reintepret_cast<NMITEMACTIVATE*>(pNMHDR);

    //For column number 1 (all rows) set color to RGB(0, 220, 220).
    if (pNMI->iSubItem == 1)
    {
        static LISTEXCOLOR clr { RGB(0, 220, 220), RGB(0, 0, 0) };
        pNMI->lParam = reinterpret_cast<LPARAM>(&clr);
    }
}

LISTEX_MSG_GETICON

void CListDlg::OnListExGetIcon(NMHDR* pNMHDR, LRESULT* /*pResult*/)
{
    //Virtual data icons.
    const auto pNMI = reinterpret_cast<NMITEMACTIVATE*>(pNMHDR);
    ...
	
    pNMI->lParam = SomeIndex; //Icon index in list's image list.
}

此消息在虚拟列表模式下用于获取列表图像列表中的图标索引。

LISTEX_MSG_LINKCLICK

列表嵌入超链接已被点击。WM_NOTIFY lParam 将指向 NMITEMACTIVATE 结构。
NMITEMACTIVATE::lParam 将包含指向点击超链接的 link 文本的 wchar_t* 指针。iItemiSubItem 成员将包含点击链接的列表项/子项的索引。

超链接语法为:L"带有 嵌入链接 的文本"
如果没有提供可选的 title 标签,则 link 文本本身将用作超链接的工具提示。
链接和标题文本必须用引号 "" 括起来。

LISTEX_MSG_HDRICONCLICK

先前通过 SetHdrColumnIcon 调用设置的标题图标已被点击。
处理此消息的示例代码

BOOL CMyDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    const auto pNMI = reinterpret_cast<LPNMITEMACTIVATE>(lParam);

    if (pNMI->hdr.code == LISTEX_MSG_HDRICONCLICK && pNMI->hdr.idFrom == IDC_MYLIST)
    {
    	const auto pNMI = reinterpret_cast<NMHEADERW*>(lParam);
    	//pNMI->iItem holds clicked column index.
    }
    ...

LISTEX_MSG_EDITBEGIN

当数据编辑框即将显示时发送。如果您不想让它显示,可以在响应中将 lParam 设置为 0

BOOL CMyDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    const auto pNMI = reinterpret_cast<LPNMITEMACTIVATE>(lParam);
    pNMI->lParam = 0; //Edit-box won't show up.
    ...

LISTEX_MSG_DATACHANGED

在虚拟模式下,当单元格文本发生更改时发送。

BOOL CMyDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    const auto pNMI = reinterpret_cast<LPNMITEMACTIVATE>(lParam);
    const auto iItem = pNMI->iItem;
    const auto iSubItem = pNMI->iSubItem;
    const pwszNewText = reinterpret_cast<LPCWSTR>(pNMI->lParam);
    ...

示例

假设您需要一个具有非标准标题高度和黄色背景色的列表控件。没有什么比这更简单的了,请看下面的代码

LISTEXCREATE lcs;
lcs.rect = CRect(0, 0, 500, 300)
lcs.pParent = this;
lcs.dwHdrHeight = 50;
lcs.stColor.clrListBkRow1 = RGB(255, 255, 0);
lcs.stColor.clrListBkRow2 = RGB(255, 255, 0);

myList->Create(lcs);

myList->InsertColumn(...);
myList->InsertItem(...);

在这里,我们将偶数行和奇数行(clrListBkRow1clrListBkRow2)都设置为相同的黄色。

外观

通过 Ctrl+鼠标滚轮 组合,您可以动态更改列表的字体大小。

© . All rights reserved.