ListCtrl使用详述及进程列表示例
作者:阿珊境界
近日同事问起ListCtrl的使用示例,我竟有一种无从下手的感觉。查了查资料,觉得有必要把常用的东西都整理出来,以备后用,也方便大家。
创建ListCtrl我们可以通过在界面上直接绘制和动态生成两种方式,得到其指针后就可以进行操作了。
ListCtrl有三种显示模式,即图标,小图标和报表形式。下面以报表为例阐述。同时,还设置了其整行选取和显示表格线的样式:
CListCtrl* pmyListCtrl=(CListCtrl*)GetDlgItem(IDC_LIST1); //获取ListCtrl指针
DWORD dwstyle=GetWindowLong(pmyListCtrl->m_hWnd,GWL_STYLE);
//获取窗口样式
SetWindowLong(pmyListCtrl->m_hWnd,GWL_STYLE,dwstyle | LVS_REPORT ); //设置报表样式
DWORD styles=pmyListCtrl->GetExStyle(); //获取扩展样式
styles &=~LVS_EX_CHECKBOXES; //去掉每行前端复选框 pmyListCtrl->SetExtendedStyle(styles | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); //设置其整行选取和显示表格线样式
给ListCtrl加上列头,需要用到LVCOLUMN结构体,代码如下:
TCHAR szHeader[3][10]={_T("col1"),_T("col2"),_T("col3")};
LVCOLUMN lvcolumn; //定义一个结构体
CRect rect;
pmyListCtrl->GetWindowRect(&rect); //获取窗口矩形
int i=0;
for(i=0;i<3;i++) //加入3列
{
lvcolumn.mask=LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT
| LVCF_WIDTH | LVCF_ORDER; //设定哪些项有效
lvcolumn.fmt=LVCFMT_LEFT; //左对齐
lvcolumn.pszText=szHeader[i]; //字符串数组的数组
lvcolumn.iSubItem=i;
lvcolumn.iOrder = i;
lvcolumn.cx=(rect.Width())/4-1; //宽度
pmyListCtrl->InsertColumn(i,&lvcolumn); //插入列
}
也可以通过发送LVM_INSERTCOLUMN消息来插入列,如下:
pmyListCtrl->SendMessage(LVM_INSERTCOLUMN,i,(LPARAM)&lvcolumn);
增加10条记录
CString strText;
for (i=0;i<=10;i++)
{
strText.Format(TEXT("item %d"), i);
pmyListCtrl->InsertItem(i, strText);
for (int j=1;j<3;j++)
{
strText.Format(TEXT("sub-item %d-%d"), i, j);
pmyListCtrl->SetItemText(i, j, strText);
}
}
与插入列其似,插行也可以通过发送LVM_INSERTITEM和LVM_SETITEMTEXT来实现。先定义一个LVITEM结构体,如下:
LVITEM item;
item.iItem=I;
item.mask=LVIF_TEXT;
item.pszText=(LPSTSTR)str;
pmyListCtrl->SendMessage(I,(LPARAM)L&item);
LVITEM lvi;
lvi.SubItem=1;
lvi.pszText=(LPTSTR)str;
pmyListCtrl->SendMessage(LVM_INSERTITEM,I,(LPARAM)&lvi);
下面说一下ListCtrl的消息处理。当事件发生时,通用控件向父窗口发送WM_NOTIFY消息,该消息的wParam参数指定了控件的ID号,lParam则是一个指向NMHDR结构体的指针。该结构体定义如下:
typedef struct tagNMHDR {
HWND hwndFrom; //控件句柄
UINT idFrom; //控件ID号
UINT code; //通知代码,如NM_CLICK
} NMHDR;
ListCtrl通知消息的lParam指向了一个更大的结构体NMLISTVIEW,它的第一个成员是NMHDR结构体。下面代码是双击一个列表项时,弹出此项的index。
if(wParam == IDC_LIST)
{
NMHDR* pHeader = (NMHDR*)lParam;
HWND hWndList = pHeader->hwndFrom;
if(pHeader->code == NM_DBLCLK)
{
NMLISTVIEW* pNMListView = (NMLISTVIEW*)pHeader;
// 用户双击的项号
int nIndex = pNMListView->iItem;
char str[20]="/0" ;
sprintf(str,"%d",nIndex);
MessageBox(0,str,"Index",0);
}
}
下面代码是用Toolhelp API实现的进程列表。注意在工程文件中包含tlhelp32.h头文件。
LVCOLUMN column;
column.mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH;
column.fmt = LVCFMT_CENTER; //居中显示
column.cx = 100; //宽度
column.pszText = "进程";
pmyListCtrl->SendMessage(LVM_INSERTCOLUMN, 0, (LPARAM)&column);
column.pszText = "PID";
column.cx = 50;
pmyListCtrl->SendMessage(LVM_INSERTCOLUMN, 1, (LPARAM)&column);
int nItem = 0;
PROCESSENTRY32 pe32 = {sizeof(PROCESSENTRY32)};
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
return;
if(Process32First(hProcessSnap, &pe32))
{
do
{
char szID[20]="/0";
wsprintf(szID, "%u", pe32.th32ProcessID);
LVITEM item = {0};
item.iItem = nItem;
item.mask = LVIF_TEXT; //设定有效项
item.pszText = (LPTSTR)pe32.szExeFile;
pmyListCtrl->SendMessageLVM_INSERTITEM, 0, (LPARAM)&item);
LVITEM lvi;
lvi.iSubItem = 1;
lvi.pszText = (LPTSTR)szID;
pmyListCtrl->SendMessage(LVM_SETITEMTEXT, nItem, (LPARAM)&lvi);
nItem++;
}
while(Process32Next(hProcessSnap, &pe32));
}
::CloseHandle(hProcessSnap);
全文结束。