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 ...
随机推荐
- C# in VS
1. DllImport是System.Runtime.InteropServices命名空间下与与非托管相关的一个属性类,负责导出从非托管的dll中导出函数信息,导出的函数在声明时必须有extern ...
- [原创]VM虚拟机Centos6.4网络配置。
关于虚拟机VMware 3种网络模式(桥接.nat.Host-only)的工作原理http://www.cnblogs.com/hehexiaoxia/p/4042583.html 操作环境 主机:W ...
- blade and soul Group Combos
Group Combos A martial artist always make friends along their way. They learn how to work and fight ...
- textbox button 模拟fileupload
方案一: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="test.asp ...
- jquery中select的应用
//得到select项的个数 jQuery.fn.size = function(){ return jQuery(this).get(0).options.length; } //获得选中项的索引 ...
- 小游戏Item表
[Config]1|0|我|1|10|500|0|8|2|4|b5222d10-55a7-4789-8541-8e7430345d54|0|0[Config] [Config]2|1|公主|1|0|5 ...
- charles抓包工具
HTTP抓包 打开Charles程序 查看Mac电脑的IP地址,如192.168.1.7 打开iOS设置,进入当前wifi连接,设置HTTP代理Group,将服务器填为上一步中获得的IP,即192.1 ...
- javap反编译解释外部类直接使用内部类private字段的原理
2016-07-04 15:56:39 我们都知道: 1.内部类可以直接访问外部类的private字段和方法: 2.非静态内部类持有外部类的引用: 3.外部类可以直接访问内部类的private字段和方 ...
- C# 中 多线程同步退出方案 CancellationTokenSource
C# 中提供多线程同步退出机制,详参对象: CancellationTokenSource CancellationTokenSource 中暂未提供复位操作,因此当调用Cancle 之后,若再次调用 ...
- 计算机网络(12)-----HTTP协议详解
HTTP协议详解 http请求 http请求由三部分组成,分别是:请求行.消息报头.请求正文 (1)请求行 请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Metho ...