解决方案

MFC中ListBox控件的简单使用

seo靠我 2023-09-25 11:10:50

MFC中listbox控件是为了显示一系列的文本,每个文本占一行。

Listbox控件可以设置属性为:

LBS_CHILD   :(默认)子窗口

LBS_Visible :(默认)可视

LBS_MultiplSEO靠我esel :可选择多行

LBS_Extendedsel :可以使用shift或ctrl选择多行

LBS_SORT:所有行按字母顺序进行排序

对Listbox进行操作:

Int listbox.AddStrinSEO靠我g (  LPCTSTR     Str)   :对listbox的首行添加一个str的文本行,即此时nIndex为0;

Int listbox.DeleteString (uint nIndex)  SEO靠我   :删除listbox中第nIndex行的文本行,注意nIndex是从0起始的;

int listbox.InsertString (uint xIndex, LPCTSTR  Str):在listSEO靠我box中第nIndex行插入一个str的文本行;

Int listbox.GetCount (  ):获取listbox的行的总数目;

Int listbox.GetCurSel  ( ):得到listbSEO靠我ox选中的文本行的行数。

Void listbox.ResetContent (  ):清除listbox中的所有数据;

Int listbox.GetCurCount ( ):获取listbox被选中的SEO靠我行的数目;

Int listbox.FindString  ( int nstart , LPCTSTR  Str ):从第nstart行开始起进行查找,查找Str的文本行;

Int listbox.SeSEO靠我lectString ( int nstart, LPCTSTR Str ) :从第nstart行开始,选择包含Str字符串的那一行;

条款一:设置ListCtrl的风格

在CSDN上常常看到有人问怎么设SEO靠我置风格的,他们ListCtrl的样子是一个列表,有横条和竖条分界线,然后选中一行,要整一行都选中,而不是只有某一列被选中,等等,这里给一个比较全面的设置方法。

//获得原有风格

DWORD dwStyleSEO靠我 = ::GetWindowLong(m_listctrl.m_hWnd, GWL_STYLE);

dwStyle &= ~(LVS_TYPEMASK);

dwStyle &= ~(LVS_EDITLABSEO靠我ELS);

//设置新风格

SetWindowLong(m_listctrl.m_hWnd, GWL_STYLE,dwStyle, |LVS_REPORT | LVS_NOLABELWRAP | LVS_SEO靠我SHOWSELALWAYS);

//设置扩展风格

DWORD styles = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_CHECKBOXES;

ListViSEO靠我ew_SetExtendedListViewStyleEx(m_listctrl.m_hWnd, styles, styles );

其中LVS_EX_FULLROWSELECT 就是前面说得整行选中

LSEO靠我VS_EX_GRIDLINES 网格线(只适用与report风格的listctrl)

LVS_EX_CHECKBOXES 前面加个checkbox

pListCtrl->SetExtendedStyle(SEO靠我 m_listctrl.GetExtendedStyle() | LVS_EX_SUBITEMIMAGES);

这也是一个很重要的属性,这样的话,可以在列表中加ICON,

条款二:加入列头

这是一个比较实质SEO靠我的东西,给列表框分列,然后加上列头.

TCHAR rgtsz[2][10] = {_T("列头1"), _T("列头2")};

LV_COLUMN lvcolumn;

CRect rect;

m_listctSEO靠我rl.GetWindowRect(&rect);

for(int i=0;i<2;i++)

{

lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LSEO靠我VCF_WIDTH | LVCF_ORDER;

 lvcolumn.fmt = LVCFMT_LEFT;

 lvcolumn.pszText = rgtsz[i];

lvcolumn.iSubItem = i;SEO靠我

 lvcolumn.iOrder = i;

 if(i==0)

 {

       lvcolumn.cx = rect.Width()*3/5 ; 

 }

 else

       lvcolumn.cx = rect.Width()*2/5;

m_lSEO靠我istctrl.InsertColumn(i, &lvcolumn);

}

这是插入两列的做法.

lvcolumn.mask 中那个mask可以有各种属性,具体去看msdn吧,

条款三:把记录,插入列表框中

iSEO靠我nt nIndex = m_listctrl.GetItemCount();

LV_ITEM   lvitemAdd = {0};

lvitemAdd.mask = LVIF_TEXT;

lvitemAddSEO靠我.iItem = nIndex ;

lvitemAdd.iSubItem = 0;

lvitemAdd.pszText =_T("毛毛1");;

if (m_listctrl.InsertItem(&lviSEO靠我temAdd) != -1)

   LV_ITEM lvitem = {0};

   lvitem.mask = LVIF_TEXT;

   lvitem.iItem = nIndex ;

lvitem.iSubItem =SEO靠我 1;

   lvitem.pszText =_T("毛毛2");

   m_listctrl.SetItem(&lvitem);   

}

nIndex 是当前的行数,然后把新的一行,插在最下面,

条款四:给列表中插入图标

在rSEO靠我eport格式中,也能插入图标

继续代码说话

m_image是个CImageList对象

m_image.Create(16,16, TRUE|ILC_COLOR24, 3, 1);

m_listctrl.SSEO靠我etImageList(&m_image,LVSIL_SMALL);

然后调用CImageList的成员函数int CImageList::Add( HICON hIcon );

把ICON插入到imagSEO靠我elist,

然后在插入记录的时候

lvitemAdd.mask = LVIF_TEXT; 

lvitemAdd.mask = LVIF_TEXT|LVIF_IMAGE

然后添加一个lvitemAdd.iImaSEO靠我ge = n;

这个n是imagelist中的序号,表示是具体的哪一个图标,list么,呵呵

条款五:插入记录时使用额外的信息,lParam 的使用

有时候,你想对于某一行,加入一些额外的信息,那么就可以使SEO靠我用这个lParam

msdn是这么描述的Specifies the 32-bit value of the item

我上次是为了在某一行加入一个信息,窗口句柄,然后是这么加的,

int nIndex = SEO靠我m_listctrl.GetItemCount();

/*在选中行之后插入

for (int i=m_listctrl.GetItemCount()-1; i>=0; i--) 

{ if(SEO靠我 m_listctrl.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED) { nIndex=i;//当前行之前插入 SEO靠我  nIndex++;//下一行,当前行之后插入 break;//找到当前行,就退出 } } */

LV_ITEMSEO靠我   lvitemAdd = {0};

lvitemAdd.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;

lvitemAdd.iItem = nIndex ;

lvitemSEO靠我Add.iSubItem = 0;

lvitemAdd.pszText =_T("毛毛1");;

lvitemAdd.iImage = n;

lvitemAdd.lParam = (LPARAM)hwnd;SEO靠我(某个窗口的窗口句柄)

if (m_listctrl.InsertItem(&lvitemAdd) != -1)

   LV_ITEM lvitem = {0};

lvitem.mask = LVIF_TEXTSEO靠我;

   lvitem.iItem = nIndex ;

   lvitem.iSubItem = 1;

   lvitem.pszText =_T("毛毛2");

   m_listctrl.SetItem(&lvitem);   

}

oSEO靠我k,这是一个比较全的例子的,又插ICON,又使用PARAM的

条款六 : 点击列表框,获取选中行信息

响应NM_CLICK消息,如果你有MSDN,可以看到,有专门关于listview的NM_CLICK的介SEO靠我

void CMyDlg::OnItemClick(NMHDR* pNMHDR, LRESULT* pResult) 

{

// TODO: Add your control notification haSEO靠我ndler code here

   int nItem = -1;

   LPNMITEMACTIVATE lpNMItemActivate = (LPNMITEMACTIVATE)pNMHDR;

if(lpNMItSEO靠我emActivate != NULL)

   {

      nItem = lpNMItemActivate->iItem;

   }

}

现在nItem就是点击选中那行的index了,有了index,获取那行的信息还难吗

懒汉说:难SEO靠我,因为你还没讲,晕,那就继续说

条款七: 根据行的index,获取该行的信息

直接上代码吧

LV_ITEM lvitem = {0};

lvitem.iItem = nIndex;

lvitem.iSubIteSEO靠我m = 0;

lvitem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;

m_listctrl.GetItem(&lvitem)

这样,就把nindex,第一列的信息取出来SEO靠我了,包括刚才我们加入的ICON,和那个额外信息(窗口句柄),比如我要获取窗口句柄,就可以hwnd = (HWND)lvitem.lParam;

mask 用来指明你想获取那些信息

具体可以查msdn中LVSEO靠我ITEM Structure的定义和CListCtrl::GetItem

条款八:用程序选中某一行,使之选中

选中之 

m_listctrl.SetItemState(nIndex,LVIS_SELECTEDSEO靠我|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);

m_listctrl.SetCheck(i);//若有checkbox,打勾

不选中,取消选中之

m_listctrl.SEO靠我SetItemState(nIndex,0,LVIS_SELECTED|LVIS_FOCUSED);

m_listctrl.SetCheck(i,false);//若有checkbox,不打勾 条款九:获SEO靠我取当前所有选中的行(多选)

// CListCtrl* pListCtrl = (CListCtrl*) GetDlgItem

(IDC_YOURLISTCONTROL);

ASSERT(pListCtrlSEO靠我 != NULL);

POSITION pos = pList->GetFirstSelectedItemPosition();

if (pos == NULL)

TRACE0("No items wereSEO靠我 selected!\n");

else

{

   while (pos)

   {

      int nItem = pList->GetNextSelectedItem(pos);

TRACE1("Item %d was seleSEO靠我cted!\n", nItem);

      // you could do your own processing on nItem here

   }

}

条款十:删除条款九中选中的行

这个相对前面九个条款是比较麻烦的,因SEO靠我为如果你要删除多行的话,往往要出错。比如,我现在要删除第0行和第1行(列表的行序列是从0开始的)

那么好啊。我来删了

m_listctrl.DeleteItem(0)

m_listctrl.DeleteItSEO靠我em(1)

恭喜你,错了,我好开心啊 :)

因为你删除第0行以后,下面的行会往上移,那么原来的第1行就变成了第0行,那么你再 m_listctrl.DeleteItem(1),那么删除的是原来的第2行,真SEO靠我麻烦,

所以,只有从下往上删,才是安全的,先删的,不会影响后面的操作,

m_listctrl.DeleteItem(1)

m_listctrl.DeleteItem(0)

但有时候,我们也不知道要删除哪些行,SEO靠我只知道要删除选中的那些行,像条款九中的那些

如果我们还是用

POSITION pos = m_listctrl.GetFirstSelectedItemPosition();

if (pos == NULLSEO靠我)

   TRACE0("No items were selected!\n");

else

{

   while (pos)

   {

int nItem = m_listctrl.GetNextSelectedItem(posSEO靠我);

      m_listctrl.DeleteItem(nItem );

   }

}

这时候我们就要B4微软了,为虾米木有GetLastselectedItemPosition 和GetPrevSelectedItemSEO靠我,多写一对成员函数会死啊 :(

没办法,办法自己想,这里有个笨办法

POSITION sSelPos = NULL;

while(sSelPos = m_listctrl.GetFirstSelectedISEO靠我temPosition())

{

   int nSelItem = -1;

   nSelItem = m_listctrl.GetNextSelectedItem(sSelPos);

if(nSelItem >= 0SEO靠我 && nSelItem

   {

      //好了,这个nSelItem 就是我们要的DD

   }

}

GetNextSelectedItem这个函数,看msdn的用法,其实是返回第一个的index,然后走到下一个选中的行去,SEO靠我所以这么做也是安全的,在实际中,俺也是这么做的,测试也通过,没问题的

当然,还有个办法,先通过GetFirstSelectedItemPosition和GetNextSelectedItem来获取所有的SEO靠我选中行的index,然后把这些index放到一个数组里,然后再从下往上删

唉真麻烦啊,还要不定数组,不说用new在堆上开吧,那么一个vector总是要的吧,麻烦啊,所以我暂时是用上述的办法来删除,也供大SEO靠我家参考,希望能找到更好的办法。

if (ok!=IDYES) {return;} m_list.SetRedraw(FALSE);       //更新内容

for (int iSEO靠我=m_listctrl.GetItemCount()-1; i>=0; i--)  { if( m_listctrl.GetItemState(i,SEO靠我 LVIS_SELECTED) == LVIS_SELECTED)//当前点击的行 { m_listctrl.DeleteItem(i);     SEO靠我 break;//只删除当前行,所以删除就退出 } } m_list.SetRedraw(TRUESEO靠我);     m_list.Invalidate(); m_list.UpdateWindow(); }

// TODO: SEO靠我在此添加额外的初始化代码m_List.DeleteAllItems();//清空 m_List.InsertColumn(0,_T("项目"));//添加列 SEO靠我 m_List.InsertColumn(1,_T("所在路径")); m_List.SetColumnWidth(0, 150);//设置列宽 SEO靠我 m_List.SetColumnWidth(1, 350); m_List.SetRedraw(FALSE);//防止重绘 iSEO靠我nt nIndex;TCHAR Path[MAX_PATH+1];//MAX_PATH最长路径nIndex=m_List.InsertItem( 0,_T("Windows目录") );if( nInSEO靠我dex < 0 ) return TRUE;GetWindowsDirectory(Path,MAX_PATH);//取得windows目录m_List.SetItemText( nIndex, 1,SEO靠我 Path );m_List.SetRedraw(TRUE);//显示return TRUE; // 除非将焦点设置到控件,否则返回TRUE

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2