创建图形列表并和CListCtrl关联:
m_image_list.Create(IDB_CALLER2, 16, 10, RGB(192,192, 192));
m_image_list.SetBkColor( GetSysColor( COLOR_WINDOW ) );
m_caller_list.SetImageList( &m_image_list, LVSIL_SMALL);
为报表添加4列:
char *szColumn[]={"昵称","IP地址","登陆时间","状态"};
int widths[]={100,98,70,55};
LV_COLUMN lvc;
lvc.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvc.fmt=LVCFMT_LEFT;
for(int i=0;i<4;i++) {//插入各列
lvc.pszText=szColumn[i];
lvc.cx=widths[i];
lvc.iSubItem=i;
m_caller_list.InsertColumn(i,&lvc);
}
为报表添加两项,以附加方式添加:
char* data[4];
data[0]="所有人";
data[1]="0.0.0.0";
data[3]="在线";
data[2]=new char;
CTime now=CTime::GetCurrentTime();
CString temp = now.Format("%H:%M:%S");
data[2]=temp.GetBuffer(1);
LV_ITEM lvi;
lvi.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
lvi.iSubItem=0;
lvi.pszText=(char *)data[0];
lvi.iImage = 0;
lvi.iItem=0;
m_caller_list.InsertItem(&lvi);
for (int j=0;j<4;j++) m_caller_list.SetItemText(count,j,data[j]);
count++;
lvi.iImage = 1;
lvi.iItem=count;
m_caller_list.InsertItem(&lvi);
data[0]="cherami";
data[1]="127.0.0.1"; 
for (int n=0;n<4;n++) m_caller_list.SetItemText(count,n,data[n]);
count++;

设置报表的样式
选中一整行:
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_left在LVN_BEGINLABELEDIT中设置

CEdit::OnWindowPosChanging(lpwndpos);

// TODO: Add your message handler code here
}

报表式CListCtrl的使用详解初稿相关推荐

  1. CSS3 @media媒体查询 适配不同尺寸设备的响应式布局(清晰详解)

    随着宽屏的不断普及,CSS3出现了@media媒体查询技术 一.了解@Media 相关知识 1.了解Media Queries Media Queries能在不同的条件下使用不同的样式,使页面在不同在 ...

  2. CListCtrl控件详解

    1.视图类别 列表视图控件可用四种不同方式显示其内容,称之为"视图",有以下四个类别: 图标视图:每一项以全尺寸图标(32×32像素)出现,下面有一个标签.用户可在列表视图窗口拖动 ...

  3. Scala 隐式(implicit)详解

    文章正文 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 1.Spark 中 ...

  4. html中隐式转换成数字,详解JS中的隐式类型转换

    JS中隐式类型转换 JS中的数据类型 JS中的数据类型分为两大类: 1.基本数据类型: 1.String 字符串 表示一段文本,例如:人的姓名.地址等 2.Number 数值 3.Boolean 布尔 ...

  5. 电磁感应式无线充电系统详解

    相较于其它电子科技发展,感应式充电的技术发展显的缓慢,几个关键技术问题直到近年才有解决方案,且解决方案还在不断的演进中.无线充电可通过许多方式去完成,以目前的技术中"电磁感应式"为 ...

  6. 鄂式破碎机与反击式破碎机的工艺详解

    近些年来随着国家对资源开采利用和环境保护要求越来越严格,资源和生态环境也越发的趋强化,砂石作为重要的建材之一,将会获得更多的发展机遇,砂石生产厂家要调动一切积极因素,使技术迈上一个新台阶.其中用于砂石 ...

  7. 合并报表编制采用的理论_合并报表编制理论知识(必读)详解

    合并会计报表的编制原理与实务 [合并报表抵消有关内部交易而不调整或抵消盈余公积的说明] 引起内部单位利润发生变化的内部交易等业务,编制合并报表抵消分录时,只需 调整或抵消收入.成本以及资产等项目,不调 ...

  8. 合并报表编制采用的理论_3.合并报表编制理论知识(必读)详解

    1 合并会计报表的编制原理与实务 [合并报表抵消有关内部交易而不调整或抵消盈余公积的说明] 引起内部单位利润发生变化的内部交易等业务,编制合并报表抵消分录时,只需 调整或抵消收入.成本以及资产等项目, ...

  9. Flutter 流式布局之Wrap详解

    Wrap Wrap可以为子控件进行水平或者垂直方向布局,且当空间用完时,Wrap会自动换行,也是常说的流式​布局. 创建多个子控件做为Wrap的子控件,代码如下: <span style=&qu ...

最新文章

  1. 查找 framework 文件中是否包含 WKWebView
  2. 万能电子狗升级工具_六个常用电脑工具,你知道吗?必收!
  3. 新站上线后应该做哪些有利于seo的工作
  4. Zabbix 2.4.5 自定义 key 监控 apache
  5. 在caffe上fine-tuning网络
  6. IBASE category 03 parent relationship remove
  7. Spring XD 1.0.0.M5在这里!
  8. Linux开发商计划停止开发32位版本
  9. SqlServer分区表概述(转载)
  10. Spring Boot开发八字箴言(以我过去这段时间的经验总结得到)
  11. 《Python数据科学实践指南》——1.2 Python解释器
  12. 【转】Printf()输出格式控制
  13. ora-01950:对表空间XXX无权限
  14. 数据库之DB2数据库备份
  15. cmake的安装与基本使用
  16. 微软sql服务器可以卸载,完美卸载SQL Server 2008的方法
  17. python编写简单漏洞扫描器(通过实别服务版本号)
  18. OpenCV——Roberts算子
  19. 网吧服务器是起什么作用的,网吧服务器的用途是什么?
  20. [OfficeExcel] OfficeExcel2010 第18讲 Lookup--浅谈数组

热门文章

  1. ElasticSearch手动创建mapping
  2. Mysql 行转列,列转行
  3. 从有赞裁员,看SCRM的挑战与机遇
  4. PC版微信,也终于上线了这个超赞的功能
  5. MySQL下载和安装以及问题解决
  6. 【MySQL】MySQL基础理论学习笔记
  7. 动态规划求解疯狂的采药问题(洛谷P1616题题解,Java语言描述)
  8. 【C语言】C语言初学者常犯的18条错误
  9. 以太坊智能合约 solidity 的常用的数据结构介绍
  10. WPF实现TextBox水印效果