0 注意:
怎么接收到命令,以及如何将结果返回给客户端在2、3、4节以及介绍清楚来,本节只讨论功能实现
锁机的本质就是==》遮蔽屏幕,控制鼠标和键盘
1 参考步骤
1.1 添加锁机对话框
由于这是一个在命令号里面集成了MFC的应用,所以我们可以直接在资源文件里面添加一个对话框,并给这个对话框添加一个类方便控制这个对话框
在这里有个问题对话框应该是模态还是非模态对话框
-
模态对话框:用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行相应,如单击【确定】、【取消】、【关闭】按钮等将该对话框关闭;
-
非模态对话框:对话框打开的时候,用户依然可以操作其他窗口
这里应该是非模态对话框,因为本应用没有窗口
代码如下:
#include "LockDialog.h" CLockDialog LockDlg; // 首先资源文件创建一个dialog 模板 // 利用模板创建dlg LockDlg.Create(IDD_DIALOG_LOCK, NULL); // showdlg LockDlg.ShowWindow(SW_SHOW);
1.2 锁机对话框窗口设置,以及鼠标键盘设置
代码入下:
-
以非模态的方式显示对话框
-
把窗口置顶
-
设置窗口大小占满屏幕
-
隐藏吸引任务栏
-
隐藏鼠标
-
限制鼠标范围
解锁时需要将鼠标显示恢复,任务栏恢复,对话框销毁
因为锁机后需要一直获取消息,所以必须新开一个线程来进行锁机操作,不然会导致无法接收其它消息,也就无法解锁了
unsigned __stdcall threadLockDialog(void* arg) { // 首先资源文件创建一个dialog 模板 // 利用模板创建dlg LockDlg.Create(IDD_DIALOG_LOCK, NULL); // showdlg LockDlg.ShowWindow(SW_SHOW); // 移动窗口到全屏 CRect rect; rect.left = 0; rect.top = 0; // GetSystemMetrics 检索指定的系统指标或系统配置设置。 rect.right = GetSystemMetrics(SM_CXFULLSCREEN); rect.bottom = GetSystemMetrics(SM_CYFULLSCREEN); rect.bottom *= 1.03; LockDlg.MoveWindow(rect); // 设置窗口置顶 LockDlg.SetWindowPos(&LockDlg.wndTopMost, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); // 隐藏系统任务栏 ::ShowWindow(::FindWindow(_T("Shell_TrayWnd"), NULL), SW_HIDE); // 本窗口里面隐藏鼠标 ShowCursor(false); // 限制鼠标范围 rect.left = 0; rect.top = 0; rect.bottom = 1; rect.right = 1; // 获取窗口大小 // LockDlg.GetWindowRect(rect); ClipCursor(&rect); // 消息循环 MSG msg; ULONGLONG tick = GetTickCount64(); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); if (msg.message == WM_KEYDOWN) { /* wParam:通常是一个与消息有关的常量值,也可能是窗口或控件的句柄。通常用于存储小段信息,如标志 lParam:通常是一个指向内存中数据的指针,通常用于存储消息所需的对象。 由于wParam,lParam和指针都是32位的,需要时可以强制类型转换。具体表示什么,与message相关, */ TRACE("msg:%04x wparam:%08X lparam:%08X\r\n", msg.message, msg.wParam, msg.lParam); if (msg.wParam == 0x1B) { break; } } } // 显示鼠标 ShowCursor(true); // 恢复任务栏 ::ShowWindow(::FindWindow(_T("Shell_TrayWnd"), NULL), SW_SHOW); // 销毁dlg LockDlg.DestroyWindow(); _endthreadex(0); return 0; } int LockMachine() { // 判断LockDlg是否被创建,防止客户端多次点击锁机,这边多次创建 if ((LockDlg.m_hWnd == NULL) || (LockDlg.m_hWnd == INVALID_HANDLE_VALUE)) { // _beginthread(threadLockDialog, 0, NULL); // 需要向这个线程发送消息,需要线程id所以用dex _beginthreadex(NULL, 0, threadLockDialog, NULL, 0, &LockThreadId); } CPacket packet(13, NULL, 0); CServerSocket::getInstance()->Send(packet); return 0; }
重点:在MFC中,组件是依赖消息循环的,消息是依赖线程的,每个线程都有自己的一个消息循环,想向另一个线程发消息必须知道另一个线程的线程id