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打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...
随机推荐
- 寻找 K8s 1.14 Release 里的“蚌中之珠”
摘要: K8s 1.14 发布了,Release Note那么长,我们该从何读起? 本文由张磊.心贵.临石.徙远.衷源.浔鸣等同学联合撰写. Kubernetes 1.14.0 Release 已经于 ...
- 洛谷4178 BZOJ1468 Tree题解点分治
点分治的入门练习. 题目链接 BZOJ的链接(权限题) 关于点分治的思想我就不再重复了,这里重点说一下如何判重. 我们来看上图,假设我们去除了1节点,求出d[2]=1,d[3]=d[4]=2 假设k为 ...
- LeetCode91 Decode Ways
题目: A message containing letters from A-Z is being encoded to numbers using the following mapping: ' ...
- 从零学React Native之11 TextInput
TextInput 组件是用来通过键盘输入文字,可以使用View组件和Text组件样式,没有自己特定的样式. 与Text组件类似,TextInput组件内部的元素不再使用FlexBox布局,而采用文本 ...
- iOS runtime整理
iOS利用Runtime自定义控制器POP手势动画 http://www.cocoachina.com/ios/20150401/11459.html Objective C运行时(runtime) ...
- DDoS攻击新趋势:海量移动设备成为新一代肉鸡
近期,阿里云安全团队观察到数十起大规模的应用层资源耗尽式DDoS攻击(应用层CC攻击).阿里云DDoS高防实现智能防护全程自动化检测并清洗,未对用户侧业务产生任何影响,这类攻击存在一些共同的特征,阿里 ...
- YUI css reset
*{ margin:0; padding:0; } 以前写CSS都会在会在样式的开头部分添加上述的内容,今天才发现这种写法很不友好,会导致很多样式显示问题,所以并不适合所有的浏览器. 下面的是雅虎的c ...
- Vue.js 第2章 钩子函数&自定义指令&过滤器&计算属性&侦听器
目标 钩子函数 自定义指令 自定义过滤器 计算属性 监听属性 局部自定义指令 为什么需要自定义指令 为了复用,为了代码的灵活 指令的分类:全局指令,局部指令 在vm外面创建的指令 通过Vue.dire ...
- ural 1519 Formula 1(插头dp)
1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...
- Tyvj-1338 QQ农场
P1338 QQ农场 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 Sandytea前段时间沉迷于QQ农场中……一天夜里,他梦见来到好友X的农场上…… 描述 ...