Windows实现防截屏--方式一

所用函数:SetWindowDisplayAffinity,通过获取窗口句柄,设置第二个参数,如果第二个参数为WDA_MONITOR表示将开关打开,当前进程的窗体就会变黑。程序结束时,记得将参数恢复为WDA_NONE。

注意:

  1. 只对当前进程有效
  2. 有系统限制:

核心代码(MFC程序:有个按钮):

void CMFCApplication2Dlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	HWND hwnd = ::FindWindow(NULL, L"MFC");
	if (hwnd != NULL)
	{
		CString tempstr;
		GetDlgItem(IDC_BUTTON1)->GetWindowText(tempstr);
		BOOL temp = FALSE;
		if (tempstr == "打开") {
			temp=SetWindowDisplayAffinity(hwnd, WDA_MONITOR);
			GetDlgItem(IDC_BUTTON1)->SetWindowText(L"关闭");
		}
		else {
			temp=SetWindowDisplayAffinity(hwnd, WDA_NONE);
			GetDlgItem(IDC_BUTTON1)->SetWindowText(L"打开");
		}

		if(!temp) {
			char szError[256];
			DWORD dwError = GetLastError();
			FormatMessage(
				FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				dwError,
				0,
				(LPWSTR)szError,
				sizeof(szError),
				NULL);
			//AfxMessageBox(szError);
			::MessageBox(0, (LPCTSTR)szError, NULL, NULL);
		}
	}
}

实现效果

将开关打开后:

还可以设置透明度,具体可以搜索函数用法。

 

因为只对当前进程有用,所以想对某个进程使用此函数,可以用dll注入的方式来实现。

64位和32位的都需要生成一下。

最好在虚拟机里面试验,我实验了一下,确实成功了,但是很卡

dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <windows.h>
#include <vector>
std::vector<HWND>ProtectedWindowsHwnd;
HHOOK h_msghook = NULL;
HHOOK h_callhook = NULL;
HINSTANCE ghInstance = NULL;
VOID SetWindowsDisplayStart()
{
    //遍历可见窗口得到窗口句柄
	HWND hwnd = NULL;
	DWORD dwpid = 0;
	hwnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
	if (NULL != hwnd)
	{
		hwnd = ::GetWindow(hwnd, GW_HWNDLAST);
		while (hwnd)
		{
			if (::GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE)//窗口必须可见
			{
				::GetWindowThreadProcessId(hwnd, &dwpid);
				SetWindowDisplayAffinity(hwnd, WDA_MONITOR);
                //没有存在过就加进去
				if (std::find(ProtectedWindowsHwnd.begin(), ProtectedWindowsHwnd.end(), hwnd) == ProtectedWindowsHwnd.end())
						ProtectedWindowsHwnd.push_back(hwnd);
			}
			hwnd = ::GetWindow(hwnd, GW_HWNDPREV);
		}
	}
}

VOID SetWindowsDisplayEnd()
{
	std::vector<HWND>::iterator it;
	for (it = ProtectedWindowsHwnd.begin(); it != ProtectedWindowsHwnd.end(); it++)
		if (NULL != *it)
			SetWindowDisplayAffinity(*it, WDA_NONE);
}

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		ghInstance = hModule;
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		SetWindowsDisplayEnd();
		//主动广播消息,用来触发消息钩子执行卸载操作
		PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
		break;
	}
	return TRUE;
}
LRESULT CALLBACK GetMsgProc(
	_In_ int    code,
	_In_ WPARAM wParam,
	_In_ LPARAM lParam
)
{
	SetWindowsDisplayStart();
	return CallNextHookEx(h_msghook, code, wParam, lParam);//继续传递消息
}

LRESULT CALLBACK CallWndProc(
	_In_ int    code,
	_In_ WPARAM wParam,
	_In_ LPARAM lParam
)
{

	SetWindowsDisplayStart();
	return CallNextHookEx(h_callhook, code, wParam, lParam);//继续传递消息
}
extern "C"
{
	__declspec(dllexport) void HookStart()
	{
		h_msghook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, ghInstance, 0);//WH_GETMESSAGE Hook只拦截由GetMessage or PostMessage PeekMessage的队列消息。
		h_callhook = SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, ghInstance, 0);//专门用来截获通过SendMessage()函数发送到窗口的消息
		//同步:SendMessage函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。
		//异步:而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。
		ProtectedWindowsHwnd.clear();
	}
	__declspec(dllexport) void HookStop()
	{
		if (h_msghook)
		{
			UnhookWindowsHookEx(h_msghook);
			h_msghook = NULL;
		}
		if (h_callhook)
		{
			UnhookWindowsHookEx(h_callhook);
			h_callhook = NULL;
		}
		ProtectedWindowsHwnd.clear();
	}
}

需要加载器去加载:

// hookdlltext64.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <windows.h>
#include <iostream>
typedef  void(*PFNHOOKSTART)();
typedef  void(*PFNHOOKSTOP)();
int main()
{
	std::cout << "输入回车开始" << std::endl;
	getchar();
#ifdef _AMD64_
	HMODULE hmod = ::LoadLibrary(L"C:\\Protect\\win64\\SetWindowDisplayAffityTest.dll");
#else
	HMODULE hmod = ::LoadLibrary(L"C:\\Protect\\win32\\SetWindowDisplayAffityTest.dll");
#endif
	if (NULL != hmod)
	{
		PFNHOOKSTART qHookStart = (PFNHOOKSTART)GetProcAddress(hmod, "HookStart");
		PFNHOOKSTOP qHookStop = (PFNHOOKSTOP)GetProcAddress(hmod, "HookStop");
		qHookStart();
		std::cout << "输入回车结束" << std::endl;
		getchar();
		qHookStop();
		FreeLibrary(hmod);
	}
	return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

以上如果有误,欢迎指正。

 

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值