屏幕抓取程序的意思是将整个屏幕图显示在应用程序的用户区中,等价于截图。

对桌面窗口的操作:
首先得知道桌面窗口的宽和高,获取宽和高需要利用窗口的设备句柄,而获取设备句柄需要知道窗口句柄,这一系列的连串关系如下:
窗口句柄——>设备句柄——>获取设备句柄属性(比如宽和高)。(书本采用的一种方法,但至少也把这种种被需要的关系复习了一下,必须承认,初学需要重复很多次才能形成熟练意识)

hwndDeskTop = GetDesktopWindow();// 获取桌面窗口的窗口句柄
hdcDeskTop = GetDC(hwndDeskTop);// 创建基本桌面窗口的设备描述表

这里借用两个函数,另外还有一种方法,直接创建一个桌面窗口设备的DC

hdcDeskTop = CreateDC("DISPLAY",NULL,NULL,NULL);//CreateDC()获得整个屏幕的DC,一步到位

有了句柄之后,就可以获得(或设置)这个DC的各种属性,比如,有多宽,多高等等....通过函数GetDeviceCaps()实现。摘抄函数原型如下:

int GetDeviceCaps(
HDC hdc; //设备DC
int nIndex; //返回的索引项
);

设备DC的信息很多,因此,nIndex的项尤其多。在这个例子只需要得到屏幕的宽和高。

cxScreen = GetDeviceCaps(hdcDeskTop, HORZRES);  // 获取桌面窗口的大小,也相当于矩形右下角的x,y坐标
cyScreen = GetDeviceCaps(hdcDeskTop, VERTRES);

接下来的这套流程比较繁杂,但是用最简易的方式描述,得到屏幕DC之后,再创建一个兼容DC(兼容屏幕设备),和一个兼容位图(兼容屏幕),将兼容位图放置在兼容DC中,准备用它来存放屏幕的位图。可以通俗的理解为是一个容器么?兼容DC容纳兼容位图。

hdcMem = CreateCompatibleDC(hdcDeskTop); // 创建与显示设备描述表兼容的内存设备描述表
hBitmap = CreateCompatibleBitmap( hdcDeskTop, cxScreen, cyScreen);
SelectObject(hdcMem, hBitmap);//并选入内存设备描述表

设备已经就绪,最后将屏幕的位图移动到兼容DC中的兼容位图上。

BitBlt(hdcMem, , , cxScreen, cyScreen,hdcDeskTop, ,  ,SRCCOPY);

再看来BitBlt()函数,摘抄如下:

BOOL BitBlt(
HDC hDCDest,//目标设备描述表
int nXDest,//目标矩形左上角x坐标
int nYDest,//目标矩形左上角y坐标
int nWidth,//目标矩形宽
int nHeight,//目标矩形高
HDC hDCSrc,//源设备描述表
int nXDSrc,//源矩形x坐标(左上角)
int nYDSrc,//源矩形y坐标
DWORD dwRop //执行的光栅操作
);

其中最后一条DWORD dwRop光栅操作,让我联想起C语言的图形复制,就是在复制的过程中,如何与目标进行某种混合操作,比如让它反色(黑变白,白变黑),OR,异或操作等等,大概就是这个意思。

兼容内存设备描述表——>应用程序设备描述表

内存设备描述表的工作已经完成,接着,再把这个内存设备描述表中的位图复制到当前应用程序的用户区中,并让它显示。
即:兼容内存描述表——>应用程序设备描述表。

书本在这里考虑这样一个问题,让位图适当缩放来适应用户区的大小,于是采用了另一种复制函数StretchBlt。它的参数与BitBlt大部分相似,省略。
但是,在缩放之前,又设置了一个缩放模式,通过函数SetStretchBltMode实现,摘抄如下:

int SetStretchBltMode(
HDC hDC,
int iStretchMode
);
//iStretchMode的选项
BLACKONWHITE;//保留黑色像素,清除白色像素,一般用于单色位图中
COLORONCOLOR;//一般用于彩色位图中保留位图的颜色
WHITEONBLACK;//保留白色像素,清除黑色像素
HALFTONE;//对源图像进行复杂处理,慢但是得到高质量的图像

参数可以任意试验,明显HALFTONE参数截出的图清晰很多。
通过这一系列移来移去的复制操作完成了屏幕截图的工作,涉及一系列的位图函数,因此有必要认真总结一下。

/*---------------桌面截图程序研究版-----------------*/

#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
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_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass))
{
return ;
}
hwnd = CreateWindow (szAppName,
TEXT ("鼠标消息"),
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 hdc,hdcDeskTop,hdcMem; PAINTSTRUCT ps ;
static int cxScreen,cyScreen,cxClient,cyClient;
HBITMAP hBitmap; switch (message)
{ case WM_CREATE: //hwndDeskTop = GetDesktopWindow();// 获取桌面窗口的窗口句柄
//hdcDeskTop = GetDC(hwndDeskTop);// 创建基本桌面窗口的设备描述表 hdcDeskTop = CreateDC("DISPLAY",NULL,NULL,NULL);//CreateDC()获得整个屏幕的DC,一步到位
hdcMem = CreateCompatibleDC(hdcDeskTop); // 创建兼容内存设备描述表 cxScreen = GetDeviceCaps(hdcDeskTop, HORZRES); // 获取桌面窗口的大小
cyScreen = GetDeviceCaps(hdcDeskTop, VERTRES); hBitmap = CreateCompatibleBitmap( hdcDeskTop, cxScreen, cyScreen);// 创建兼容位图
SelectObject(hdcMem, hBitmap);//选入内存设备描述表 //ShowWindow(hwnd, SW_HIDE);//先隐藏窗口,有这个必要吗?此时窗口未出现 BitBlt(hdcMem, , , cxScreen, cyScreen,hdcDeskTop, , ,SRCCOPY); // 将桌面位图的像素传送到兼容位图上
//Sleep(1000);
//ShowWindow(hwnd, SW_SHOW);//显示窗口
DeleteDC(hdcDeskTop); return ; case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ;
// 将内存设备描述表的位图压缩显示到程序窗口内
//SetStretchBltMode(hdc, COLORONCOLOR);//iStretchMode参数任意选择观察
//SetStretchBltMode(hdc, HALFTONE);
StretchBlt(hdc, , , cxClient, cyClient, hdcMem, , , cxScreen, cyScreen, SRCCOPY);
EndPaint (hwnd, &ps) ;
return ; case WM_DESTROY:
PostQuitMessage () ;
return ;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}

屏幕抓取程序 (位图DDB的例子)的更多相关文章

  1. WinDbg抓取程序报错dump文件的方法

    程序崩溃的两种主要现象: a. 程序在运行中的时候,突然弹出错误窗口,然后点错误窗口的确定时,程序直接关闭 例如: “应用程序错误” “C++错误之类的窗口” “程序无响应” “假死”等 此种崩溃特点 ...

  2. python学习(十五) 屏幕抓取

    15.1 屏幕抓取 15.1.1 Tidy和XHTML解析 Tidy:用来修复不规范且随意的HTML文档的工具. 为什么用XHTML: 和旧版本的HTML之间最主要的区别:HTML可能只用一个开始标签 ...

  3. UiPath屏幕抓取Screen Scraping的介绍和使用

    一.屏幕抓取(Screen Scraping)的介绍 屏幕抓取使您能够在特定的UI元素或文档(如.PDF文档)中提取数据 二.屏幕抓取(Screen Scraping)在UiPath中的使用 [if ...

  4. 基于python编写的天气抓取程序

    以前一直使用中国天气网的天气预报组件都挺好,可是自从他们升级组件后数据加载变得非常不稳定,因为JS的阻塞常常导致网站打开速度很慢.为了解决这个问题决定现学现用python编写一个抓取程序,每天定时抓取 ...

  5. Windbg抓取程序崩溃的dmp文件的方法

    Windbg抓取程序崩溃的dmp文件的方法 一.        简介 windbg是在windows平台下,强大的用户态和内核态调试工具.相比较于Visual Studio,它是一个轻量级的调试工具, ...

  6. 一个极其简洁的Python网页抓取程序,自己主动从雅虎財经抓取股票数据

    本程序使用Python 2.7.6编写,扩展了Python自带的HTMLParser,自己主动依据预设的股票代码列表,从Yahoo Finance抓取列表中的数据日期.股票名称.实时报价.当日变化率. ...

  7. 吴裕雄--天生自然python学习笔记:python通过“任务计划程序”实现定时自动下载或更新运行 PM2.5 数据抓取程序数据

    在 Windows 任务计划程序中,设置每隔 30 分钟自动抓取 PM2.5 数据,井保存 在 SQLite 数据库中 . import sqlite3,ast,requests,os from bs ...

  8. Python 15__屏幕抓取

  9. [转]使用Scrapy建立一个网站抓取器

    英文原文:Build a Website Crawler based upon Scrapy 标签: Scrapy Python 209人收藏此文章, 我要收藏renwofei423 推荐于 11个月 ...

随机推荐

  1. shell加密工具shc的安装和使用

    1) 工具说明 shell脚本是可读写的, 很有可能会泄露敏感信息, 如用户名/密码/路径/IP等. 同样在shell脚本运行时会也泄露敏感信息. shc是一个加密shell脚本的工具, 它的作用是把 ...

  2. mysql中如何使用一句话将一个表的数据导入到另一个表中:insert into ...select

    INSERT INTO cdcd2015(`filename`,`xmlfile`,`updatetime`,`isDel`) SELECT `filename`,`xmlfile`,`updatet ...

  3. python 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

    http://www.cnblogs.com/linhaifeng/articles/7580830.html 三元表达式.列表推导式.生成器表达式.递归.匿名函数.内置函数

  4. 简单DP入门四连发

    复习一下一直不太懂的dp. dp博大精深,路还长着呢 第一题;http://acm.hdu.edu.cn/showproblem.php?pid=2084 从下往上就是水题 #include<c ...

  5. Canvas绘图 (html5新增特性)

    Canvas 使用<canvas>对象,需要设置属性:width,height.指定绘图的区域大小.在canvas标签前后出现的信息将在不支持<canvas>元素的浏览器中显示 ...

  6. iOS push新的调用方法

    // IOS8 新系统需要使用新的代码if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0){    [[UIAppl ...

  7. shell脚本返回字符串

    shell脚本的return只能返回数值类型,可是我们很多时候想返回字符串 #!/bin/sh function getStr () { String="very good" ec ...

  8. UI设计教程分享:设计一个高质量的logo要从哪方面入手呢?

    有的人觉得logo只是一个简单的图形,对品牌影响无关紧要:但有的人却觉得logo对品牌有较大的影响.其实logo承载着一个公司的品牌形象.公司背景.公司理念等.就像Landor往往给一个企业做logo ...

  9. python连接Linux服务器

    import paramikoimport os #当前脚本路径CUR_PATH = os.path.dirname(__file__) #服务器ipHost=''Port=22#登录用户名Usern ...

  10. Hadoop知识点

    1.小文件合并:如果文件有一定的规律或者是在同一个文件夹下,可以采用获取文件夹下所有的文件,通过流进行合并,然后再存到hdfs上. 2.mapreduce的优点:1.离线计算.2.高容错性,一个节点挂 ...