• 【MFC】tab控件 仿任务管理器 枚举窗口和进程


    界面和关联变量设置

    创建一个基于对话框的MFC项目,给主对话框添加一个tab控件(设置关联变量 类型:CTabCtrl 名称:m_tab),添加两个子对话框(IDC_PAGE1和IDC_PAGE2),给子对话框添加一个list control控件(设置关联变量 类型:CListCtrl 名称:m_list),并将子对话框的边框属性设置为None,窗口样式设为child
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在资源视图界面右击对话框给IDC_PAGE1和IDC_PAGE2添加对话框类,类名分别为CPage1,CPage2。
    在这里插入图片描述

    CTabCtrl类

    主窗口界面

    C任务管理器Dlg类中添加CPage1和CPage2类型的变量page1和page2。
    要通过这两成员来创建子窗口。不要忘记在pch.h中包含"CPage1.h","CPage2.h"头文件。
    这个时候运行程序,结果如下
    在这里插入图片描述

    tab添加选项卡

    C任务管理器Dlg类的OnInitDialog()方法中添加如下代码

    m_tab.InsertItem(0, L"窗口名");
    m_tab.InsertItem(1, L"进程");
    
    • 1
    • 2

    这个时候运行程序tab控件上就有选项卡了
    在这里插入图片描述

    添加子窗口

    	CRect rect;
    	m_tab.GetClientRect(&rect);
    	//Create函数通过资源ID和所属的父窗口对象创建一个无模式对话框
    	//创建的对话框如果要显示需要通过ShowWindow(SW_SHOW)显示
    	page1.Create(IDD_PAGE1, &m_tab);
    	page2.Create(IDD_PAGE2, &m_tab);
    	rect.top += 22;
    	rect.left += 1;
    	rect.right -= 3;
    	rect.bottom -= 2;
    
    	page1.MoveWindow(&rect);
    	page2.MoveWindow(&rect);
    
    	page1.ShowWindow(SW_SHOW);
    	page2.ShowWindow(SW_HIDE);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    获取tab控件的窗口大小并把子对话框显示在tab控件合适的位置。
    运行效果如下
    在这里插入图片描述
    这个时候tab的选项卡还不能切换显示对应的对话框。需要通过类向导添加TCN_SELCHANGE消息的响应函数

    TCN_SELCHANGE消息

    在这里插入图片描述

    void C任务管理器Dlg::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult)
    {
    	// TODO: 在此添加控件通知处理程序代码
    	int sel = m_tab.GetCurSel();
    	switch (sel)
    	{
    	case 0:
    		page1.ShowWindow(SW_SHOW);
    		page2.ShowWindow(SW_HIDE);
    		break;
    	case 1:
    		page2.ShowWindow(SW_SHOW);
    		page1.ShowWindow(SW_HIDE);
    		break;
    	}
    
    	*pResult = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    注意
    这里有两个命令TCN_SELCHANGE和TCN_SELCHANGING,选项卡改变是先执行TCN_SELCHANGING,后执行TCN_SELCHANGE,在执行TCN_SELCHANGING的时候,选项卡还未最终完成切换,在这个时候m_tab.GetCurSel()得到的是原来那个选项卡。所以在进行选项卡切换的时候响应的是TCN_SELCHANGE消息

    可以在TCN_SELCHANGING的响应函数中加入这段代码简单的验证一下

    int sel = m_tab.GetCurSel();
    CString str;
    str.Format(L"%d", sel);
    MessageBox(str);
    
    • 1
    • 2
    • 3
    • 4

    运行程序发现实现了选项卡切换的功能,但是如果拉大主窗口,tab控件和子对话框的大小不会变。这个时候要响应WM_SIZE消息使主窗口在变化的时候对话框和tab控件也进行相应的变化。在子对话框中的list control控件也要如此
    在这里插入图片描述

    控件和子对话框适应主窗口的大小变化

    	//GetSafeHwnd()用来判断...是否存在
    	CRect rect;
    	if (m_tab.GetSafeHwnd())
    	{
    		m_tab.MoveWindow(0, 0, cx, cy);
    		m_tab.GetClientRect(&rect);
    	}
    	rect.top += 22;
    	rect.left += 1;
    	rect.right -= 3;
    	rect.bottom -= 2;
    	if (page1.GetSafeHwnd() && page2.GetSafeHwnd())
    	{
    		page1.MoveWindow(&rect);
    		page2.MoveWindow(&rect);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    子对话框界面

    CPage1

    通过类向导添加OnInitDialog()

    BOOL CPage1::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    	m_list.ModifyStyle(0,
    		LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | 
    		LVS_ALIGNLEFT | WS_VSCROLL | WS_BORDER);
    	m_list.InsertColumn(0, L"序号", LVCFMT_LEFT, 50);
    	m_list.InsertColumn(1, L"窗口标题", LVCFMT_LEFT,200);
    	m_list.InsertColumn(2, L"窗口句柄", LVCFMT_LEFT, 200);
    	m_list.InsertColumn(3, L"窗口类", LVCFMT_LEFT, 200);
    
    	int i = 0;
    	CWnd*pwnd=AfxGetMainWnd()->GetWindow(GW_HWNDFIRST);
    	while (pwnd)
    	{
    		CString str;
    		str.Format(L"%d", i + 1);
    		m_list.InsertItem(i,str);
    
    		pwnd->GetWindowTextW(str);//获取窗口标题
    		m_list.SetItemText(i, 1, str);
    
    		str.Format(L"%x", pwnd->m_hWnd);//获取窗口句柄
    		m_list.SetItemText(i, 2, str);
    
    		TCHAR name[256];
    		GetClassName(pwnd->m_hWnd, name, 256);//获取窗口类名
    		m_list.SetItemText(i, 3, name);
    
    		pwnd = pwnd->GetWindow(GW_HWNDNEXT);
    		i++;
    	}
    
    
    
    
    	return TRUE;  // return TRUE unless you set the focus to a control
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在OnInitDialog()中实现枚举所有的窗口并显示,枚举窗口的流程是
    获取主窗口(AfxGetMainWnd())-》获取和主窗口平级的第一个窗口(GetWindow(GW_HWNDFIRST))-》循环获取下一个窗口(GetWindow(GW_HWNDNEXT))

    添加WM_SIZE消息响应

    if (m_list.GetSafeHwnd())
    		m_list.MoveWindow(0, 0, cx, cy);
    
    • 1
    • 2

    在这里插入图片描述

    CPage2

    通过类向导添加OnInitDialog()

    枚举进程要在CPage2类中加上头文件#include

    BOOL CPage2::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    	m_list.ModifyStyle(0,
    		LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | 
    		LVS_ALIGNLEFT | WS_VSCROLL | WS_BORDER);
    	m_list.InsertColumn(0, L"进程名", LVCFMT_LEFT, 300);
    	m_list.InsertColumn(1, L"进程ID", LVCFMT_LEFT, 100);
    
    	//枚举进程
    	//获取当前进程的快照
    	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    	PROCESSENTRY32 pe = { 0 };
    	pe.dwSize = sizeof(pe);
    	//获取快照中的第一个进程
    	bool b=Process32First(hSnapshot, &pe);
    	int i = 0;
    	while (b)
    	{
    		m_list.InsertItem(i, pe.szExeFile);
    
    		DWORD id=pe.th32ProcessID;
    		CString str;
    		str.Format(L"%d", id);
    		m_list.SetItemText(i, 1, str);
    		//获取快照中的下一个进程
    		b = Process32Next(hSnapshot, &pe);
    		i++;
    	}
    
    	return TRUE;  // return TRUE unless you set the focus to a control
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    枚举进程的流程,获取系统快照-》获取快照中第一个进程-》循环获取下一个进程

    添加WM_SIZE消息响应

    void CPage2::OnSize(UINT nType, int cx, int cy)
    {
    	CDialogEx::OnSize(nType, cx, cy);
    
    	if (m_list.GetSafeHwnd())
    	{
    		m_list.MoveWindow(0, 0, cx, cy);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行效果
    在这里插入图片描述

    源码

  • 相关阅读:
    AutoJs学习-MC我的世界自动钓鱼
    07_整合spring boot
    【HTML+REACT+ANTD 表格操作】处理(改变)数据,改变DOM
    Live800:服务不是销售的终点,而是营销的起点
    论文阅读:Editing Large Language Models: Problems, Methods, and Opportunities
    Sentinel配置持久化到Nacos实现流控熔断
    Mac 使用 Homebrew 安装 Python3
    The file was loaded in a wrong encoding: ‘UTF-8
    js中的深拷贝浅拷贝
    1932. 合并多棵二叉搜索树-哈希法+深度优先遍历
  • 原文地址:https://blog.csdn.net/m0_72895175/article/details/132839468