定义
电脑黑屏通常有两种定义,一种是指硬件黑屏,包括但不限于硬件故障、断电、显示器被硬件或软件关闭等;另一种是指系统层面上的黑屏,两种黑屏的最大差别就是系统层面上的黑屏会发光,而硬件黑屏则基本上不会。
这里讲的是使用C++进行系统层面上的黑屏。
为了读者能够不加修改的复现,这里使用的是Win32程序。
知识链接
C++ while 循环 | 菜鸟教程C++ while 循环 C++ 循环 只要给定的条件为真,while 循环语句会重复执行一个目标语句。 语法 C++ 中 while 循环的语法: while(condition) { statement(s); } 在这里,statement(s) 可以是一个单独的语句,也可以是几个语句组成的代码块。condition 可以是任意的表达式,当为任意非零值时都为真。当条件为真时执行循环。 当条件为假时,程序流将继续..https://www.runoob.com/cplusplus/cpp-while-loop.htmlGetDesktopWindow function (winuser.h) - Win32 apps | Microsoft DocsRetrieves a handle to the desktop window. The desktop window covers the entire screen. The desktop window is the area on top of which other windows are painted.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdesktopwindowGetWindowDC function (winuser.h) - Win32 apps | Microsoft DocsThe GetWindowDC function retrieves the device context (DC) for the entire window, including title bar, menus, and scroll bars.https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdcBitBlt function (wingdi.h) - Win32 apps | Microsoft DocsThe BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-bitblt
API详解
首先需要用到以下几个系统API。
- GetDesktopWindow
- GetWindowDC
- BitBlt
接下来一一讲解。
GetDesktopWindow
字面意思:获取桌面窗口,也就是获取桌面所属的窗口。
函数原型:
WINUSERAPI HWND WINAPI GetDesktopWindow(VOID);
调用此API后。将会返回一个系统桌面所对应的窗口句柄,可用HWND数据类型接收,如:
HWND hWnd = ::GetDesktopWindow();
在该程序中的意义:获取窗口句柄,以便获取DC。
GetWindowDC
字面意思:获取窗口的DC
函数原型:
WINUSERAPI HDC WINAPI GetWindowDC(_In_opt_ HWND hWnd);
调用此API,需要传入一个数据类型为HWND的窗口句柄,这个参数为要获取DC的窗口。
调用后返回一个类型为HDC的绘画控制版(DC),可以用于对窗口展现内容进行操作,如:
HDC hdc = ::GetWindowDC(hWnd);
在该程序中的意义:为后续向窗口绘制黑色内容作准备。
BitBlt
字面意思:比特复制
作用:将一个DC(绘画控制板)或预设中的内容复制到另一个DC。
误区:该API只会复制内容,而其他信息则会直接忽略。
函数原型:
WINGDIAPI BOOL WINAPI BitBlt( _In_ HDC hdc, _In_ int x, _In_ int y, _In_ int cx, _In_ int cy, _In_opt_ HDC hdcSrc, _In_ int x1, _In_ int y1, _In_ DWORD rop);
参数介绍:
hdc:传入一个类型为HDC的绘画控制板,表示将要复制内容到此的绘画控制板。
x、y:按顺序分别表示复制到目标绘画控制板的左上角的x、y坐标。
cx、cy:按顺序分别表示要复制的矩形的宽度、高度。
hdcSrc:同hdc,但是表示要复制的原绘画控制板,复制的内容来自这个绘画控制板。
x1、y1:按顺序分别表示要复制的原矩形的左上角的x和y坐标,宽度和高度由cx、cy决定。
rop:光栅操作代码。这些代码定义了如何将源矩形的颜色数据与目标矩形的颜色数据组合以实现最终颜色。
MSDN提供的操作代码:
很显然,由于我们需要让系统黑屏,需要使用 BLACKNESS这个宏,这是决定所复制的内容的关键。
具体实现
由于随时都可能有窗口被刷新,而刷新则会破坏掉我们所复制的环境,因此我们需要源源不断的使系统黑屏,那么使用死循环可能是最好的办法。
将我们前面所讲的结合起来,于是便得到了:
#include "stdafx.h"
#include "systemblack.h"
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
HWND hwnd = ::GetDesktopWindow(); //获取桌面句柄
HDC hdc = ::GetWindowDC(hwnd); //获取桌面上下文的句柄
while (1) //死循环
{
BitBlt(hdc, 0, 0,
GetSystemMetrics(SM_CXSCREEN),/*获取屏幕宽度*/
GetSystemMetrics(SM_CYSCREEN),/*获取屏幕高度*/
hdc, 0, 0, BLACKNESS);
}
return 0;
}
gitee仓库(带发行版):https://gitee.com/love-programming-of-yeyixiao/c-realize-system-black-screen
github仓库(带发行版):
GitHub - love-code-yeyixiao/systemblackscreen
虽然代码并不难,但打字耗时间啊,起码来个点赞吧。