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);
    }
  • 相关阅读:
    Silverlight 中使用不同面板进行布局的效果比较
    将PDF格式文件添加到iPhone4手机 iBooks程序中.
    [转]学习WPF参考书
    [转]OEM版XP SP3安装时提示“序列号无效”的解决方法
    关于系统响应函数OnSysCommand
    为何在自定义消息处理函数中无法利用wParam或lParam传递指针?
    自定义消息(上)
    VC++中单选与复选按钮的使用
    VC++ Combo Box/Combo Box Ex控件
    VC++中的ON_COMMAND_RANGE宏
  • 原文地址:https://www.cnblogs.com/tinaluo/p/5406646.html
Copyright © 2011-2022 走看看