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打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...
随机推荐
- 【C++】反向迭代器(rbegin,rend)(转载)
转自:http://blog.csdn.net/kjing/article/details/6936325 rbegin和rend,很有用! C++ primer (中文版第四版)第273页 9.3. ...
- 安装 FastAdmin 时忘记 MySQL 密码怎么办?
安装 FastAdmin 时忘记 MySQL 密码怎么办? 给 MySQL 启动时加上 skip-grant-tables 参数,然后随便使用用户名都可以进入 MySQL. 接着就可以使用 命令改了 ...
- 字体图标font-awesome
其实有一些常见的图标使用字体图标比使用img来得好 Font Awesome 官网:http://fortawesome.github.io/Font-Awesome/ 字体代码:http://for ...
- Ubuntu+Apache+PHP+Mysql环境搭建(完整版)(转)
http://www.2cto.com/os/201505/401588.html Ubuntu+Apache+PHP+Mysql环境搭建(完整版) 一.操作系统Ubuntu 14.04 64位,阿里 ...
- Java练习 SDUT-1132_斐波那契数列
C/C++经典程序训练2---斐波那契数列 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 编写计算斐波那契(Fibon ...
- 13 -1 BOM和定时器
一 BOM JavaScript基础分为三个部分: ECMAScript:JavaScript的语法标准.包括变量.表达式.运算符.函数.if语句.for语句等. DOM:文档对象模型,操作网页上的元 ...
- Hbase数据模型 列族
- oracle函数 sqrt(x)
[功能]返回x的平方根 [参数]x数字型表达式 [返回]数字 [示例] select sqrt(64),sqrt(10) from dual; 返回:8 , 3.16227766
- python selenium 处理悬浮窗口(baidu tj_more)
python selenium 处理悬浮窗口 from selenium.webdriver.common.action_chains import ActionChainsActionChains( ...
- 深入理解iptables防火墙
0x00 Linux 安全性和 netfilter/iptables Linux 因其健壮性.可靠性.灵活性以及好象无限范围的可定制性而在 IT 业界变得非常受欢迎.Linux 具有许多内置的能力, ...