MFC CListCtrl 列表視圖類使用方法 以及幾種技巧

 以下未經說明,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); //設置擴展風格

 

      注:listview的style請查閱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("點在listctrl的checkbox上");

           }

           *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. listctrl內容進行大數據量更新時,避免閃爍

      m_list.SetRedraw(FALSE);

      //更新內容

      m_list.SetRedraw(TRUE);

      m_list.Invalidate();

      m_list.UpdateWindow();

 

或者參考

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cwnd.3a3a.setredraw.asp

 

 

23. listctrl排序

Q250614:How To Sort Items in a CListCtrl in Report View

http://support.microsoft.com/kb/250614/en-us

 

 

24. 在listctrl中選中某個item時動態改變其icon或bitmap

Q141834: How to change the icon or the bitmap of a CListCtrl item in Visual C++

http://support.microsoft.com/kb/141834/en-us

How to change the icon or the bitmap of a

CListCtrl item in Visual C++

View products that this article applies to.

Article ID : 141834
Last Review : June 2, 2005
Revision : 3.0


This article was previously published under Q141834

NOTE: Microsoft Visual C++ NET (2002) supported both the managed code model that is provided by the .NET Framework and the unmanaged native Windows code model. The information in this article applies to unmanaged Visual C++ code only.

T>

SUMMARY

This article shows how to change the icon or bitmap of a CListCtrl item when it is selected.

MORE INFORMATION

When you initialize the CListCtrl by calling CListCtrl::InsertItem(), you can pass in a value of I_IMAGECALLBACK for the index of the image. This means that the system expects you to fill in the image index when you get an LVN_GETDISPINFO notification. Inside of the handler for LVN_GETDISPINFO, you can check if the item is selected and set the appropriate image index.

Sample Code

BEGIN_MESSAGE_MAP(CTestView, CView)

//{{AFX_MSG_MAP(CTestView)

ON_WM_CREATE()

//}}AFX_MSG_MAP

ON_NOTIFY (LVN_GETDISPINFO, IDI_LIST, OnGetDispInfo)

END_MESSAGE_MAP()

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CView::OnCreate(lpCreateStruct) == -1)

return -1;

// m_pImage is a CTestView's member variable of type CImageList*

// create the CImageList with 16x15 images

m_pImage = new CImageList();

VERIFY (m_pImage->Create (16, 15, TRUE, 0, 1));

CBitmap bm;

// IDR_MAINFRAME is the toolbar bitmap in a default AppWizard

// project.

bm.LoadBitmap (IDR_MAINFRAME);

// This will automatically parse the bitmap into nine images.

m_pImage->Add (&bm, RGB (192, 192, 192));

// m_pList is CTestView's member variable of type CListCtrl*

// create the CListCtrl.

m_pList = new CListCtrl();

VERIFY (m_pList->Create (WS_VISIBLE | WS_CHILD | LVS_REPORT |

LVS_EDITLABELS, CRect (0, 0, 400, 400), this, IDI_LIST));

// Create column.

m_pList->InsertColumn (0, "Button Number", LVCFMT_LEFT, 100);

// Associate CImageList with CListCtrl.

m_pList->SetImageList (m_pImage, LVSIL_SMALL);

char szTemp[10];

for (int iCntr = 0; iCntr < 9; iCntr++)

{

wsprintf (szTemp, "%d", iCntr);

m_pList->InsertItem (LVIF_IMAGE | LVIF_TEXT,

iCntr, szTemp, 0, 0, I_IMAGECALLBACK, 0L);

}

return 0;

}

void CTestView::OnGetDispInfo (NMHDR* pnmhdr, LRESULT* pResult)

{

LV_DISPINFO* pdi = (LV_DISPINFO *) pnmhdr;

// Fill in the LV_ITEM structure with the image info.

// When an item is selected, the image is set to the first

// image (the new bitmap on the toolbar).

// When it is not selected, the image index is equal to the

// item number (that is, 0=new, 1=open, 2=save, and so on.)

if (LVIS_SELECTED == m_pList->GetItemState (pdi->item.iItem,

LVIS_SELECTED))

pdi->item.iImage = 0;

else

pdi->item.iImage = pdi->item.iItem;

}

CTestView::~CTestView()

{

// Clean up.

delete m_pImage;

delete m_pList;

}

 

25. 在添加item後,再InsertColumn()後導致整列數據移動的問題

Q151897: CListCtrl::InsertColumn() Causes Column Data to Shift

http://support.microsoft.com/kb/151897/en-us

 

 

26. 關於listctrl第一列始終居左的問題

解決辦法:把第一列當一個虛列,從第二列開始插入列及數據,最後刪除第一列。

     

具體解釋參閱   http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/listview/structures/lvcolumn.asp

 

 

27. 鎖定column header的拖動

http://msdn.microsoft.com/msdnmag/issues/03/06/CQA/

 

 

28. 如何隱藏clistctrl的列

    把需隱藏的列的寬度設爲0,然後檢測當該列爲隱藏列時,用上面第27點的鎖定column 的拖動來實現

 

29. listctrl進行大數據量操作時,使用virtual list   

http://www.microsoft.com/msj/archive/S2061.aspx

http://www.codeguru.com/cpp/controls/listview/advanced/article.php/c4151/

http://www.codeproject.com/listctrl/virtuallist.asp

 

 

30. 關於item只能顯示259個字符的問題

解決辦法:需要在item上放一個edit。

 

 

31. 響應在listctrl的column header上的鼠標右鍵單擊

Q125694: How To Find Out Which Listview Column Was Right-Clicked

http://support.microsoft.com/kb/125694/en-us

 

 

32. 類似於windows資源管理器的listview

Q234310: How to implement a ListView control that is similar to Windows Explorer by using DirLV.exe

http://support.microsoft.com/kb/234310/en-us

 

 

33. 在ListCtrl中OnTimer只響應兩次的問題

Q200054:

PRB: OnTimer() Is Not Called Repeatedly for a List Control

http://support.microsoft.com/kb/200054/en-us

 

34. 以下爲一些爲實現各種自定義功能的listctrl派生類

          (1)    拖放       

                   http://www.codeproject.com/listctrl/dragtest.asp

                   在CListCtrl和CTreeCtrl間拖放

                   http://support.microsoft.com/kb/148738/en-us

 

          (2)    多功能listctrl

                   支持subitem可編輯,圖標,radiobutton,checkbox,字符串改變顏色的類

                   http://www.codeproject.com/listctrl/quicklist.asp

 

                   支持排序,subitem可編輯,subitem圖標,subitem改變顏色的類

                   http://www.codeproject.com/listctrl/ReportControl.asp

          (3)    subitem中顯示超鏈接

                   http://www.codeproject.com/listctrl/CListCtrlLink.asp

          (4)    subitem的tooltip提示

                   http://www.codeproject.com/listctrl/ctooltiplistctrl.asp

          (5)    subitem中顯示進度條   

                   http://www.codeproject.com/listctrl/ProgressListControl.asp

                   http://www.codeproject.com/listctrl/napster.asp

                   http://www.codeguru.com/Cpp/controls/listview/article.php/c4187/

          (6)    動態改變subitem的顏色和背景色

                    http://www.codeproject.com/listctrl/highlightlistctrl.asp

                    http://www.codeguru.com/Cpp/controls/listbox/colorlistboxes/article.php/c4757/

 

          (7)    類vb屬性對話框

                    http://www.codeproject.com/listctrl/propertylistctrl.asp

                    http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c995/

                    http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c1041/

 

          (8)    選中subitem(只高亮選中的item)

                    http://www.codeproject.com/listctrl/SubItemSel.asp

                    http://www.codeproject.com/listctrl/ListSubItSel.asp

 

          (9)    改變行高

                    http://www.codeproject.com/listctrl/changerowheight.asp

 

          (10)   改變行顏色

                    http://www.codeproject.com/listctrl/coloredlistctrl.asp

 

          (11)   可編輯subitem的listctrl

                    http://www.codeproject.com/listctrl/nirs2000.asp

                    http://www.codeproject.com/listctrl/editing_subitems_in_listcontrol.asp

 

          (12)   subitem可編輯,插入combobox,改變行顏色,subitem的tooltip提示

                    http://www.codeproject.com/listctrl/reusablelistcontrol.asp

 

          (13)   header 中允許多行字符串

                    http://www.codeproject.com/listctrl/headerctrlex.asp

 

          (14)   插入combobox

                    http://www.codeguru.com/Cpp/controls/listview/editingitemsandsubitem/article.php/c979/

 

          (15)   添加背景圖片

http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c4173/

http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c983/

http://www.vchelp.net/vchelp/archive.asp?type_id=9&class_id=1&cata_id=1&article_id=1088&search_term=

   

          (16)  自適應寬度的listctrl

                    http://www.codeproject.com/useritems/AutosizeListCtrl.asp

          (17)  改變ListCtrl高亮時的顏色(默認爲藍色)

                   處理NM_CUSTOMDRAW

           http://www.codeproject.com/listctrl/lvcustomdraw.asp

     (18)  改變header顏色

          http://www.pocketpcdn.com/articles/hdr_color.html

 

歡迎訪問:樂園www.ly8.co

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章