C语言 屏幕截图 (GDI)

摘要:
hbmScreen){echo;gotodone;}//将位图块传送到我们兼容的内存DC中SelectObject;if(!*/截取指定窗口#includevoidecho(CH

截取全屏幕

#include <windows.h>
voidecho(CHAR*str);
intCaptureImage(HWNDhWnd, CHAR*dirPath, CHAR*filename);
intmain()
{
echo(TEXT("Ready"));
CaptureImage(GetDesktopWindow(), "E:", "screen"); // 保存为 E:screen.bmp
echo(TEXT("end"));
return0;
}
/**
* 调试输出
*/
voidecho(CHAR*str)
{
MessageBox(NULL, str, NULL, MB_OK);
}
/**
* GDI 截屏函数
*
* 参数 hwnd 要截屏的窗口句柄
* 参数 dirPath 截图存放目录
* 参数 filename 截图名称
*/
intCaptureImage(HWNDhwnd, CHAR*dirPath, CHAR*filename)
{
HANDLEhDIB;
HANDLEhFile;
DWORDdwBmpSize;
DWORDdwSizeofDIB;
DWORDdwBytesWritten;
CHARFilePath[MAX_PATH];
HBITMAPhbmScreen = NULL;
BITMAP bmpScreen;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
CHAR*lpbitmap;
INTwidth = GetSystemMetrics(SM_CXSCREEN); // 屏幕宽
INTheight = GetSystemMetrics(SM_CYSCREEN); // 屏幕高
HDChdcScreen = GetDC(NULL); // 全屏幕DC
HDChdcMemDC = CreateCompatibleDC(hdcScreen); // 创建兼容内存DC
if(!hdcMemDC)
{
echo(TEXT("CreateCompatibleDC has failed"));
gotodone;
}
// 通过窗口DC 创建一个兼容位图
hbmScreen = CreateCompatibleBitmap(hdcScreen, width, height);
if(!hbmScreen)
{
echo(TEXT("CreateCompatibleBitmap Failed"));
gotodone;
}
// 将位图块传送到我们兼容的内存DC中
SelectObject(hdcMemDC, hbmScreen);
if(!BitBlt(
hdcMemDC, // 目的DC
0, 0, // 目的DC的 x,y 坐标
width, height, // 目的 DC 的宽高
hdcScreen, // 来源DC
0, 0, // 来源DC的 x,y 坐标
SRCCOPY)) // 粘贴方式
{
echo(TEXT("BitBlt has failed"));
gotodone;
}
// 获取位图信息并存放在 bmpScreen 中
GetObject(hbmScreen, sizeof(BITMAP), &bmpScreen);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
// 在 32-bit Windows 系统上, GlobalAlloc 和 LocalAlloc 是由 HeapAlloc 封装来的
// handle 指向进程默认的堆. 所以开销比 HeapAlloc 要大
hDIB = GlobalAlloc(GHND, dwBmpSize);
lpbitmap = (char*)GlobalLock(hDIB);
// 获取兼容位图的位并且拷贝结果到一个 lpbitmap 中.
GetDIBits(
hdcScreen, // 设备环境句柄
hbmScreen, // 位图句柄
0, // 指定检索的第一个扫描线
(UINT)bmpScreen.bmHeight, // 指定检索的扫描线数
lpbitmap, // 指向用来检索位图数据的缓冲区的指针
(BITMAPINFO *)&bi, // 该结构体保存位图的数据格式
DIB_RGB_COLORS // 颜色表由红、绿、蓝(RGB)三个直接值构成
);
wsprintf(FilePath, "%s\%s.bmp", dirPath, filename);
// 创建一个文件来保存文件截图
hFile = CreateFile(
FilePath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
// 将 图片头(headers)的大小, 加上位图的大小来获得整个文件的大小
dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// 设置 Offset 偏移至位图的位(bitmap bits)实际开始的地方
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
// 文件大小
bmfHeader.bfSize = dwSizeofDIB;
// 位图的 bfType 必须是字符串 "BM"
bmfHeader.bfType = 0x4D42; //BM
dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
// 解锁堆内存并释放
GlobalUnlock(hDIB);
GlobalFree(hDIB);
// 关闭文件句柄
CloseHandle(hFile);
// 清理资源
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL, hdcScreen);
return0;
}
/**
*其实这样截取出来的图片会过大,而且效率也不是很高,如果要改善这个情况的话,需要重新写一
*个拷贝函数,因为没有必要每一个颜色(bit)全都拷贝出来,过滤到很多再拷贝的话程序效率会更高,
*而且图片也会更小,唯一就是图片质量可能会下降。
*/

截取指定窗口

#include <windows.h>
voidecho(CHAR*str);
intCaptureImage(HWNDhWnd, CHAR*dirPath, CHAR*filename);
intmain()
{
echo("准备截图");
CaptureImage(GetDesktopWindow(), "E:", "hello"); // 保存为 E:hello.bmp
echo("截图结束");
return0;
}
/**
* 调试输出
*/
voidecho(CHAR*str)
{
MessageBox(NULL, str, NULL, MB_OK);
}
/**
* GDI 截取指定窗口
*
* 参数 hwnd 要截屏的窗口句柄
* 参数 dirPath 截图存放目录
* 参数 filename 截图名称
*/
intCaptureImage(HWNDhwnd, CHAR*dirPath, CHAR*filename)
{
HDCmdc;
HBITMAPhbmp;
CHARFilePath[MAX_PATH];
HDChdcScreen;
HDChdcWindow;
HDChdcMemDC = NULL;
HBITMAPhbmScreen = NULL;
BITMAP bmpScreen;
RECT rcClient;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
DWORDdwBmpSize;
HANDLEhDIB;
CHAR*lpbitmap;
HANDLEhFile;
DWORDdwSizeofDIB;
DWORDdwBytesWritten;
hdcScreen = GetDC(NULL); // 全屏幕DC
hdcWindow = GetDC(hwnd); // 截图目标窗口DC
// 创建兼容内存DC
hdcMemDC = CreateCompatibleDC(hdcWindow);
if(!hdcMemDC)
{
echo(TEXT("CreateCompatibleDC has failed"));
gotodone;
}
// 获取客户端区域用于计算大小
GetClientRect(hwnd, &rcClient);
// 设置延展模式
SetStretchBltMode(hdcWindow, HALFTONE);
// 来源 DC 是整个屏幕而目标 DC 是当前的窗口 (HWND)
if(!StretchBlt(hdcWindow,
0,0,
rcClient.right, rcClient.bottom,
hdcScreen,
0,0,
GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN),
SRCCOPY))
{
echo(TEXT("StretchBlt has failed"));
gotodone;
}
// 通过窗口DC 创建一个兼容位图
hbmScreen = CreateCompatibleBitmap(
hdcWindow,
rcClient.right-rcClient.left,
rcClient.bottom-rcClient.top
);
if(!hbmScreen)
{
echo(TEXT("CreateCompatibleBitmap Failed"));
gotodone;
}
// 将位图块传送到我们兼容的内存DC中
SelectObject(hdcMemDC,hbmScreen);
if(!BitBlt(
hdcMemDC, // 目的DC
0,0, // 目的DC的 x,y 坐标
rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, // 目的 DC 的宽高
hdcWindow, // 来源DC
0,0, // 来源DC的 x,y 坐标
SRCCOPY)) // 粘贴方式
{
echo(TEXT("BitBlt has failed"));
gotodone;
}
// 获取位图信息并存放在 bmpScreen 中
GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
// 在 32-bit Windows 系统上, GlobalAlloc 和 LocalAlloc 是由 HeapAlloc 封装来的
// handle 指向进程默认的堆. 所以开销比 HeapAlloc 要大
hDIB = GlobalAlloc(GHND,dwBmpSize);
lpbitmap = (char*)GlobalLock(hDIB);
// 获取兼容位图的位并且拷贝结果到一个 lpbitmap 中.
GetDIBits(
hdcWindow, // 设备环境句柄
hbmScreen, // 位图句柄
0, // 指定检索的第一个扫描线
(UINT)bmpScreen.bmHeight, // 指定检索的扫描线数
lpbitmap, // 指向用来检索位图数据的缓冲区的指针
(BITMAPINFO *)&bi, // 该结构体保存位图的数据格式
DIB_RGB_COLORS // 颜色表由红、绿、蓝(RGB)三个直接值构成
);
wsprintf(FilePath, "%s\%s.bmp", dirPath, filename);
// 创建一个文件来保存文件截图
hFile = CreateFile(
FilePath,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
// 将 图片头(headers)的大小, 加上位图的大小来获得整个文件的大小
dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// 设置 Offset 偏移至位图的位(bitmap bits)实际开始的地方
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
// 文件大小
bmfHeader.bfSize = dwSizeofDIB;
// 位图的 bfType 必须是字符串 "BM"
bmfHeader.bfType = 0x4D42; //BM
dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
// 解锁堆内存并释放
GlobalUnlock(hDIB);
GlobalFree(hDIB);
// 关闭文件句柄
CloseHandle(hFile);
// 清理资源
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL,hdcScreen);
ReleaseDC(hwnd,hdcWindow);
return0;
}

免责声明:文章转载自《C语言 屏幕截图 (GDI)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇linux命令&amp;lt;服务进程、查看日志、文件编辑、赋权等&amp;gt;elk部署(实战一)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

获取DOS命令的返回值.

procedure CheckResult(b: Boolean);begin  if not b then    raise Exception.Create(SysErrorMessage(GetLastError));end;function RunDOS(const Prog, CommandLine, Dir: string; var Exit...

C指针——C语言手记

近期敲代码的时候。发现自己非常多东西都開始忘了。 今天最终有机会好好总结一下指针。当做个笔记同一时候也希望对大家实用。假设有不对的地方。希望大家能帮我指正一下。然后我的实验环境是32位RHEL+eclipse。 一、指针基本属性 指针的属性主要包含指针的类型、指针所指向的类型、指针的值。以下以一个简单的样例为例 int *p; 指针的类型:int *...

针对TCP连接异常断开的分析

我们知道,一个基于TCP/IP的客户端-服务器的程序中,正常情况下,我会是启动服务器使其在一个端口上监听请求,等待客户端的连接;通过TCP的三次握手,客户端能够通过socket建立一个到服务器的连接;然后,两者就可以基于这个socket连接通信了。连接结束后,客户端(进程)会退出;在不需要继续处理客户请求的情况下,服务器(进程)也将退出。而且,当一个进程退...

Linux C语言中gotoxy函数

在Linux中很多函数都不能使用,gotoxy就是其中的一个 实现方法: void gotoxy(int x,int y) { printf("%c[%d;%df",0x1B,y,x); }  解析: ANSI转义序列,很多类unix的终端,包括linux控制台都解释ANSI转义序列,转义符就是ESC,ASCII码是0x1b,比如...

linux系统socket通信编程1

Linux下的Socket编程大体上包括Tcp Socket、Udp Socket即Raw Socket这三种,其中TCP和UDP方式的Socket编程用于编写应用层的socket程序,是我们用得比较多的,而Raw Socket则用得相对较少,不在本文介绍范围之列。 TCP Socket 基于TCP协议的客户端/服务器程序的一般流程一般如下: 它基本上可...

CImageList使用指南

在MFC中CImageList类封装了图像列表控件的功能,图像列表是一个具有相同大小的图像(可以是不同类型)的集合,其主要用于应用程序中大规模图标的存储。该控件是不可见的,通常与其它如CListBox,CComboBox,CComboBoxEx,CTabCtrl以及CTreeCtrl一起使用,为他们提供图标资源。 图象的每个集合中均以0为图象索引基数,可以...