屏幕抓取程序 (位图DDB的例子)

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

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

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, 0, 0, cxScreen, cyScreen,hdcDeskTop, 0, 0 ,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    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     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 0 ;
     }
     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, 0, 0))
     {
          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, 0, 0, cxScreen, cyScreen,hdcDeskTop, 0, 0 ,SRCCOPY); // 将桌面位图的像素传送到兼容位图上
    //Sleep(1000);
    //ShowWindow(hwnd, SW_SHOW);//显示窗口
    DeleteDC(hdcDeskTop);

    return 0 ;

case WM_SIZE:
    cxClient = LOWORD(lParam);
    cyClient = HIWORD(lParam);
    return 0;

case WM_PAINT:

    hdc = BeginPaint (hwnd, &ps) ;
    // 将内存设备描述表的位图压缩显示到程序窗口内
    //SetStretchBltMode(hdc, COLORONCOLOR);//iStretchMode参数任意选择观察
    //SetStretchBltMode(hdc, HALFTONE);
    StretchBlt(hdc, 0, 0, cxClient, cyClient,  hdcMem, 0 ,0 , cxScreen, cyScreen, SRCCOPY);
    EndPaint (hwnd, &ps) ;
    return 0 ;

     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam);
}
时间: 2024-11-07 04:12:29

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

python之屏幕抓取

Tidy 和 HTML 解析 Beautiful Soup 屏幕抓取:是通过程序下载网页并从中提取信息的过程. 简单来见:下载数据并对其进行分析 思路:可使用urllib来获取网页的HTML代码,再使用正则表达式从中提取信息. 例如:假设要从python Job Board(http://python.org/jobs)提取招聘单位的名称和网站. 通过查看该网站的源代码,可发现类似于下面的链接中找到名称和URL: <a href="/jobs/1970/">Python E

python学习(十五) 屏幕抓取

15.1 屏幕抓取 15.1.1 Tidy和XHTML解析 Tidy:用来修复不规范且随意的HTML文档的工具. 为什么用XHTML: 和旧版本的HTML之间最主要的区别:HTML可能只用一个开始标签(<p>)结束一段然后开始下一段,而在XHTML中,首先要显示的关闭当前段落(</p>),  这种行为让XHTML更容易解析, 另外一个好处是:它是XML的一种,可以对他使用XML工具,例如xpath. 解析XTML用HTMLParser. 15.1.2 Beautiful Soup

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

程序崩溃的两种主要现象: a. 程序在运行中的时候,突然弹出错误窗口,然后点错误窗口的确定时,程序直接关闭 例如: “应用程序错误” “C++错误之类的窗口” “程序无响应” “假死”等 此种崩溃特点:程序已异常,在你未点出错窗口的确定或其他按,所有错误信息都还保留在PC的内存中,可以直接抓取Dump文件.当然,如果你知道 怎么样操作可以让程序崩溃,也可以用守株待兔的抓取方法抓Dump文件. b.程序在运行中的时候,窗口和进程突然消失,没有任何错误窗体 典型的现象:程序自动关闭 或者玩游戏时,游

一个极其简洁的Python网页抓取程序

paip. 混合编程的实现resin4 (自带Quercus ) 配置 php 环境 #---混合编程的类型 1.代码inline 方式 2.使用库/api  解析方式. #----配置resin 支持php resin4默认自动支持php.. 也能手动配置了.web.xml加php的servlet解析..参考Quercus让你的PHP开心在Servlet容器奔跑 #----配置 php.ini路线 运行t.php,,看见 Configuration File (php.ini) Path =>

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

本程序使用Python 2.7.6编写,扩展了Python自带的HTMLParser,自己主动依据预设的股票代码列表,从Yahoo Finance抓取列表中的数据日期.股票名称.实时报价.当日变化率.当日最低价.当日最高价. 因为Yahoo Finance的股票页面中的数值都有对应id. 比如纳斯达克100指数ETF(QQQ)http://finance.yahoo.com/q?s=qqq 当中实时报价的HTML标记为 <span id="yfs_l84_qqq">87.4

记录一次网页抓取程序的实现

2016年一月,刚做完三个课程设计,C++网络版打地鼠,北山超市收银系统J2EE,JAVA聊天程序,累不堪言,置身奋斗之年承受这些是应该的,毕竟自己的技术还太菜了,没有一个开发者应有的底气. -------------------------------------- 前记 在此之际,一同事介绍了一个项目,做一个教务信息记录抓取到自己的网页显示之. --------------------------------------缘由 做这个东西首先也百度了下,网上的文章大多没什么营养,不过也基于网上

python爬取ajax动态生成的数据 以抓取淘宝评论为例子

在学习python的时候,一定会遇到网站内容是通过ajax动态请求.异步刷新生成的json数据的情况,并且通过python使用之前爬取静态网页内容的方式是不可以实现的,所以这篇文章将要讲述如果在python中爬取ajax动态生成的数据. 至于读取静态网页内容的方式,有兴趣的可以查看博客内容. 这里我们以爬取淘宝评论为例子讲解一下如何去做到的. 这里主要分为了四步: 一 获取淘宝评论时,ajax请求链接(url) 二 获取该ajax请求返回的json数据 三 使用python解析json数据 四

beautifulsoup库简单抓取网页--获取所有链接例子

简介: 通过BeautifulSoup 的 find_all方法,找出所有a标签中的href属性中包含http的内容,这就是我们要找的网页的一级链接( 这里不做深度遍历链接) 并返回符合上述条件的a标签的href属性的内容,这就是我们要找的某个网页的所带有的一级链接 #!/opt/yrd_soft/bin/python import re import urllib2 import requests import lxml from bs4 import BeautifulSoup url = 

58反抓取简介

0x00 介绍 网络爬虫,常又被称呼为Spider,网络机器人,主要模拟网络交互协议,长时间,大规模的获取目标数据. 普通爬虫会从网站的一个链接开始,不断收集网页资源,同时不断延伸抓取新获取的URL以及相应的资源. 在对抓取目标内容结构分析的基础上,还会有目的性更强的聚焦型爬虫. 爬虫对网站的抓取,最直接的影响就是增加服务器负载,影响正常业务的使用. 但是仅仅限制爬虫的抓取频次是远远不够的. 更重要的是对网站资源的保护,比如房产类信息中的小区名称.户型.建造年代.房型图.视频.面积.总价.单价等