list control的用法(二)

 

1。先来介绍REPORT类型的 CListCtrl:

首先使用下面的语句设置CListCtrl的style:

 DWORD SetExtendedStyle( DWORD dwNewStyle );

其中

 LVS_EX_CHECKBOXES 表 示添加CheckBox

 LVS_EX_FULLROWSELECT 表示选择整行

 LVS_EX_GRIDLINES 表示添加表格线

如果设置了LVS_EX_CHECKBOXES属性,则可以用

 BOOL GetCheck( int nItem ) const;

来得到某一行是否Checked。

可以先用下面的语句来删除以前的东西:

 for(int k=2;k>=0;k--) //注意要从后往前删,否则出错

  m_ListCtrl.DeleteColumn(k);

 m_ListCtrl.DeleteAllItems();

用下面的语句新建列:

 m_ListCtrl.InsertColumn(0,_T(" 文件名"),LVCFMT_IMAGE|LVCFMT_LEFT);

 m_ListCtrl.InsertColumn(1,_T("仪器类别"));

 m_ListCtrl.InsertColumn(2,_T("项目类别"));

 

其中 LVCFMT_IMAGE表示可以在第一列加入图标。如果不要图标可以删去。

然后设置列宽:

 for(j=0;j<3;j++)

  m_ListCtrl.SetColumnWidth(j ,100);

 

以下为列表加入图标,如果不需要图标,可以跳过这一步。注意只在第一次加入,如果多次加入会出错!

先 在头文件中加入声明:

 CImageList m_ImageList;

这是必要的,如果在cpp的某个函数中加入由于生命期结束,CImageList自动释放,则效果是列表中看不到图标,只看到一个白方块。

下面生成 CImageList,并将其绑定到CListCtrl中,这是CImageList中还没有图标,只是一个容器:

 static int flag=2;

 if(flag==2){//只调用一次SetImageList,否 则出错

  m_ImageList.Create(128, 128, ILC_COLORDDB|ILC_MASK, 20, 1); 

  m_ListCtrl.SetImageList(&m_ImageList,LVSIL_SMALL);

 }

 flag=(flag+1)%2;

如果CListCtrl已经用过,曾经加过图标进去,这时就要删除上次放进m_ImageList中的Image

 for(int kk=0;kk<m_ImageList.GetImageCount();kk++)

  m_ImageList.Remove(k);

 

下面介绍如何向CListCtrl里面加入行,并同时为每一行动态加入图标:

假设m_listRowCount 为要加入的行数。

 CBitmap* bitmap;

 bitmap=new CBitmap[m_list1rowCount];

 HBITMAP hbitmap; 

 

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

 {

  //为每一行插入相应的缩略图

  CFile f;

  CFileException e;  

  if( !f.Open(m_FileName, CFile::modeRead, &e )){ //m_FileNamebmp文件名,由你来定

   hbitmap = (HBITMAP)LoadImage(NULL,path+"blank.bmp",IMAGE_BITMAP,0,0,

    LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);

  }else{

   f.Close();

   hbitmap = (HBITMAP)LoadImage(NULL,bmpFile,IMAGE_BITMAP,0,0,

    LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);

  }

  bitmap[i].Attach(hbitmap);

  m_ImageList.Add(&bitmap[i], RGB(0, 128, 128));

  

  //插入行

  m_ListCtrl.InsertItem(i,m_FileName,i);

  m_ListCtrl.SetItemText(i,1,type);

  m_ListCtrl.SetItemText(i,2,m_Path);

 }

  

 // 记得删除已经没用的临时文件

 if(m_list1rowCount!=0)

  delete[] bitmap;

2。如果是ICON类型的CListCtrl,则要做一点点改动:

把绑定图标集的代码由

 SetImageList(&m_ImageList,LVSIL_SMALL);

改为

 SetImageList(&m_ImageList,LVSIL_NORMAL);

插入行时只用

 InsertItem(i,mainSet.m_FileName,i);

不 用

 SetItemText(i,1,type);

之类的代码。

设置报表的样式

选中一整行:

m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_FULLROWSELECT); 

绘 制表格:

m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_GRIDLINES);

带 复选框:

m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_CHECKBOXES);

自 动切换:

m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_TRACKSELECT);

选 定一行:

设置CListCtrl的Show selection always选项

SetItemState (iIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED)

 

选中一个或多个项目时,会发送LVN_ITEMCHANGED消息,可以使用

GetSelectedCount()方法得到被选定的项的数目。

点击列头的 消息响应:

ON_NOTIFY(HDN_ITEMCLICKW, 0, ResponseFunc)

消息,需要自己添加

或者:

ON_NOTIFY(LVN_COLUMNCLICK, ID_yourCtrl,  ResponseFunc)//向导添加

前者后响应,后者先响应

响应函数:

ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)

双击CListCtrl中的ITEM的消息是及消息函数:

ON_NOTIFY(NM_DBLCLK, ID_yourCtrl, ResponseFunc)

单击ITEM的消息响应:

ON_NOTIFY(NM_CLICK, ID_yourCtrl, ResponseFunc)

ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)

HDN_ITEMCLICK    就是Header control Notify message for mouse left click on the Header control!

而HDN_ITEMCLICK是当List View中存在一个Header Contrl时,Header Ctrl通知父窗口List View的!

CListCtrl中的Item被选中触发LBN_SELCHANGE(通过WM_COMMAND)消息!

删除CListCtrl中选定的项:

POSITION pos;

int nIndex;

for(; pos= GetFirstSelectedItemPosition();)

{

nIndex = GetNextSelectedItem(pos);

DeleteItem(nIndex);

}

在ListCtrl中进行排序

列表控件(CListCtrl)的顶部有一排按钮,用户可以通过选择不同的列来对记录进行排序。但是 CListCtrl并没有自动排序的功能,我们需要自己添加一个用于排序的回调函数来比较两个数据的大小,此外还需要响应排序按钮被点击的消息。下面讲述一下具体的做法。

CListCtrl提供了用于排序的函数,函数原型为:BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData )。其中第一个参数为全局排序函数的地址,第二个参数为用户数据,你可以根据你的需要传递一个数据或是指针。该函数返回-1代表第一项排应在第二项前面,返回1代表第一项排应在第二项后面,返回0代表两项相等。

用于排序的函数原形为:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三个参数为调用者传递的数据(即调用SortItems时的第二个参数dwData)。第一和第二个参数为用于比较的两项的ItemData,你可以通过DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )来对每一项的ItemData进行存取。在添加项时选用特定的CListCtrl::InsertItem也可以设置该值。由于你在排序时只能通过该值来确定项的位置所以你应该比较明确的确定该值的含义。

最后一点,我们需要知道什么时候需要排序,实现这点可以在父窗口中对 LVN_COLUMNCLICK消息进行处理来实现。

下面我们看一个例子,这个例子是一个派生类,并支持顺序/倒序两种方式排序。为了简单我对全局数据进行排序,而在实际应用中会有多组需要排序的数据,所以需要通过传递参数的方式来告诉派序函数需要对什么数据进行排序。

//全局数据

struct DEMO_DATA

{

 char szName[20];

 int iAge;

}strAllData[5]={{" 王某",30},{"张某",40},{"武某",32},{"陈某",20},{"李某",36}};

//CListCtrl派生类定义

class CSortList : public CListCtrl

{

// Construction

public:

 CSortList();

 BOOL m_fAsc;//是否顺序排序

 int m_nSortedCol;//当前排序的列

protected:

 //{{AFX_MSG(CSortList)

 //}}AFX_MSG

...

};

// 父窗口中包含该CListCtrl派生类对象

class CSort_in_list_ctrlDlg : public CDialog

{

// Construction

public:

 CSort_in_list_ctrlDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data

 //{{AFX_DATA(CSort_in_list_ctrlDlg)

 enum { IDD = IDD_SORT_IN_LIST_CTRL_DIALOG };

 CSortList m_listTest;

 //}}AFX_DATA

}

// 在父窗口中定义LVN_COLUMNCLICK消息映射

BEGIN_MESSAGE_MAP(CSort_in_list_ctrlDlg, CDialog)

 //{{AFX_MSG_MAP(CSort_in_list_ctrlDlg)

 ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, OnColumnclickList1)

 //}}AFX_MSG_MAP

END_MESSAGE_MAP()

// 初始化数据

BOOL CSort_in_list_ctrlDlg::OnInitDialog()

{

 CDialog::OnInitDialog();

 // 初始化ListCtrl中数据列表

 m_listTest.InsertColumn(0,"姓名");

 m_listTest.InsertColumn(1," 年龄");

 m_listTest.SetColumnWidth(0,80);

 m_listTest.SetColumnWidth(1,80);

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

 {

  m_listTest.InsertItem(i,strAllData[i].szName);

  char szAge[10];

  sprintf(szAge,"%d",strAllData[i].iAge);

  m_listTest.SetItemText(i,1,szAge);

  // 设置每项的ItemData为数组中数据的索引

  //在排序函数中通过该ItemData来确定数据

  m_listTest.SetItemData(i,i);

 }

 return TRUE;  // return TRUE  unless you set the focus to a control

}

// 处理消息

void CSort_in_list_ctrlDlg::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult)

{

 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

 //设置排序方式

 if( pNMListView->iSubItem == m_listTest.m_nSortedCol )

  m_listTest.m_fAsc = !m_listTest.m_fAsc;

 else

 {

  m_listTest.m_fAsc = TRUE;

  m_listTest.m_nSortedCol = pNMListView->iSubItem;

 }

 // 调用排序函数

 m_listTest.SortItems( ListCompare, (DWORD)&m_listTest );       

 *pResult = 0;

}

//排序函数实现

int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)

{

 // 通过传递的参数来得到CSortList对象指针,从而得到排序方式

 CSortList* pV=(CSortList*)lParamSort;

 

 //通过ItemData来确定数据

 DEMO_DATA* pInfo1=strAllData+lParam1;

 DEMO_DATA* pInfo2=strAllData+lParam2;

 CString szComp1,szComp2;

 int iCompRes;

 switch(pV->m_nSortedCol)

 {

 case(0):

  // 以第一列为根据排序

  szComp1=pInfo1->szName;

  szComp2=pInfo2->szName;

  iCompRes=szComp1.Compare(szComp2);

  break;

 case(1):

  // 以第二列为根据排序

  if(pInfo1->iAge == pInfo2->iAge)

   iCompRes = 0;

  else

   iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;

  break;

 default:

  ASSERT(0);

  break;

 }

 // 根据当前的排序方式进行调整

 if(pV->m_fAsc)

  return iCompRes;

 else

  return iCompRes*-1;

}

排序最快:

CListCtrl::SortItems

Example

// Sort the item in reverse alphabetical order.

static int CALLBACK

MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)

{

  // lParamSort contains a pointer to the list view control.

  // The lParam of an item is just its index.

  CListCtrl* pListCtrl = (CListCtrl*) lParamSort;

  CString    strItem1 = pListCtrl->GetItemText(lParam1, 0);

  CString    strItem2 = pListCtrl->GetItemText(lParam2, 0);

  return strcmp(strItem2, strItem1);

}

void snip_CListCtrl_SortItems()

{

  // The pointer to my list view control.

  extern CListCtrl* pmyListCtrl;

  // Sort the list view items using my callback procedure.

  pmyListCtrl->SortItems(MyCompareProc, (LPARAM) pmyListCtrl);

}

If you don’t want to allow the users to sort the list by clicking on the header, you can use the style LVS_NOSORTHEADER. However, if you do want to allow sorting, you do not specify the LVS_NOSORTHEADER. The control, though, does not sort the items. You have to handle the HDN_ITEMCLICK notification from the header control and process it appropriately. In the code below, we have used the sorting function SortTextItems() developed in a previous section. You may choose to sort the items in a different manner.

Step 1: Add two member variables

Add two member variables to the CListCtrl. The first variable to track which column has been sorted on, if any. The second variable to track if the sort is ascending or descending.

        int nSortedCol;

        BOOL bSortAscending;

 

Step 2: Initialize them in the constructor.

Initialize nSortedCol to -1 to indicate that no column has been sorted on. If the list is initially sorted, then this variable should reflect that.

 

        nSortedCol = -1;

        bSortAscending = TRUE;

 

Step 3: Add entry in message map to handle HDN_ITEMCLICK

Actually you need to add two entries. For HDN_ITEMCLICKA and HDN_ITEMCLICKW. Do not use the class wizard to add the entry. For one, you need to add two entries whereas the class wizard will allow you only one. Secondly, the class wizard uses the wrong macro in the entry. It uses ON_NOTIFY_REFLECT() instead of ON_NOTIFY(). Since the HDN_ITEMCLICK is a notification from the header control to the list view control, it is a direct notification and not a reflected one.

ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)

ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)

 Note that we specify the same function for both the notification. Actually the program will receive one or the other and not both. What notification it receives will depend on the OS. The list view control on Windows 95 will send the ANSI version and the control on NT will send the UNICODE version.

Also, note that the second argument is zero. This value filters for the id of the control and we know that header control id is zero.

Step 4: Write the OnHeaderClicked() function

Here’s where you decide what to do when the user clicks on a column header. The expected behaviour is to sort the list based on the values of the items in that column. In this function we have used the SortTextItems() function developed in a previous section. If any of the columns displays numeric or date values, then you would have to provide custom sorting for them.

 

void CMyListCtrl::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)

{

        HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;

        if( phdn->iButton == 0 )

        {

                // User clicked on header using left mouse button

                if( phdn->iItem == nSortedCol )

                        bSortAscending = !bSortAscending;

                else

                        bSortAscending = TRUE;

                nSortedCol = phdn->iItem;

                SortTextItems( nSortedCol, bSortAscending );

        }

        *pResult = 0;

}

让CListCtrl的SubItem也具有编辑功能:

要重载一个文本框,然后在 LVN_BEGINLABELEDIT时改变文本框位置。

CInEdit m_InEdit;

    if( ( GetStyle() & LVS_TYPEMASK ) == LVS_REPORT && ( m_nEditSubItem != 0 ) )

    {

        HWND    hwndEdit;

        CRect    rtBound;

        CString strText;

        hwndEdit = (HWND)SendMessage( LVM_GETEDITCONTROL );

        GetSubItemRect( pDispInfo->item.iItem, m_nEditSubItem, LVIR_LABEL, rtBound );

        m_InEdit.SubclassWindow( hwndEdit );

        m_InEdit.m_left = rtBound.left;

        strText = GetItemText( pDispInfo->item.iItem, m_nEditSubItem );

        m_InEdit.SetWindowText( strText );

    }

void CInEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)

{

    CRect rtClient;

    lpwndpos->x = m_left;  // m_leftLVN_BEGINLABELEDIT中设置

    CEdit::OnWindowPosChanging(lpwndpos);

   

    // TODO: Add your message handler code here

}

 

源文档 <http://www.cppblog.com/justin-shi/archive/2008/06/14/53192.html>

 

 

  •  
    1. m_pCtrl = &this->GetListCtrl(); //获得指针
    2. //CListCtrl样式改变
    3. LONG lStyle;
    4. lStyle = GetWindowLong(m_pCtrl->m_hWnd, GWL_STYLE);     //获取当前窗口 style
    5. lStyle &= ~LVS_TYPEMASK;        //清除显示方式
    6. lStyle |= LVS_REPORT;   //设置style Report显示
    7. SetWindowLong(m_pCtrl->m_hWnd, GWL_STYLE, lStyle);      
    8. //CListCtrl扩展样式改变
    9. DWORD dwStyle;
    10. dwStyle = m_pCtrl->GetStyle();  //取得样式
    11. dwStyle |=    LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT ;   //添加样式
    12. m_pCtrl->SetExtendedStyle(dwStyle);     //重新设置
    1. //插入列
    2. m_pCtrl->InsertColumn(1,"第一列",LVCFMT_CENTER,47);  //序 号,标题,标题显示位置,列宽度
    3. m_pCtrl->InsertColumn(2,"第二列",LVCFMT_CENTER,100);
    4. //写入数据
    5. int nRow = m_list.InsertItem(0, “无用字符串”); //插入行
    6. m_list.SetItemText(nRow, 1, “1111”);        //设置数据
    7. m_list.SetItemText(nRow, 2, “2222”);        //设置数据
    1. int n = -1;
    2. POSITION pos = m_pCtrl->GetFirstSelectedItemPosition(); //返回第一个选中的行位置
    3. if (pos != NULL)
    4. {
    5.    while (pos)
    6.    {
    7.                   n = m_pCtrl->GetNextSelectedItem(pos);  //返回下一个选中的行数(返回值从0开始)
    8.                 //做相应操作
    9.    }
    10. }
    1. //直接用VC类向导生成后,不用再次添加声明和消息映射
    2. //添加函数声明
    3. afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult);
    4. //添加消息映射
    5. ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
    6. void CMyListView::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
    7. {
    8.         // TODO: Add your control notification handler code here
    9.           NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    10.         if(pNMListView->iItem != -1)
    11.         {
    12.                 /*
    13.                   CString strtemp;
    14.                   strtemp.Format("单击的是第%d行第%d",
    15.                                                   pNMListView->iItem, pNMListView->iSubItem);
    16.                   AfxMessageBox(strtemp);
    17.                   */
    18.                 //值从0开始计算,无数据区不相应 时间
    19.                 //相应操作
    20.         }
    21.           *pResult = 0;
    22. }
    • LVS_ICON LVS_SMALLICON LVS_LIST LVS_REPORT 这四种风格决定控件的外观,同时只可以选择其中一种,分别对应:大图标显示,小图标显示,列表显示,详细报表显示
    • LVS_EDITLABELS 结点的显示字符可以被编辑,对于报表风格来讲可编辑的只为第一列。
    • LVS_SHOWSELALWAYS 在失去焦点时也显示当前选中的结点
    • LVS_SINGLESEL 同时只能选中列表中一项
    • LVN_BEGINLABELEDIT 在开始某项编辑字符时发送,所用结构:NMLVDISPINFO
    • LVN_ENDLABELEDIT 在结束某项编辑字符时发送,所用结构:NMLVDISPINFO
    • LVN_GETDISPINFO 在需要得到某项信息时发送,(如得到某项的显示字符)所用结构:NMLVDISPINFO
  • 列表控件可以看作是功能增强的ListBox,它提供了四种风格,而且可以同时显示一列的多中属性 值。MFC中使用CListCtrl类来封装列表控件的各种操作。通过调用 BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );创建一个窗口,dwStyle中可以使用以下一些列表控件的专用风格:

    首先你需要设置列表控件所使用的ImageList,如果你使用大图标显示风格,你就需要以如下形式调用: CImageList* SetImageList( CImageList* pImageList, LVSIL_NORMAL); 如果使用其它三种风格显示而不想显示图标你可以不进行任何设置,否则需要以如下形式调用: CImageList* SetImageList( CImageList* pImageList, LVSIL_SMALL);

    通过调用int InsertItem( int nItem, LPCTSTR lpszItem );可以在列表控件中nItem指明位置插入一项,lpszItem为显示字符。除LVS_REPORT风格外其他三种风格都只需要直接调用 InsertItem就可以了,但如果使用报表风格就必须先设置列表控件中的列信息。

    通过调用int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat , int nWidth, int nSubItem);可以插入列。iCol为列的位置,从零开始,lpszColumnHeading为显示的列名,nFormat为显示对齐方式, nWidth为显示宽度,nSubItem为分配给该列的列索引。

    在有多列的列表控件中就需要为每一项指明其在每一列中的显示字符,通过调用 BOOL SetItemText( int nItem, int nSubItem, LPTSTR lpszText );可以设置每列的显示字符。nItem为设置的项的位置,nSubItem为列位置,lpszText为显示字符。下面的代码演示了如何设置多列并插入 数据:

    m_list.SetImageList(&m_listSmall,LVSIL_SMALL);//设置ImageList
    m_list.InsertColumn(0,"Col 1",LVCFMT_LEFT,300,0);//设置列
    m_list.InsertColumn(1,"Col 2",LVCFMT_LEFT,300,1);
    m_list.InsertColumn(2,"Col 3",LVCFMT_LEFT,300,2);

    m_list.InsertItem(0,"Item 1_1");//插入行
    m_list.SetItemText(0,1,"Item 1_2");//设置该行的不同列的显示字符
    m_list.SetItemText(0,2,"Item 1_3");

    此外CListCtrl还提供了一些函数用于得到/修改控件的状态。 COLORREF GetTextColor( )/BOOL SetTextColor( COLORREF cr );用于得到/设置显示的字符颜色。 COLORREF GetTextBkColor( )/BOOL SetTextBkColor( COLORREF cr );用于得到/设置显示的背景颜色。 void SetItemCount( int iCount );用于得到添加进列表中项的数量。 BOOL DeleteItem(int nItem);用于删除某一项,BOOL DeleteAllItems( );将删除所有项。 BOOL SetBkImage(HBITMAP hbm, BOOL fTile , int xOffsetPercent, int yOffsetPercent);用于设置背景位图。 CString GetItemText( int nItem, int nSubItem );用于得到某项的显示字符。

    列表控件的消息映射同样使用ON_NOTIFY宏,形式如同:ON_NOTIFY( wNotifyCode, id, memberFxn ),wNotifyCode为通知代码,id为产生该消息的窗口ID,memberFxn为处理函数,函数的原型如同void OnXXXList(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR为一数据结构,在具体使用时需要转换成其他类型的结构。对于列表控件可能取值和对应的数据结构为:

    关于ON_NOTIFY有很多内容,将在以后的内容中进行详细讲解。

    关于动态提供结点所显示的字符:首先你在项时需要指明 lpszItem参数为: LPSTR_TEXTCALLBACK。在控件显示该结点时会通过发送TVN_GETDISPINFO来取得所需要的字符,在处理该消息时先将参数 pNMHDR转换为LPNMLVDISPINFO,然后填充其中item.pszText。通过item中的iItem,iSubItem可以知道当前显 示的为那一项。下面的代码演示了这种方法:

    char szOut[8][3]={"No.1","No.2","No.3"};

    //添加结点
    m_list.InsertItem(LPSTR_TEXTCALLBACK,...)
    m_list.InsertItem(LPSTR_TEXTCALLBACK,...)
    //处理消息
    void CParentWnd::OnGetDispInfoList(NMHDR* pNMHDR, LRESULT* pResult)
    {
     LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;
     pLVDI->item.pszText=szOut[pTVDI->item.iItem];//通过iItem得到需要显示的字符在数组中的位置
     *pResult = 0;
    }

    关于编辑某项的显示字符:(在报表风格中只对第一列有效)首先需 要设置列表控件的 LVS_EDITLABELS风格,在开始编辑时该控件将会发送LVN_BEGINLABELEDIT,你可以通过在处理函数中返回TRUE来取消接下来 的编辑,在编辑完成后会发送LVN_ENDLABELEDIT,在处理该消息时需要将参数pNMHDR转换为LPNMLVDISPINFO,然后通过其中 的item.pszText得到编辑后的字符,并重置显示字符。如果编辑在中途中取消该变量为NULL。下面的代码说明如何处理这些消息:

    //处理消息 LVN_BEGINLABELEDIT
    void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)
    {
     LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;
     if(pLVDI->item.iItem==0);//判断是否取消该操作
      *pResult = 1;
     else
      *pResult = 0;
    }
    //处理消息 LVN_BEGINLABELEDIT
    void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)
    {
     LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;
     if(pLVDI->item.pszText==NULL);//判断是否已经取消取消编辑
      m_list.SetItemText(pLVDI->item.iItem,0,pLVDI->pszText);//重置显示字符
     *pResult = 0;
    }

    上面讲述的方法所进行的消息映射必须在父窗口中进行(同样WM_NOTIFY的所有消息都需要在父窗口中处 理)。

    如何得到当前选中项位置:在列表控件中没有一个类似于 ListBox中GetCurSel()的函数,但是可以通过调用GetNextItem( -1, LVNI_ALL | LVNI_SELECTED);得到选中项位置。

    下面是一些例子

    作者:lixiaosan 时间:04/06/2006

    以下未经说明,listctrl默认view 风格为report

    相关类及处理函数

    MFC:CListCtrl类

    SDK:以 “ListView_”开头的一些宏。如 ListView_InsertColumn

     

    1. CListCtrl 风格

          LVS_ICON: 为每个item显示大图标       LVS_SMALLICON: 为每个item显示小图标       LVS_LIST: 显示一列带有小图标的item       LVS_REPORT: 显示item详细资料

          直观的理解:windows资源管理器,“查看”标签下的“大图标,小图标,列表,详细资料”

     

     

    2. 设置listctrl 风格及扩展风格

          LONG lStyle;       lStyle. = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口style       lStyle. &= ~LVS_TYPEMASK; //清除显示方式位       lStyle.|= LVS_REPORT; //设置style       SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style       DWORD dwStyle. = m_list.GetExtendedStyle();       dwStyle.|= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl      dwStyle.|= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl      dwStyle.|= LVS_EX_CHECKBOXES;//item前生成checkbox控件       m_list.SetExtendedStyle(dwStyle); //设置扩展风格       注:listviewstyle请查阅msdn       http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50lrflistviewstyles.asp

     

     

    3. 插入数据

          m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列       m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 );       int nRow = m_list.InsertItem(0, “11”);//插入行       m_list.SetItemText(nRow, 1, “jacky”);//设置数据

     

     

    4. 一直选中item

        选中style中的Show selection always,或者在上面第2点中设置LVS_SHOWSELALWAYS

     

    5. 选中和取消选中一行

        int nIndex = 0;     //选中     m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);     //取消选中     m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);

     

    6. 得到listctrl中所有行的checkbox的状态

          m_list.SetExtendedStyle(LVS_EX_CHECKBOXES);       CString str;       for(int i=0; i<m_list.GetItemCount(); i++)       {            if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i))            {                 str.Format(_T("%d行的checkbox为选中状态"), i);                 AfxMessageBox(str);            }       }

     

     

    7. 得到listctrl中所有选中行的序号

           方法一:       CString str;       for(int i=0; i<m_list.GetItemCount(); i++)       {            if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED )            {                 str.Format(_T("选中了第%d"), i);                 AfxMessageBox(str);            }       }

          方法二:       POSITION pos = m_list.GetFirstSelectedItemPosition();       if (pos == NULL)            TRACE0("No items were selected!/n");       else       {            while (pos)            {                 int nItem = m_list.GetNextSelectedItem(pos);                 TRACE1("Item %d was selected!/n", nItem);                 // you could do your own processing on nItem here            }       }

     

     

    8. 得到item的信息

          TCHAR szBuf[1024];       LVITEM lvi;       lvi.iItem = nItemIndex;       lvi.iSubItem = 0;       lvi.mask = LVIF_TEXT;       lvi.pszText = szBuf;       lvi.cchTextMax = 1024;       m_list.GetItem(&lvi);

          关于得到设置item的状态,还可以参考msdn文章       Q173242: Use Masks to Set/Get Item States in CListCtrl                http://support.microsoft.com/kb/173242/en-us

     

    9. 得到listctrl的所有列的header字符串内容

          LVCOLUMN lvcol;       char str[256];       int   nColNum;       CString strColumnName[4];//假如有4

          nColNum = 0;       lvcol.mask = LVCF_TEXT;       lvcol.pszText = str;       lvcol.cchTextMax = 256;       while(m_list.GetColumn(nColNum, &lvcol))       {            strColumnName[nColNum] = lvcol.pszText;            nColNum++;       }

     

     

    10. 使listctrl中一项可见,即滚动滚动条

        m_list.EnsureVisible(i, FALSE);

     

    11. 得到listctrl列数

        int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();

     

    12. 删除所有列

        方法一:          while ( m_list.DeleteColumn (0))        因为你删除了第一列后,后面的列会依次向上移动。

        方法二:       int nColumns = 4;       for (int i=nColumns-1; i>=0; i--)           m_list.DeleteColumn (i);

     

     

    13. 得到单击的listctrl的行列号

          添加listctrl控件的NM_CLICK消息相应函数       void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)       {            // 方法一:            /*            DWORD dwPos = GetMessagePos();            CPoint point( LOWORD(dwPos), HIWORD(dwPos) );               m_list.ScreenToClient(&point);               LVHITTESTINFO lvinfo;            lvinfo.pt = point;            lvinfo.flags = LVHT_ABOVE;                 int nItem = m_list.SubItemHitTest(&lvinfo);            if(nItem != -1)            {                 CString strtemp;                 strtemp.Format("单击的是第%d行第%d", lvinfo.iItem, lvinfo.iSubItem);                 AfxMessageBox(strtemp);            }           */              // 方法二:           /*            NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;            if(pNMListView->iItem != -1)            {                 CString strtemp;                 strtemp.Format("单击的是第%d行第%d",                                 pNMListView->iItem, pNMListView->iSubItem);                 AfxMessageBox(strtemp);            }           */            *pResult = 0;       }

     

     

    14. 判断是否点击在listctrl的checkbox上

          添加listctrl控件的NM_CLICK消息相应函数       void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)       {            DWORD dwPos = GetMessagePos();            CPoint point( LOWORD(dwPos), HIWORD(dwPos) );               m_list.ScreenToClient(&point);               LVHITTESTINFO lvinfo;            lvinfo.pt = point;            lvinfo.flags = LVHT_ABOVE;                 UINT nFlag;            int nItem = m_list.HitTest(point, &nFlag);            //判断是否点在checkbox           if(nFlag == LVHT_ONITEMSTATEICON)            {                 AfxMessageBox("点在listctrlcheckbox");            }            *pResult = 0;       }

     

     

    15. 右键点击listctrl的item弹出菜单

          添加listctrl控件的NM_RCLICK消息相应函数       void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)       {            NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;            if(pNMListView->iItem != -1)            {                 DWORD dwPos = GetMessagePos();                 CPoint point( LOWORD(dwPos), HIWORD(dwPos) );                     CMenu menu;                 VERIFY( menu.LoadMenu( IDR_MENU1 ) );                 CMenu* popup = menu.GetSubMenu(0);                 ASSERT( popup != NULL );                 popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );            }            *pResult = 0; }

      

     

    16. item切换焦点时(包括用键盘和鼠标切换item时),状态的一些变化顺序

          添加listctrl控件的LVN_ITEMCHANGED消息相应函数       void CTest6Dlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)       {            NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;            // TODO: Add your control notification handler code here                CString sTemp;            if((pNMListView->uOldState & LVIS_FOCUSED) == LVIS_FOCUSED &&             (pNMListView->uNewState & LVIS_FOCUSED) == 0)            {                 sTemp.Format("%d losted focus",pNMListView->iItem);            }            else if((pNMListView->uOldState & LVIS_FOCUSED) == 0 &&                (pNMListView->uNewState & LVIS_FOCUSED) == LVIS_FOCUSED)            {                 sTemp.Format("%d got focus",pNMListView->iItem);            }            if((pNMListView->uOldState & LVIS_SELECTED) == LVIS_SELECTED &&             (pNMListView->uNewState & LVIS_SELECTED) == 0)            {                 sTemp.Format("%d losted selected",pNMListView->iItem);            }            else if((pNMListView->uOldState & LVIS_SELECTED) == 0 &&             (pNMListView->uNewState & LVIS_SELECTED) == LVIS_SELECTED)            {                 sTemp.Format("%d got selected",pNMListView->iItem);            }                *pResult = 0;       }

     

    17. 得到另一个进程里的listctrl控件的item内容

     http://www.codeproject.com/threads/int64_memsteal.asp

     

    18. 选中listview中的item

    Q131284: How To Select a Listview Item Programmatically http://support.microsoft.com/kb/131284/en-us

     

    19. 如何在CListView中使用CListCtrl的派生类

    http://www.codeguru.com/cpp/controls/listview/introduction/article.php/c919/

     

    20. listctrl的subitem添加图标

          m_list.SetExtendedStyle(LVS_EX_SUBITEMIMAGES);       m_list.SetItem(..); //具体参数请参考msdn

     

    21. 在CListCtrl显示文件,并根据文件类型来显示图标

          网上找到的代码,share       BOOL CTest6Dlg::OnInitDialog()       {            CDialog::OnInitDialog();               HIMAGELIST himlSmall;            HIMAGELIST himlLarge;            SHFILEINFO sfi;            char cSysDir[MAX_PATH];            CString strBuf;            memset(cSysDir, 0, MAX_PATH);               GetWindowsDirectory(cSysDir, MAX_PATH);            strBuf = cSysDir;            sprintf(cSysDir, "%s", strBuf.Left(strBuf.Find("//")+1));            himlSmall = (HIMAGELIST)SHGetFileInfo ((LPCSTR)cSysDir,                       0,                       &sfi,                       sizeof(SHFILEINFO),                       SHGFI_SYSICONINDEX | SHGFI_SMALLICON );               himlLarge = (HIMAGELIST)SHGetFileInfo((LPCSTR)cSysDir,                       0,                       &sfi,                       sizeof(SHFILEINFO),                       SHGFI_SYSICONINDEX | SHGFI_LARGEICON);               if (himlSmall && himlLarge)            {                 ::SendMessage(m_list.m_hWnd, LVM_SETIMAGELIST,                              (WPARAM)LVSIL_SMALL, (LPARAM)himlSmall);                 ::SendMessage(m_list.m_hWnd, LVM_SETIMAGELIST,                              (WPARAM)LVSIL_NORMAL, (LPARAM)himlLarge);            }            return TRUE; // return TRUE unless you set the focus to a control       }       void CTest6Dlg::AddFiles(LPCTSTR lpszFileName, BOOL bAddToDocument)       {            int nIcon = GetIconIndex(lpszFileName, FALSE, FALSE);            CString strSize;            CFileFind filefind;            // get file size            if (filefind.FindFile(lpszFileName))            {                 filefind.FindNextFile();                 strSize.Format("%d", filefind.GetLength());            }            else                 strSize = "0";               // split path and filename            CString strFileName = lpszFileName;            CString strPath;            int nPos = strFileName.ReverseFind('//');            if (nPos != -1)            {                 strPath = strFileName.Left(nPos);                 strFileName = strFileName.Mid(nPos + 1);            }               // insert to list            int nItem = m_list.GetItemCount();            m_list.InsertItem(nItem, strFileName, nIcon);            m_list.SetItemText(nItem, 1, strSize);            m_list.SetItemText(nItem, 2, strFileName.Right(3));            m_list.SetItemText(nItem, 3, strPath);       }       int CTest6Dlg::GetIconIndex(LPCTSTR lpszPath, BOOL bIsDir, BOOL bSelected)       {            SHFILEINFO sfi;            memset(&sfi, 0, sizeof(sfi));               if (bIsDir)            {             SHGetFileInfo(lpszPath,                          FILE_ATTRIBUTE_DIRECTORY,                          &sfi,                          sizeof(sfi),                          SHGFI_SMALLICON | SHGFI_SYSICONINDEX |                          SHGFI_USEFILEATTRIBUTES |(bSelected ? SHGFI_OPENICON : 0));             return sfi.iIcon;            }            else            {             SHGetFileInfo (lpszPath,                          FILE_ATTRIBUTE_NORMAL,                          &sfi,                          sizeof(sfi),                          SHGFI_SMALLICON | SHGFI_SYSICONINDEX |                          SHGFI_USEFILEATTRIBUTES | (bSelected ? SHGFI_OPENICON : 0));             return   sfi.iIcon;            }            return -1;       }

    22.MFC的CListCtrl的排序功能

      // 排序用的比较函数

    staticintCALLBACK

    MyCompareProc(LPARAMlParam1, LPARAMlParam2, LPARAMlParamSort)

    {

         CString &lp1 = *((CString *)lParam1);

         CString &lp2 = *((CString *)lParam2);

         int &sort = *(int *)lParamSort;

         if (sort == 0)

         {

             returnlp1.CompareNoCase(lp2);

         }

         else

         {

             returnlp2.CompareNoCase(lp1);

         }

    }

    //要处理的事件

    ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, &CDlg::OnLvnColumnclickList1)

    //处理代码

    voidCDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)

    {

         LPNMLISTVIEWpNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

         intLength = m_ListCtrl.GetItemCount();

         CArray<CString,CString> ItemData;

         ItemData.SetSize(Length);

         for (inti = 0; i < Length; i++)

         {

             ItemData[i] = m_ListCtrl.GetItemText(i,pNMLV->iSubItem);

             m_ListCtrl.SetItemData(i,(DWORD_PTR)&ItemData[i]);//设置排序关键字

        }

         staticintsort = 0;

         staticintSubItem = 0;

         if (SubItem != pNMLV->iSubItem)

         {

             sort = 0;

             SubItem = pNMLV->iSubItem;

         }

         else

         {

             if (sort == 0)

             {

                  sort = 1;

             }

             else

             {

                  sort = 0;

             }

         }

         m_ListCtrl.SortItems(MyCompareProc,(DWORD_PTR)&sort);//排序

         *pResult = 0;

    }

    23.CListCtrl显示样式的改变

    需要的样式(根据自己的需要的样式选择) LVS_ICON: 为每个item显示大图标 LVS_SMALLICON: 为每个item显示小图标 LVS_LIST: 显示一列带有小图标的item LVS_REPORT: 显示item详细资料 LVS_EX_FULLROWSELECT: 表示选中某行使整行高亮(只适用与report风格的CListCtrl) LVS_EX_GRIDLINES: 表示显示网格线(只适用与report风格的CListCtrl) 24.添加CListCtrl的记录

    25.判断CListCtrl的哪行记录被选中了

    26.响应单击CListCtrl事件

    //响应CMyListView的=NUM_CLICK消息

    27 CListCtrl,CListView与LVN_ITEMCHANGED消息

    若要在CListCtrl中行发生改变时得到通知,可以映射 LVN_ITEMCHANGED消息。

        ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemchanged)

        afx_msg void OnItemchanged(NMHDR* pNMHDR,LRESULT* pResult);

    // 行选择改变
    void CMyListCtrl::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult)
    {
        NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
        ...您要进行的操作...
        *pResult = 0;
    }

        注意,LVN_ITEMCHANGED消息的产生有以下几种可能:     1、由选中到没选中的变化;     2、由没选中到选中的变化;     3、由选中一行到选中另外一行的变化;     4、使用CListCtrl::SetItem函数更改了行;     如何检测LVN_ITEMCHANGED消息是由那一变化产生的呢?     NM_LISTVIEW结构成员变量uChangeduNewState包含着这类信息,看如下代码:

    void CRunListView::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult)
    {
        NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
        if(pNMListView->uChanged == LVIF_STATE)
        {
            if(pNMListView->uNewState)
               TRACE0("选择改变且有选中的行/r/n");
            else
               TRACE0("选择改变且没有选中的行/r/n");
        }
        else
        TRACE0("行改变(CListCtrl::SetItem)/r/n");

        *pResult = 0;
    }

     

    源文档 <http://blog.csdn.net/danforn/archive/2008/06/03/2508070.aspx>

     

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值