ListView常用用法2(分类总结)

listView系列之分类显示 今天,我们继续来进行listView的深入了解,来进行一个简单的分类显示的例子,但主要是突出解决这类问题的思路与解法。 要实现的要求:是让1-100以内的奇数先显示,再显示偶数,同时奇数和偶数的显示开头有条目标记着。 步骤:1.我们首先得从1-100这类数中分开奇数和偶数,并将他们分别存储在集合中,方便后面的使用。 2.肯定是在适配器中的getView()的方法中来进行的操作。 3.在g 阅读详情

1. CListCtrl 风格

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

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



 

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

     DWORD dwStyle = m_list.GetStyle();//获取当前窗口style
      dwStyle &= ~LVS_TYPEMASK; //清除显示方式位
      dwStyle |= LVS_REPORT; //设置style

     dwStyle &= ~(LVS_EDITLABELS); // 清除可编辑标签位

    dwStyle |= LVS_NOLABELWRAP; // 不换行
    dwStyle |= LVS_SHOWSELALWAYS; // 总显示选择的行

      SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置style


      DWORD dwExStyle = m_list.GetExtendedStyle();
      dwEXStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl)
      dwExStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl)
      dwExStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件
      m_list.SetExtendedStyle(dwExStyle); //设置扩展风格
  
      注: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;
      }

 注:

单击或双击事件都需要在父窗口的头文件增加事件处理函数

afx_msg void OnClickListCtrl(NMHDR* pNMHDR, LRESULT* pResult);
 afx_msg void OnDoubleClickListCtrl(NMHDR *pNMHDR,LRESULT *pRESULT);

并在父窗口cpp文件的消息映射区域内中增加:

ON_NOTIFY(NM_CLICK,IDC_LIST,OnClickListCtrl)
 ON_NOTIFY(NM_DBLCLK,IDC_LIST,OnDoubleClickListCtrl)

 


 

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



 

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


ListCtrl的扩展使用

所有者绘制(owner-draw)和自定义绘制(custom-draw)
    这两种方法应该是控件自绘中最常用到的普遍方法。(当然如果只是改变控件颜色只需要处理WM_CTLCOLOR消息就可以了。)但是对于这两者的区别,可能很多开发人员并不是很清楚。如果你做过控件自绘,可能对owner-draw已经很熟悉了。一般只要设置控件的自绘风格属性,并实现owner-draw的消息(WM_DRAWITEM)响应虚函数(DrawItem)就可以了。可以应用这种方法的控件包括拥有自绘风格的Button、ComboBox、ListCtrl、Menu、StatusBar、HeaderCtrl、TabCtrl等大部分控件,MFC在控件需要重绘的时候调用绘制函数,并传递DC及控件位置、大小等信息,我们需要做的就是利用这些信息来绘制自己需求的控件外观。但是这种方式不能用于EditCtrl,也不能用于非report风格的ListCtrl。
 
   custom-draw方式是响应的NM_CUSTOMDRAW消息,与WM_DRAWITEM消息不同,它是被包含在WM_NOTIFY消息中被发送的,需要在类实现中加入消息映射。与owner-draw方式比较,这种绘制方式最大的优势是对绘制的阶段进行了严格控制,可以在不同的响应阶段进行不同的绘制策略,比如既可以进行默认绘制,也可以重载函数进行特殊绘制,还可以只改变一些变量的值让MFC自己去按照要求重绘。我们知道owner-draw方式的绘制函数中,对于所有的绘制细节都需要进行GDI或GDI+的代码控制,而custom-draw方式中,我们可能仅仅改变几个变量值(比如控件颜色)就完成了需求。custom-draw方式支持的控件包括ListView、ToolBar、ToolTip、TreeView等,其中对于ListCtrl支持所有的样式。关于custom-draw的详细信息,可以参考这篇文章http://msdn.microsoft.com/zh-cn/library/ms364048(VS.80).aspx。

 

二、加载缩略图
 
  这个其实很简单,自己创建一个CImageList类型的对象,并自定义图像的大小及像素类型,然后调用CListCtrl的SetImageList函数设置就可以了。需要注意的一点是,normal和small两种type中,small类型必须设置。


三、自定义表头
 
   需要写一个继承CHeaderCtrl的子类,实现DrawItem函数,在其中进行表头背景和字体、文本颜色等设置并进行绘制;如果要改变表头的高度,可以映射HDM_LAYOUT消息响应函数,在其中设置控件布局。之后在自己的ListCtrl类中声明一个自定义的HeaderCtrl类型变量,并在PreSubclassWindow函数中调用HeaderCtrl的SubclassWindow函数使其子类化,然后在初始化的时候使其各Item的format具有HDF_OWNERDRAW风格就可以了。


 

四、调整CListCtrl的背景、字体、文本颜色和行高
 
   实现思路与上述表头的方法基本相同。当然要设置list的自绘风格,并选择自绘的方式。另外对于调整行高,如果加载了缩略图的话,行高就会随之调整了。另一个简单的办法就是设置字体的大小来实现,与缩略图是一个道理。如果想自己精确定义行高,则比较麻烦一点。首先设置list的自绘风格,然后重载MeasureItem函数,在其中设置结构体中的item高度变量的值,再在消息映射中添加ON_WM_MEASUREITEM_REFLECT(),就可以让list在合适的时候响应来改变行高。需要注意的两点是:
 
   1、MeasureItem与WM_MEASUREITEM消息响应函数OnMeasureItem是不同的;
 
   2、触发MeasureItem函数调用的WM_MEASUREITEM消息是在一定的情况下才被发送,比较简单的方法是send一个WM_WINDOWPOSCHANGED消息来触发。
 
   3、设置LVS_OWNERDRAWFIXED风格需要在Create或者PreSubclassWindow函数中进行,否则MeasureItem不会被调用。

给控件添加排序功能
 

  report风格的list控件很多情况下都需要支持排序功能,而且最好支持按不同列进行排序。CListCtrl的类方法SortItems支持排序功能,但是在排序过程中,两个数据真正的比较过程是通过SortItems的第一个参数指向的回调比较函数来完成的。这个函数通过比较SetItemData函数设置的每个Item对应数值,返回一个代表比较结果的值,SortItems便可以依据这个返回值进行排序实现。可以看出,这种方法虽然简单,
却有一个比较严重的缺陷,即不能支持按照不同列数据进行排序。
 
  对于自绘控件来说,要想支持按不同列排序功能,需要完成以下几件事:
 
  1、list控件响应LNV_COLUMNCLICK消息,得到需要排序的列号,并通知HeaderCtrl在列头上绘制正序或倒序三角标识;
 
  2、写一个比较函数,功能类似上面提到的回调函数,只不过这个函数将由我们自己的排序函数调用。为了支持多种类型的列数值排序,这个函数应该能对不同类型的数值进行比较;
 
  3、写一个list控件行交换函数,排序函数在调用比较函数后,根据返回值会调用此交换函数完成排序效果。实现此函数既可以通过调用DeleteItem和InsertItem两个类功能函数实现,也可以通过GetItem和SetItem两个函数交换两行的数据信息实现;
 
  4、写一个排序函数,这个函数类似上面SortItems函数完成的功能。通过指定列号、排序方式(正序或倒序)以及排序开始和结束的行号,按照某种排序策略(插入排序、快速排序等),通过调用比较函数和行交换函数完成排序效果。如果list中的数据项不是很多的话,用递归调用实现快速排序,效果还是十分令人满意的。


添加进度条
 

  给list控件添加进度条也是常见的需求之一,可惜CListCtrl好像并没有提供直接的方法可以解决这个问题。思路有两个:一是创建进度条控件,将其嵌入到list控件相应的位置上,并通过响应消息来处理进度条显示;而对于自绘控件来说,直接绘制自己的进度条可能是一个更简单有效的方法,而且这种思路出来的效果可能给人更多惊喜。
 
  这里介绍一种利用贴图自绘进度条的方法,效果非常不错。首先,需要定义两个CBitmap类型的变量加载进度条背景和前景的位图资源;然后计算进度条所在subitem的区域大小、进度条背景区域大小和前景区域大小;最后,在控件自绘函数DrawItem中需要绘制进度条的位置,调用DC的StretchBlt函数以拉伸方式显示进度条背景和前景位图即可。

支持多行文本
 

  如果某个subitem的显示文本太长的话,多行文本便显得很重要。其实多行文本显示很大程度上体现了自绘控件的思路纲领:在需要绘制的时刻,自己计算绘制区域的大小,自己计算显示内容所需区域大小,自己制定合理的策略以正确合理的方式进行显示。
 
  支持多行文本显示,首先计算显示区域的大小;然后通过GetLogFont函数查询当前设置的字体属性,得到字体高度和宽度;之后便可以计算出显示文本内容需要显示几行,每一行显示多少个字。当然实际情况中由于有中英文的区别,不能简单的按照字体宽度计算;可以用DC的GetTextExtent函数得到文本实际需要区域大小,然后进行相应调整。另外,当显示区域填满仍然不能显示所有文本时,可以用“...”表示剩余字符。

关于滚动条
 

  list控件的滚动条非常有用,在此我不想多谈滚动条的自绘等内容,那是一个比较复杂的话题。其实MFC的CWnd类是可以设置WS_VSCROLL和WS_HSCROLL风格的,分别代表支持竖直滚动条和水平滚动条,CListCtrl是从CWnd继承而来,自然也不例外。更让我们欣喜的是,CListCtrl基类已经实现了滚动条的功能和控制,不过这里的滚动条并不是一个ScrollBar控件,而是CListCtrl自己绘制的。
 
  虽然不用我们自己实现滚动条功能,但是关于CListCtrl中滚动条一些属性和特点还是要有概念,因为有的时候就要用到。比如,我们利用DrawItem函数绘制每个Item的显示;那么就要在背景刷新函数OnEraseBkgnd中刷新剩余区域,这时就要根据item的个数和行高计算剩余区域的位置,这时我们就要考虑
滚动条的位置。通过GetScrollInfo函数可以得到滚动条信息,其中SCROLLINFO类型的信息结构体需要说明一下。定义如下:
 
  typedef struct tagSCROLLINFO
 
  {
 
       UINT   cbSize;
 
      UINT   fMask;
 
      int    nMin;
 
      int    nMax;
 
      UINT   nPage;
 
      int    nPos;
 
      int    nTrackPos;
 
  }   SCROLLINFO, FAR*LPSCROLLINFO;
 
  typedef SCROLLINFO CONST FAR*LPCSCROLLINFO; 
其中nMin,nMax分别表示目前滚动条设置的滚动范围,而nPos则表示当前滚动块在滚动条中的位置。这个位置正是相对于nMin和nMax而言的位置,比如设置的范围为(10,20),如果滚动块位于滚动条的中间,则其值为15。nPage表示滚动条每页的滚动位置数,通俗一点讲,其实就是点击滚动条中滚动块之外的位置时,滚动条就会向上或向下翻页,翻页时滚动的位置数即为nPage的值。由上可知,滚动一个位置对应的像素数,是可以根据滚动窗口大小和设置的滚动范围计算出来的。那么CListCtrl中,根据实际调试可知,竖直滚动条滚动一个位置的像素数其实就是list控件的行高,也就是说,info中nMin为0,nMax为隐藏区域高度可以包含的行数。

防止刷新时的闪烁
 

  这个问题几乎是所有控件和视图刷新都要面对的问题,解决的手段也几乎被全部归算到“双缓冲”技术上。其实有的时候双缓冲不一定能解决问题,有的时候不一定像双缓冲那么复杂。最重要的一点,就是要搞清楚为什么会有闪烁现象,除去显卡性能的因素,闪烁的罪魁祸首就是刷新前后的画面差别太大。知道了这一点,很多现象都可以清楚地分析其缘由了。比如,你明明在刷新函数中完成了双缓冲,但是却遗憾的发现闪烁依然存在。我想很可能是你没有制止MFC自己默认对窗口背景的刷新动作,你需要做的就是覆盖掉基类的OnEraseBkgnd函数,自己绘制背景,并返回TRUE,来告诉Windows不用帮你绘制背景了。
 
  所以我们防止闪烁的手段其实有很多种,我们可以在OnEraseBkgnd中自己处理背景来消除背景差异过大引起的闪烁;我们可以在OnPaint或OnDraw函数中用双缓冲技术来减少由于绘制复杂画面导致频繁刷新引起的闪烁;我们可以在调用引起区域或窗口无效的函数时,设置参数防止背景重绘;我们可以在强制刷新时,尽量细化重绘区域,使重绘区域减到最小...

调整列宽引起的麻烦事
 

  当你不经意调整HeaderCtrl的列宽时,对于自绘list控件,你可能突然发现不少问题:
 
  1、你的第一列是一个缩略图,你根本不想这一列的列宽被调整;
 
  2、某一列列宽被你调整到0,你竟然看不到它了,再把它弄出来似乎也很费劲;或者你将某列列宽减小到一定程度时,发现两个列的绘制竟然重合了;
 
  3、你缩小了某一列列宽,发现最后一列向左移动了相应位置,但HeaderCtrl最右边却露出了不同背景颜色的区域。(这一点对于不同版本似乎情况不尽相同,Unicode有这个问题,MultiBytes版本没有,未搞清楚原因)
 
  对于第一个问题,需要支持某列不支持调整列宽;第二个问题,需要设置一个最小列宽;第三个问题,一个有效的解决办法是动态调整最右边一列的宽度,使之总是符合list控件窗口宽度。
 
  1、支持某列列宽固定。
 
  很简单,只要在HeaderCtrl中重写虚函数OnChildNotify,当消息类型为HDN_BEGINTRACKW及HDN_BEGINTRACKA,且列号为需要固定的那一列时,直接给参数pLResult赋值为TRUE,并返回TRUE即可。
 
  这样调整列之间的间隔条的消息就被屏蔽,因此list控件就不会收到对应消息。当然,如果想做的漂亮一点,可以把此时Cursor改变这个动作也屏蔽掉。
 
  2、设置某列最小宽度
 
  也很简单,重写list控件的虚函数OnNotify,当消息类型为HDN_ITEMCHANGINGW或HDN_ITEMCHANGINGA,列号为需要设置最小宽度的那一列,且此时列宽小于设置列宽时,直接给参数pResult赋值为TRUE,并返回TRUE即可。这里需要说明一个问题,当你的list控件设置了ImageList后,则所有的subitem最小宽度和高度为ImageList中Image的大小,因此当你在DrawItem函数中调用GetSubItemRect查询subitem大小时,返回的结果与你看到界面上的结果是不一样的,这一点一定要注意。这也是很引起上面提到的两列绘制内容重合问题的原因。
 
  3、动态设置最右一列宽度为合适大小
 
  在同上函数的位置,处理某列宽度被调整的消息时,调整最右一列的宽度。需要注意的是,由于调用SetColumnWidth函数又会触发这个消息,所以要判断当前调整列是否为最右一列,否则就会不断循环下去,使程序崩溃。
 
  另外,调用SetColumnWidth函数时设置参数为LVSCW_AUTOSIZE_USEHEADER,并不会使宽度立即更新,而是需要设置具体的数值。猜想可能是LVSCW_AUTOSIZE_USEHEADER这个参数不会立即强迫list控件刷新,只有在list控件下次刷新时才起作用。
 
      
 
  CListCtrl控件是MFC控件中功能最丰富的控件之一,能总结和学习的很多,其他可以研究和丰富的功能还有ToolTip、自绘滚动条、编辑subitem、拖拽、组功能、虚拟列表等,希望以后有机会的话能够进行总结。

先说一下实现自绘滚动条的思路。首先要隐藏CListCtrl自带的滚动条,如果你简单的认为加上LVS_NOSCROLL风格就能搞定的话,你一定会大失所望,具体我们后面会讲到。然后就是要封装自己的滚动条控件了,考虑到有竖直滚动条和水平滚动条两种,我们的封装可能还要费一番周折。除了要响应消息自绘外,滚动条控件还要向parent控件(即CListCtrl)发送相应的WM_VSCROLL和WM_HSCROLL消息及消息参数。
最后,CListCtrl控件要响应这两个消息并进行相应处理,这个过程需要清楚地理解SCROLLINFO结构体中各个变量含义并进行应用,另外就是处理一些UI绘制和刷新上的麻烦。
 

  好了,下面我们就重点总结一下上面过程中会遇到的难题,并给出解决方法。

 

   一、隐藏CListCtrl自带滚动条
 
  CWnd类有一系列的关于Scroll的函数,感觉好像有很多方法可以实现我们的目的。
 
  1、调用EnableScrollBarCtrl直接将不需要的类型的滚动条disable掉;
 
  2、调用GetScrollBarCtrl得到滚动条指针,然后用ShowWindow(SW_HIDE)将其隐藏掉;
 
  3、调用ShowScrollBar直接隐藏。
 
  遗憾的是,对于report类型的CListCtrl来说,上面的方法全部无效。(好像对于其他非report类型的CListCtrl控件或者CListView控件有些方法是有效的,没有进行具体验证。)其实用spy++查看一下就知道,CListCtrl中的滚动条根本不是窗口,也就是说滚动条不是scrollbar控件,只是CListCtrl自行绘制上去的假滚动条。因此上面这些对于scrollbar操作的函数都无效也就可以理解了,大家可以留意一下GetScrollBarCtrl函数返回的全是NULL。

   那么我们能不能通过修改CListCtrl的窗口风格来实现呢?
 
  涉及到滚动条的风格有两个,一个是通用的窗口风格WS_HSCROLL和WS_VSCROLL,另一个是列表控件专有风格LVS_NOSCROLL。
 
  先说LVS_NOSCROLL。如果你给CListCtrl设置该风格的话,你会发现list中关于scroll的窗口过程都被屏蔽了,也就是说,CListCtrl将只显示设定的列表窗口区域,对于区域以外的包括UI显示和消息处理在内的这些过程,将全部忽略。这样的话,隐藏原有滚动条并加载自己的滚动条这个思路将行不通。而且根据MSKBID为137520文章所说,对于report类型的列表控件,设置LVS_NOSCROLL风格还要面临header控件不能正常显示的问题。
 
  再来看WS_HSCROLL和WS_VSCROLL。如果只是简单的通过调用ModifyStyle去掉窗口WS_HSCROLL或WS_VSCROLL风格是没作用的,我们需要在每次重新计算窗口的客户区域的时候都调用ModifyStyle设置scroll风格才行,这样CListCtrl将没有机会自动为窗口加上滚动条,代码如下:

   

   void CXXListCtrl::OnNcCalcSize(BOOL bCalcValidRects,NCCALCSIZE_PARAMS FAR*lpncsp)             
   {                                                                                               
       ModifyStyle( WS_HSCROLL | WS_VSCROLL, 0 ); //去掉水平滚动条和竖直滚动条                   
       CListCtrl::OnNcCalcSize(bCalcValidRects,lpncsp);                                          
   }                                                                                              

 

   麻烦还没完,在XP窗口风格下上面的代码没有任何问题。但是当我们链接Windows经典窗口风格的代码库时,上面的代码就不能实现隐藏滚动条的功能了。具体原因不是很清楚,我猜想可能是Windows的不同窗口风格库的内部窗口过程不同引起的。
   还有解决的办法吗?只要我们想,总会有办法!那就是调用Windows的API函FlatSB_EnableScrollBar。你只要在你的自绘listctrl类的合适的位置调用以下代码,控件的滚动条将完美地被隐藏起来,而且只需要调用一次就可以:


   InitializeFlatSB(this->m_hWnd);                                                 
   FlatSB_EnableScrollBar(this->m_hWnd, SB_BOTH,ESB_DISABLE_BOTH);                 


 
  具体关于该函数的细节大家可以去查阅MSDN,但是我并没有想明白为什么这个API函数能做到EnableScrollBarCtrl成员函数做不到的功能,没有源码无从考证:(

 

   二、结构体SCROLLINFO
 
  在这里我并不想过多讨论关于自绘滚动条控件的实现问题,因为看上去思路很简单,并且实现起来也只是细节和完善性的工作。我认为这一块的问题在于一些概念的理解和把握,其中最重要的就是结构体SCROLLINFO。
 
  首先说一下GetScrollInfo和SetScrollInfo这两个函数。CListCtrl类和CScrollBar类都有这两个成员函数,其中CListCtrl类的成员函数是从CWnd继承而来。对于CScrollBar类来说,GetScrollInfo用来得到滚动条的滚动信息,也就是结构体SCROLLINFO中包含的内容;SetScrollInfo用来设置滚动信息使滚动条进行相应的滚动。我们可以理解为CScrollBar类通过这两个函数完成滚动条正确的位置滚动和绘制。前面提到,CListCtrl控件自带的滚动条并不是CScrollBar控件,而是自己画上去的假窗口,因此实际上是通过CLIstCtrl的GetScrollInfo和SetScrollInfo函数完成了滚动条位置信息的查询和设置。而且在CListCtrl中,这些信息是有其特殊性的,后面讲SCROLLINFO的时候会详细说明。
 
  那么当我们把CListCtrl的滚动条隐藏了,甚至用API将其disable了,GetScrollInfo和SetScrollInfo还会正常工作吗?回答是肯定的。用CListCtrl自带的滚动条和用自己封装的滚动条的区别在于:
 
  1、用CListCtrl的滚动条,可通过GetScrollInfo查询滚动信息,通过SetScrollInfo可使滚动条调整位置,且list客户区会自动滚动;用户通过操作滚动条可以滚动list客户区,且改变list的滚动信息;
 
  2、用自己的滚动条,调用CListCtrl的GetScrollInfo可查询滚动信息,通过SetScrollInfo可设置滚动信息但滚动条控件不会自动调整位置,但list客户区可以自动滚动;用户操作滚动条,需要通过调用CScrollBar的SetScrollInfo进行设置才能影响滚动条绘制,而list客户区不会自动滚动,此时list的滚动信息不会被自动修改。
 
  因此,加自己的滚动条实际上是将list和滚动条的滚动信息一致化的问题。或者你也可以完全抛弃CListCtrl中保存的SCROLLINFO信息,完全用scrollbar的信息。无论哪种方法,都必须对结构体SCROLLINFO中的参数意义有比较深刻的理解。

 

   SCROLLINFO的定义如下:
 
   typedefstruct tagSCROLLINFO
 
   {
 
      UINT   cbSize;
 
      UINT   fMask;
 
      int    nMin;
 
      int    nMax;
 
      UINT   nPage;
 
      int    nPos;
 
      int    nTrackPos;
 
  }   SCROLLINFO, FAR*LPSCROLLINFO;
 
   typedefSCROLLINFO CONST *LPCSCROLLINFO;

 

   cbSize是该结构体的字节数,每次应用之前设置为sizeof(SCROLLINFO);
 
  fMask指明下面的几个参数哪些是有效值,具体请参考MSDN;
 
  nMin和nMax指明了滚动条最小和最大滚动位置。字面上很好理解,但是这个位置以什么为单位呢?MSDN上并没有说明。其实单位并没有规定和限制,只要在这个结构体的参数中统一就可以。比如在CListCtrl中就以控件中的行为单位,nMin为0,nMax一般为list的总行数。
 
  nPage为页大小,也就是你点击滚动条上滑块以外的区域时,滚动条会滚动一页,而页的大小就是由该值指定;同时,滚动条绘制滑块的大小时也会依据此值;
 
  nPos为滑块当前的位置,也就是滚动位置;
 
  nTrackPos是用户拖动滑块时的即时位置,该值一般用于响应滚动条消息时与SB_THUMBTRACK消息一起作为消息参数,而不能用于设置滚动条信息。
 
  
 
  OK,现在可以完善我们的思路了。加载自绘滚动条的步骤如下:
 
  1、隐藏CListCtrl原有滚动条;
 
  2、封装继承于CScrollBar的自绘滚动条控件,根据SCROLLINFO完成滚动条绘制,并将用户操作封装成WM_HSCROLL或WM_VSCROLL消息传递给父类CListCtrl。以竖直滚动条为例,我们要将WM_VSCROLL消息的消息参数分为以下几类:SB_LINEDOWN,SB_LINEUP,SB_PAGEDOWN,SB_PAGEUP,SB_THUMBTRACK和SB_THUMBPOSITION,其意义分别为向下移动一个位置,向上移动一个位置,向下移动一页,向上移动一页,滑块当前正在被拖动的位置和滑块被结束拖动到某位置。CListCtrl接收到消息以后需要根据类型调用滚动条的SetScrollInfo设置滚动信息,使滚动条绘制滚动位置,并调用Scroll函数滚动list的客户区;
 
  3、ClistCtrl子类负责初始化滚动条控件,设置控件尺寸及位置,并响应OnSize函数随时改变控件大小位置。还要响应WM_MOUSEWHEEL消息使滚动条控件进行正确滚动。当然还有刚才提到的接收滚动条控件的消息,并进行相应处理。

   看上去应该没什么问题了,但是你还是会遇到一些麻烦。

 

   三、SB_THUMBTRACK和SB_THUMBPOSITION
 
  滚动条控件的消息码是在OnVScroll或OnHScroll响应函数中作为nSBCode参数被传递的,指明了当前的操作类型。但是对于CListCtrl来说,以上两个消息码却比较特殊,因为在CScrollBar中给CListCtrl发送带有这两个消息码的消息,响应函数并不会做出响应。也就是说,CListCtrl内部自动处理了该消息,并没有调用OnVScroll或OnHScroll做响应。具体为什么这样设计,可能是出于某种考虑;但是如果我们要对这两个操作自己特有的处理,或者我们应用的SCROLLINFO中的单位与CListCtrl默认的不统一的话,list的默认响应将满足不了我们的需要。
 
  要解决这个问题,可以自己定义新的消息码来代替。
 
  
 
  四、滚动条绘制问题
 
  当你按照上面步骤写好代码,操作滚动条的时候,你可能失望的看到你的滚动条并不能正确绘制,而且现象很特别,好像是绘制函数出了问题。
 
  如果要深入的理解这个问题的原因,可以看一下我前面写的一篇博文——“Windows窗口相关的一些概念解释”。简单一点说,就是CListCtrl的窗口风格没有设置正确。我们自己的滚动条肯定是要时刻保持在list窗口的上方,因此我们需要在CListCtrl中写上这样的代码:


   scrollCtrl.Create(WS_CHILD|WS_VISIBLE|WS_GROUP|SBS_VERT,scrollRect, this, ID_SCROLL_XX);
   scrollCtrl.SetWindowPos(&wndTop, 0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE |SWP_SHOWWINDOW);  


 
  可以看到,滚动条控件是作为list窗口的子窗口被创建的,而且被放在窗口的z-order的最上方,因为它一定在list窗口及其子窗口的最上面显示。如果这个时候你的list窗口是自绘控件,或者说上面放置了其他控件作为子窗口,那么滚动条的刷新一定会出问题,原因是因为你没有给滚动条控件设置WS_CLIPSIBLINGS风格。
 
  这样可以了吗?此时你还要为CListCtrl子类加上WS_CLIPCHILDREN风格,原因是你的滚动条控件是顶层窗口,系统会认为在刷新list窗口时它是不用刷新的,这样滚动条和list窗口重合的部分在刷新上会出现问题;当我们给list窗口设置了WS_CLIPCHILDREN风格之后,系统就会在list窗口刷新时告诉重合区域不用重画,从而保证滚动条绘制正确


CListCtrl 自绘 含滚动条 挺不错的自绘列表框 含滚动条 分享一下 立即下载

相关推荐

使用CScrollBar的CScrollView

使用CScrollBar的CScrollView

关于ListCtrol的owner-draw和custom-draw

一、所有者绘制(owner-draw)和自定义绘制(custom-draw) 一、给控件添加排序功能report风格的list控件很多情况下都需要支持排序功能,而且最好支持按不同列进行排序。CListCtrl的类方法SortItems支持排序功能,但是在排序过程中,两个数据真正的比较过程是通过SortItems的第一个参数指向的回调比较函数来完成的。这个函数通过比较SetItemDat...

bankelei6741的博客 445

VC++ LVHITTESTINFO结构体说明

LVHITTESTINFO structure 说明

滑动条:

1.  GetScrollBarCtrl  The CWnd implementation of this function simply returns NULL. Derived classes, such as CView, implement the described functionality. 在cwnd中是null,在view中才会有值 但可以直接用滑动条的函数,比如

wateryh的专栏 745

CPG控制网络入门

从线性变换开始推导

妖米的博客 5044

从零上手HiAgent:构建能听懂指令的智能体框架实战指南

智能体(Agent)作为人工智能领域的重要范式,正从传统的预设流程自动化转向以目标驱动的自主规划与执行。其核心原理在于利用大语言模型(LLM)作为决策大脑,通过任务规划、工具调用与记忆机制,将模糊的自然语言指令转化为可执行的工作流。这一技术显著提升了人机协作的效率和自然度,其价值在自动化办公、数据分析与智能流程编排等场景中尤为突出。本文聚焦于HiAgent这一具体框架,深入解析其作为智能体开发平台的核心架构,涵盖规划器、执行器、工具集等关键组件,并提供从环境配置、自定义工具开发到复杂任务链构建的完整工程实践

weixin_29266007的博客 896

Android—— ListView 的简单用法及定制ListView界面

一、ListView的简单用法 2. 训练目标 1) 掌握 ListView 控件的使用 2) 掌握 Adapter 桥梁的作用 二、定制ListView界面 1.训练目标 1) 掌握 ListView 控件的使用 2) 掌握如何自定义 Adapter 的使用

小小小森屿的博客 16万+

几款支持国标GB28181的平台以及视频监控设备接入的配置方法(Web端无插件播放)

GB28181解决的一个主要问题就是如何远程、跨网络、跨区域、跨级别的访问网络中的监控设备(包括IPC、NVR等),本文介绍几款G28181平台的接入配置方法,适合有监控视频摄像头的远程接入和预览需求的人群参考使用。

一名高级工程师的博客 1万+

Android Studio之ListView的用法(上)

List绝对可以称得上是Android中最常用的控件之一,几乎所有的应用程序都会用到它。由于手机屏幕空间都比较有限,能够一次性在屏幕上显示的内容并不多,当我们的程序中有大量的程序需要展示时,就可以借助ListView来实现。ListView允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上的数据则会滚动出屏幕。其实你每天都在使用这个控件,比如查看微信联系人列表,翻阅朋友圈的。 L...

qq_24883353的博客 4702

SAP Fiori 从技术上而言到底包含哪些组件?

SAP Fiori是企业级UX设计的系统化解决方案,基于五大原则构建:角色导向(Role-based)、自适应(Adaptive)、简洁(Simple)、一致(Coherent)和愉悦(Delightful)。其技术实现包含SAPUI5开发框架、Fiori Launchpad统一入口、OData服务网关等核心组件,通过标准化设计模式与开发工具链,显著提升企业应用的用户体验和开发效率。典型案例显示,遵循Fiori原则可缩短30%以上的操作时长,降低50%的培训成本。该体系既保持跨设备一致性,又支持业务场景的深

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 223

【LSTM回归预测】attention机制LSTM时间序列回归预测【含Matlab源码 1992期】

attention机制LSTM时间序列回归预测 完整的代码,方可运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 2591

ListView在delphi中的常用用法

本文版权归原作者所有 来源:http://blog.sina.com.cn/s/blog_9e2e840501013r78.html ListView在delphi中的常用用法 //增加 i := ListView1.Items.Count; with ListView1 do begin ListItem:=Items.Add; ListItem.Caption:=Int

K.B.H—第七栈博客 1051

KEPServerEX物联网网关(IoT Gateway)REST客户端代理(非原创)

(中文版)资料来源于【OPC-KEPServerEX学习KEPWare交流】905485143群的【455196383】【零下一度】 一。KEPServerEX物联网网关REST客户端代理演示 在KSE中,首先构建一个带有通道/设备/标签的模拟器系统。 例如,下面是三个随机项目。 直接到IoT网关插件,添加新代理。 从类型列表中选择REST Client。 终结点...

-雲飛兄-博客 5808

Android中ListView分类

Android中ListView组件分类实现。

为梦想而努力(马英才) 1万+

AUTOSAR OS详细介绍及配置说明(更新版20240115)

AUTOSAR OS扩展了OSEK/VDX标准中的操作系统,所以本文结合OSEK/VDX的标准来介绍AUTOSAR OS,并借助Vector Configurator讲解AUTOSAR OS的配置。源于德语,英文意思是:“车载电子设备的开发系统和接口”,它是一个标准,用来产生嵌入式操作系统的规范,通讯协议栈,和汽车网络管理协议,也产生其他相关的规范。OSEK被设计来提供整车的各种电子控制单元的软件标准架构。

酒无忧的博客 1422

uboot引导vxworks6.9(T4240) 启动

vxworks内核配置下搜索RAM_LOW_ADRS, 值为0x01000000, 是vxworks下载启动的地址,uboot启动时会用到。vxworks6.9 t4240用的是32地址空间,uboot下用的是64位地址空间,去uboot下修改law物理地址空间为32位。vxworks下flash基地址为 0xff000000, 将vx下的地址修改为0xe0000000,和uboot下地址一致。uboot下flash基地址为0xe000000,vxworks内核配置为build-in 符号表。

珂珂可爱多 3236

Android ListView常用用法

Android ListView常用用法(一)   ListView是比较常用的控件,但一直都觉得创建ListView步骤有点繁琐,故在此总结一下,方便查阅。 程序效果是实现一个ListView,ListView里面有标题,内容和图片,并加入点击和长按响应。         首先在xml里面定义一个ListView <LinearLayout android:i

4872

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

ListView的用法

一、ListView的简介 <ListView>:用于展示大量数据的一种列表视图,通过上下滑动的方式将屏幕外的数据滚动到屏幕内。数据无法直接传递给ListView,需要适配器Adapter:作用是将各种数据以合适的形式展示到View上。 说白了,就是ListView是一个框架,然后在Adapter中创建视图,再把Adapter放到ListView中。 二、实例:购物商城 构建过程: 1.activity_main.xml中的布局 就两个布局,最上面的购物商城是一个TextVi

m0_54353756的博客 6859

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Android ListView用法

ListView 用法 ListView用于将数据展示为一个列表,常用于显示通讯消息,用处较为广泛 用ListView展示水果 创建一个fruit_item.xml用来动态加载布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

叶上初阳_285557的博客 1130

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

自己对于ListView的理解以及常用用法

ListView虽然现在几乎被RecyclerView所替代,但是在一些简单的列表中ListView会自动给每个子项之间添加一条分隔线,如果使用RecyclerVIew实现相同的功能的话会显复杂。而且学习使用ListView会进一步了数据填充器Adapter和如何优化简单的代码。 ListView的简单用法 1.最简单的创建一个只含有ListView的布局:在ListView控件中设置完id和宽高后,就完成一个最简单的控件初始化 <?xml version="1.0" encoding="ut

weixin_47425891的博客 972

Delphi ListView的用法(常用技巧)

//增加i := ListView1.Items.Count;with ListView1 dobeginListItem:=Items.Add;ListItem.Caption:= IntToStr(i);ListItem.SubItems.Add(第 +IntToStr(i)+ 行);ListItem.SubItems.Add(第三列内容);end;//按标题删除for i:=Li

愚公移山的专栏 1352

Android listView用法详解

1. 前言 在android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。 列表的显示需要三个元素: 1.ListVeiw:用来展示列表的View。 2.适配器:用来把数据映射到ListView上的中介。 3.数据:被映射的字符串,图片,或者基本组件。 2.listView的使用 listVi

keep studying 4962

listview的分类,仿京东分类

listview的分类,今天看到京东的app分类做的很ok,自己也尝试了下,效果实现了. //先上图,京东的,我自己的 //代码很容易就不过多做解释了. //主要的话就是两个方法的使用 //listview.smoothScrollToPosition(0)设置listview到排头 //listview.smoothScrollToPosition(adapter.getCount(

hyf97135的博客 2113

Android的分类ListView

最近在项目版本迭代中需要用到分类的ListView,小区下面的N条收货地址(类似联系人)。以前都是用的很普通的ListView,都写熟透了,这种倒是没写过,就研究了下。如果是联系人那种简单的布局到也好解决,标题和子Item都可以用一个Xml布局解决。主要的难点是此次的需求是标题和子Item布局不一样,子Item还有很多点击事件需要处理,删除、编辑、选中等,有三个入口,还要根据不同的入口进行布局相应的显示。

指尖飞落的博客 1362
上一篇: VS 常用快捷键
下一篇: CSplitterWnd类的使用
htt9931
博客等级 码龄24年 43粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值