MFC List Control 控件添加单元格编辑和单元格下拉列表项

原理很简单:

就是在点击到列表相应单元格的时候,在相应的位置生成一个跟单元格大小相当的编辑框或者下拉列表框并贴在单元格上面而已。 

实现如下: 在对话框类声明中添加如下变量和函数:

头文件中添加:

int e_Item;    //刚编辑的行  
int e_SubItem; //刚编辑的列  

CEdit m_Edit;  //生成单元编辑框对象
bool haveeditcreate;//标志编辑框已经被创建
void createEdit(NM_LISTVIEW  *pEditCtrl, CEdit *createdit, int &Item, int &SubItem, bool &havecreat);//创建单元格编辑框函数
void distroyEdit(CListCtrl *list, CEdit* distroyedit, int &Item, int &SubItem);//销毁单元格编辑框对象

CComboBox m_comBox;//生产单元格下拉列表对象
bool haveccomboboxcreate;//标志下拉列表框已经被创建
void createCcombobox(NM_LISTVIEW  *pEditCtrl, CComboBox *createccomboboxobj, int &Item, int &SubItem, bool &havecreat);//创建单元格下拉列表框函数
void distroyCcombobox(CListCtrl *list, CComboBox* distroyccomboboxobj, int &Item, int &SubItem);//销毁单元格下拉列表框

在对话框的初始化函数OnInitDialog()中添加初始化代码如下:

haveeditcreate = false;//初始化标志位,表示还没有创建编辑框
haveccomboboxcreate = false;//初始化标志位,表示还没有创建下拉列表框
RECT  m_rect;
m_list.GetClientRect(&m_rect); //获取list的客户区,方便调节每一列的宽度  
m_list.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); //设置list风格,LVS_EX_GRIDLINES为网格线(只适用与report风格的listctrl)
                                                                      //LVS_EX_FULLROWSELECT为选中某行使整行高亮(只适用与report风格的listctrl)
m_list.InsertColumn(0, _T("学号"), LVCFMT_LEFT, m_rect.right / 4);
m_list.InsertColumn(1, _T("姓名"), LVCFMT_LEFT, m_rect.right / 4);
m_list.InsertColumn(2, _T("性别"), LVCFMT_LEFT, m_rect.right / 4);
m_list.InsertColumn(3, _T("班级"), LVCFMT_LEFT, m_rect.right / 4);

m_list.InsertItem(0, _T("09090901"));//添加第一个学生数据
m_list.SetItemText(0, 1, _T("小李"));
m_list.SetItemText(0, 2, _T("男"));
m_list.SetItemText(0, 3, _T("计科0901"));

m_list.InsertItem(1, _T("09090902"));//添加第二个学生数据
m_list.SetItemText(1, 1, _T("小王"));
m_list.SetItemText(1, 2, _T("男"));
m_list.SetItemText(1, 3, _T("计科0902"));

为列表框添加单击响应函数:

void CNephoVisionDatabaseDlg::OnNMClickListStudentdata(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    NM_LISTVIEW  *pEditCtrl = (NM_LISTVIEW *)pNMHDR;
    printf("行:%d,列:%d\n", pEditCtrl->iItem, pEditCtrl->iSubItem);
    if (pEditCtrl->iItem==-1)//点击到非工作区
    {
        if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
        {
            distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
            haveeditcreate = false;
        }
        if (haveccomboboxcreate == true)//如果之前创建了下拉列表框就销毁掉
        {
            distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
            haveccomboboxcreate = false;
        }
    }
    else if (pEditCtrl->iSubItem != 2)//如果不是性别选项
    {
        if (haveccomboboxcreate == true)//如果之前创建了编辑框就销毁掉
        {
            distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
            haveccomboboxcreate = false;
        }
        if (haveeditcreate == true)
        {
            if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//如果点中的单元格不是之前创建好的
            {
                distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);
                haveeditcreate = false;
                createEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, haveeditcreate);//创建编辑框
            }
            else//点中的单元格是之前创建好的
            {
                m_Edit.SetFocus();//设置为焦点 
            }
        }
        else
        {
            e_Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
            e_SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
            createEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, haveeditcreate);//创建编辑框
        }
    }
    else//如果是性别选项,在单元格处生成下拉列表项
    {
        if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
        {
            distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);
            haveeditcreate = false;
        }
        if (haveccomboboxcreate == true)
        {
            if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//如果点中的单元格不是之前创建好的
            {
                distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
                haveccomboboxcreate = false;
                createCcombobox(pEditCtrl, &m_comBox, e_Item, e_SubItem, haveccomboboxcreate);//创建编辑框
                m_comBox.AddString(L"男");
                m_comBox.AddString(L"女");
                m_comBox.ShowDropDown();//自动下拉
            }
            else//点中的单元格是之前创建好的
            {
                m_comBox.SetFocus();//设置为焦点 
            }
        }
        else
        {
            e_Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
            e_SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
            createCcombobox(pEditCtrl, &m_comBox, e_Item, e_SubItem, haveccomboboxcreate);//创建编辑框
            m_comBox.AddString(L"男");
            m_comBox.AddString(L"女");
            m_comBox.ShowDropDown();//自动下拉
        }
    }
    *pResult = 0;
}

写创建与销毁单元格编辑框和下拉列表框函数的实现:

//创建单元格编辑框函数 
//pEditCtrl为列表对象指针,createdit为编辑框指针对象,      
//Item为创建单元格在列表中的行,SubItem则为列,havecreat为对象创建标准

void CNephoVisionDatabaseDlg::createEdit(NM_LISTVIEW  *pEditCtrl, CEdit *createdit, int &Item, int &SubItem, bool &havecreat)   
{
    Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
    SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
    createdit->Create(ES_AUTOHSCROLL | WS_CHILD | ES_LEFT | ES_WANTRETURN,
        CRect(0, 0, 0, 0), this, IDC_EDIT_CREATEID);//创建编辑框对象,IDC_EDIT_CREATEID为控件ID号3000,在文章开头定义
    havecreat = true;
    createdit->SetFont(this->GetFont(), FALSE);//设置字体,不设置这里的话上面的字会很突兀的感觉
    createdit->SetParent(&m_list);//将list control设置为父窗口,生成的Edit才能正确定位,这个也很重要
    CRect  EditRect;
    m_list.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//获取单元格的空间位置信息
    EditRect.SetRect(EditRect.left+1, EditRect.top+1, EditRect.left + m_list.GetColumnWidth(e_SubItem)-1, EditRect.bottom-1);//+1和-1可以让编辑框不至于挡住列表框中的网格线
    CString strItem = m_list.GetItemText(e_Item, e_SubItem);//获得相应单元格字符
    createdit->SetWindowText(strItem);//将单元格字符显示在编辑框上
    createdit->MoveWindow(&EditRect);//将编辑框位置放在相应单元格上
    createdit->ShowWindow(SW_SHOW);//显示编辑框在单元格上面
    createdit->SetFocus();//设置为焦点 
    createdit->SetSel(-1);//设置光标在文本框文字的最后
}

void CNephoVisionDatabaseDlg::distroyEdit(CListCtrl *list,CEdit* distroyedit, int &Item, int &SubItem)
{
    CString meditdata;
    distroyedit->GetWindowTextW(meditdata);
    list->SetItemText(Item, SubItem, meditdata);//获得相应单元格字符
    distroyedit->DestroyWindow();//销毁对象,有创建就要有销毁,不然会报错
}

 //创建单元格下拉列表框函数
//pEditCtrl为列表对象指针,createccombobox为下拉列表框指针对象,
//Item为创建单元格在列表中的行,SubItem则为列,havecreat为对象创建标准

void CNephoVisionDatabaseDlg::createCcombobox(NM_LISTVIEW  *pEditCtrl, CComboBox *createccomboboxobj, int &Item, int &SubItem, bool &havecreat) 
{
    Item = pEditCtrl->iItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
    SubItem = pEditCtrl->iSubItem;//将点中的单元格的行赋值给“刚编辑过的行”以便后期处理
    havecreat = true;
    createccomboboxobj->Create(WS_CHILD | WS_VISIBLE |  CBS_DROPDOWN | CBS_OEMCONVERT, CRect(0, 0, 0, 0), this, IDC_COMBOX_CREATEID);
    createccomboboxobj->SetFont(this->GetFont(), FALSE);//设置字体,不设置这里的话上面的字会很突兀的感觉
    createccomboboxobj->SetParent(&m_list);//将list control设置为父窗口,生成的Ccombobox才能正确定位,这个也很重要
    CRect  EditRect;
    m_list.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//获取单元格的空间位置信息
    EditRect.SetRect(EditRect.left + 1, EditRect.top + 1, EditRect.left + m_list.GetColumnWidth(e_SubItem) - 1, EditRect.bottom - 1);//+1和-1可以让编辑框不至于挡住列表框中的网格线
    CString strItem = m_list.GetItemText(e_Item, e_SubItem);//获得相应单元格字符
    createccomboboxobj->SetWindowText(strItem);//将单元格字符显示在编辑框上
    createccomboboxobj->MoveWindow(&EditRect);//将编辑框位置放在相应单元格上
    createccomboboxobj->ShowWindow(SW_SHOW);//显示编辑框在单元格上面
}

void CNephoVisionDatabaseDlg::distroyCcombobox(CListCtrl *list, CComboBox* distroyccomboboxobj, int &Item, int &SubItem)
{
    CString meditdata;
    distroyccomboboxobj->GetWindowTextW(meditdata);
    list->SetItemText(Item, SubItem, meditdata);//更新相应单元格字符
    distroyccomboboxobj->DestroyWindow();//销毁对象,有创建就要有销毁,不然会报错
}

OK,到此我们已经实现了添加单元格编辑框和单元格下拉列表框的功能了,点击除性别列外的列表单元格看到以下效果:
这里写图片描述

在单元格编辑框中写东西的时候往往喜欢按回车,这个时候如果不加处理的话会发现一个很崩溃的现象,程序直接退出了。这个可以重载对话框类的OnOK()函数来避免。就是在对话框类声明中添加

afx_msg void OnOK();

然后将其定义为什么都不做:

void CNephoVisionDatabaseDlg::OnOK()
{
}

这样就不会有按回车直接退出程序的事情发生了。

此外,如果希望在编辑框或者下拉列表框失去焦点的时候就将数据列表中的相关信息更新,可以响应动态创建的这两个控件的失去焦点消息,方法如下: 在对话框类声明中添加

afx_msg void OnKillfocusEdit();//动态生成编辑框失去焦点响应函数
afx_msg void OnKillfocusCcomboBox();//动态生成下拉列表框失去焦点响应函数

在对话框类实现的消息映射描述中添加

//添加动态生成编辑框的失去焦点响应函数
ON_EN_KILLFOCUS(IDC_EDIT_CREATEID, &CNephoVisionDatabaseDlg::OnKillfocusEdit)

ON_CBN_KILLFOCUS(IDC_COMBOX_CREATEID, &CNephoVisionDatabaseDlg::OnKillfocusCcomboBox)

这样这两个控件在失去焦点的时候就会响应分别定义好的函数,我们只需要在相应的函数添加处理代码就可以了:

void CNephoVisionDatabaseDlg::OnKillfocusEdit()
{
    if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
    {
        distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
        haveeditcreate = false;
    }
    if (haveccomboboxcreate == true)//如果之前创建了下拉列表框就销毁掉
    {
        distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
        haveccomboboxcreate = false;
    }
}

void CNephoVisionDatabaseDlg::OnKillfocusCcomboBox()
{
    if (haveeditcreate == true)//如果之前创建了编辑框就销毁掉
    {
        distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//销毁单元格编辑框对象
        haveeditcreate = false;
    }
    if (haveccomboboxcreate == true)//如果之前创建了下拉列表框就销毁掉
    {
        distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem);
        haveccomboboxcreate = false;
    }
}

本文参考红黑联盟:
http://www.2cto.com/database/201411/355997.html

### 回答1: MFC ListControl控件的颜色可以通过以下方法进行设置: 1. 设置整个ListControl的背景颜色: 可以使用CListCtrl类的SetBkColor()函数来设置ListControl的背景颜色,例如: m_ListCtrl.SetBkColor(RGB(255, 255, 255)); // 设置背景颜色为白色 2. 设置ListControl中某一行或某一列的颜色: 可以使用CListCtrl类的SetItem()函数来设置ListControl中某一行或某一列的颜色,例如: m_ListCtrl.SetItem(, , LVIF_TEXT | LVIF_STATE, _T("第一行第一列"), , , , , LVIS_SELECTED, LVIS_SELECTED); // 设置第一行第一列的文本和选中状态 m_ListCtrl.SetItemText(, 1, _T("第一行第二列")); // 设置第一行第二列的文本 m_ListCtrl.SetItemState(, LVIS_SELECTED, LVIS_SELECTED); // 设置第一行选中状态 m_ListCtrl.SetItemData(, (DWORD_PTR)&m_Data); // 设置第一行的数据 可以在SetItem()函数中设置LVITEM结构体的iItem、iSubItem、pszText、state、stateMask等参数来设置行或列的颜色和状态。 3. 设置ListControl中某一单元格的颜色: 可以使用CListCtrl类的SetCell()函数来设置ListControl中某一单元格的颜色,例如: m_ListCtrl.SetCell(, , RGB(255, , ), RGB(255, 255, 255)); // 设置第一行第一列的前景色为红色,背景色为白色 可以在SetCell()函数中设置行、列、前景色和背景色等参数来设置单元格的颜色。 以上是MFC ListControl控件颜色设置的一些方法,希望能对您有所帮助。 ### 回答2: MFC ListControl 控件是非常常用的控件之一,可以用于展示大量数据。在使用 ListControl 控件的过程中,我们可能会遇到需要修改控件颜色的需求。下面就来介绍一下 MFC ListControl 控件的颜色设置方法。 MFC ListControl 控件的颜色可以通过属性编辑器或代码进行设置。在属性编辑器中,我们可以找到相应的属性(如:Background Color、Text Color、Selected Text Color、Selected Background Color 等),并通过改变相应的属性值来修改控件的颜色。同样地,在代码中,我们也可以通过修改相应的控件属性值来实现对控件颜色的修改。例如: // 获取 ListControl 控件指针 CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_CONTROL); // 设置控件的背景色 pListCtrl->SetBkColor(RGB(255, 0, 0)); // 设置控件文本颜色 pListCtrl->SetTextColor(RGB(0, 255, 0)); // 设置选中行的背景色和文本颜色 pListCtrl->SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); pListCtrl->SetSelectionMark(0); pListCtrl->SetItemState(0, LVIS_SELECTED, LVIS_SELECTED); 以上代码中,通过调用 SetBkColor() 函数和 SetTextColor() 函数分别对控件的背景色和文本颜色进行设置。同时,代码也演示了如何设置选中行的背景色和文本颜色。需要注意的是,当设置控件的颜色时,如果控件已经被创建,需要先调用控件的 RedrawItems() 函数进行重绘操作,否则,新设置的颜色可能不会立即生效。 总之,MFC ListControl 控件是非常强大的控件之一,灵活的颜色设置能够更好地满足各种需求,开发者需要注意控件的颜色设置时需要先重绘才会生效。 ### 回答3: MFC ListControl控件MFC中非常常用的控件之一,它可以用于显示列表、图形视图等。在使用ListControl控件时,有时候需要对列表中的某些行或列进行颜色的设置以达到更好的视觉效果。下面我们来了解一下MFC ListControl控件的颜色设置。 MFC ListControl控件的背景颜色是由ListControl的背景色和父窗口的背景色共同决定的。用户可以在资源编辑器中或运行时使用CListCtrl类的SetBackgroundColor()函数来设置ListControl的背景颜色。 MFC ListControl控件的前景颜色是由用户在添加数据时指定的。在使用CListCtrl类的InsertItem()函数添加行的时候,可以指定该行的前景颜色和背景颜色;在使用CListCtrl类的SetItemText()函数设置列的时候,也可以指定该列的前景颜色和背景颜色。 如果需要动态地设置某一行或某一列的颜色,可以使用CListCtrl类的SetItem()函数。例如,设置第一行红色,第二行蓝色,可以用以下代码: ``` m_ListCtrl.SetItem(0, 0, LVIF_TEXT | LVIF_STATE, _T("第一行"), 0, LVIS_SELECTED, LVIS_SELECTED, 0); m_ListCtrl.SetItemText(0, 1, _T("第一列")); m_ListCtrl.SetItemData(0, 100); m_ListCtrl.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); m_ListCtrl.SetItemText(1, 0, _T("第二行")); m_ListCtrl.SetItem(1, 0, LVIF_TEXT | LVIF_STATE, _T("第二行"), 0, LVIS_SELECTED, LVIS_SELECTED, 0); m_ListCtrl.SetItemText(1, 1, _T("第二列")); m_ListCtrl.SetItemData(1, 200); m_ListCtrl.SetItemState(1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); m_ListCtrl.SetItemText(2, 0, _T("第三行")); m_ListCtrl.SetItemText(2, 1, _T("第三列")); m_ListCtrl.SetItemText(0, 0, _T("第一行")); m_ListCtrl.SetItemText(0, 1, _T("第一列")); m_ListCtrl.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); m_ListCtrl.SetTextColor(0, RGB(255, 0, 0)); // 设置第1行红色 m_ListCtrl.SetItem(1, 0, LVIF_TEXT | LVIF_STATE, _T("第二行"), 0, LVIS_SELECTED, LVIS_SELECTED, 0); m_ListCtrl.SetItemText(1, 1, _T("第二列")); m_ListCtrl.SetItemState(1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); m_ListCtrl.SetTextColor(1, RGB(0, 0, 255)); // 设置第2行蓝色 ``` 除了设置整行或整列的颜色,还可以为不同的单元格设置不同的颜色。可以在添加行时使用LVITEM结构体的iItem、iSubItem、mask、pszText等成员,分别指定行号、列号、要设置的属性和单元格中要显示的文本。在通过CListCtrl类的GetItem()函数获取某一行列时,也可以获得单元格的前景色和背景色等属性信息。 通过上述方法,可以实现对MFC ListControl控件的颜色自定义设置。至于要如何设置出美观的颜色组合,需要根据实际情况和个人喜好来决定。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值