zoukankan      html  css  js  c++  java
  • 屏幕抓取程序 (位图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);
    }
  • 相关阅读:
    实例属性 类属性 实例域 类域
    研究数据集
    static 静态域 类域 静态方法 工厂方法 he use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class 非访问修饰符
    accessor mothod mutator mothod 更改器方法 访问器方法 类的方法可以访问类的任何一个对象的私有域!
    上钻 下钻 切片 转轴 降采样
    识别会话
    Performance Tuning Using Linux Process Management Commands
    Secure Hash Algorithm 3
    grouped differently across partitions
    spark 划分stage Wide vs Narrow Dependencies 窄依赖 宽依赖 解析 作业 job stage 阶段 RDD有向无环图拆分 任务 Task 网络传输和计算开销 任务集 taskset
  • 原文地址:https://www.cnblogs.com/tinaluo/p/5406646.html
Copyright © 2011-2022 走看看