目录
方法二常用一点。
效果:
如图

方法一:
思路:获取屏幕图像,反色后,设置为壁纸。
头文件:#include <windows.h>
#include <vector.h>
#include <cstdio>
#include <string>
#include <tchar.h>
代码:(调用Screenshot反转颜色)
BOOL GetHDCData(HDC hdc, const RECT& rcDC, std::vector<BYTE>& vtBuf)
{
BOOL bRes = FALSE;
HBITMAP hBmp = NULL;
HDC hdcMem = NULL;
__try
{
//Initilaize the bitmap information
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = rcDC.right - rcDC.left;
bmpInfo.bmiHeader.biHeight = rcDC.bottom - rcDC.top;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
//Create the compatible DC to get the data
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem == NULL)
{
//ASSERT(FALSE);
//RETAILMSG(TRUE,(TEXT("CreateCompatibleDC failed! Error Code:0x%x\r\n"),GetLastError()));
__leave;
}
//Get the data from the memory DC
BYTE* pData = NULL;
hBmp = CreateDIBSection(hdcMem, &bmpInfo, DIB_RGB_COLORS, reinterpret_cast<VOID**>(&pData), NULL, 0);
if (hBmp == NULL)
{
//ASSERT(FALSE);
//RETAILMSG(TRUE,(TEXT("CreateDIBSection failed! Error Code:0x%x\r\n"),GetLastError()));
__leave;
}
HGDIOBJ hOldObj = SelectObject(hdcMem, hBmp);
//Draw to the memory DC
SIZE sizeImg = { bmpInfo.bmiHeader.biWidth,bmpInfo.bmiHeader.biHeight };
SIZE sizeDC = { rcDC.right - rcDC.left,rcDC.bottom - rcDC.top };
StretchBlt(hdcMem,
0,
0,
sizeImg.cx,
sizeImg.cy,
hdc,
rcDC.left,
rcDC.top,
sizeDC.cx,
sizeDC.cy,
SRCCOPY);
vtBuf.resize(sizeImg.cx * sizeImg.cy * 3);
memcpy(&vtBuf[0], pData, vtBuf.size());
SelectObject(hdcMem, hOldObj);
bRes = TRUE;
}
__finally
{
if (hBmp != NULL)
{
DeleteObject(hBmp);
}
if (hdcMem != NULL)
{
DeleteDC(hdcMem);
}
}
return bRes;
}
// 保存HDC为BMP文件
BOOL WriteBmp(const string strFile, HDC hdc, const RECT& rcDC)
{
std::vector<BYTE> vtData;
if (GetHDCData(hdc, rcDC, vtData) == FALSE)
{
return FALSE;
}
SIZE sizeImg = { rcDC.right - rcDC.left,rcDC.bottom - rcDC.top };
BITMAPINFOHEADER bmInfoHeader = { 0 };
bmInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfoHeader.biWidth = sizeImg.cx;
bmInfoHeader.biHeight = sizeImg.cy;
bmInfoHeader.biPlanes = 1;
bmInfoHeader.biBitCount = 24;
//Bimap file header in order to write bmp file
BITMAPFILEHEADER bmFileHeader = { 0 };
bmFileHeader.bfType = 0x4d42; //bmp
bmFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmFileHeader.bfSize = bmFileHeader.bfOffBits + ((bmInfoHeader.biWidth * bmInfoHeader.biHeight) * 3); ///3=(24 / 8)
HANDLE hFile = CreateFile(C2LW(strFile.c_str()), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
DWORD dwWrite = 0;
WriteFile(hFile, &bmFileHeader, sizeof(BITMAPFILEHEADER), &dwWrite, NULL);
WriteFile(hFile, &bmInfoHeader, sizeof(BITMAPINFOHEADER), &dwWrite, NULL);
WriteFile(hFile, &vtData[0], vtData.size(), &dwWrite, NULL);
CloseHandle(hFile);
return TRUE;
}
int InvertImage(const char* srcImage, const char* destIMage, int iFlag)
{
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bmiHeader;
int i;
FILE* pFile;
if ((pFile = fopen(srcImage, "rb")) == NULL)
{
printf("open bmp file error.");
exit(-1);
}
//读取文件和Bitmap头信息
fseek(pFile, 0, SEEK_SET);
fread(&bmfHeader, sizeof(BITMAPFILEHEADER), 1, pFile);
fread(&bmiHeader, sizeof(BITMAPINFOHEADER), 1, pFile);
//先不支持小于16位的位图
int bitCount = bmiHeader.biBitCount;
if (bitCount < 16)
{
printf("Image format is error!");
exit(-1);
}
int srcW = bmiHeader.biWidth;//宽度,多少像素点
int srcH = bmiHeader.biHeight;//高度
int lineSize = bitCount * srcW / 8;
//偏移量,windows系统要求每个扫描行按四字节对齐
//int alignBytes = ((bmiHeader.biWidth * bitCount + 31) & ~31) / 8L
//- bmiHeader.biWidth * bitCount / 8L;
int srcLine = ((srcW * bitCount + 31) / 32) * 4;
//int srcBufLine = srcLine * srcH;
int srcBufSize = srcLine * srcH;
BYTE* srcBuf = (BYTE*)malloc(srcBufSize);
if (!srcBuf) {
printf("Malloc memory fail!");
exit(-1);
}
for (i = 0; i < srcH; i++) {
fread(&srcBuf[i * srcLine], srcLine, 1, pFile);
//fseek(pFile, alignBytes, SEEK_CUR);
}
//iFlag equal 1 表示灰度
if (iFlag) {
for (i = 0; i < srcH; i++) {
for (int j = 0; j < srcW; j++) {
int k = (srcBuf[i * srcLine + j * bitCount / 8 + 0] +
srcBuf[i * srcLine + j * bitCount / 8 + 1] +
srcBuf[i * srcLine + j * bitCount / 8 + 2]) / 3;
srcBuf[i * srcLine + j * bitCount / 8 + 0] = k;
srcBuf[i * srcLine + j * bitCount / 8 + 1] = k;
srcBuf[i * srcLine + j * bitCount / 8 + 2] = k;
}
}
}
else {//反色
for (i = 0; i < srcH; i++) {
for (int j = 0; j < srcW; j++) {
for (int k = 0; k < 3; k++) {
srcBuf[i * srcLine + j * bitCount / 8 + k] =
abs(srcBuf[i * srcLine + j * bitCount / 8 + k] - 255);
}
}
}
}
HFILE hfile = _lcreat(destIMage, 0);
//写入文件头信息
_lwrite(hfile, (LPCSTR)&bmfHeader, sizeof(BITMAPFILEHEADER));
//写入Bitmap头信息
_lwrite(hfile, (LPCSTR)&bmiHeader, sizeof(BITMAPINFOHEADER));
//写入图像数据
_lwrite(hfile, (LPCSTR)srcBuf, srcBufSize);
_lclose(hfile);
fclose(pFile);
free(srcBuf);
return 0;
}
enum WallpaperStyle
{
Tile,//平铺
Center,//居中
Stretch,//拉伸
Fit, //适应
Fill//填充
};
HRESULT SetDesktopWallpaper(LPCSTR pszFile, WallpaperStyle style)
{
HRESULT hr = S_OK;
//设置壁纸风格和展开方式
//在Control Panel\Desktop中的两个键值将被设置
// TileWallpaper
// 0: 图片不被平铺
// 1: 被平铺
// WallpaperStyle
// 0: 0表示图片居中,1表示平铺
// 2: 拉伸填充整个屏幕
// 6: 拉伸适应屏幕并保持高度比
// 10: 图片被调整大小裁剪适应屏幕保持纵横比
//以可读可写的方式打开HKCU\Control Panel\Desktop注册表项
HKEY hKey = NULL;
//更改注册表以更改展开方式
hr = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CURRENT_USER,
_T("Control Panel\\Desktop"), 0, KEY_READ | KEY_WRITE, &hKey));
if (SUCCEEDED(hr))
{
LPCSTR pszWallpaperStyle = "2";
LPCSTR pszTileWallpaper = "0";
switch (style)
{
case Tile:
pszWallpaperStyle = "0";
pszTileWallpaper = "1";
break;
case Center:
pszWallpaperStyle = "0";
pszTileWallpaper = "0";
break;
case Stretch:
pszWallpaperStyle = "2";
pszTileWallpaper = "0";
break;
case Fit: // (Windows 7 and later)
pszWallpaperStyle = "6";
pszTileWallpaper = "0";
break;
case Fill: // (Windows 7 and later)
pszWallpaperStyle = "10";
pszTileWallpaper = "0";
break;
}
// 设置 WallpaperStyle 和 TileWallpaper 到注册表项.
DWORD cbData = lstrlen(pszWallpaperStyle) * sizeof(*pszWallpaperStyle);
hr = HRESULT_FROM_WIN32(RegSetValueExA(hKey, "WallpaperStyle", 0, REG_SZ,
reinterpret_cast<const BYTE*>(pszWallpaperStyle), cbData));
if (SUCCEEDED(hr))
{
cbData = lstrlen(pszTileWallpaper) * sizeof(*pszTileWallpaper);
hr = HRESULT_FROM_WIN32(RegSetValueExA(hKey, "TileWallpaper", 0, REG_SZ,
reinterpret_cast<const BYTE*>(pszTileWallpaper) , cbData));
}
RegCloseKey(hKey);
}
if (SUCCEEDED(hr))
{
//调用windows api函数实现更改壁纸
if (!SystemParametersInfo(SPI_SETDESKWALLPAPER, 0,(PVOID)pszFile, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
return hr;
}
void Screenshot() {
DeleteFileA(_T("C:\\1.bmp"));
DeleteFileA(_T("C:\\2.bmp"));
HDC hdc1 = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
RECT szrc1 = { 0,0,GetDeviceCaps(hdc,HORZRES),GetDeviceCaps(hdc,VERTRES) };
WriteBmp("C:\\1.bmp", hdc1, szrc1);
InvertImage("C:\\1.bmp", "C:\\2.bmp", 0);//将1.bmp反色,得到2.bmp
DeleteDC(hdc);
Sleep(100);
SetDesktopWallpaper("C:\\2.bmp", Stretch);//设置壁纸为2.bmp
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)_T("C:\\2.bmp"), SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}方法二:
将屏幕颜色反转,包括所有窗口。
void InvertColor() {
HDC hdc = GetDC(0);
BitBlt(hdc, 0, 0, cx, cy, hdc, 0, 0, NOTSRCCOPY);
}是不是很简单?但是容易被刷新掉。
VS2019环境下编译运行成功。
版权声明:本文为larwar原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。