MFC之任务管理器篇

【前言】

1.运用知识点

SDK、MFC、进程、线程

2.设计思路

  • 主对话框:菜单、状态栏、选项卡
  • 选项卡:窗口、进程、线程、模块、堆、文件操作、VS垃圾清理
  • 其他:运行新任务、开机关机、快捷键、窗口置顶

3.难点

1.不同窗口之间传递消息

  • 进程->获取父窗口选项卡指针对象/句柄->发送(自定义)消息选项卡->选项卡接收消息在发(自定义)给线程->线程响应消息

2.如何获取窗口类对象,并且正确发送消息

3.进程对应的CPU使用率计算

【知识点记录】

1.自定义消息

【子类A函数中】【怎么发的消息】----自己给自己发WM_SHOWTHREAD消息

    //1.获取进程对话框的父窗口->选项卡
    CWnd* parent = GetParent();
    //2.给选项卡发消息->选项卡在给子窗口线程发消息
    parent->SendMessage(WM_SHOWTHREAD, int_ProcPID[Prorow],0);

【自己函数中】【怎么响应消息】-----自定义WM_SHOWTHREAD消息

【自己函数中】【解释】

1.定义消息后,立刻马上定义宏-> WM_XXXX WM_USER + X

2.自动生成头文件声明、函数定义、消息映射

3.在函数定义里面写接收此消息后的操作

2.选项卡 -列表-菜单

2.1 【选项卡】表头宽度

m_Tab.SetMinTabWidth(宽度);

2.2 【列表】背景图标

// 4.设置列表背景图及风格 CBitmap bmp; bmp.LoadBitmapW(IDB_BITMAP1); 
m_WndMsg_List.SetBkImage(bmp); 
m_WndMsg_List.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);

2.3 右键跳出【菜单】

【SDK和MFC对比】:一个是C版本获取句柄,一个是C++版本获取类对象

句柄 有点等价于 类指针对象

void WindwoMsg::WndMsg_RCLICK(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    //0.获取点击的行
    row = pNMItemActivate->iItem;
    //1.获取菜单资源
    CMenu m_Menu;
    m_Menu.LoadMenu(IDR_MENU1);
    //2.菜单弹出位置
    CPoint PosMouse;
    GetCursorPos(&PosMouse);
    CMenu* pSubMenu = NULL;
    pSubMenu = m_Menu.GetSubMenu(0);
    pSubMenu->TrackPopupMenu(0, PosMouse.x, PosMouse.y, this);
    // ||----------------------------------------------------------------||
    // ||===========================对比SDK区别==========================||
    // ||                                                                ||
    // ||   .创建菜单资源,并获取句柄                                    ||
    // ||    HMENU hMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));   ||
    // ||    获取哪一个子菜单?第二个参数是哪个子菜单                    ||
    // ||    HMENU hPopup = GetSubMenu(hMenu, 1);                        ||
    // ||    获取光标坐标                                                ||
    // ||    POINT pt = {};                                              ||
    // ||    GetCursorPos(&pt);                                          ||
    // ||    弹出菜单                                                    ||
    // ||    TrackPopupMenuEx(hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON,   ||
    // ||       pt.x, pt.y, hwnd, // hwnd 是响应菜单消息的窗口句柄       ||
    // ||       NULL);                                                   ||
    // ||    释放菜单资源                                                ||
    // ||    DestroyMenu(hMenu);                                         ||
    // ||----------------------------------------------------------------||
    *pResult = 0;
}

3.拓展知识

3.1 获取系统时间

//1.获取系统时间 
CString Sys_Time; 
CTime Time; 
Time = CTime::GetCurrentTime(); 
Sys_Time = Time.Format("北京时间:%Y年%m月%d日%X");

3.2 窗口置顶功能

//1.获取菜单指针对象->GetMenu()此窗口的菜单指针->GetSubMenu()菜单的第几个子菜单
	CMenu* menu = GetMenu()->GetSubMenu(1); 
	//2.返回指定菜单项的状态或弹出菜单中的项数->MF_BYCOMMAND指定参数提供现有菜单项的命令 ID
	//  感觉是在获取这个菜单是否被选中信息
	UINT state = menu->GetMenuState(ID_32783, MF_BYCOMMAND);
	ASSERT(state != 0xFFFFFFFF);
	//3.将复选标记属性设置为所选状态
	if (state & MF_CHECKED)
	{
		//4.选中状态:点击就取消
		menu->CheckMenuItem(ID_32783, MF_UNCHECKED | MF_BYCOMMAND);
		//4.1窗口取消置顶
		SetWindowPos(&CWnd::wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
	}
	else
	{
		//5.未选中状态下:点击就选中
		menu->CheckMenuItem(ID_32783, MF_CHECKED | MF_BYCOMMAND);
		//5.1窗口置顶
		SetWindowPos(&CWnd::wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
	}

3.3 获取更改权限开关机

	//1.请求令牌
	HANDLE hToken = NULL;
	//2.进程伪句柄
	HANDLE hProcess = GetCurrentProcess();
	//3.OpenProcessToken函数打开与进程关联的访问令牌
	//  所有权限可以写TOKEN_ALL_ACCESS ,去查看一个令牌特权可以用TOKEN_QUERY
	OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
	//4.使用AdjustTokenPrivileges需要的内容
	//  在这个函数中的第3和第5个参数中需要用到一个TOKEN_PRIVILEGES的结构体
	//  在这个结构体中还有个LUID_AND_ATTRIBUTES结构体
	//  TOKEN_PRIVILEGES:参数1.要修改的特权数目  参数2.特权数组
	//  LUID_AND_ATTRIBUTES:
	//  参数1.第一个参数是Luid是一个标志,不同的Luid代表着各种不同的特权类型
	//        Luid的值需要用LookupPrivilegeValue来获取
	//  参数2.第二个参数是要这个特权干嘛,如启用这个特权(SE_PRIVILEGE_ENABLED)
	//  LookupPrivilegeValue:
	//  第一个参数是系统的名字,如果为NULL,就是本地名字
	//  第二个参数是特权的名字
	//  第三个参数就可以通过指针返回一个LUID类型的Luid的标识了
	TOKEN_PRIVILEGES tp = { 0 };
	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tp.Privileges[0].Luid);
	tp.PrivilegeCount = 1;
	//5.权限使用
	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	//6.调用函数提升权限
	//AdjustTokenPrivileges(
	//	 HANDLE TokenHandle,                  OpenProcessToken第三个指针参数传出的句柄值
	//	 BOOL DisableAllPrivileges,           是否禁用所有所有的特权
	//	 PTOKEN_PRIVILEGES NewState,          新的TOKEN_PRIVILEGES的特权结构体指针
	//	 DWORD BufferLength,                  新的TOKEN_PRIVILEGES的特权结构体指针
	//	 PTOKEN_PRIVILEGES PreviousState,     接受原先的特权的结构体
	//	 PDWORD ReturnLength                  这个结构体的字节长度的指针
	//);
	AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
	switch (nID)
	{
	//A.关机
	case ID_32792:
	{
		//ExitWindowsEx注销交互式用户、关闭系统或关闭并重新启动系统
		//  EWX_POWEROFF 关闭系统并关闭电源
		//  EWX_FORCE 如果启用了终端服务,则此标志不起作用,这可能会导致应用程序丢失数据
		//  SHTDN_REASON_MAJOR_APPLICATION 应用程序问题
		//  EWX_REBOOT 关闭系统,然后重新启动系统
		//  EWX_LOGOFF 它会将用户注销
		//ExitWindowsEx(EWX_POWEROFF | EWX_POWEROFF, SHTDN_REASON_MAJOR_APPLICATION);
		MessageBox(_T("电脑已关机--注释"));
		break;
	}
	//B.重启
	case ID_32793:
	{
		//ExitWindowsEx(EWX_REBOOT | EWX_POWEROFF, SHTDN_REASON_MAJOR_APPLICATION);
		MessageBox(_T("电脑已重启--注释"));
		break;
	}
	//C.注销
	case ID_32794:
	{
		//ExitWindowsEx(EWX_LOGOFF | EWX_POWEROFF, SHTDN_REASON_MAJOR_APPLICATION);
		MessageBox(_T("电脑已注销--注释"));
		break;
	}
	//D.休眠
	case ID_32795:
	{
		//包含头文件:挂起或休眠系统,或请求挂起或休眠系统
        //#include<powrprof.h>
        //#pragma comment(lib,"PowrProf.lib")
		SetSuspendState(TRUE, FALSE, FALSE);
		break;
	}
	//E.睡眠
	case ID_32796:
	{
		SetSuspendState(FALSE, FALSE, FALSE);
		break;
	}
	//F.锁屏
	case ID_32797:
	{
		LockWorkStation();
		break;
	}
	default:
		break;
	}

3.4 静态文本控件超链接并设置颜色

【静态文本超链接】

   RECT rc;
	//1.获取的是电脑屏幕的坐标
	m_About_15PB.GetWindowRect(&rc);
	//2.转换客户区坐标
	ScreenToClient(&rc);
	//3.判断鼠标位置
	if (point.x >= rc.left && point.x <= rc.right && point.y >= rc.top && point.y <= rc.bottom)
	{
		ShellExecute(NULL, _T("open"), TEXT("http://www.15pb.com.cn/"), NULL, NULL, SW_SHOW);
	}

【静态文本颜色】--响应消息WM_CtlColor

HBRUSH CTaskManagerDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
	if (IDC_STATIC100 == pWnd->GetDlgCtrlID())//判断发出消息的空间是否是该静态文本框
	{
		pDC->SetTextColor(RGB(0, 0, 255));//设置文本颜色为红色
		pDC->SetBkMode(OPAQUE);//设置文本背景模式为透明
	    //pDC->SetBkColor(RGB(0, 0, 255));//设置文本背景为蓝色
		//hbr = CreateSolidBrush(RGB(0, 255, 0));//控件的背景色为绿色
	}
	return hbr;
}

3.5 枚举窗口信息

【理解】:EnumWindows这个函数获得了当前的窗口信息,进入到回调函数EnumWinProc遍历;

一直在回调函数循环遍历窗口的信息!

   // 2.枚举窗口信息->获取行内容
    BOOL CALLBACK EnumWinProc(HWND hwnd, LPARAM);
    EnumWindows(&EnumWinProc, NULL);
    BOOL CALLBACK EnumWinProc(HWND hwnd, LPARAM)
{
    TCHAR buff[200];
    //1.获取窗口名
    GetWindowText(hwnd, buff, 200);
    //2.判定窗口存在并且窗口名不等于0
    if (IsWindowVisible(hwnd) == true && wcslen(buff) != 0)
    {
        int temp = 0;
        //3.限制窗口名重复
        for (int i = 0; i < WndName.size(); i++)  
        {                                         
            if (WndName[i] == buff)               
            {                                     
                temp = 1;
                break;                            
            }                                     
        }                                         
        if (temp == 0)
        {                                         
            WndName.push_back(buff);              
        }                                         
    }
    return true;
}

3.6 当前进程内存使用情况


//显示当前程序的内存使用情况
void LogCurrentProcessMemoryInfo()
{
	HANDLE handle=GetCurrentProcess();
	PROCESS_MEMORY_COUNTERS_EX pmc = {0};
	int a = sizeof(pmc);
	if (!GetProcessMemoryInfo(handle,(PROCESS_MEMORY_COUNTERS*)&pmc,sizeof(pmc)))
	{
		DWORD errCode = GetLastError();
		DEBUG_TRACE("GetProcessMemoryInfo fail, lastErrorCode:%d",errCode);
		return;
	}
 
	CString strInfo;
	//占用的物理内存峰值
	strInfo.Format("PeakWorkingSetSize:%d(KB)\n",pmc.PeakWorkingSetSize/1024);
	OutputDebugString(strInfo);
 
	//当前占用的物理内存
	strInfo.Format("WorkingSetSize:%d(KB)\n",pmc.WorkingSetSize/1024);
	OutputDebugString(strInfo);
 
	//占用的虚拟内存峰值(物理内存+页文件),对应任务管理器中的commit列值
	strInfo.Format("PeakPagefileUsage:%d(KB)\n",pmc.PeakPagefileUsage/1024);
	OutputDebugString(strInfo);
 
	//当前占用的虚拟内存(物理内存+页文件),对应任务管理器中的commit列值
	strInfo.Format("PagefileUsage:%d(KB)\n",pmc.PagefileUsage/1024);
	OutputDebugString(strInfo);
 
	//等同于当前占用的虚拟内存(物理内存+页文件),对应任务管理器中的commit列值,并不是任务管理器中的私有独占内存的意思。
	strInfo.Format("PrivateUsage:%d(KB)\n",pmc.PrivateUsage/1024);
	OutputDebugString(strInfo);
}

3.7 【lstrcmp】比较函数

	// 3.判断是否是本级目录或上级目录的名称,是的话则结束本次循环
if (!lstrcmp(wfd.cFileName, L".")|| !lstrcmp(wfd.cFileName, L"..")) 
{
	continue;
}

3.8 【CString】的使用

【Find】找到对应的字符在哪里,返回顺序(0开始)

【Mid】 从左移动到什么位置

【Right】返回右边第几个元素

CString VSFileClean::GetExtName(CString fileName)
{
	//1.根据.获得位置
	int pos = fileName.Find(_T(".")); 
	//2.如果没有就返回剩余的就是后缀
	if (pos == -1) { 
		return fileName;
	}
	//3.找到在进去遍历,找到最后一个
	else {
		return GetExtName(fileName.Mid(pos + 1)); 
	}
}

3.9 【StringCbPrintf】拼接函数

StringCbPrintf(WCHAR数组名,数组长度,格式化字符)->"%sADD%s",s1,s2->s1+ADD+s2

3.10 【MFC】分割字符串函数

 

 

3.11.快捷键注册

//1.快捷键注册
::RegisterHotKey(g_hDlg, 0x1995, MOD_CONTROL | MOD_ALT, 'Z');
//2.调用虚函数
BOOL CTaskManagerDlg::PreTranslateMessage(MSG* pMsg)
{
	if ((pMsg->message == WM_HOTKEY) && (pMsg->wParam == 0x1995))
	{
		if (::IsWindowVisible(m_hWnd) == TRUE)
		{
			ShowWindow(SW_HIDE);
		}
		else {
			ShowWindow(SW_SHOW);
		}
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值