C++ MFC-带有可选复选框的CListCtrl行

C++ MFC-带有可选复选框的CListCtrl行,c++,mfc,clistctrl,clistbox,C++,Mfc,Clistctrl,Clistbox,在运行时,我试图使用MFC创建一个单列自定义CListCtrl(或CMFCListCtrl,但不是CheckListBox——我希望将来能够添加多个列)。使用LVS\u EX\u复选框style会强制所有项目都有该复选框。所需控件应如下所示(item1和item3有复选框,item2没有): 从用户的角度来看,所需的列表控件应如下创建: int main() { MyCListCtrl list_control; list_control.AddItem("item1", tr

在运行时,我试图使用MFC创建一个单列自定义
CListCtrl
(或
CMFCListCtrl
,但不是
CheckListBox
——我希望将来能够添加多个列)。使用
LVS\u EX\u复选框
style会强制所有项目都有该复选框。所需控件应如下所示(item1和item3有复选框,item2没有):

从用户的角度来看,所需的列表控件应如下创建:

int main() {
    MyCListCtrl list_control;
    list_control.AddItem("item1", true) // true indicates checkbox presence
    list_control.AddItem("item2", false) // false - item without checkbox
    list_control.AddItem("item3", true) // true indicates checkbox presence
}
    void MyCListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
    {
        *pResult = CDRF_DODEFAULT; // default windows painting
        LPNMLVCUSTOMDRAW lpn = (LPNMLVCUSTOMDRAW)pNMHDR;

        if (CDDS_PREPAINT == lpn->nmcd.dwDrawStage)
        {
            *pResult = CDRF_NOTIFYITEMDRAW; // notify on every item
        }
        else if (CDDS_ITEMPREPAINT == lpn->nmcd.dwDrawStage)
        {
            int row = lpn->nmcd.dwItemSpec;
            if (row == 1) {
                lpn->nmcd.rc.left -= 16; // not working
                lpn->rcText.left -= 16; // not working

                SetItemState(row, INDEXTOSTATEIMAGEMASK(0), 
                                  LVIS_STATEIMAGEMASK); // erase checkbox
            }
        }
    }
到目前为止,我能够创建这样的控件,但是添加
LVS_OWNERDRAWFIXED
会在调用基类
CListCtrl::DrawItem
方法时触发失败的断言:

这就是我的(不起作用的)解决方案的样子,如果你知道如何解决这个问题,也许更简单,请让我知道。谢谢

编辑

在@landstapper的帮助下,我现在可以用自定义图形删除复选框,但我仍然需要将文本移到左侧(因此它取代了不存在的复选框,如上图所示)。当前解决方案会导致此结果:

这是通过如下方式处理NM_CUSTOMDRAW消息实现的:

int main() {
    MyCListCtrl list_control;
    list_control.AddItem("item1", true) // true indicates checkbox presence
    list_control.AddItem("item2", false) // false - item without checkbox
    list_control.AddItem("item3", true) // true indicates checkbox presence
}
    void MyCListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
    {
        *pResult = CDRF_DODEFAULT; // default windows painting
        LPNMLVCUSTOMDRAW lpn = (LPNMLVCUSTOMDRAW)pNMHDR;

        if (CDDS_PREPAINT == lpn->nmcd.dwDrawStage)
        {
            *pResult = CDRF_NOTIFYITEMDRAW; // notify on every item
        }
        else if (CDDS_ITEMPREPAINT == lpn->nmcd.dwDrawStage)
        {
            int row = lpn->nmcd.dwItemSpec;
            if (row == 1) {
                lpn->nmcd.rc.left -= 16; // not working
                lpn->rcText.left -= 16; // not working

                SetItemState(row, INDEXTOSTATEIMAGEMASK(0), 
                                  LVIS_STATEIMAGEMASK); // erase checkbox
            }
        }
    }

经过长时间的调查。。。我为您找到了一个解决方案:使用
SetItemState()
magic函数:

Remarque:拥有多个列不是问题

MyCListCtrl.h

class MyCListCtrl : public CListCtrl 
{
    DECLARE_DYNAMIC(MyCListCtrl)

public:
    afx_msg void DrawItem(NMHDR* pNMHDR, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
};  
IMPLEMENT_DYNAMIC(MyCListCtrl, CListCtrl)

BEGIN_MESSAGE_MAP(MyCListCtrl, CListCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, DrawItem)
END_MESSAGE_MAP()

void MyCListCtrl::DrawItem(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
    LPNMLVCUSTOMDRAW  pLPN = (LPNMLVCUSTOMDRAW)pNMHDR;
    int iRow = pLPN->nmcd.dwItemSpec;

    // Get item flag : true or false (true we show checkbox, false we hide it)
    // Here i simulate, i disable rows 1 and 3
    SetItemState(1, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);
    SetItemState(3, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);

    switch(pLPN->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT | CDDS_ITEM | CDDS_SUBITEM :
        {
            *pResult = CDRF_DODEFAULT | CDRF_DOERASE; return;
        }
    case CDDS_PREPAINT :
        {
            *pResult = CDRF_NOTIFYITEMDRAW; return;
        }
    case CDDS_ITEMPREPAINT:
        {
            pLPN->clrText = RGB(0,0,0);
            *pResult = CDRF_NOTIFYSUBITEMDRAW;  return;
        }
    }
}  
CRect rect (30, 30, 180, 180);
list_control.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER |LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST2);
list_control.SetExtendedStyle(list_control.GetExtendedStyle() | LVS_EX_FLATSB | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);

LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 70; 
lvColumn.pszText = "Column 1";
list_control.InsertColumn(0, &lvColumn);  

lvColumn.pszText = "Column 2";
list_control.InsertColumn(1, &lvColumn);

//// add 1 test item
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = "Test";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Stack";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Over";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Flow";
list_control.InsertItem(&lvItem);
MyCListCtrl.cpp

class MyCListCtrl : public CListCtrl 
{
    DECLARE_DYNAMIC(MyCListCtrl)

public:
    afx_msg void DrawItem(NMHDR* pNMHDR, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
};  
IMPLEMENT_DYNAMIC(MyCListCtrl, CListCtrl)

BEGIN_MESSAGE_MAP(MyCListCtrl, CListCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, DrawItem)
END_MESSAGE_MAP()

void MyCListCtrl::DrawItem(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
    LPNMLVCUSTOMDRAW  pLPN = (LPNMLVCUSTOMDRAW)pNMHDR;
    int iRow = pLPN->nmcd.dwItemSpec;

    // Get item flag : true or false (true we show checkbox, false we hide it)
    // Here i simulate, i disable rows 1 and 3
    SetItemState(1, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);
    SetItemState(3, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);

    switch(pLPN->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT | CDDS_ITEM | CDDS_SUBITEM :
        {
            *pResult = CDRF_DODEFAULT | CDRF_DOERASE; return;
        }
    case CDDS_PREPAINT :
        {
            *pResult = CDRF_NOTIFYITEMDRAW; return;
        }
    case CDDS_ITEMPREPAINT:
        {
            pLPN->clrText = RGB(0,0,0);
            *pResult = CDRF_NOTIFYSUBITEMDRAW;  return;
        }
    }
}  
CRect rect (30, 30, 180, 180);
list_control.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER |LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST2);
list_control.SetExtendedStyle(list_control.GetExtendedStyle() | LVS_EX_FLATSB | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);

LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 70; 
lvColumn.pszText = "Column 1";
list_control.InsertColumn(0, &lvColumn);  

lvColumn.pszText = "Column 2";
list_control.InsertColumn(1, &lvColumn);

//// add 1 test item
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = "Test";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Stack";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Over";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Flow";
list_control.InsertItem(&lvItem);
MainDlg.cpp

class MyCListCtrl : public CListCtrl 
{
    DECLARE_DYNAMIC(MyCListCtrl)

public:
    afx_msg void DrawItem(NMHDR* pNMHDR, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
};  
IMPLEMENT_DYNAMIC(MyCListCtrl, CListCtrl)

BEGIN_MESSAGE_MAP(MyCListCtrl, CListCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, DrawItem)
END_MESSAGE_MAP()

void MyCListCtrl::DrawItem(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
    LPNMLVCUSTOMDRAW  pLPN = (LPNMLVCUSTOMDRAW)pNMHDR;
    int iRow = pLPN->nmcd.dwItemSpec;

    // Get item flag : true or false (true we show checkbox, false we hide it)
    // Here i simulate, i disable rows 1 and 3
    SetItemState(1, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);
    SetItemState(3, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);

    switch(pLPN->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT | CDDS_ITEM | CDDS_SUBITEM :
        {
            *pResult = CDRF_DODEFAULT | CDRF_DOERASE; return;
        }
    case CDDS_PREPAINT :
        {
            *pResult = CDRF_NOTIFYITEMDRAW; return;
        }
    case CDDS_ITEMPREPAINT:
        {
            pLPN->clrText = RGB(0,0,0);
            *pResult = CDRF_NOTIFYSUBITEMDRAW;  return;
        }
    }
}  
CRect rect (30, 30, 180, 180);
list_control.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER |LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST2);
list_control.SetExtendedStyle(list_control.GetExtendedStyle() | LVS_EX_FLATSB | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);

LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 70; 
lvColumn.pszText = "Column 1";
list_control.InsertColumn(0, &lvColumn);  

lvColumn.pszText = "Column 2";
list_control.InsertColumn(1, &lvColumn);

//// add 1 test item
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = "Test";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Stack";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Over";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Flow";
list_control.InsertItem(&lvItem);

经过长时间的调查。。。我为您找到了一个解决方案:使用
SetItemState()
magic函数:

Remarque:拥有多个列不是问题

MyCListCtrl.h

class MyCListCtrl : public CListCtrl 
{
    DECLARE_DYNAMIC(MyCListCtrl)

public:
    afx_msg void DrawItem(NMHDR* pNMHDR, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
};  
IMPLEMENT_DYNAMIC(MyCListCtrl, CListCtrl)

BEGIN_MESSAGE_MAP(MyCListCtrl, CListCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, DrawItem)
END_MESSAGE_MAP()

void MyCListCtrl::DrawItem(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
    LPNMLVCUSTOMDRAW  pLPN = (LPNMLVCUSTOMDRAW)pNMHDR;
    int iRow = pLPN->nmcd.dwItemSpec;

    // Get item flag : true or false (true we show checkbox, false we hide it)
    // Here i simulate, i disable rows 1 and 3
    SetItemState(1, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);
    SetItemState(3, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);

    switch(pLPN->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT | CDDS_ITEM | CDDS_SUBITEM :
        {
            *pResult = CDRF_DODEFAULT | CDRF_DOERASE; return;
        }
    case CDDS_PREPAINT :
        {
            *pResult = CDRF_NOTIFYITEMDRAW; return;
        }
    case CDDS_ITEMPREPAINT:
        {
            pLPN->clrText = RGB(0,0,0);
            *pResult = CDRF_NOTIFYSUBITEMDRAW;  return;
        }
    }
}  
CRect rect (30, 30, 180, 180);
list_control.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER |LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST2);
list_control.SetExtendedStyle(list_control.GetExtendedStyle() | LVS_EX_FLATSB | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);

LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 70; 
lvColumn.pszText = "Column 1";
list_control.InsertColumn(0, &lvColumn);  

lvColumn.pszText = "Column 2";
list_control.InsertColumn(1, &lvColumn);

//// add 1 test item
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = "Test";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Stack";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Over";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Flow";
list_control.InsertItem(&lvItem);
MyCListCtrl.cpp

class MyCListCtrl : public CListCtrl 
{
    DECLARE_DYNAMIC(MyCListCtrl)

public:
    afx_msg void DrawItem(NMHDR* pNMHDR, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
};  
IMPLEMENT_DYNAMIC(MyCListCtrl, CListCtrl)

BEGIN_MESSAGE_MAP(MyCListCtrl, CListCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, DrawItem)
END_MESSAGE_MAP()

void MyCListCtrl::DrawItem(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
    LPNMLVCUSTOMDRAW  pLPN = (LPNMLVCUSTOMDRAW)pNMHDR;
    int iRow = pLPN->nmcd.dwItemSpec;

    // Get item flag : true or false (true we show checkbox, false we hide it)
    // Here i simulate, i disable rows 1 and 3
    SetItemState(1, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);
    SetItemState(3, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);

    switch(pLPN->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT | CDDS_ITEM | CDDS_SUBITEM :
        {
            *pResult = CDRF_DODEFAULT | CDRF_DOERASE; return;
        }
    case CDDS_PREPAINT :
        {
            *pResult = CDRF_NOTIFYITEMDRAW; return;
        }
    case CDDS_ITEMPREPAINT:
        {
            pLPN->clrText = RGB(0,0,0);
            *pResult = CDRF_NOTIFYSUBITEMDRAW;  return;
        }
    }
}  
CRect rect (30, 30, 180, 180);
list_control.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER |LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST2);
list_control.SetExtendedStyle(list_control.GetExtendedStyle() | LVS_EX_FLATSB | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);

LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 70; 
lvColumn.pszText = "Column 1";
list_control.InsertColumn(0, &lvColumn);  

lvColumn.pszText = "Column 2";
list_control.InsertColumn(1, &lvColumn);

//// add 1 test item
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = "Test";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Stack";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Over";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Flow";
list_control.InsertItem(&lvItem);
MainDlg.cpp

class MyCListCtrl : public CListCtrl 
{
    DECLARE_DYNAMIC(MyCListCtrl)

public:
    afx_msg void DrawItem(NMHDR* pNMHDR, LRESULT* pResult);
    DECLARE_MESSAGE_MAP()
};  
IMPLEMENT_DYNAMIC(MyCListCtrl, CListCtrl)

BEGIN_MESSAGE_MAP(MyCListCtrl, CListCtrl)
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, DrawItem)
END_MESSAGE_MAP()

void MyCListCtrl::DrawItem(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0;
    LPNMLVCUSTOMDRAW  pLPN = (LPNMLVCUSTOMDRAW)pNMHDR;
    int iRow = pLPN->nmcd.dwItemSpec;

    // Get item flag : true or false (true we show checkbox, false we hide it)
    // Here i simulate, i disable rows 1 and 3
    SetItemState(1, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);
    SetItemState(3, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);

    switch(pLPN->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT | CDDS_ITEM | CDDS_SUBITEM :
        {
            *pResult = CDRF_DODEFAULT | CDRF_DOERASE; return;
        }
    case CDDS_PREPAINT :
        {
            *pResult = CDRF_NOTIFYITEMDRAW; return;
        }
    case CDDS_ITEMPREPAINT:
        {
            pLPN->clrText = RGB(0,0,0);
            *pResult = CDRF_NOTIFYSUBITEMDRAW;  return;
        }
    }
}  
CRect rect (30, 30, 180, 180);
list_control.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER |LBS_OWNERDRAWVARIABLE , rect, this, IDC_LIST2);
list_control.SetExtendedStyle(list_control.GetExtendedStyle() | LVS_EX_FLATSB | LVS_EX_CHECKBOXES | LVS_EX_GRIDLINES);

LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = 70; 
lvColumn.pszText = "Column 1";
list_control.InsertColumn(0, &lvColumn);  

lvColumn.pszText = "Column 2";
list_control.InsertColumn(1, &lvColumn);

//// add 1 test item
LVITEM lvItem;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.pszText = "Test";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Stack";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Over";
list_control.InsertItem(&lvItem);

lvItem.pszText = "Flow";
list_control.InsertItem(&lvItem);

这也不例外。这是一个失败的调试断言。对话框告诉你如何继续。对不起,我在那里犯了一个错误。现在我明白了,出于某种原因,函数中有ASSERT(FALSE)。我需要找到另一种方法,继续寻找答案。这也不例外。这是一个失败的调试断言。对话框告诉你如何继续。对不起,我在那里犯了一个错误。现在我明白了,出于某种原因,函数中有ASSERT(FALSE)。我需要找到另一种方法,继续搜索答案。
LBS_OWNERDRAWVARIABLE
会强制系统调用
MeasureItem
函数,但我是否能够将项目移到左侧?该函数向我发送
MEASUREITEMSTRUCT
结构,但没有“左边框”字段,我可以使用它进行操作。另外,我需要动态创建列表框,而不是通过工具箱,但我下次会先尝试,谢谢。@mrdecompilator我知道你是动态创建控件的,这只是为了将来帮助你:)发布你的
DrawItem()
函数的完整代码现在,它是空的,但是
DrawItem
发送
DRAWITEMSTRUCT
,它具有带有项目矩形的
rcItem
字段,因此我可以执行类似于
rcItem.left-=20的操作。我已经使用了
CCheckListBox
,但后来我意识到,用户可能希望在将来添加多个列。@mrdecompilator在编辑的答案代码中,我只需将两列搜索一下,就可以得到一个令人精疲力竭的答案!出于某种原因,使用此代码,列表包含网格,但似乎没有任何项。然后我发现,他们都在那里,但都是白色或其他东西(他们可以被选中,但看不见)。当我删除整个
开关时
项目正常显示。现在的问题是,没有复选框的行有一个空格,而不是复选框。我需要这样一行中的文本来代替一个不存在的复选框(如我的图片中的项目2)——不幸的是,这是必须的,并且
pLPN->rcText.left+=20
没有任何作用。如果
LBS_OWNERDRAWVARIABLE
强制系统调用
MeasureItem
函数,但是我能把物品移到左边吗?该函数向我发送
MEASUREITEMSTRUCT
结构,但没有“左边框”字段,我可以使用它进行操作。另外,我需要动态创建列表框,而不是通过工具箱,但我下次会先尝试,谢谢。@mrdecompilator我知道你是动态创建控件的,这只是为了将来帮助你:)发布你的
DrawItem()
函数的完整代码现在,它是空的,但是
DrawItem
发送
DRAWITEMSTRUCT
,它具有带有项目矩形的
rcItem
字段,因此我可以执行类似于
rcItem.left-=20的操作。我已经使用了
CCheckListBox
,但后来我意识到,用户可能希望在将来添加多个列。@mrdecompilator在编辑的答案代码中,我只需将两列搜索一下,就可以得到一个令人精疲力竭的答案!出于某种原因,使用此代码,列表包含网格,但似乎没有任何项。然后我发现,他们都在那里,但都是白色或其他东西(他们可以被选中,但看不见)。当我删除整个
开关时
项目正常显示。现在的问题是,没有复选框的行有一个空格,而不是复选框。我需要这样一行中的文本来代替不存在的复选框(如图片中的item2)——不幸的是,这是必须的,并且
pLPN->rcText.left+=20
没有任何作用。