The principle is simple:
When you click on the corresponding cell in the list, you can create an edit box or drop-down list box in the corresponding location, which is the same size as the cell, and paste it on the cell.
Implemented as follows: Add the following variables and functions to the dialog class declaration:
Add:
int e_Item; //Newly edited lines int e_SubItem; //Columns just edited CEdit m_Edit; //Generate unit edit box object bool haveeditcreate;//Logo edit box has been created void createEdit(NM_LISTVIEW *pEditCtrl, CEdit *createdit, int &Item, int &SubItem, bool &havecreat);//Create a cell edit box function void distroyEdit(CListCtrl *list, CEdit* distroyedit, int &Item, int &SubItem);//Destroy the cell edit box object CComboBox m_comBox;//Production cell drop-down list object bool haveccomboboxcreate;//The logo drop-down list box has been created void createCcombobox(NM_LISTVIEW *pEditCtrl, CComboBox *createccomboboxobj, int &Item, int &SubItem, bool &havecreat);//Create a cell drop-down list box function void distroyCcombobox(CListCtrl *list, CComboBox* distroyccomboboxobj, int &Item, int &SubItem);//Destroy cell drop-down list box
In the initialization function OnInitDialog() of the dialog box, add the initialization code as follows:
haveeditcreate = false;//Initialize the flag bit to indicate that an edit box has not been created haveccomboboxcreate = false;//Initialize the flag bit to indicate that a drop-down list box has not been created RECT m_rect; m_list.GetClientRect(&m_rect); //Get the client area of the list to easily adjust the width of each column m_list.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); //Set list style, LVS_EX_GRIDLINES as grid line (only for list Ctrl with report style) //LVS_EX_FULLROWSELECT is selected for a list Ctrl exercising full line highlighting (only applicable to report style) m_list.InsertColumn(0, _T("Student ID"), LVCFMT_LEFT, m_rect.right / 4); m_list.InsertColumn(1, _T("Full name"), LVCFMT_LEFT, m_rect.right / 4); m_list.InsertColumn(2, _T("Gender"), LVCFMT_LEFT, m_rect.right / 4); m_list.InsertColumn(3, _T("class"), LVCFMT_LEFT, m_rect.right / 4); m_list.InsertItem(0, _T("09090901"));//Add the first student data m_list.SetItemText(0, 1, _T("petty thief")); m_list.SetItemText(0, 2, _T("male")); m_list.SetItemText(0, 3, _T("Ji Ke 0901")); m_list.InsertItem(1, _T("09090902"));//Add a second student data m_list.SetItemText(1, 1, _T("Xiao Wang")); m_list.SetItemText(1, 2, _T("male")); m_list.SetItemText(1, 3, _T("Ji Ke 0902"));
Add a click response function to the list box:
void CNephoVisionDatabaseDlg::OnNMClickListStudentdata(NMHDR *pNMHDR, LRESULT *pResult) { LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); NM_LISTVIEW *pEditCtrl = (NM_LISTVIEW *)pNMHDR; printf("That's ok:%d,Column:%d\n", pEditCtrl->iItem, pEditCtrl->iSubItem); if (pEditCtrl->iItem==-1)//Click on the non-workspace { if (haveeditcreate == true)//If you created an edit box before, destroy it. { distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//Destroy the cell edit box object haveeditcreate = false; } if (haveccomboboxcreate == true)//If you created a drop-down list box before, destroy it { distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem); haveccomboboxcreate = false; } } else if (pEditCtrl->iSubItem != 2)//If not the gender option { if (haveccomboboxcreate == true)//If you created an edit box before, destroy it. { distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem); haveccomboboxcreate = false; } if (haveeditcreate == true) { if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//If the cell in the point is not created before { distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem); haveeditcreate = false; createEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, haveeditcreate);//Create edit boxes } else//The cells in the point are created previously { m_Edit.SetFocus();//Set Focus } } else { e_Item = pEditCtrl->iItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing e_SubItem = pEditCtrl->iSubItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing createEdit(pEditCtrl, &m_Edit, e_Item, e_SubItem, haveeditcreate);//Create edit boxes } } else//If it is a gender option, generate drop-down list items at the cell { if (haveeditcreate == true)//If you created an edit box before, destroy it. { distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem); haveeditcreate = false; } if (haveccomboboxcreate == true) { if (!(e_Item == pEditCtrl->iItem && e_SubItem == pEditCtrl->iSubItem))//If the cell in the point is not created before { distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem); haveccomboboxcreate = false; createCcombobox(pEditCtrl, &m_comBox, e_Item, e_SubItem, haveccomboboxcreate);//Create edit boxes m_comBox.AddString(L"male"); m_comBox.AddString(L"female"); m_comBox.ShowDropDown();//AutoDrop } else//The cells in the point are created previously { m_comBox.SetFocus();//Set Focus } } else { e_Item = pEditCtrl->iItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing e_SubItem = pEditCtrl->iSubItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing createCcombobox(pEditCtrl, &m_comBox, e_Item, e_SubItem, haveccomboboxcreate);//Create edit boxes m_comBox.AddString(L"male"); m_comBox.AddString(L"female"); m_comBox.ShowDropDown();//AutoDrop } } *pResult = 0; }
Write the implementation of creating and destroying cell edit box and drop-down list box functions:
//Create a cell edit box function //pEditCtrl is the list object pointer and createdit is the edit box pointer object. //Item creates rows for cells in the list, SubItem for columns, and havecreat creates criteria for objects void CNephoVisionDatabaseDlg::createEdit(NM_LISTVIEW *pEditCtrl, CEdit *createdit, int &Item, int &SubItem, bool &havecreat) { Item = pEditCtrl->iItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing SubItem = pEditCtrl->iSubItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing createdit->Create(ES_AUTOHSCROLL | WS_CHILD | ES_LEFT | ES_WANTRETURN, CRect(0, 0, 0, 0), this, IDC_EDIT_CREATEID);//Create edit box object with IDC_EDIT_CREATEID as control ID number 3000, defined at the beginning of the article havecreat = true; createdit->SetFont(this->GetFont(), FALSE);//Setting fonts, without setting up here, the words on it will feel very abrupt. createdit->SetParent(&m_list);//It is also important to set the list control to the parent window so that the generated Edit can be positioned correctly. CRect EditRect; m_list.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//Obtaining the Spatial Position Information of Cells EditRect.SetRect(EditRect.left+1, EditRect.top+1, EditRect.left + m_list.GetColumnWidth(e_SubItem)-1, EditRect.bottom-1);//+ 1 and - 1 keep edit boxes from blocking grid lines in list boxes CString strItem = m_list.GetItemText(e_Item, e_SubItem);//Get the corresponding cell character createdit->SetWindowText(strItem);//Display cell characters on the edit box createdit->MoveWindow(&EditRect);//Place the edit box on the corresponding cell createdit->ShowWindow(SW_SHOW);//Display the edit box on the cell createdit->SetFocus();//Set Focus createdit->SetSel(-1);//Set cursor at the end of text box text } void CNephoVisionDatabaseDlg::distroyEdit(CListCtrl *list,CEdit* distroyedit, int &Item, int &SubItem) { CString meditdata; distroyedit->GetWindowTextW(meditdata); list->SetItemText(Item, SubItem, meditdata);//Get the corresponding cell character distroyedit->DestroyWindow();//Destroy objects, create them and destroy them, otherwise they will report errors. } //Create a cell drop-down list box function //pEditCtrl is the list object pointer and createccombobox is the drop-down list box pointer object. //Item creates rows for cells in the list, SubItem for columns, and havecreat creates criteria for objects void CNephoVisionDatabaseDlg::createCcombobox(NM_LISTVIEW *pEditCtrl, CComboBox *createccomboboxobj, int &Item, int &SubItem, bool &havecreat) { Item = pEditCtrl->iItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing SubItem = pEditCtrl->iSubItem;//Assigning rows of cells in a point to "newly edited rows" for post-processing 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);//Setting fonts, without setting up here, the words on it will feel very abrupt. createccomboboxobj->SetParent(&m_list);//It's also important to set list control to the parent window so that the generated Ccombobox can be positioned correctly. CRect EditRect; m_list.GetSubItemRect(e_Item, e_SubItem, LVIR_LABEL, EditRect);//Obtaining the Spatial Position Information of Cells EditRect.SetRect(EditRect.left + 1, EditRect.top + 1, EditRect.left + m_list.GetColumnWidth(e_SubItem) - 1, EditRect.bottom - 1);//+ 1 and - 1 keep edit boxes from blocking grid lines in list boxes CString strItem = m_list.GetItemText(e_Item, e_SubItem);//Get the corresponding cell character createccomboboxobj->SetWindowText(strItem);//Display cell characters on the edit box createccomboboxobj->MoveWindow(&EditRect);//Place the edit box on the corresponding cell createccomboboxobj->ShowWindow(SW_SHOW);//Display the edit box on the cell } void CNephoVisionDatabaseDlg::distroyCcombobox(CListCtrl *list, CComboBox* distroyccomboboxobj, int &Item, int &SubItem) { CString meditdata; distroyccomboboxobj->GetWindowTextW(meditdata); list->SetItemText(Item, SubItem, meditdata);//Update the corresponding cell characters distroyccomboboxobj->DestroyWindow();//Destroy objects, create them and destroy them, otherwise they will report errors. }
OK, so far we have realized the function of adding cell edit box and cell drop-down list box. Click on the list cell except gender column to see the following effect:
When writing in the cell edit box, you often like to press Enter. If you don't handle it, you will find a very crashing phenomenon, and the program will exit directly. This can be avoided by overloading the OnOK() function of the dialog class. It's added to the dialog class declaration
afx_msg void OnOK();
Then define why not:
void CNephoVisionDatabaseDlg::OnOK() { }
That way, there will be no direct exit by return.
In addition, if you want to update the relevant information in the data list when the edit box or drop-down list box loses focus, you can respond to the lost focus message of the two dynamically created controls by adding the following method: in the dialog box class declaration
afx_msg void OnKillfocusEdit();//Dynamically Generating Focus Lost Response Function for Editing Box afx_msg void OnKillfocusCcomboBox();//Dynamic generation of drop-down list box loss of focus response function
Add to the message mapping description of the dialog class implementation
//Lost Focus Response Function with Dynamic Generation Editor Box ON_EN_KILLFOCUS(IDC_EDIT_CREATEID, &CNephoVisionDatabaseDlg::OnKillfocusEdit) ON_CBN_KILLFOCUS(IDC_COMBOX_CREATEID, &CNephoVisionDatabaseDlg::OnKillfocusCcomboBox)
In this way, the two controls will respond to separately defined functions when they lose focus. We just need to add processing code to the corresponding functions.
void CNephoVisionDatabaseDlg::OnKillfocusEdit() { if (haveeditcreate == true)//If you created an edit box before, destroy it. { distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//Destroy the cell edit box object haveeditcreate = false; } if (haveccomboboxcreate == true)//If you created a drop-down list box before, destroy it { distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem); haveccomboboxcreate = false; } } void CNephoVisionDatabaseDlg::OnKillfocusCcomboBox() { if (haveeditcreate == true)//If you created an edit box before, destroy it. { distroyEdit(&m_list, &m_Edit, e_Item, e_SubItem);//Destroy the cell edit box object haveeditcreate = false; } if (haveccomboboxcreate == true)//If you created a drop-down list box before, destroy it { distroyCcombobox(&m_list, &m_comBox, e_Item, e_SubItem); haveccomboboxcreate = false; } }