1.首先是ListControl
简介: 列表视图控件List Control同样比较常见,它能够把任何字符串内容以列表的方式显示出来,这种显示方式的特点是整洁、直观,在实际应用中能为用户带来方便。
列表视图控件是列表框控件List Box的改进和延伸。列表视图控件的列表项一般有图标(Icon)和标签(Label)两部分。图标是对列表项的图形描述,标签是文字描述。当然列表项可以只包含图标也可以只包含标签。
列表视图控件有4种风格:Icon、Small Icon、List和Report。下面简单说下4种风格各自的特点:
Icon大图标风格:列表项的图标通常为32×32像素,在图标的下面显示标签。
Small Icon小图标风格:列表项的图标通常为16×16像素,在图标的右面显示标签。
List列表风格:与小图标风格类似,图标和文字的对齐方式不同。
Report报表风格:列表视图控件可以包含一个列表头来描述各列的含义。每行显示一个列表项,通常可以包含多个列表子项。最左边的列表子项的标签左边可以添加一个图标,而它右边的所有子项则只能显示文字。这种风格的列表视图控件很适合做各种报表。
我的理解就是windows资源管理器,“查看”标签下的“大图标,小图标,列表,详细资料”
创建: MFC同样为列表视图控件的操作提供了CListCtrl类。
如果我们不想在对话框模板中直接拖入List Control来使用列表视图控件,而是希望动态创建它,则要用到CListCtrl类的成员函数Create函数,原型如下:
virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
参数rect为列表视图控件的位置和尺寸,pParentWnd为指向父窗口的指针,nID指定列表视图控件的ID,最复杂的一个参数同样还是dwStyle,它用于设定列表视图控件的风格,可以是以下风格的组合:
风格 | 含义 |
LVS_ALIGNLEFT | 显示格式是大图标或小图标时,标签放在图标的左边 |
LVS_ALIGNTOP | 显示格式是大图标或小图标时,标题放在图标的上边 |
LVS_AUTOARRANGE | 显示格式是大图标或小图标时,自动排列控件中的列表项 |
LVS_EDITLABELS | 用户可以修改标签文本 |
LVS_ICON | 指定大图标显示格式 |
LVS_LIST | 指定列表显示格式 |
LVS_NOCOLUMNHEADER | 在报表格式中不显示列的表头 |
LVS_NOLABELWRAP | 显示格式是大图标时,使标签文本单行显示。默认是多行显示 |
LVS_NOSCROLL | 列表视图控件无滚动条,此风格不能与LVS_LIST或LVS_REPORT组合使用 |
LVS_NOSORTHEADER | 报表格式的列表视图控件的表头不能作为排序按钮使用 |
LVS_OWNERDRAWFIXED | 由控件的拥有者负责绘制表项 |
LVS_REPORT | 指定报表显示格式 |
LVS_SHAREIMAGELISTS | 使列表视图共享图像序列 |
LVS_SHOWSELALWAYS | 即使控件失去输入焦点,仍显示出项的选择状态 |
LVS_SINGLESEL | 指定只能有一个列表项被选中。默认时可以多项选择 |
LVS_SMALLICON | 指定小图标显示格式 |
LVS_SORTASCENDING | 按升序排列列表项 |
LVS_SORTDESCENDING | 按降序排列列表项 |
常用方法:以下未经说明,ListControl默认view,风格为report
--1.设置ListControl风格及扩展风格
1 LONG lStyle; 2 lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口style 3 lStyle &= ~LVS_TYPEMASK; //清除显示方式位 4 lStyle |= LVS_REPORT; //设置style 5 SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style 6 7 DWORD dwStyle = m_list.GetExtendedStyle(); 8 dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl) 9 dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl) 10 dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件 11 m_list.SetExtendedStyle(dwStyle); //设置扩展风格
--2.插入数据
1 m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列 2 m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 ); 3 int nRow = m_list.InsertItem(0, “11”);//插入行 4 m_list.SetItemText(nRow, 1, “jacky”);//设置数据
--3.一直选中item
选中style中的Show selection always,或者在上面第2点中设置LVS_SHOWSELALWAYS
--4.选中和取消选中一行
1 int nIndex = 0; 2 //选中 3 m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED); 4 //取消选中 5 m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);
--5.得到ListControl中的所有行的checkbox的状态
1 m_list.SetExtendedStyle(LVS_EX_CHECKBOXES); 2 CString str; 3 for(int i=0;i<m_list.GetItemCount();i++) 4 { 5 if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i)) 6 { 7 str.Format(_T("第%d行的checkbox为选中状态"), i); 8 AfxMessageBox(str); 9 } 10 }
--6.得到ListControl中所有选中行的序号
1 CString str; 2 for(int i=0; i<m_list.GetItemCount();i++) 3 { 4 if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED ) 5 { 6 str.Format(_T("选中了第%d行"), i); 7 AfxMessageBox(str); 8 } 9 }
--7.得到item的信息
1 TCHAR szBuf[1024]; 2 LVITEM lvi; 3 lvi.iItem = nItemIndex; 4 lvi.iSubItem = 0; 5 lvi.mask = LVIF_TEXT; 6 lvi.pszText = szBuf; 7 lvi.cchTextMax = 1024; 8 m_list.GetItem(&lvi);
--8.得到ListControl的所有列的header字符串内容
1 LVCOLUMN lvcol; 2 char str[256]; 3 int nColNum; 4 CString strColumnName[4];//假如有4列 5 6 nColNum = 0; 7 lvcol.mask = LVCF_TEXT; 8 lvcol.pszText = str; 9 lvcol.cchTextMax = 256; 10 while(m_list.GetColumn(nColNum, &lvcol)) 11 { 12 strColumnName[nColNum] = lvcol.pszText; 13 nColNum++; 14 }
--9.使ListControl中一项可见,即滚动滚动条
m_list.EnsureVisible(i, FALSE);
--10.得到ListControl列数
int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();
--11.删除所有列
1 // 方法一: 2 while ( m_list.DeleteColumn (0)) 3 因为你删除了第一列后,后面的列会依次向上移动。 4 5 //方法二: 6 int nColumns = 4; 7 for (int i=nColumns-1; i>=0; i--) 8 m_list.DeleteColumn (i);
--12.得到单击的ListControl的行列号
1 // 添加listctrl控件的NM_CLICK消息相应函数 2 void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult) 3 { 4 CString str; 5 for(int i=0; i<m_list.GetItemState();i++) 6 { 7 if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED ) 8 { 9 str.Format(_T("选中了第%d行"), i); 10 AfxMessageBox(str); 11 } 12 } 13 14 *pResult = 0; 15 }
--13.判断是否点击在ListControl的checkbox上
1 //添加listctrl控件的NM_CLICK消息相应函数 2 void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult) 3 { 4 DWORD dwPos = GetMessagePos(); 5 CPoint point( LOWORD(dwPos), HIWORD(dwPos) ); 6 7 m_list.ScreenToClient(&point); 8 9 LVHITTESTINFO lvinfo; 10 lvinfo.pt = point; 11 lvinfo.flags = LVHT_ABOVE; 12 13 UINT nFlag; 14 int nItem = m_list.HitTest(point, &nFlag); 15 //判断是否点在checkbox上 16 if(nFlag == LVHT_ONITEMSTATEICON) 17 { 18 AfxMessageBox("点在listctrl的checkbox上"); 19 } 20 *pResult = 0; 21 }
--14.右键点击ListControl的item弹出菜单
1 //添加listctrl控件的NM_RCLICK消息相应函数 2 void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult) 3 { 4 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; 5 if(pNMListView->iItem != -1) 6 { 7 DWORD dwPos = GetMessagePos(); 8 CPoint point( LOWORD(dwPos), HIWORD(dwPos) ); 9 10 CMenu menu; 11 VERIFY( menu.LoadMenu( IDR_MENU1 ) ); 12 CMenu* popup = menu.GetSubMenu(0); 13 ASSERT( popup != NULL ); 14 UINT Cmd =popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON| TPM_RETURNCMD, point.x, point.y, this ); 15 16 switch(Cmd) 17 18 { 19 20 case ID_Log_SELECT: 21 22 break; 23 24 case ID_Log_CANCEL: 25 26 break; 27 28 } 29 } 30 *pResult = 0; 31 }
--14.修改某一行的某一项
m_listRecvDetail.SetItem(m_listItemCount-2,3,LVIF_TEXT,"不应答",0,0,0,NULL);
--15.失去焦点后依然高亮显示某一行或者熄灭某一行
1 //获得选中行的索引 2 m_SecCount = (int)m_lc.GetFirstSelectedItemPosition()-1; 3 4 //设置选中行一直高亮显示 5 m_lc.SetItemState(m_SecCount,LVIS_DROPHILITED,LVIF_STATE); 6 7 //取消在失去高亮时候选中行的高亮显示 8 m_lc.SetItemState(m_SecCount,FALSE,LVIF_STATE);
--16.单击ListControl获取行号
1 /添加响应NM_CLICK消息 2 3 void CEventAddDlg::OnNMClickListEventselect(NMHDR *pNMHDR, LRESULT *pResult) 5 { 6 LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast(pNMHDR) ; 7 int nItem = -1 ; 8 if( pNMItemActivate != NULL ) 9 { 10 nItem = pNMItemActivate->iItem ; // To get selected RAW NUM 11 } 12 *pResult = 0 ; 13 }
2.编辑框Edit Control
编辑框的通知消息
编辑框发生某些事件时会向父窗口发送通知消息。在对话框模板中的编辑框上点右键,选择“Add Event Handler”,为编辑框添加消息处理函数时,可以在“Message type”列表中看到这些消息。下面简单介绍编辑框的部分通知消息。
EN_CHANGE:编辑框的内容被用户改变了,与EN_UPDATE 不同,该消息是在编辑框显示的正文被刷新后才发出的
EN_ERRSPACE: 编辑框控件无法申请足够的动态内存来满足需要
EN_HSCROLL: 用户在水平滚动条上单击鼠标
EN_KILLFOCUS: 编辑框失去输入焦点
EN_MAXTEXT:输入的字符超过了规定的最大字符数。在没有ES_AUTOHSCROLL 或
ES_AUTOVSCROLL: 的编辑框中,当正文超出了编辑框的边框时也会发出该消息
EN_SETFOCUS: 编辑框获得输入焦点
EN_UPDATE: 在编辑框准备显示改变了的正文时发送该消息
EN_VSCROLL: 用户在垂直滚动条上单击鼠标
编辑框的创建
MFC为编辑框提供了CEdit类。编辑框的所有操作都封装到了CEdit类中。
与静态文本框的创建类似,除了可以在对话框模板上拖进一个编辑框,然后关联一个变量或通过API函数使用,也可以在程序中动态创建编辑框,即调用CEdit类的成员函数Create。Create成员函数的原型如下:
virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
参数说明:
dwStyle:指定编辑框的风格。可以是MSDN中“edit styles”包含风格的任意组合。下面是“edit styles”的所有风格说明。
ES_AUTOHSCROLL:当用户在行尾键入一个字符时,正文将自动向右滚动10 个字符,当用户按回车键时,正文总是滚向左边
ES_AUTOVSCROLL: 当用户在最后一个可见行按回车键时,正文向上滚动一页
ES_CENTER: 在多行编辑框中使正文居中
ES_LEFT :左对齐正文
ES_LOWERCASE: 把用户输入的字母统统转换成小写字母
ES_MULTILINE:指定一个多行编辑器。若多行编辑器不指定ES_AUTOHSCROLL 风格,则会自动换行,若不指定ES_AUTOVSCROLL,则多行编辑器会在窗口中正文装满时
发出警告声响
ES_NOHIDESEL:默认时,当编辑框失去输入焦点后会隐藏所选的正文,当获得输入焦点时又显示出来。设置该风格可禁止这种默认行为
ES_NUMBER :编辑框中只允许输入数字
ES_OEMCONVERT:使编辑框中的正文可以在ANSI 字符集和OEM 字符集之间相互转换。这在编辑框中包含文件名时是很有用的
ES_PASSWORD: 使所有键入的字符都用“*”来显示
ES_READONLY: 将编辑框设置成只读的
ES_RIGHT :右对齐正文
ES_UPPERCASE: 把用户输入的字母统统转换成大写字母
ES_WANTRETURN:使多行编辑器接收回车键输入并换行。如果不指定该风格,按回车键会选择默认的命令按钮,这往往会导致对话框的关闭
除了上面的风格外,编辑款一般还会设置WS_CHILD、WS_VISIBLE、WS_BORDER等窗口风格。另外,编辑框可以是多行的,也就是在编辑框中显示多行文字,这就需要设置ES_MULTILINE风格,如果想要多行编辑框支持回车键,
则还要设置ES_WANTRETURN。
对于在对话框模板中创建的编辑框,它的属性中包含了上述的风格,例如,Multiline属性对应的就是ES_MULTILINE风格,Want Return属性对应ES_WANTRETURN风格。
其他三个参数与静态文本框的Create函数的参数类似,就不介绍了。
CEdit类的主要成员函数
使用编辑框最重要的莫过于,获取和设置编辑框中的正文,它们对应的成员函数分别是GetWindowText和SetWindowText,这两个函数都是继承自CWnd类的成员函数,
另外,还可以使用CWnd类的GetWindowTextLength函数获取编辑框中正文的长度。
下面简单介绍CEdit类的其他几个主要的成员函数:
int LineFromChar(int nIndex = –1) const;
返回多行编辑框中指定索引的字符所在行的行号(从零开始),只适用于多行编辑框。nIndex等于-1则返回所选择正文的第一个字符所在行的索引。如果没有选择正文,则返回当前行的行号。
int LineIndex(int nLine = –1) const;
返回由nLine指定行的起始字符在编辑框的整个字符串中的索引,只适用于多行编辑框。如果指定行超过编辑框的最大行数,则返回-1,而如果nLine为-1,则返回当前插入符所在行的起始字符的索引。
void GetSel(int& nStartChar,int& nEndChar) const;
获取选择正文的索引范围。nStartChar返回被选择正文的起始索引,nEndChar返回被选择正文的终止索引(不包括在选择范围内)。如果没有选择正文,则两者均为当前插入符的索引。
void SetSel(int nStartChar,int nEndChar,BOOL bNoScroll=FALSE);
选择编辑框中的正文。nStartChar为选择开始处的索引,nEndChar为选择结束处的索引。如果nStartChar为0并且nEndChar为-1,则选择所有正文,而如果nStartChar为-1则取消所有选择。bNoScroll为FALSE时滚动插入符并使之可见,为TRUE时不滚动。
void ReplaceSel(LPCTSTR lpszNewText,BOOL bCanUndo = FALSE);
用lpszNewText指向的字符串来替换选择的正文。如果bCanUndo为TRUE则替换可以被撤销。
int GetLineCount() const;
获取正文的行数,只适用于多行编辑框。如果编辑框没有正文则返回1。
int LineLength( int nLine = –1 ) const;
获取指定字符索引所在行的字节长度(行尾的回车和换行符不计算在内),参数nLine 说明了为字符索引。如果nLine 的值为-1,则函数返回当前行的长度(假如没有正文被选择),或选择正文占据的行的字符总数减去选择正文的字符数(假如有正文被选择)。若用于单行编辑框,则函数返回整个正文的长度。
int GetLine( int nIndex, LPTSTR lpszBuffer ) const;
int GetLine( int nIndex, LPTSTR lpszBuffer, int nMaxLength ) const;
用来获得指定行的正文(不包括行尾的回车和换行符),只适用于多行编辑框。参数nIndex 是行号,lpszBuffer 指向存放正文的缓冲区,nMaxLength 规定了拷贝的最大字节数。若指定的行号小于编辑框的实际行数,函数返回实际拷贝的字节数,若指定的行号大于编辑框的实际行数,则函数返回0。需要注意的是,GetLine 函数不会在缓冲区中字符串的末尾添加字符串结束符(NULL)。
UINT GetLimitText( ) const;
获取编辑框能够接受的正文的最大字节数。
void LimitText(int nChars = 0);
设置用户在编辑框中可以输入的正文的最大长度(字节数)。如果nChars为0,则最大长度为UINT_MAX个字节。
3.字符转换
1. CString向char类型转换
1 CString str = "hello"; 2 string st = (string)(CStringA)str; 3 int len = st.length(); 4 char* ch = (char*)malloc(len); //动态申请char*大小的空间 5 for(int i = 0 ; i <len ; i++) 6 { 7 ch[i] = st[i]; 8 } 9 ch[len] = '