写这篇文章之前,其实我是有写过一篇CListCtrl的介绍文章的,突然发现,自己写的那篇文章介绍得实在太基础,完全就是介绍一下这个控件,导致自己后面做项目时,这个控件费时很久,以至于这次研究了一下,写了这篇文章,这里关于CListCtrl不做重复介绍,感兴趣可以去了解一下这篇文章:https://blog.csdn.net/m0_43458204/article/details/107641264
常规样式与扩展样式:
首先区分LVS_与LVS_EX_,哪些是常规样式,哪些是扩展样式:能在属性对话框里看到的样式都是常规样式,例如LVS_REPORT。
重点介绍一下扩展样式!
常用扩展样式如下表:
样式宏 | 宏描述 |
---|---|
LVS_EX_CHECKBOXES | 您可以获得 ListView_GetCheckState 指定项目的复选框的状态。若要设置检查状态,请使用 ListView_SetCheckState。如果设置了此样式,则当用户单击该复选框,或按空格键在列表视图控件自动切换复选状态。 |
LVS_EX_FLATSB | 扁平滚动条 列表视图中的启用平面滚动条。如果您需要更多的控制列表视图滚动条的外观,您应该操作平的滚动栏 Api 使用直接的列表视图滚动条。如果更改系统度量,您负责调整与 FlatSB_SetScrollProp 的滚动栏度量。有关进一步的详细信息请参阅平滚动条。 |
LVS_EX_FULLROWSELECT | 选择整行/高亮 当选择某个项目时,强调了项目和其所有子项。此样式是仅在 LVS_REPORT 风格结合中可用。 |
LVS_EX_GRIDLINES | 绘制表格 显示项及其子项周围的网格线。此样式是仅在 LVS_REPORT 风格结合中可用 |
LVS_EX_HEADERDRAGDROP | 报表头可以拖拽 允许拖放的列表视图控件中的列重新排序。此样式是只可用于使用 LVS_REPORT 样式的列表视图控件。 |
LVS_EX_INFOTIP | 将提示信息窗口的消息通知父窗口 当列表视图控件使用的 LVS_EX_INFOTIP 样式时,LVN_GETINFOTIP 通知代码发送到父窗口显示工具提示项之前。 |
LVS_EX_LABELTIP | \ |
LVS_EX_MULTIWORKAREAS | 多工作区 |
LVS_EX_ONECLICKACTIVATE | 单击激活 |
LVS_EX_REGIONAL | \ |
LVS_EX_SUBITEMIMAGES | 子项目图标列表 |
LVS_EX_TRACKSELECT | 自动换行 |
LVS_EX_TWOCLICKACTIVATE | 双击激活 |
LVS_EX_UNDERLINECOLD | \ |
LVS_EX_UNDERLINEHOT | \ |
因为这里的样式我们是没法更改的,但是有的时候又想显示跟默认不一样的样式,比如选中行不要默认的蓝色。这个时候就需要我们自绘ListCtrl,我试着写了下,但是失败了,遇到点问题没法解决,就没有实现此功能。(后面会补上此类)
本程序,不出意外应该是会出很多版,最后成品的效果大概就是,通过QQ或者微信登陆,选择大区,可以查询当前大区的各种榜单排行榜
内含:python爬虫、MFC界面搭建、Json解析、远程连接、等相关知识。
第一版界面图如下所示:(基本信息)
巅峰查询器V1.0内容包括:基础信息支持手动添加、单选删除、全部删除、选择一项数据、选择多项数据(支持反选、全选)。
关于界面的搭建,这里属于MFC基本功,我这里不多叙述,直接开始我们的码程序教程。
下面将贴上部分核心源码及操作:
如此,我们就可以去OnInitDialog()中添加初始化程序,代码如下:
m_ListCtrl.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_INFTIP);
DWORD dwStyle = ::GetWindowLong(m_ListCtrl.m_hWnd, CWL_STYLE);
dwStyle &= ~(LVS_TYPEMASK); //~ 按位取反,此语句用于去掉TYPEMASK风格
SetWindowLong(m_ListCtrl.m_hWnd,CWL_STYLE, dwStyle | LVS_REPORT | LVS_NOLABELWRAP | LVS_SHOWSELALWAYE | LVS_EDITLABELS);
//设置扩展风格:使选中行高亮(蓝色)、网格线、增加CheckBox
DWORD styles = LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_CHECKBOXES;
ListView_SetExtendedListViewStyleEx(m_ListCtrl.m_hWnd, styles, styles);
//加入列头
const TCHAR* ListName[5] = {_T("ID"),_T("所在大区"),_T("当前段位"),_T("最高段位"),_T("巅峰积分")};
//数据列表
LV_COLUMN lvCol;
CRect rect;
m_ListCtrl.GetWindowRect(&rect);
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
int wt = rect.width(); //列表视图总宽度,可通过增加对话框大小扩大(此程序)
int w[5] = {0}; //各列数据的宽度
w[0] = wt / 5, w[1] = wt / 5, w[2] = wt / 5, w[3] = wt / 5, w[4] = wt / 5;
//将里面的五个列标题插入列表
for(int i = 0; i < 5; i++)
{
lvCol.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH | LVCF_ORDER;
lvCol.fmt = LVCFMT_LEFT;
lvCol.pszText = (LPWSTR)listName[i];
lvCol.iSubItem = i;
lvCol.iOrder = i;
lvCol.cx = w[i];
m_ListCtrl.InsertColumn(i, &lvCol);
}
m_ListCtrl.SetBKColor(RGB(223,223,223));
m_ListCtrl.SetTextBKColor(RGB(255,255,255)); //红色
m_ListCtrl.SetTextColor(RGB(0,0,0));
添加信息:
双击添加按钮,添加消息响应函数,然后里面就写上添加逻辑。
UpdateData();
int count = m_ListCtrl.GetItemCount(); //初始计数,防止删除之后,序号错乱,导致信息添加不完整
TCHAR rgtsz[5][256];
_stprintf(rgtsz[0], _T("%s"),m_strID.GetString());
_stprintf(rgtsz[1], _T("%s"),m_strSuperMarket.GetString());
_stprintf(rgtsz[2], _T("%s"),m_strCurPos.GetString());
_stprintf(rgtsz[3], _T("%s"),m_strBestPos.GetString());
_stprintf(rgtsz[4], _T("%d"),m_nPeakScore);
int bRet = MySetItem(rgtsz[0],rgtsz[1],rgtsz[2],rgtsz[3],rgtsz[4],count);
if (bRet == -1)
{
MessageBox(_T("ID为NULL,请检查!",_T("Tencent"),MB_ICONINFORMATION);
return;
}
else if (bRet == -2)
{
MessageBox(_T("所在大区为NULL,请检查!",_T("Tencent"),MB_ICONINFORMATION);
return;
}
else if (bRet == -3)
{
MessageBox(_T("当前段位为NULL,请检查!",_T("Tencent"),MB_ICONINFORMATION);
return;
}
else if (bRet == -4)
{
MessageBox(_T("最高段位为NULL,请检查!",_T("Tencent"),MB_ICONINFORMATION);
return;
}
else if (bRet == -5)
{
MessageBox(_T("巅峰积分为NULL,请检查!",_T("Tencent"),MB_ICONINFORMATION);
return;
}
count++; //计数++
UpdateData(FALSE);
插入函数MySetItem如下:
if(*tchar1 == NULL)
{
return -1;
}
else if(*tchar2 == NULL)
{
return -2;
}
else if(*tchar3 == NULL)
{
return -3;
}
else if(*tchar4 == NULL)
{
return -4;
}
else if(*tchar5 == NULL)
{
return -5;
}
//Col、tchar1~tchar5均为传递的参数
m_ListCtrl.InsertItem(Col, tchar1);
m_ListCtrl.SetItemText(Col, 1 , tchar2);
m_ListCtrl.SetItemText(Col, 2 , tchar3);
m_ListCtrl.SetItemText(Col, 3 , tchar4);
m_ListCtrl.SetItemText(Col, 4 , tchar5);
return TRUE;
按钮都是同样的方法添加消息响应。
UpdateData();
//删除一项,这里提供两种方法
#if 0
BOOL state = FALSE;
int len = m_ListCtrl.GetItemCount();
for(int i = 0; i < len; i++)
{
state = m_ListCtrl.GetCheck(i);
if(state == TRUE)
{
m_ListCtrl.DeleteItem(i);
}
}
#else
int nCurSelIndex = GetCurSel();
m_ListCtrl.DeleteItem(nCurSelIndex);
#endif
UpdateData(FALSE);
//删除全部
UpdateData();
m_ListCtrl.DeleteAllItems();
UpdateData(FALSE)
//反选
UpdateData();
BOOL state = FALSE;
int len = m_ListCtrl.GetItemCount();
for(int i = 0; i < len; i++)
{
state = m_ListCtrl.GetCheck(i); //得到选中项的状态
if(state == FALSE)
{
m_ListCtrl.SetItemState(i , LVIS_SELECTED,LVIS_SELECTED);
m_ListCtrl.SetCheck(i , TRUE);
}
else
{
m_ListCtrl.SetItemState(i, ~LVIS_SELECTED,LVIS_SELECTED);
m_ListCtrl.SetCheck(i , FALSE);
}
}
UpdateData(FALSE);
//全选
UpdateData();
int len = m_ListCtrl.GetItemCount(); //获得当前项数
for(int i = 0; i < len; i++)
{
m_ListCtrl.SetCheck(i , TRUE);
m_ListCtrl.SetItemState(i , LVIS_SELECTED, LVIS_SELECTED);
}
UpdateData(FALSE);
按照图中所示添加双击函数,然后手动添加一个函数,删除中方法二也用到了。
//得到点
POSITION pos = m_ListCtrl.GetFirstSelectedItemPosition();
if(pos == NULL)
{
return -1;
}
else
{
int nSelIndex = m_ListCtrl.GetNextSelectedItem(pos);
return nSelIndex;
}
//选中点
int nCurSelIndex = GetCurSel();
if( -1 == nCurSelIndex)
{
MessageBox(_T("未选中数据!"),_T("Tencent"),MB_ICONINFORMATION);
return;
}
MessageBox(_T("编辑功能有待完善,请等待版本更新!"),_T("Tencent"),MB_ICONINFORMATION);
关于巅峰查询器的版本更新问题,博主这里有时间就继续写,工作之余做一款软件出来,虽然功能不一定很强,但是主要是练手与熟悉各种技术为重,先发布一下V1.0版本源码吧,至于源码下载,等软件做出来之后,我会发布到github上,到时候需要请大家自行下载。
版权声明:转载请注明出处,谢谢!