SDK截图程序(二):保存截图
怎样将我们上一篇截取的位图保存在文件夹里。根据MSDN,思路是这样的,用CreateFile函数在磁盘建立一个bmp文件,用WriteFile填充该bmp文件的文件头、信息头,像素等信息。之前我们只有一个位图的句柄即,hBitmap。所以保存截图的重点是,从hBitmap着手,获得建立一张位图所需要的信息。
我们使用GetObject和GetDIBits分别得到hBitmap“携带”的位图的文件头、信息头和像素位的信息。
这里用到的主要是《windows程序设计》15章的内容
程序代码如下:
#include <windows.h>
#pragma comment(linker,"/subsystem:\"windows\"" )//我这里开始建的是控制台程序
HBITMAP GetBitmap();
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{ static TCHAR szAppName [] = TEXT ("BitBlt") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = ;
wndclass.cbWndExtra = ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_INFORMATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return ;
}
hwnd = CreateWindow (szAppName, TEXT ("BitBlt Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, , ))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HDC hdcClient, hdcWindow ;
static HDC hdcMem;
HBITMAP hBitmap; PAINTSTRUCT ps ;
switch (message)
{
case WM_CREATE:
{
hdcClient=GetDC(hwnd); //获得应用程序客户区窗口句柄
hdcWindow = GetWindowDC (NULL) ; //GetWindowDC可以获得整个应用程序窗口句柄(客户区和非客户区)
//当参数传值为NULL的时候,得到系统窗口的句柄
hBitmap=CreateCompatibleBitmap(hdcClient,,); //创建与设备兼容的位图,宽100像素,高100像素
hdcMem=CreateCompatibleDC(hdcClient); //创建内存设备环境句柄
SelectObject(hdcMem,hBitmap); //将位图选进内存设备环境
BitBlt (hdcMem, , , ,, hdcWindow, , , SRCCOPY) ; //将系统窗口左上角100*100的图像像素复制到内存设备环境 OpenClipboard( hwnd ) ; //打开粘贴板
EmptyClipboard() ; //清空粘贴板
SetClipboardData( CF_BITMAP, hBitmap ) ; //设置粘贴板数据,即将位图设置进粘贴板
//之前有将新建的位图选进内存设备环境,后来将系统窗口100*100像素图像复制移动到内存
//设备环境。我的理解是,将位图选进内存设备环境之后,针对内存设备环境的操作,改变了
//位图的内容,而不需要再将内存设备环境选进位图了
CloseClipboard() ; //关闭粘贴板 //Get the BITMAP from the HBITMAP
BITMAP bmpScreen;
GetObject(hBitmap,sizeof(BITMAP),&bmpScreen);
//设置位图信息,《windows程序设计15章节的内容》
BITMAPFILEHEADER bmfHeader; //位图文件头
BITMAPINFOHEADER bi; //信息头
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = ;
bi.biBitCount = ;
bi.biCompression = BI_RGB;
bi.biSizeImage = ;
bi.biXPelsPerMeter = ;
bi.biYPelsPerMeter = ;
bi.biClrUsed = ;
bi.biClrImportant = ;
//bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4是每一行所用的字节数
DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + ) / ) * * bmpScreen.bmHeight; HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize); //分配内存并锁定
char *lpbitmap = (char *)GlobalLock(hDIB); //// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpbitmap.
GetDIBits(hdcWindow, hBitmap, ,
(UINT)bmpScreen.bmHeight,
lpbitmap,
(BITMAPINFO *)&bi, DIB_RGB_COLORS); // A file is created, this is where we will save the screen capture. HANDLE hFile = CreateFile("captureqwsx.bmp",
GENERIC_WRITE,
,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL); // Add the size of the headers to the size of the bitmap to get the total file size
DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //Offset to where the actual bitmap bits start.
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); //Size of the file
bmfHeader.bfSize = dwSizeofDIB; //bfType must always be BM for Bitmaps
bmfHeader.bfType = 0x4D42; //BM
DWORD dwBytesWritten = ; //将位图文件头,信息头,由GetDIBits获得的保存在lpbitmap指向的内存的bit写入文件中
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL); //Unlock and Free the DIB from the heap
GlobalUnlock(hDIB);
GlobalFree(hDIB); //Close the handle for the file that was created
CloseHandle(hFile);
ReleaseDC (hwnd, hdcWindow) ;
return ;
}
case WM_SIZE: return ; case WM_PAINT:
hdcClient=BeginPaint (hwnd, &ps) ;
BitBlt (hdcClient, , , ,, hdcMem, , , SRCCOPY) ; //这里我们做一个小测试,将截取的图片显示在客户区
//这样需要将hdcClient和hdcMem定义成static的
EndPaint (hwnd, &ps) ;
return ; case WM_DESTROY:
PostQuitMessage () ;
return ;
} return DefWindowProc (hwnd, message, wParam, lParam) ; }
MSDN上的实例 https://msdn.microsoft.com/en-us/library/dd183402(v=vs.85).aspx
(简单翻译了下)
捕获图像
你可以bitmap去捕获一个图像,你也能将捕获的图像存储进内存,显示在你应用窗口的不同的位置,或者显示在其他的窗口上。
有时候,你可能只是想让你的应用程序暂时地捕获一张图像和存储它们。例如,当你在绘图应用上按比例缩放一张图片,应用程序必须首先临时地保存正常尺寸的图像,再显示被缩放的图像;通过复制被临时保存的正常尺寸的图像,使用者在选择正常尺寸图片时,能够替换掉被缩放的图形。
要临时地存储一张图片,你的应用必须调用CreateCompatibleDC去创建一个和你的windowDC相兼容的DC,在你创建一个兼容的DC之后,你可以通过CreateCompatibleBitmap功能函数创建一个合适尺寸的位图,再通过SelectObject函数将其选进设备环境。
兼容设备环境被创建以及合适尺寸位图被选进设备环境之后,你就可以捕获图像了。BitBlt函数可以捕获图像,该函数执行一个位块传输,它可以将资源位图的数据复制到目标位图。然后,该函数使用的非两张位图的句柄,而是两个设备环境的句柄,复制一个被选进源DC的位图数据到一个被选进目标DC的位图上。在此情形下,目标DC是一个兼容DC,所以当BitBlt完成传输之后,图形被存储在内存中,要重新显示图形,再次调用BitBlt,指定兼容DC作为原DC,并将Window DC作为目标DC就可以了。
下面的代码示例,捕获整个桌面的图像,将它缩放当适应当前窗口的大小,并将其保存进文件。
原文如下:
Capturing an Image
You can use a bitmap to capture an image, and you can store the captured image in memory, display it at a different location in your application's window, or display it in another window.
In some cases, you may want your application to capture images and store them only temporarily. For example, when you scale or zoom a picture created in a drawing application, the application must temporarily save the normal view of the image and display the zoomed view. Later, when the user selects the normal view, the application must replace the zoomed image with a copy of the normal view that it temporarily saved.
To store an image temporarily, your application must call CreateCompatibleDC to create a DC that is compatible with the current window DC. After you create a compatible DC, you create a bitmap with the appropriate dimensions by calling the CreateCompatibleBitmap function and then select it into this device context by calling the SelectObjectfunction.
After the compatible device context is created and the appropriate bitmap has been selected into it, you can capture the image. The BitBlt function captures images. This function performs a bit block transfer that is, it copies data from a source bitmap into a destination bitmap. However, the two arguments to this function are not bitmap handles. Instead, BitBlt receives handles that identify two device contexts and copies the bitmap data from a bitmap selected into the source DC into a bitmap selected into the target DC. In this case, the target DC is the compatible DC, so when BitBlt completes the transfer, the image has been stored in memory. To redisplay the image, call BitBlt a second time, specifying the compatible DC as the source DC and a window (or printer) DC as the target DC.
The following example code is from an application that captures an image of the entire desktop, scales it down to the current window size and then saves it to a file.
SDK截图程序(二):保存截图的更多相关文章
- Ocr答题辅助神器 OcrAnswerer4.x,通过百度OCR识别手机文字,支持屏幕窗口截图和ADB安卓截图,支持四十个直播App,可保存题库
http://www.cnblogs.com/Charltsing/p/OcrAnswerer.html 联系qq:564955427 最新版为v4.1版,开放一定概率的八窗口体验功能,请截图体验(多 ...
- Selenium2学习-033-WebUI自动化实战实例-031-页面快照截图应用之二 -- 区域截图
我在之前的文章中曾给出浏览器显示区域截图的方法,具体请参阅 .或许,有些小主已经想到了,每次都获取整个显示区域的截图存储,那么经过一段时间后,所使用的图片服务器的容量将会受到极大的挑战,尤其是在产品需 ...
- 采用WPF开发截图程序,so easy!
前言 QQ.微信截图功能已很强大了,似乎没必要在开发一个截图程序了.但是有时QQ热键就是被占用,不能快速的开启截屏:有时,天天挂着QQ,领导也不乐意.既然是程序员,就要自己开发截屏工具,功能随心所欲 ...
- 采用WPF技术开发截图程序
前言 QQ.微信截图功能已很强大了,似乎没必要在开发一个截图程序了.但是有时QQ热键就是被占用,不能快速的开启截屏:有时,天天挂着QQ,领导也不乐意.既然是程序员,就要自己开发截屏工具,功能随心所欲 ...
- app内区域截图利用html2Canvals保存到手机 截屏 (html2Canvas使用版本是:0.5.0-beta3。)
app内区域截图利用html2Canvals保存到手机 app内有时候需要区域内的截图保存dom为图像,我们可以使用html2Canvas将dom转换成base64图像字符串,然后再利用5+api保存 ...
- appium 学习各种小功能总结--功能有《滑动图片、保存截图、验证元素是否存在、》---新手总结(大牛勿喷,新手互相交流)
1.首页滑动图片点击 /** * This Method for swipe Left * 大距离滑动 width/6 除数越大向左滑动距离也越大. * width:720 *height:1280 ...
- 用单进程、多线程并发、多线程分别实现爬一个或多个网站的所有链接,用浏览器打开所有链接并保存截图 python
#coding=utf-8import requestsimport re,os,time,ConfigParserfrom selenium import webdriverfrom multipr ...
- Selenium+Python+Webdriver:保存截图到指定文件夹
保存图片到指定文件夹: from selenium import webdriverfrom pathlib import Pathfrom time import sleepdriver = web ...
- Python+selenium之截图图片并保存截取的图片
本文转载:http://blog.csdn.net/u011541946/article/details/70141488 http://www.cnblogs.com/timsheng/archiv ...
随机推荐
- F2工作流引擎这工作流引擎体系架构(二)
F2工作流体系架构概览图 为了能更好的了解F2工作流引擎的架构体系,花了些时间画了整个架构的体系图.F2工作流引擎遵循参考WFCM规范,目标是实现轻量级的工作流引擎,支持多种数据库及快速应用到任何基于 ...
- EntityFramework CodeFirst SQLServer转Oracle踩坑笔记
接着在Oracle中使用Entity Framework 6 CodeFirst这篇博文,正在将项目从SQLServer 2012转至Oracle 11g,目前为止遇到的问题在此记录下. SQL Se ...
- windows下部署Redis
1.去github上下载最新的项目源码https://github.com/MSOpenTech/redis 2.打开项目文件redis-3.0\msvs\RedisServer.sln 编译所有项目 ...
- Rendering Problems:android.support.v7.internal.widget.ActionBarOverlayLayout 解决方法
不知道是不是android studio安装不对的问题,每次新建项目都有这个问题. 临时解决方法是: 打开 styles.xml 在Theme.AppCompat.Light.DarkActionBa ...
- ios项目中安装和使用CocoaPods
CocoaPods是什么? http://code4app.com/article/cocoapods-install-usage http://blog.csdn.net/jjmm2009/arti ...
- erlang服务器启动,有情况会报,enif_send: env==NULL no ono-SMP VMAborted 的错误报告?
问题的原因所在: 1:因为你当前使用的主机是一个单核的主机(不会自动启动): 2:多核上如果不设置-smp enable是不会有什么问题的,因为从OTP R12B开始,如果操作系统报告有多于1个的CP ...
- Git 撤消
现在添加一个新的文件 t.c, 写一行 int a; 用 git add . 添加跟踪,当前状态 $ git status On branch master Changes to be committ ...
- HDU--杭电--1026--Ignatius and the Princess I--广搜--直接暴力0MS,优先队列的一边站
别人都是广搜+优先队列,我没空临时学,所以就直接自己暴力了 Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others) ...
- Making the Grade(POJ3666)
题目大意: 给出长度为n的整数数列,每次可以将一个数加1或者减1,最少要多少次可以将其变成单调增或者单调减(不严格). 题解: 1.一开始我有一个猜想,就是不管怎么改变,最终的所有数都是原来的某个数. ...
- js判断鼠标向上滚动并浮动导航
<div id="Jnav"> <ul class="nav"> <li><a href="#"& ...