枚举桌面和窗口title,判断是否锁屏,自动锁屏,自动开机

调用Windows API打印当前窗口和该窗口的隶属桌面,判断是否锁屏,自动锁屏,自动开机

代码


#include <iostream>
#include "atlstr.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <chrono>
#include <thread>
#include <Windows.h>
#include <WtsApi32.h>
#include <unordered_map>
#include <ntsecapi.h>

using namespace std;
unordered_map <char, int> record = { {'f',0x46},{'w' ,0x57},{'h',0x48},{'1',0x31},
{'9',0x39},{'7',0x37},{'0',0x30},{'6',0x36},{'1',0x31},{'5',0x35},{'2',0x32},{'3',0x33}};

 
void independentThread()
{
	std::cout << "Starting concurrent thread.\n";
	std::this_thread::sleep_for(std::chrono::seconds(2));
	std::cout << "Exiting concurrent thread.\n";
}

void threadCaller(float time)
{
	std::cout << "Starting thread caller.\n";
	std::thread t(independentThread);
	t.detach();
	std::this_thread::sleep_for(std::chrono::seconds((int)time));
	std::cout << "Exiting thread caller.\n";
}

string getTime()
{
	time_t timep;
	time(&timep);
	char tmp[64];
	strftime(tmp, sizeof(tmp), "%H:%M:%S %Y-%m-%d", localtime(&timep));
	return tmp;
}

BOOL CALLBACK EnumChildProc(_In_ HWND   hwnd, _In_ LPARAM lParam)
{
    char szTitle[MAX_PATH] = { 0 };
    char szClass[MAX_PATH] = { 0 };
    int nMaxCount = MAX_PATH;

    LPSTR lpClassName = szClass;
    LPSTR lpWindowName = szTitle;

    GetWindowTextA(hwnd, lpWindowName, nMaxCount);
    GetClassNameA(hwnd, lpClassName, nMaxCount);
    cout << "[Child window] window handle: " << hwnd << " window name: "
        << lpWindowName << " class name: " << lpClassName << endl;

    return TRUE;
}
/*
** Function:EnumWindowsProc
** Using: 应用程序定义的函数,用于EnumWindows()或EnumDesktopWindos()函数。
			接收顶层窗口句柄。WNDENUMPROC类型定义了指向这种回调函数的指针。
			EnumWindowsProc是一个应用程序定义的函数名称的占位符。

*/
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
	//除了少数具有 WS_CHILD 样式的系统的顶级窗口,EnumWindows函数不枚举子窗口。
	char szTitle[MAX_PATH] = { 0 };//MAX_PATH 这个变量是windows自己宏定义的变量 #define MAX_PATH          260
	char szClass[MAX_PATH] = { 0 };
	int nMaxCount = MAX_PATH;

	LPSTR lpClassName = szClass;//LPSTR相当于char*
	LPSTR lpWindowName = szTitle;
	//Function: GetWindowTextA
	//Using : 该函数将指定窗口的标题条文本(如果存在)拷贝到一个缓存区内。如果指定的窗口是一个控件,则拷贝控件的文本。
	//但是,GetWindowText可能无法获取外部应用程序中控件的文本,获取自绘的控件或者是外部的密码编辑框很有可能会失败。
	//Return : 如果函数成功,返回值是拷贝的字符串的字符个数,不包括中断的空字符;
	//如果窗口无标题栏或文本,或标题栏为空,或窗口或控制的句柄无效,则返回值为零。
	GetWindowTextA(hwnd, lpWindowName, nMaxCount);
	GetClassNameA(hwnd, lpClassName, nMaxCount);

	cout << "[Parent window] window handle: " << hwnd << " window name: "
		<< lpWindowName << " class name: " << lpClassName << endl;
	EnumChildWindows(hwnd, EnumChildProc, lParam);

	return TRUE;
}

BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam) {
	//关于LPTSTR 打印乱码 
	/*
		1.首先 setlocale(LC_ALL, "chs");
		2.LPTSTR lpDeskName = lpszDesktop;
		3.printf("Desktop name:%s\n", lpDeskName);
	
	*/
	//setlocale(LC_ALL, "chs");
	LPTSTR lpDeskName = lpszDesktop;

	printf("Desktop name:%s\n", lpDeskName);
	EnumWindows(EnumWindowsProc, lParam);
	return TRUE;
}
//判断是否锁屏(0是没锁屏,1是锁屏)
bool IsSessionLocked()
{
	typedef BOOL(PASCAL* WTSQuerySessionInformation)(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR* ppBuffer, DWORD* pBytesReturned);
	typedef void (PASCAL* WTSFreeMemory)(PVOID pMemory);

	WTSINFOEXW* pInfo = NULL;
	WTS_INFO_CLASS wtsic = WTSSessionInfoEx;
	bool bRet = false;
	LPTSTR ppBuffer = NULL;
	DWORD dwBytesReturned = 0;
	LONG dwFlags = 0;
	WTSQuerySessionInformation pWTSQuerySessionInformation = NULL;
	WTSFreeMemory pWTSFreeMemory = NULL;

	HMODULE hLib = LoadLibrary(L"wtsapi32.dll");
	if (!hLib)
	{
		return false;
	}
	pWTSQuerySessionInformation = (WTSQuerySessionInformation)GetProcAddress(hLib, "WTSQuerySessionInformationW");
	if (pWTSQuerySessionInformation)
	{
		pWTSFreeMemory = (WTSFreeMemory)GetProcAddress(hLib, "WTSFreeMemory");
		if (pWTSFreeMemory != NULL)
		{
			DWORD dwSessionID = WTSGetActiveConsoleSessionId();
			if (pWTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionID, wtsic, &ppBuffer, &dwBytesReturned))
			{
				if (dwBytesReturned > 0)
				{
					pInfo = (WTSINFOEXW*)ppBuffer;
					if (pInfo->Level == 1)
					{
						dwFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
					}
					if (dwFlags == WTS_SESSIONSTATE_LOCK)
					{
						bRet = true;
					}
				}
				pWTSFreeMemory(ppBuffer);
				ppBuffer = NULL;
			}
		}
	}
	if (hLib != NULL)
	{
		FreeLibrary(hLib);
	}
	return bRet;
}

//模拟键盘点击(不能用在登录界面,屏蔽其他进程)
//没有支持的机制来解锁工作站。你将不得不编写一个自定义的GINA模块,然后以某种方式与之通信。
//对于标准GINA,您可以得到最接近的是做自动登录(例如使用Autologon tool from SysInternals)。
//但是,自动登录只能在机器重新启动后或用户注销后启动,因此用户会话将会丢失。
void key_hit() {
	keybd_event(VK_RETURN, 0, 0, 0);
	keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
	/*string temp = "123";
			for (int i = 0; i < temp.size(); i++) {
				keybd_event(record[temp[i]], 0, 0, 0);
				keybd_event(record[temp[i]], 0, KEYEVENTF_KEYUP, 0);
				cout << record[temp[i]] << endl;
			}
			keybd_event(VK_RETURN, 0, 0, 0);
			keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);*/

}
//锁屏(模拟win+l不行)
void lock_screen() {
	//cout << "请输入锁屏时间(秒)\n";
	float time = 5;
	//cin >> time;
	clock_t delay;
	delay = time * CLOCKS_PER_SEC;
	clock_t start = clock();
	cout << "计时开始时间:";
	string  v_s_start = getTime();
	cout << v_s_start << endl;
	threadCaller(time);
	//while(clock()-start<delay);
	system("rundll32.exe user32.dll,LockWorkStation");
}
//通过get Windows title,关闭Windows
void close_windows() {
	HWND m_handle = 0;
	int num = 0;
	while (m_handle == 0 && num < 60) {
		m_handle = ::FindWindowA(NULL, "Chat | Microsoft Teams");
		++num;
		Sleep(100);
	}
	if (m_handle != 0)
	{
		::SendMessageA(m_handle, WM_CLOSE, 0, 0);
	}
}
void MouseMove(int x, int y)
{
	double fScreenWidth = ::GetSystemMetrics(SM_CXSCREEN) - 1;
	double fScreenHeight = ::GetSystemMetrics(SM_CYSCREEN) - 1;
	double fx = x * (65535.0f / fScreenWidth);
	double fy = y * (65535.0f / fScreenHeight);
	INPUT Input = { 0 };
	Input.type = INPUT_MOUSE;
	Input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
	Input.mi.dx = fx;
	Input.mi.dy = fy;
	SendInput(1, &Input, sizeof(INPUT));
}
void MouseLeftDown() //鼠标左键按下
{
	INPUT Input = { 0 };
	Input.type = INPUT_MOUSE;
	Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
	SendInput(1, &Input, sizeof(INPUT));
}

void MouseLeftUp() //鼠标左键放开
{
	INPUT Input = { 0 };
	Input.type = INPUT_MOUSE;
	Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
	SendInput(1, &Input, sizeof(INPUT));
}

void MouseRightDown() //鼠标右键按下
{
	INPUT Input = { 0 };
	Input.type = INPUT_MOUSE;
	Input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
	SendInput(1, &Input, sizeof(INPUT));
}

void MouseRightUp() //鼠标右键放开
{
	INPUT Input = { 0 };
	Input.type = INPUT_MOUSE;
	Input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
	SendInput(1, &Input, sizeof(INPUT));
}
int main(int argc, char* argv[])
{
	/*
	枚举屏幕上的所有的顶层窗口,轮流地将这些窗口的句柄传递给一个应用程序定义的回调函数。
	EnumWindows会一直进行下去,直到枚举完所有的顶层窗口,或者回调函数返回了FALSE.
	*/
     Sleep(7 * 1000);
	//HWINSTA hwinsta = GetProcessWindowStation();
	//EnumDesktopsA(hwinsta,(DESKTOPENUMPROCA)EnumDesktopProc, 0);
	//EnumWindows(EnumWindowsProc, 0);//EnumWindowsProc EnumChildProc
	 close_windows();
	//cout<<IsSessionLocked()<<endl;
	//MouseMove(0.1,0.1);
	return 0;
}

API

EnumDesktopsA
EnumDesktopProc
EnumWindows
EnumWindowsProc

解释

EnumWindows有两个参数:

BOOL EnumWindows(
  WNDENUMPROC lpEnumFunc,
  LPARAM      lParam
);

其中,WNDENUMPROC指向应用程序定义的回调函数的指针。也就是EnumWindowsProc。
EnumWindowsProc是回调函数:

BOOL CALLBACK EnumWindowsProc(
  _In_ HWND   hwnd,
  _In_ LPARAM lParam
);

hwnd是窗口的句柄,lParam是在EnumWindows或EnumDesktopWindows中给定的应用程序定义的值。

根据代码,我在EnumWindowsProc的回调函数中,得到窗口的title后,再调用EnumDesktopsA函数。

BOOL EnumDesktopsA(
  HWINSTA          hwinsta,
  DESKTOPENUMPROCA lpEnumFunc,
  LPARAM           lParam
);

它的lpEnumFunc为EnumDesktopProc,但是,实际操作中,我不能直接写入会报转换类型错误,而WNDENUMPROC lpEnumFunc则不会。(这里我强转了一下可以了,以后可以看看为什么:))

BOOL CALLBACK EnumDesktopProc(
  _In_ LPTSTR lpszDesktop,
  _In_ LPARAM lParam
);

这里打印LPTSTR,它的不能正常打印。查看定义后,发现wchar_t类型,打印会出现乱码。我找到以下解决方法:
关于LPTSTR 打印乱码

	setlocale(LC_ALL, "chs");
    LPTSTR lpDeskName = lpszDesktop;
	printf("Desktop name:%s\n", lpDeskName);

具体可以看看代码:)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值