MFC小型工具通用界面框架CLIST控件+右键菜单功能
MFC-小型工具通用界面框架
0x1 场景
由于工作需要我会写代码开发工具给客户或者同事用。代码都能实现,但写个黑乎乎的命令行工具给别人用确实显得不够专业,用别人写好的成型工具又担心有后门。
所以掌握积累几个MFC的常用控件随时调用,代码量堆起来了就是不断反复利用的过程了。未来还是会把精力用在实现实际功能上,以成为界面工程师作为目标学习很容易找不到工作。
这篇文章主要分享给大家使用MFC做GUI的技巧,选用它是因为我更熟悉C++。而且VS是非常强大的调试器,除了下载就可以用之外,还能看反汇编、内存、堆栈。
环境:VS2017
效果
0x2 技术点
- CListCtrl,界面增加列名、跟随界面调整、增加内容
- 菜单使用,删除单条、删除多条
0x3 代码
1、CListCtrl控件
界面使用部分
1、【对话框编辑器】-【List Control】,增加一个List控件拖到指定位置
2、【属性】-【View】-【Report】,把显示方式改成报表形式
3、【类向导】-【成员变量】-【添加变量】-【m_List_xxx】,绑定一个操作的变量
代码部分
- 添加List控件的列表头,增加列 InsertColumn();
m_List_xxx.InsertColumn(i, // 插入的列
g_Column_Message_Data[i].title, // 插入的标题
LVCFMT_CENTER, // 插入的样式
g_Column_Message_Data[i].nWidth); // 插入的宽度
封装函数,定义结构体部分:
定义一个结构体,成员是标题【WCHAR *title】、宽度【int nWidth】。然后初始化每一列的列名占据叫什么名字,占据多宽。
/////////////////////////////////////////// 列表控件
typedef struct
{
WCHAR *title; //列表的名称
int nWidth; //列表的宽度
}COLUMNSTRUCT;
COLUMNSTRUCT g_Column_Message_Data[] =
{
{ _T("信息类型"), 80 },
{ _T("时间"), 100 },
{ _T("信息内容"), 300 }
};
//变量声明
int g_Column_Message_Count = 3; //列表的个数
int g_Column_Message_Width = 0; //列总宽度,初始化为0。在后面的函数中会赋值
新建一个函数【int GUI_InitList(void)】,在【OnInitDialog()】里调用。初始化List显示的列表名
int CAPTFilecheckDlg::GUI_InitList(void)
{
// init online list
m_CList_dirlist.SetExtendedStyle(LVS_EX_FULLROWSELECT);
for (int i = 0; i < g_Column_Online_Count; i++)
{
m_CList_dirlist.InsertColumn(i, g_Column_Online_Data[i].title, LVCFMT_CENTER, g_Column_Online_Data[i].nWidth);
g_Column_Online_Width += g_Column_Online_Data[i].nWidth; //得到总宽度
}
m_CList_MESSAGE.SetExtendedStyle(LVS_EX_FULLROWSELECT);
for (int i = 0; i < g_Column_Message_Count; i++)
{
m_CList_MESSAGE.InsertColumn(i, g_Column_Message_Data[i].title, LVCFMT_CENTER, g_Column_Message_Data[i].nWidth);
g_Column_Message_Width += g_Column_Message_Data[i].nWidth; //得到总宽度
}
return 0;;
}
- 跟随界面调整大小
最大化的时候界面跟着变大。
【类向导】-【消息】-【WM_SIZE】-【添加处理程序】,增加一个【OnSize】的消息函数
void CMFCClistDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
// 命中目标
double dcx = cx; //对话框的总宽度
if (m_List_xxx.m_hWnd != NULL)
{
CRect rc;
rc.left = 1; //列表的左坐标
rc.top = 20; //列表的上坐标
rc.right = cx - 1; //列表的右坐标
rc.bottom = cy - 20; //列表的下坐标
m_List_xxx.MoveWindow(rc);
for (auto i = 0; i < g_Column_Message_Count; i++) { //遍历每一个列
double dd = g_Column_Message_Data[i].nWidth; //得到当前列的宽度
dd /= g_Column_Message_Width; //看一看当前宽度占总长度的几分之几
dd *= dcx; //用原来的长度乘以所占的几分之几得到当前的宽度
auto lenth = dd; //转换为int 类型
m_List_xxx.SetColumnWidth(i, (lenth)); //设置当前的宽度
}
}
}
- 增加列内容InsertItem()/SetItemText()
m_List_xxx.InsertItem(0, L"ok"); // 第一行的第一列内容
m_List_xxx.SetItemText(0, 1, L"2"); // 第一行的第二列内容
m_List_xxx.SetItemText(0, 2, L"hello world"); // 第一行的第三列内容
封装函数部分1:
void CAPTFilecheckDlg::GUI_ShowMessage(bool bIsOK, CString strMsg)
{
CString strIsOK, strTime;
CTime t = CTime::GetCurrentTime();
strTime = t.Format("%H:%M:%S");
if (bIsOK)
{
strIsOK = "执行成功";
}
else {
strIsOK = "执行失败";
}
m_CList_MESSAGE.InsertItem(0, strIsOK);
m_CList_MESSAGE.SetItemText(0, 1, strTime);
m_CList_MESSAGE.SetItemText(0, 2, strMsg);
}
调用方法:
GUI_ShowMessage(true, L"mesage");
GUI_ShowMessage(true, L"mesage1");
GUI_ShowMessage(true, L"mesage2");
2、菜单控件
新建菜单
【资源视图】-【添加资源】-【Menu】控件增加右键的说明
【删除单条】
【删除全部】
【增加内容】添加右键菜单
在【List Control】控件右键属性找到【NM_RCLICK】,双击绑定右键事件,根据需要再增加改动。
void CMFCClistDlg::OnNMRClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
CMenu popup;
popup.LoadMenu(IDR_MENU1);
CMenu* pM = popup.GetSubMenu(0);
CPoint p;
GetCursorPos(&p);
int count = pM->GetMenuItemCount();
//如果没有选中
if (m_List_xxx.GetSelectedCount() == 0)
{
for (int i = 2; i < count; i++)
{ //菜单全部变灰
pM->EnableMenuItem(i, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
}
}
pM->TrackPopupMenu(TPM_LEFTALIGN, p.x, p.y, this);
*pResult = 0;
}
- 绑定事件
在每个安全事件上添加事件处理程序,在消息类型【COMMAND】、类列表【xxxxDlg】,指定事件函数比如删除单条就绑定【GUI_Dir_Delete()】、删除全部就绑定【GUI_Dir_DeleteALL_Items()】。
- 右键删除单行功能实现,GetItemCount()/DeleteItem():
删除单条要先获取选中的条目,然后遍历
void CMFCClistDlg::GUI_Dir_Delete()
{
// TODO: 在此添加命令处理程序代码
int i, iState;
// 当前选择的条目
int nItemSelected = m_List_xxx.GetSelectedCount();
// 检索在列表视图控件中的项的数目。
int nItemCount = m_List_xxx.GetItemCount();
// 如果没有选择值,就退出这个函数,不执行删除判断。
if (nItemSelected < 1)
return;
// 遍历当前所有的列,找到选中的那条删除。
for (i = nItemCount - 1; i >= 0; i--)
{
iState = m_List_xxx.GetItemState(i, LVIS_SELECTED); // 获取选择状态
if (iState != 0)
{
m_List_xxx.DeleteItem(i); // 删除
}
}
}
- 右键删除所有行功能实现,DeleteAllItems()/SetRedraw()/RedrawWindow();
// 删除所有特征
void CMFCClistDlg::GUI_Dir_DeleteALL_Items()
{
// TODO: 在此添加命令处理程序代码
m_CList_dirlist.DeleteAllItems();
m_CList_dirlist.SetRedraw(FALSE);
//do erase and insert operation
m_CList_dirlist.SetRedraw(TRUE);
m_CList_dirlist.RedrawWindow();
}
- 右键增加内容功能实现
结合前面增加内容的函数,可以绑定一个【增加内容】的函数,【GUI_Add_Check_Dir()】。
函数作用主要是打开文件浏览器,然后选中路径,增加到LIST控件中。
void CMFCClistDlg::GUI_Add_Check_Dir()
{
// TODO: 在此添加命令处理程序代码
CString m_strFileOut = _T("");
TCHAR servPath[MAX_PATH];//用来存放文件夹路径
BROWSEINFO bi;
LPITEMIDLIST pidl;
bi.hwndOwner = this->m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = servPath;
bi.lpszTitle = _T("选择文件路径");
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = NULL;
bi.iImage = NULL;
if ((pidl = SHBrowseForFolder(&bi)) != NULL)
{
//得到文件夹的全路径,不要的话,只得本文件夹名
if (SHGetPathFromIDList(pidl, servPath))
{
// 增加内容
GUI_ShowMessage(true, servPath);
}
}
// 把变量内容更新到对话框
UpdateData(FALSE);
}
0x4 总结
界面功能并不会太复杂,知道怎么得到结果,怎么插入数据和扩展就足够了。
主要功能:
CListCtrl控件使用,右键菜单功能删除单行、删除全部、增加自定义内容。
扩展性:
主要考虑在右键菜单栏增加处理函数,实现主要功能,然后得到结果返回到界面上。
0x5 参考
MSDN VS2017
https://docs.microsoft.com/zh-cn/cpp/mfc/reference/clistctrl-class?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DZH-CN%26k%3Dk(AFXCMN%2FCListCtrl%3A%3AInsertItem)%3Bk(CListCtrl%3A%3AInsertItem)%3Bk(InsertItem)%3Bk(DevLang-C%2B%2B)%3Bk(TargetOS-Windows)%26rd%3Dtrue&view=vs-2017#insertcolumn
VS2010/MFC编程入门之二十九(常用控件:列表视图控件List Control 下)
http://www.jizhuomi.com/software/197.html
MFC小型工具通用界面框架CLIST控件+右键菜单功能的更多相关文章
- WPf 带滚动条WrapPanel 自动换行 和控件右键菜单
原文:WPf 带滚动条WrapPanel 自动换行 和控件右键菜单 技能点包括 WPf 样式的引用 数据的验证和绑定 比较适合初学者 前台: <Window.Resources> < ...
- FineUI Grid控件右键菜单的实现
FineUI官方Demo上一直没有Grid右键菜单的实现,其实从4.1.x的版本开始,允许添加自定义的事件监听(Listeners),所以要实现这个功能已经相当容易了. ExtJs右键菜单有很多种,对 ...
- win32 listctrl控件右键菜单的实现
HMENU Menu_list,Menu_all; POINT point; HINSTANCE hInstance;//下面代码放到BOOL WINAPI DialogProc下 case WM_C ...
- VS编程,编辑WPF过程中,点击设计器中界面某一控件,在XAML中高亮突出显示相应的控件代码的设置方法。
原文:VS编程,编辑WPF过程中,点击设计器中界面某一控件,在XAML中高亮突出显示相应的控件代码的设置方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net ...
- asp.net中遍历界面上所有控件进行属性设置
* 使用方法: * 前台页面调用方法,重置: protected void Reset_Click(object sender, EventArgs e) { ...
- 不在界面上用控件 动态创建idhttp,IdAntiFreeze来用
不在界面上用控件 动态创建idhttp,IdAntiFreeze来用 var IdHTTP: Tidhttp; IdAntiFreeze: TidAntiFreeze; begin IdAntiFre ...
- FoxOne---一个快速高效的BS框架--WEB控件属性编辑器
FoxOne---一个快速高效的BS框架--(1) FoxOne---一个快速高效的BS框架--(2) FoxOne---一个快速高效的BS框架--(3) FoxOne---一个快速高效的BS框架-- ...
- Android仿苹果版QQ下拉刷新实现(一) ——打造简单平滑的通用下拉刷新控件
前言: 忙完了结婚乐APP的开发,终于可以花一定的时间放在博客上了.好了,废话不多说,今天我们要带来的效果是苹果版本的QQ下拉刷新.首先看一下目标效果以及demo效果: 因为此效果实现的步骤 ...
- .NET Framework的属性类对控件的支持功能
ToolBoxItem 此属性为类特性.属于工具箱属性,可以设置当前控件是否在工具箱中显示,以及所在工具箱项的类型名称等信息.默认生成的控件都显示在工具箱中. 更多设计时属性介绍: 4.3 属性的 ...
随机推荐
- 对常用软件的评价(TGP腾讯游戏平台)
1,首先说下界面,这款软件的界面有些类似于QQ的界面,登录方式和QQ的方式是一样的,可以简单的说是一款给游戏用的QQ,就是里面的用户变成了游戏 2,功能,简单的说就是将你常玩的游戏放于这游戏平台的表面 ...
- webpack 学习笔记 (一)
webpack 作为当下前端前沿最受欢迎的打包工具,作为一个前端开发人员是很有必要去了解下它的. 题外话: npm i -D 是 npm install --save-dev的简写,是安装模块并保存 ...
- 解决局域网IP冲突
进入cmd ipconfig -all 查看现有IP,发现IP不是192.168.1.*的形式,而是192.168.0.*等异常 ipconfig -release 释放现有IP ipconfig ...
- multer详解
Express默认并不处理HTTP请求体中的数据,对于普通请求体(JSON.二进制.字符串)数据,可以使用body-parser中间件.而文件上传(multipart/form-data请求),可以基 ...
- java配置环境变量与常用技巧
一.java入门 --->java平台 •Java SE Java Platform,Standard Edition-Java平台标准版. •Java EE Java Platform,Ent ...
- java自定义注解学习(一)_demo小练习
自定义注解 现在大家开发过程中,经常会用到注解. 比如@Controller 等等,但是有时候也会碰到自定义注解,在开发中公司的记录日志就用到了自定义注解.身为渣渣猿还是有必要学习下自定义注解的. 这 ...
- iOS—— iOS 内存管理:增长+泄漏
1.如果是循环中局部变量data没有释放导致的,给NSData 手动添加释放池 @autoreleasepool { your code } 2.url 转变字典key值的时候出现内存暴增! //设置 ...
- 【Mysql】根据时间去除重复数据
SELECT a.project_id,a.user_id,a.app_version,a.src_system,a.channel,a.thedate FROM rpt_innoreport_luc ...
- Lua 调试库
Lua 调试库 http://blog.csdn.net/vermilliontear/article/details/50851045 http://blog.csdn.net/vermillion ...
- linq 获取列表最大值
string depth = formList.OrderByDescending(s => s.VersionId).FirstOrDefault().VersionId;