怎样将我们上一篇截取的位图保存在文件夹里。根据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截图程序(二):保存截图的更多相关文章

  1. Ocr答题辅助神器 OcrAnswerer4.x,通过百度OCR识别手机文字,支持屏幕窗口截图和ADB安卓截图,支持四十个直播App,可保存题库

    http://www.cnblogs.com/Charltsing/p/OcrAnswerer.html 联系qq:564955427 最新版为v4.1版,开放一定概率的八窗口体验功能,请截图体验(多 ...

  2. Selenium2学习-033-WebUI自动化实战实例-031-页面快照截图应用之二 -- 区域截图

    我在之前的文章中曾给出浏览器显示区域截图的方法,具体请参阅 .或许,有些小主已经想到了,每次都获取整个显示区域的截图存储,那么经过一段时间后,所使用的图片服务器的容量将会受到极大的挑战,尤其是在产品需 ...

  3. 采用WPF开发截图程序,so easy!

    前言  QQ.微信截图功能已很强大了,似乎没必要在开发一个截图程序了.但是有时QQ热键就是被占用,不能快速的开启截屏:有时,天天挂着QQ,领导也不乐意.既然是程序员,就要自己开发截屏工具,功能随心所欲 ...

  4. 采用WPF技术开发截图程序

    前言  QQ.微信截图功能已很强大了,似乎没必要在开发一个截图程序了.但是有时QQ热键就是被占用,不能快速的开启截屏:有时,天天挂着QQ,领导也不乐意.既然是程序员,就要自己开发截屏工具,功能随心所欲 ...

  5. app内区域截图利用html2Canvals保存到手机 截屏 (html2Canvas使用版本是:0.5.0-beta3。)

    app内区域截图利用html2Canvals保存到手机 app内有时候需要区域内的截图保存dom为图像,我们可以使用html2Canvas将dom转换成base64图像字符串,然后再利用5+api保存 ...

  6. appium 学习各种小功能总结--功能有《滑动图片、保存截图、验证元素是否存在、》---新手总结(大牛勿喷,新手互相交流)

    1.首页滑动图片点击 /** * This Method for swipe Left * 大距离滑动 width/6 除数越大向左滑动距离也越大. * width:720 *height:1280 ...

  7. 用单进程、多线程并发、多线程分别实现爬一个或多个网站的所有链接,用浏览器打开所有链接并保存截图 python

    #coding=utf-8import requestsimport re,os,time,ConfigParserfrom selenium import webdriverfrom multipr ...

  8. Selenium+Python+Webdriver:保存截图到指定文件夹

    保存图片到指定文件夹: from selenium import webdriverfrom pathlib import Pathfrom time import sleepdriver = web ...

  9. Python+selenium之截图图片并保存截取的图片

    本文转载:http://blog.csdn.net/u011541946/article/details/70141488 http://www.cnblogs.com/timsheng/archiv ...

随机推荐

  1. js面向对象的使用方法

    标准用法: function Sprite(){ //函数内容部设置属性 this.name='shimily'; } //原型上设置方法 Sprite.prototype.show=function ...

  2. C# 中的 Static

    今天测试了一下C#中 static 的初始化顺序: 1.调用时才初始化, 2.按照调用顺序初始化 3.先执行类的静态方法,然后初始化静态变量及方法 4.继承时,先执行子类的静态方法,然后执行父类的静态 ...

  3. C#.NET微信公众账号接口开发系列文章整理--微信接口开发目录,方便需要的博友查询

    前言: 涉及微信接口开发比较早也做的挺多的,有时间的时候整理了开发过程中一些思路案例,供刚学习微信开发的朋友参考.其实微信接口开发还是比较简单的,但是由于调试比较麻烦,加上微信偶尔也会给开发者挖坑,并 ...

  4. C#之委托

    委托是C#中非常重要的一个概念,并在C#中得到了丰富的应用,如事件,线程等.那什么是委托呢?具体来说,委托是一种引用方法的类型.一旦为委托分配了方法,委托将与该方法具有完全相同的行为.委托方法的使用可 ...

  5. js归并排序法

    function mergeSort(arr) { var len = arr.length; if(len > 1) { var index = Math.floor(len / 2); le ...

  6. 在VMware中安装ubuntu出现菜单栏无法显示的情况

    在VMware中安装ubuntu出现菜单栏无法显示的情况 其实这个问题的原因时由于VMware中enable了3D图形加速界面,只需要shutdown当前运行的虚拟机,然后在虚拟机,设置,显示器,3D ...

  7. 用PowerMock mock final类constructors

    也相对简单,直接贴代码 被测方法 public class EmployeeServiceWithParam { public void createEmployee(final Employee e ...

  8. 使用CSS3动画属性实现360°无限循环旋转【代码片段】

    使用CSS3的animation动画属性实现360°无限循环旋转. 代码片段: <div id="test"> <img src="/CSS3/img/ ...

  9. JS 4 新特性:混合属性(mixins)之二

    Mixins many classes[混合许多个类] 迄今为止,我们已经学会了简单的继承,我们还能够通过使用mixins处理机制来混合许多类.源于这种理念是非常简单的:我们能够把许多个类最终混合到一 ...

  10. 软件测试第四周--关于int.parse()的类型转换问题

    先来归纳一下我们用过的所有类型转换方法: 1. 隐式类型转换,即使用(int) 直接进行强制类型转换.这种方法的优点是简单粗暴,直接指定转换类型,没有任何保护措施,所以也很容易抛出异常导致程序崩溃.当 ...