zoukankan      html  css  js  c++  java
  • 基于visual c++之windows核心编程代码分析(40)实现屏幕截取

    屏幕截取器(Screen scraper)是允许一台 PC 来从主机上截取基于字符的数据和显示它在一个更容易了解的图形用户界面(GUI)上的一类软件。现在更新的屏幕截取器在 HTML 上显示信息,因此它能够用一个浏览器来访问。区别屏幕截取与常规剖析的关键因素在于被截取的输出是名义上送给人类消费,而不是机器解释。有很多屏幕截取的同义词在那里:数据抓取、数据萃取、网络抓取、网页包装和 HTML 抓取(后四个特定用于抓取 web 页面)。

    我们都体验过QQ的截图功能特别好使,下面我们亲自来实践基于C++开发一个我们自己的截图功能。

    请见代码讲解。

    #include<windows.h>
    
    HANDLE DDBtoDIB( HBITMAP bitmap, DWORD dwCompression, HPALETTE  hPal,DWORD * sizeimage) ;
    BOOL CapScreen(LPTSTR FileName);//截屏函数
    
    HANDLE DDBtoDIB( HBITMAP bitmap, DWORD dwCompression, HPALETTE  hPal,DWORD * sizeimage) 
    {
        BITMAP            bm;
        BITMAPINFOHEADER    bi;
         LPBITMAPINFOHEADER     lpbi;
        DWORD            dwLen;
        HANDLE            hDib;
        HANDLE            handle;
        HDC             hdc;
    
        //不支持BI_BITFIELDS类型
        if( dwCompression == BI_BITFIELDS )
            return NULL;
    
        //如果调色板为空,则用默认调色板
        if (hPal==NULL)
            hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE );
    
        //获取位图信息
        GetObject(bitmap,sizeof(bm),(LPSTR)&bm);
    
        //初始化位图信息头
        bi.biSize        = sizeof(BITMAPINFOHEADER);
        bi.biWidth        = bm.bmWidth;
        bi.biHeight         = bm.bmHeight;
        bi.biPlanes         = 1;
        bi.biBitCount        = bm.bmPlanes * bm.bmBitsPixel;
        bi.biCompression    = dwCompression;
        bi.biSizeImage        = 0;
        bi.biXPelsPerMeter    = 0;
        bi.biYPelsPerMeter    = 0;
        bi.biClrUsed        = 0;
        bi.biClrImportant    = 0;
    
        //计算信息头及颜色表大小
        int ncolors = (1 << bi.biBitCount); if( ncolors> 256 ) 
            ncolors = 0;
        dwLen  = bi.biSize + ncolors * sizeof(RGBQUAD);
    
        // we need a device context to get the dib from
        hdc = GetDC(NULL);
        hPal = SelectPalette(hdc,hPal,FALSE);
        RealizePalette(hdc);
    
        //为信息头及颜色表分配内存
        hDib = GlobalAlloc(GMEM_FIXED,dwLen);
    
        if (!hDib){
            SelectPalette(hdc,hPal,FALSE);
            ReleaseDC(NULL,hdc);
            return NULL;
        }
    
        lpbi = (LPBITMAPINFOHEADER)hDib;
        *lpbi = bi;
        //调用 GetDIBits 计算图像大小
        GetDIBits(hdc, bitmap, 0L, (DWORD)bi.biHeight,
                (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS );
    
        bi = *lpbi;
        //图像的每一行都对齐(32bit)边界
    	if (bi.biSizeImage == 0){
            bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 
                            * bi.biHeight;
        if (dwCompression != BI_RGB)
                bi.biSizeImage = (bi.biSizeImage * 3) / 2;
        }
    
        //重新分配内存大小,以便放下所有数据
        dwLen += bi.biSizeImage;
        if (handle = GlobalReAlloc(hDib, dwLen, GMEM_MOVEABLE))
            hDib = handle;
        else{
            GlobalFree(hDib);
    
            //重选原始调色板
            SelectPalette(hdc,hPal,FALSE);
            ReleaseDC(NULL,hdc);
            return NULL;
        }
    
        //获取位图数据
        lpbi = (LPBITMAPINFOHEADER)hDib;
    
        //最终获得的DIB
        BOOL bgotbits = GetDIBits( hdc, bitmap,
                      0L,                      //扫描行起始处
                    (DWORD)bi.biHeight,      //扫描行数
                    (LPBYTE)lpbi             //位图数据地址
                    + (bi.biSize + ncolors * sizeof(RGBQUAD)),
                    (LPBITMAPINFO)lpbi,      //位图信息地址
                    (DWORD)DIB_RGB_COLORS);  //颜色板使用RGB
    
        if( !bgotbits )
        {
            GlobalFree(hDib);
            
            SelectPalette(hdc,hPal,FALSE);
            ReleaseDC(NULL,hdc);
    		return NULL;
        }
    
        SelectPalette(hdc,hPal,FALSE);
        ReleaseDC(NULL,hdc);
    	*sizeimage=bi.biSizeImage;
        return hDib;
    } 
    
    BOOL CapScreen(LPTSTR FileName)
    {
    	DWORD sizeimage;
    	HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL); 
    	HDC CompatibleHDC = CreateCompatibleDC(hdc); 
    	HBITMAP BmpScreen = CreateCompatibleBitmap(hdc,GetDeviceCaps(hdc, HORZRES),GetDeviceCaps(hdc, VERTRES)); 
    	SelectObject(CompatibleHDC, BmpScreen);
    	BitBlt(CompatibleHDC,0,0,GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES),hdc,0,0,SRCCOPY);
    	
    HANDLE	pbitmapwithoutfileh=DDBtoDIB(BmpScreen, BI_RGB,0,&sizeimage);
    	BITMAPFILEHEADER bfh;
       //设置位图信息头结构
    	bfh.bfType = ((WORD)('M'<< 8)|'B');
    	bfh.bfReserved1 = 0;
    	bfh.bfReserved2 = 0;
    	bfh.bfSize = 54+sizeimage;
    	bfh.bfOffBits = 54;
    	//创建位图文件    
    HANDLE  hFile=CreateFile(FileName,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
    DWORD dwWrite;
    // 写入位图文件头
    WriteFile(hFile,&bfh,sizeof(BITMAPFILEHEADER),&dwWrite,NULL);
    // 写入位图文件其余内容
    WriteFile(hFile,pbitmapwithoutfileh,bfh.bfSize,&dwWrite,NULL);  
    DeleteDC(hdc);
       
    CloseHandle(CompatibleHDC);
    return true;
    }
    
    int main(void)
    {
    CapScreen("d:\\desktop.bmp");
    return 0;
    }


     

  • 相关阅读:
    NETCore EF 数据库连接正确nuget和MySql错误异常
    JS 对象属性名排序
    NET 在一个数组中查找另一个数组所在起始位置(下标从0开始,未找到返回-1)
    NET 判断是否为回文
    NET/Regex 处理连续空格
    NET 已知excel表格前面26个是a到z,27是aa28是ab,以此类推,N是多少
    Regex 首字母转大写/小写,全大写,全小写
    .NETCore下访问img、js等静态资源404解决办法
    WPF-后台代码使用Behavior
    Socket-服务器端与客户端互相通信
  • 原文地址:https://www.cnblogs.com/new0801/p/6177785.html
Copyright © 2011-2022 走看看