工作中遇到一个需求,需要在用户操作过后,需要截图来确认用户操作过后,真实的呈现结果,用来后期验证
直接上代码
直接使用,修改自己需要捕获的窗口名字就可以了
OnBnClickedBtUpimage(){
CString strPathTmp;
GetAppPath(strPathTmp);//获取当前程序的路径
char szpath[MAX_PATH] = {0};
//控件大小和位置
CRect r1;
CoverCStringToChar(strPathTmp+_T("jietu.png"),szpath,MAX_PATH);
//根据窗口名字获取窗口位置
HWND hwnd=::FindWindow(NULL,_T("CarCps")); //后面一个参数是窗口名称
::GetWindowRect(hwnd, r1);
Screenbmp(hwnd, 0 ,0 , r1.Width(), r1.Height(),szpath);
}
两个工具方法
获取工程安装路径
void GetAppPath(CString &path)
{
TCHAR szPath[MAX_PATH] = {0};
TCHAR szDrive[MAX_PATH] = {0};
TCHAR szDir[MAX_PATH] = {0};
TCHAR szFname[MAX_PATH] = {0};
TCHAR szExt[MAX_PATH] = {0};
//CString strPath;
CString strDrive;
CString strDir;
GetModuleFileName(NULL,szPath,MAX_PATH);
_wsplitpath(szPath,szDrive,szDir,szFname,szExt);
strDrive.Format(_T("%s"),szDrive);
strDir.Format(_T("%s"),szDir);
path = strDrive + strDir;
}
//字符转换
int CoverCStringToChar(const CString &strsrc,char *szdet,int len)
{
int n = strsrc.GetLength();
//获取宽字节字符的大小,大小是按字节计算的
int lenByte = WideCharToMultiByte(CP_ACP, 0, strsrc, n, NULL, 0, NULL, NULL);
if ((len - 1) < lenByte)
{
lenByte = len - 1;
}
//宽字节编码转换成多字节编码
WideCharToMultiByte(CP_ACP, 0, strsrc, n, szdet, lenByte, NULL, NULL);
return 0;
}
实际截图的方法
//输入目标窗口的句柄、左上角的位置以及截图的长宽和保存地址(左上角位置以目标窗口为基准)
void Screenbmp(HWND hwnd, int left, int top, int width, int height, CHAR* path){
//1、获得指定窗口的dc(源dc)
//注意GetWindowDC会把窗口的标题栏也同时截图,如果不需要窗口的标题就使用GetDC(hwnd)
HDC sourceDC= GetWindowDC(hwnd);
//2、根据源dc创建兼容内存DC
HDC momDC;//内存DC
momDC = ::CreateCompatibleDC(sourceDC);
//3、根据源dc创建兼容位图
HBITMAP memBitmap;
memBitmap = ::CreateCompatibleBitmap(sourceDC, width, height);
//4、将兼容位图写入内存dc
SelectObject(momDC, memBitmap);
//5、截图
BitBlt(momDC, 0, 0, width, height, sourceDC, left, top, SRCCOPY);
//6、以下代码保存截图信息到文件中
//6.1获得位图信息
BITMAP bmp;
GetObject(memBitmap, sizeof(BITMAP), &bmp);
//6.2图片保存路径和方式
FILE* fp;
fopen_s(&fp, path, "w+b");
//6.3创建位图文件头
//位图文件头设置默认值为0
BITMAPFILEHEADER bfh = { 0 };
//到位图数据的偏移量(此步骤固定,位图编译量即为位图文件头+位图信息头+调色板的大小,调色板设置为0)
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
//文件总的大小
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;
//bfType固定为BM,(WORD)0x4d42表示为BM
bfh.bfType = (WORD)0x4d42;
//6.4创建文件信息头
//位图信息头,默认设置为0
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;
//6.5写入位图文件头
fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);
//6.6写入位图信息头
fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);
//6.7申请内存保存位图数据
byte* p = new byte[bmp.bmWidthBytes * bmp.bmHeight];
//6.8获取位图数据
GetDIBits(momDC, (HBITMAP)memBitmap, 0, height, p,
(LPBITMAPINFO)&bih, DIB_RGB_COLORS);
//6.9写入位图数据
fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);
//6.10先删除开辟的内存,然后关闭文件
delete[] p;
fclose(fp);
//7删除链接
//7.1删除创建的位图
DeleteObject(memBitmap);
//7.2删除创建的兼容内存DC
DeleteDC(momDC);
//7.3#释放窗口DC
ReleaseDC(hwnd, sourceDC);
}
//以下方法可用获取鼠标当前指向的控件,可以小到一个按钮控件
HWND GetCurPointedWindow()
{
POINT point;
BOOL ret = GetCursorPos(&point);
if (ret) {
HWND hwnd = WindowFromPoint(point);
if (hwnd != nullptr && hwnd != INVALID_HANDLE_VALUE) {
return hwnd;
}
}
return nullptr;
}