C++截屏当前活动窗口保存成BMP文件以及BMP文件的比较

这篇博客介绍了如何使用C++快速截取并保存当前活动窗口为BMP文件,同时详细说明了如何进行BMP文件的比较,实测在处理1024 * 768尺寸的图片时,比较操作能在200ms内完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


#include <time.h>
#include <afxwin.h>
#include <stdio.h>
#include <comdef.h>
#include <iostream>
#include <atlimage.h>

/*
* hwnd:要截图的窗口的句柄
* fileName:要比较的图片的路径
* offsets:有4个成员的int型数组,用于设置比较图片时,上、下、左、右的偏移量
* offsets[0]:左
* offsets[1]:上
* offsets[2]:右
* offsets[3]:下
*/
bool print_screen(HWND hwnd, const char* fileName, int offsets[])
{
LPCTSTR pFileName = NULL;

if(sizeof(TCHAR)==sizeof(char))
{
pFileName=(LPCTSTR)fileName;
}
else
{
int length= sizeof(TCHAR)*(strlen(fileName)+1);
LPTSTR tcBuffer=new TCHAR[length];
memset(tcBuffer,0,length);
MultiByteToWideChar(CP_ACP,0,fileName,strlen(fileName),tcBuffer,length);
pFileName=(LPCTSTR)tcBuffer ;
}
long t_start = ::GetTickCount();
CDC dc;
CDC *pDC = &dc;//屏幕DC

// HWND hwnd = ::GetForegroundWindow(); // 获得当前活动窗口
HDC activeDC = ::GetWindowDC(hwnd); //获得要截屏的窗口的hDC

pDC->Attach(activeDC);//获取当前活动窗口的DC
RECT rect;
::GetWindowRect(hwnd,&rect);//得到窗口的大小
int Width = rect.right - rect.left;

int Height = rect.bottom - rect.top;

/*cout << "Width:" << Width << endl

<< "Height:" << Height << endl << endl;*/

CDC memDC;//内存DC

memDC.CreateCompatibleDC(pDC);

CBitmap memBitmap, *oldmemBitmap;//建立和屏幕兼容的bitmap

memBitmap.CreateCompatibleBitmap(pDC, Width, Height);

oldmemBitmap = memDC.SelectObject(&memBitmap);//将memBitmap选入内存DC

memDC.BitBlt(0, 0, Width, Height, pDC, 0, 0, SRCCOPY);//复制屏幕图像到内存DC
//以下代码保存memDC中的位图到文件

BITMAP bmp;

memBitmap.GetBitmap(&bmp);//获得位图信息

FILE *fp = fopen("C:\\abc.bmp", "w+b");
BITMAPINFOHEADER bih = {0};//位图信息头

bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小

bih.biCompression = BI_RGB;

bih.biHeight = bmp.bmHeight;//高度

bih.biPlanes = 1;

bih.biSize = sizeof(BITMAPINFOHEADER);

bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小

bih.biWidth = bmp.bmWidth;//宽度

BITMAPFILEHEADER bfh = {0};//位图文件头

bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//到位图数据的偏移量

bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;//文件总的大小

bfh.bfType = (WORD)0x4d42;

fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);//写入位图文件头

fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);//写入位图信息头

byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight];//申请内存保存位图数据

GetDIBits(memDC.m_hDC, (HBITMAP) memBitmap.m_hObject, 0, Height, p,

(LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据

fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);//写入位图数据

delete [] p;

fclose(fp);

// 以下代码用于比较指定的BMP文件与内存中的截图
CImage img;
img.Load(pFileName);
int nWidth = img.GetWidth();//获取图像宽度
int nHeight = img.GetHeight();//获取图像高度
if (Width != nWidth || Height != nHeight)
{
return false;
}
byte* pRealData;
pRealData=(byte*)img.GetBits();

int pit=img.GetPitch();

int bitCount=img.GetBPP()/8;

for (int y = offsets[1]; y < Height - offsets[3]; ++y)
{
for (int x = offsets[0]; x < Width - offsets[2]; ++x)
{
int pity = pit * y;
int pitx = x*bitCount;
if (up[bmp.bmWidth * (bmp.bmHeight - y - 1) + x] !=
(*(pRealData + pity + pitx + 2) << 16) + (*(pRealData + pity + pitx + 1) << 8) +
*(pRealData + pity + pitx))
{
printf("(%d, %d) = %x, ",x, y, up[bmp.bmWidth *
(bmp.bmHeight - y - 1) + x]);
printf("(%d, %d) = %x\n",x, y, (*(pRealData +
pity + pitx + 2) << 16) + (*(pRealData + pity + pitx + 1) << 8) + *(pRealData +
pity + pitx));
return false;
}
}
}
return true;
}

/*
* hwnd:要截图的窗口的句柄
* fileName:要比较的图片的路径
* left:比较图片时的左偏移量
* top:比较图片时的上偏移量
* right:比较图片时的右偏移量
* bottom:比较图片时的下偏移量
*/
int screenPrint(HWND hwnd, const char* fileName, int left, int top, int right, int bottom)
{
if (left < 0 || top < 0 || right < 0 || bottom < 0)
{
return -1;
}
int offsets[4];
offsets[0] = left;
offsets[1] = top;
offsets[2] = right;
offsets[3] = bottom;
bool isTheSame = print_screen(hwnd, fileName, offsets);
if (isTheSame)
{
return 0;
}
else
{
return -1;
}
}

速度尚可,比较两张1024 * 768的图片,耗时200ms以内
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值