C语言 屏幕截图 (GDI)
截取全屏幕
#include <windows.h>
void
echo(
CHAR
*str);
int
CaptureImage(
HWND
hWnd,
CHAR
*dirPath,
CHAR
*filename);
int
main()
{
echo(TEXT(
"Ready"
));
CaptureImage(GetDesktopWindow(),
"E:\", "
screen");
// 保存为 E:screen.bmp
echo(TEXT(
"end"
));
return
0;
}
/**
* 调试输出
*/
void
echo(
CHAR
*str)
{
MessageBox(NULL, str, NULL, MB_OK);
}
/**
* GDI 截屏函数
*
* 参数 hwnd 要截屏的窗口句柄
* 参数 dirPath 截图存放目录
* 参数 filename 截图名称
*/
int
CaptureImage(
HWND
hwnd,
CHAR
*dirPath,
CHAR
*filename)
{
HANDLE
hDIB;
HANDLE
hFile;
DWORD
dwBmpSize;
DWORD
dwSizeofDIB;
DWORD
dwBytesWritten;
CHAR
FilePath[MAX_PATH];
HBITMAP
hbmScreen = NULL;
BITMAP bmpScreen;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
CHAR
*lpbitmap;
INT
width = GetSystemMetrics(SM_CXSCREEN);
// 屏幕宽
INT
height = GetSystemMetrics(SM_CYSCREEN);
// 屏幕高
HDC
hdcScreen = GetDC(NULL);
// 全屏幕DC
HDC
hdcMemDC = CreateCompatibleDC(hdcScreen);
// 创建兼容内存DC
if
(!hdcMemDC)
{
echo(TEXT(
"CreateCompatibleDC has failed"
));
goto
done;
}
// 通过窗口DC 创建一个兼容位图
hbmScreen = CreateCompatibleBitmap(hdcScreen, width, height);
if
(!hbmScreen)
{
echo(TEXT(
"CreateCompatibleBitmap Failed"
));
goto
done;
}
// 将位图块传送到我们兼容的内存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"
));
goto
done;
}
// 获取位图信息并存放在 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);
return
0;
}
截取指定窗口
#include <windows.h>
void
echo(
CHAR
*str);
int
CaptureImage(
HWND
hWnd,
CHAR
*dirPath,
CHAR
*filename);
int
main()
{
echo(
"准备截图"
);
CaptureImage(GetDesktopWindow(),
"E:\", "
hello");
// 保存为 E:hello.bmp
echo(
"截图结束"
);
return
0;
}
/**
* 调试输出
*/
void
echo(
CHAR
*str)
{
MessageBox(NULL, str, NULL, MB_OK);
}
/**
* GDI 截取指定窗口
*
* 参数 hwnd 要截屏的窗口句柄
* 参数 dirPath 截图存放目录
* 参数 filename 截图名称
*/
int
CaptureImage(
HWND
hwnd,
CHAR
*dirPath,
CHAR
*filename)
{
HDC
mdc;
HBITMAP
hbmp;
CHAR
FilePath[MAX_PATH];
HDC
hdcScreen;
HDC
hdcWindow;
HDC
hdcMemDC = NULL;
HBITMAP
hbmScreen = NULL;
BITMAP bmpScreen;
RECT rcClient;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
DWORD
dwBmpSize;
HANDLE
hDIB;
CHAR
*lpbitmap;
HANDLE
hFile;
DWORD
dwSizeofDIB;
DWORD
dwBytesWritten;
hdcScreen = GetDC(NULL);
// 全屏幕DC
hdcWindow = GetDC(hwnd);
// 截图目标窗口DC
// 创建兼容内存DC
hdcMemDC = CreateCompatibleDC(hdcWindow);
if
(!hdcMemDC)
{
echo(TEXT(
"CreateCompatibleDC has failed"
));
goto
done;
}
// 获取客户端区域用于计算大小
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"
));
goto
done;
}
// 通过窗口DC 创建一个兼容位图
hbmScreen = CreateCompatibleBitmap(
hdcWindow,
rcClient.right-rcClient.left,
rcClient.bottom-rcClient.top
);
if
(!hbmScreen)
{
echo(TEXT(
"CreateCompatibleBitmap Failed"
));
goto
done;
}
// 将位图块传送到我们兼容的内存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"
));
goto
done;
}
// 获取位图信息并存放在 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);
return
0;
}
C语言 屏幕截图 (GDI)的更多相关文章
- 疯狂的图形(利用C# + GDI plus模拟杂乱无章的现实场景)
原文:疯狂的图形(利用C# + GDI plus模拟杂乱无章的现实场景) 本文给出了模拟竹叶.长叶草.杂乱石头.天上繁星等关键代码.使用.Net环境下C#语言,GDI+编写. 模拟竹叶 挺像的吧? ...
- iOS - Harpy版本更新工具兼容版本第三方库
Harpy(兼容版) git地址:https://github.com/yangchao0033/Harpy ###(iOS5-9适配版本,基于ArtSabintsev/Harpy v3.4.5) 提 ...
- 如何在GooglePlay上面发布应用
上传和发布应用 注册开发者帐户后,您便可使用 Google Play 开发者控制台将应用上传到 Google Play. 访问 Google Play 开发者控制台. 点击屏幕顶部附近的添加新用户. ...
- C语言集锦(三)Direct3D和GDI+的例子
0.前言 有些时候你可能想了解,如何用纯C语言来写Direct3D和GDI+的Demo.注意,下面的Direct3D例子不适用于TCC编译器,GDI+的例子是可以的. 1.Direct3D C语言的例 ...
- Windows GDI 窗口与 Direct3D 屏幕截图
前言 Windows 上,屏幕截图一般是调用 win32 api 完成的,如果 C# 想实现截图功能,就需要封装相关 api.在 Windows 上,主要图形接口有 GDI 和 DirectX.GDI ...
- WinForm GDI+ 资料收集
UI(User Interface)编程在整个项目开发过程中是个颇为重要的环节,任何好的解决方案若没有良好的用户界面呈现给最终用户,那么就算包含了最先进的技术也不能算是好程序.UI编程体现在两个方面, ...
- C# WinForm开发系列 - GDI+【转】
http://blog.csdn.net/blue_sky6/article/details/53811435?locationNum=6&fps=1 C# WinForm开发系列 - GDI ...
- 使用Python保存屏幕截图(不使用PIL)
起因 在极客学院讲授<使用Python编写远程控制程序>的课程中,涉及到查看被控制电脑屏幕截图的功能. 如果使用PIL,这个需求只需要三行代码: from PIL import Image ...
- 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇
上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...
随机推荐
- bzoj3732 Network(NOIP2013 货车运输)
Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_ ...
- 装了ubuntu之后,只能进入ubuntu系统,不能进入windows系统
电脑之前安装的是Windows 7系统, 后来在安装Linux系统中(快要完成)出现了故障, 没办法只能关机,之后重启,重启后只能进入Linux系统了 解决方案: 使用sudo update-grub ...
- 【uml】之类图中的关系 标签: uml图形类 2014-11-29 09:02 1198人阅读 评论(23)
uml早就画完了图,但是自己迟迟没有总结,因为总觉的自己把握的不到位,虽然现在也还是不到位,废话少说,上篇博客总结了用例图中的几种关系,这篇就讨论一下类图中的几种关系. 在uml的所有图中,就我目前的 ...
- 火狐自动填写表单autofill forms的用法和注意事项
1.安装后,打开要表单页面,右键
- php-textarea 换行
PHP接收表单提交的信息之后 存入数据库 再次从数据库获取数据再前端显示时 空格还有回车都消失了: 解决办法: 1,存入数据库时候进行替换 2,或者在取出数据之后进行替换 然后再在html中显示 s ...
- mysql 中合并查询结果union用法 or、in与union all 的查询效率
mysql 中合并查询结果union用法 or.in与union all 的查询效率 (2016-05-09 11:18:23) 转载▼ 标签: mysql union or in 分类: mysql ...
- 全站加速(DCDN)- IP应用加速产品解读
5月22日下午15点,阿里云全站加速(DCDN)-IP应用加速如期发布.IP应用加速是阿里云自主研发的一款更高效.更安全.更便捷的动态加速产品,结合阿里云CDN本身的资源优势,利用就近接入.智能路由, ...
- sublime 插件安装packagecontrol
https://packagecontrol.io/installation 第一步: Installation Simple The simplest method of installation ...
- Android Xutils框架使用问题及解决办法
刚刚写了篇博客,提了下在使用XUtils时遇到的一个问题Android Xutils框架HttpUtil Get请求缓存问题 ,既然已经提起来这个问题,那我想了下,就把之前使用Xutils时遇到的几个 ...
- 一个简单的hexo搭建博客网站的故事
首先安装hexo mkdir hexo #创建一个文件夹 cd hexo #切换到hexo目录下面 npm install -g hexo-cli npm install hexo --save 然后 ...