MFC-小型工具通用界面框架

MFC-小型工具通用界面框架

0x1 场景

开发桌面版小工具使用的通用界面,命令行使用起来不方便。

但是又不应该以成为界面工程师作为目标学习,掌握积累几个MFC的常用控件就可以在以后的日子里随时调用。

把代码积累出来,把精力用在实现实际功能上。

环境: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,2018);
    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 效果

0x6 参考

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

猜你喜欢

转载自www.cnblogs.com/17bdw/p/10238922.html
今日推荐