说明如何编辑报表样式
列表
控件中的子项
介绍
几乎我们每个在VC ++中编程的人都会遇到List 控件。在许多情况下,需要在多个列中的List Control中表示数据。默认情况下,无法修改List 控件本身中的数据。在这篇小文章中,我将简单的方法来编辑报表样式列表 控件中任何列中的任何值。这里的逻辑很简单,只要用户点击他想在该地方修改的子项目,我正在显示一个编辑框,并允许修改该值。一旦修改并单击ENTER键,更新的值将在List 控件中设置。
执行步骤:
- 使用MFC AppWizard,创建一个基于对话框的应用程序。将应用程序名称命名为MultipleColumns。默认情况下,向导将“确定”和“取消”按钮添加到对话框中,删除这两个按钮。
- 现在添加列表 - 控件和属性将样式更改为报告,如果我们需要多个列,则此样式是必需的
- 将两个按钮添加到对话框中,并将其命名为“确定”并退出
- 添加一个编辑框,并在属性中删除边框样式
- 使用类向导为OK和Exit按钮添加消息处理程序。将以下代码添加到这些函数
隐藏 复制代码
void CMultipleColumnsDlg::OK() { CDialog::EndDialog (0); // Add this line }
隐藏 复制代码void CMultipleColumnsDlg::OnExit() { CDialog::EndDialog (0); // Add this line }
- 添加一个调用的函数
InsertItems()
的CMulipleColumnsDlg
类。隐藏 复制代码void InsertItems();
在函数处理程序中添加以下代码
隐藏 收缩 复制代码// This function inserts the default values // into the listControl void CMultipleColumnsDlg::InsertItems() { HWND hWnd = ::GetDlgItem(m_hWnd, IDC_LIST1); // Set the LVCOLUMN structure with the required // column information LVCOLUMN list; list.mask = LVCF_TEXT |LVCF_WIDTH| LVCF_FMT |LVCF_SUBITEM; list.fmt = LVCFMT_LEFT; list.cx = 50; list.pszText = "S.No"; list.iSubItem = 0; //Inserts the column ::SendMessage(hWnd,LVM_INSERTCOLUMN, (WPARAM)0,(WPARAM)&list); list.cx = 100; list.pszText = "Name"; list.iSubItem = 1; ::SendMessage(hWnd ,LVM_INSERTCOLUMN, (WPARAM)1,(WPARAM)&list); list.cx = 100; list.pszText = "Address"; list.iSubItem = 2; ::SendMessage(hWnd ,LVM_INSERTCOLUMN, (WPARAM)1,(WPARAM)&list); list.cx = 100; list.pszText = "Country"; list.iSubItem = 2; ::SendMessage(hWnd ,LVM_INSERTCOLUMN, (WPARAM)1,(WPARAM)&list); // Inserts first Row with four columns . SetCell(hWnd,"1",0,0); SetCell(hWnd,"Prabhakar",0,1); SetCell(hWnd,"Hyderabad",0,2); SetCell(hWnd,"India",0,3); // Inserts second Row with four columns . SetCell(hWnd,"2",1,0); SetCell(hWnd,"Uday",1,1); SetCell(hWnd,"Chennai",1,2); SetCell(hWnd,"India",1,3); // Inserts third Row with four columns . SetCell(hWnd,"3",2,0); SetCell(hWnd,"Saradhi",2,1); SetCell(hWnd,"Bangolore",2,2); SetCell(hWnd,"India",2,3); // Inserts fourth Row with four columns . SetCell(hWnd,"4",3,0); SetCell(hWnd,"Surya",3,1); SetCell(hWnd,"Calcutta",3,2); SetCell(hWnd,"India",3,3); }
- 添加另一个叫函数
SetCell( )
的CMultipleColumnsDlg
类隐藏 复制代码void SetCell(HWND hWnd1, CString value, int nRow, int nCol);
在函数处理程序中添加以下代码
隐藏 复制代码// This function set the text in the specified // SubItem depending on the Row and Column values void CMultipleColumnsDlg::SetCell(HWND hWnd1, CString value, int nRow, int nCol) { TCHAR szString [256]; wsprintf(szString,value ,0); //Fill the LVITEM structure with the //values given as parameters. LVITEM lvItem; lvItem.mask = LVIF_TEXT; lvItem.iItem = nRow; lvItem.pszText = szString; lvItem.iSubItem = nCol; if(nCol >0) //set the value of listItem ::SendMessage(hWnd1,LVM_SETITEM, (WPARAM)0,(WPARAM)&lvItem); else //Insert the value into List ListView_InsertItem(hWnd1,&lvItem); }
- 再添加一个调用
GetItemText()
到同一个Class的 函数隐藏 复制代码CString GetItemText(HWND hWnd, int nItem, int nSubItem) const;
功能内部添加以下代码
隐藏 复制代码//this function will returns the item //text depending on the item and SubItem Index CString CMultipleColumnsDlg::GetItemText( HWND hWnd, int nItem, int nSubItem) const { LVITEM lvi; memset(&lvi, 0, sizeof(LVITEM)); lvi.iSubItem = nSubItem; CString str; int nLen = 128; int nRes; do { nLen *= 2; lvi.cchTextMax = nLen; lvi.pszText = str.GetBufferSetLength(nLen); nRes = (int)::SendMessage(hWnd, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi); } while (nRes == nLen-1); str.ReleaseBuffer(); return str; }
- 还要向
CMultipleColumnsDlg
类中添加两个成员变量int
隐藏 复制代码int nItem, nSubItem;
- 从Class向
NM_CLICK
导向List 控件添加通知。函数处理程序内部写下面的代码隐藏 收缩 复制代码//This function Displays an EditBox at the position //where user clicks on a particular SubItem with //Rectangle are equal to the SubItem, thus allows to //modify the value void CMultipleColumnsDlg::OnClickList( NMHDR* pNMHDR, LRESULT* pResult) { Invalidate(); HWND hWnd1 = ::GetDlgItem (m_hWnd,IDC_LIST1); LPNMITEMACTIVATE temp = (LPNMITEMACTIVATE) pNMHDR; RECT rect; //get the row number nItem = temp->iItem; //get the column number nSubItem = temp->iSubItem; if(nSubItem == 0 || nSubItem == -1 || nItem == -1) return ; //Retrieve the text of the selected subItem //from the list CString str = GetItemText(hWnd1,nItem , nSubItem); RECT rect1,rect2; // this macro is used to retrieve the Rectanle // of the selected SubItem ListView_GetSubItemRect(hWnd1,temp->iItem, temp->iSubItem,LVIR_BOUNDS,&rect); //Get the Rectange of the listControl ::GetWindowRect(temp->hdr.hwndFrom,&rect1); //Get the Rectange of the Dialog ::GetWindowRect(m_hWnd,&rect2); int x=rect1.left-rect2.left; int y=rect1.top-rect2.top; if(nItem != -1) ::SetWindowPos(::GetDlgItem(m_hWnd,IDC_EDIT1), HWND_TOP,rect.left+x,rect.top+4, rect.right-rect.left - 3, rect.bottom-rect.top -1,NULL); ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT1),SW_SHOW); ::SetFocus(::GetDlgItem(m_hWnd,IDC_EDIT1)); //Draw a Rectangle around the SubItem ::Rectangle(::GetDC(temp->hdr.hwndFrom), rect.left,rect.top-1,rect.right,rect.bottom); //Set the listItem text in the EditBox ::SetWindowText(::GetDlgItem(m_hWnd,IDC_EDIT1),str); *pResult = 0; }
- 要处理ENTER键,我们需要
OnOk
在 MultipleColumnsDlg.h中写入虚拟函数,因此添加以下作为受保护的成员隐藏 复制代码afx_msg void OnOK();
在MultipleColumnsDlg.cpp中编写以下代码。
隐藏 复制代码// This function handles the ENTER key void CMultipleColumnsDlg::OnOK() { CWnd* pwndCtrl = GetFocus(); // get the control ID which is // presently having the focus int ctrl_ID = pwndCtrl->GetDlgCtrlID(); CString str; switch (ctrl_ID) { //if the control is the EditBox case IDC_EDIT1: //get the text from the EditBox GetDlgItemText(IDC_EDIT1,str); //set the value in the listContorl with the //specified Item & SubItem values SetCell(::GetDlgItem (m_hWnd,IDC_LIST1), str,nItem,nSubItem); ::SendDlgItemMessage(m_hWnd,IDC_EDIT1, WM_KILLFOCUS,0,0); ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT1), SW_HIDE); break; default: break; } }
- 实现的最后一步是在
OnInitDialog
函数的旁边添加以下代码隐藏 复制代码//Set the style to listControl ListView_SetExtendedListViewStyle(::GetDlgItem (m_hWnd,IDC_LIST1),LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); InsertItems(); ::ShowWindow(::GetDlgItem(m_hWnd,IDC_EDIT1),SW_HIDE);