本人对 GDI 不熟悉,可目前又急需高效的抓屏方法,用 C + GDI 的就行,
 请不要说写驱动或 DirectShow 之类的,
 BitBlt 这种常规方法的已经实现了,但希望找到一种速度更快的方法,
 据说 GetDIBits、GetObject、GetCurrentObject 之类的某个函数可以直接从
 屏幕 HDC 中取得 BITMAP,不知到该怎么写
 
 大家帮帮忙,高分相赠。谢谢!!!

解决方案 »

  1.   

    http://community.csdn.net/Expert/topic/4867/4867627.xml?temp=.3163721
    http://community.csdn.net/Expert/topic/4867/4867625.xml?temp=.266659
    http://community.csdn.net/Expert/topic/4867/4867626.xml?temp=.2284204
      

  2.   

    blog.joycode.com/jiangsheng/ archive/2004/01/01/10410.aspx
      

  3.   

    需要截获显示器的显示内容,首先创建显示器的设备内容句柄,也就是在GetDC的时候传入一个NULL,而不是某个窗口的句柄,传入NULL可以获得整个当前屏幕的设备内容句柄。然后再准备一个内存位图和一个内存DC,把内存位图选入内存Dc,并且用Bitblt把整个屏幕的位图画到内存位图上,从而完成截图的过程。如果你需要一个简单的示例,可以发邮件给我。[email protected]
      

  4.   

    HDC hScreen = GetDC(NULL);   // 取得屏幕 DC能不能直接从这个 DC 中察看 BITMAP 中某些点的 RGB 数据? (不用 GetPixel)另外,谁知道 BitBlt 和 GetDIBits 的区别和效率有什么不同呢?
      

  5.   

    改用 CreateDIBSection、DIBSection 速度会有提高么?
      

  6.   

    HDC hScreen = GetDC(NULL);   // 取得屏幕 DC
    HBITMAP hBmp = (HBITMAP) GetCurrentObject (hScreen, OBJ_BITMAP);
       // 取得屏幕DC装载的位图句柄BITMAPINFO bh = {0};
    bh.bmiHeader.biSize = sizeof(bh.bmiHeader);
    GetDIBits(hScreen, hBmp, 0, 0, NULL, &bh, DIB_RGB_COLORS); // 查询BITMAPINFO int nBitClrUsed = 0;
    if (bh.bmiHeader.biBitCount == 24)
        nBitClrUsed = 3;  // 每个像素占用的字节数,以24位为例,其余色深自己判断
    BYTE * bits =new BYTE[bh.bmiHeader.biWidth * bh.bmiHeader.biHeight * nBitClrUsed];
    GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);
           // 获得整张位图的数据,保存到bits指向的空间然后就可以按图像的坐标在bits中查找你要的像素的RGB信息了。
    BitBlt 是复制位图,GetDIBits 是取位图的位图数组。
    此外,有一个结论是,BitBlt将图像从屏幕拷到内存DC较慢,而用BitBlt将图像从内存DC拷到屏幕则相对快一些。
      

  7.   

    再精确下去,你其实就不要在GDI上下功夫了,提高效率也有限还是DShow来得快些。。
      

  8.   

    多谢羽兄
    我对 DirectX 更陌生,暂时没空研究了。请问 GetDIBits 比 BitBlt 能快多少呢?
    (我的目标不是完整的BMP,只要能得到 "RGB位图数组" 就可以了:)另外在 http://www.shenming.net/shen/oblog/user1/shenming/archives/2006/50.html
    中提到 DIBSection 要更快些,要从 Screen 获取 DIBSection 应该按怎样的顺序调用呢?我想从 BitBlt、GetDIBits、DIBsection 中选择一个最快的方法就可以了
      

  9.   


    pomelowu兄,上面的代码可以执行,我把他放在一个函数里
     
    void TestRGB( void )
    {
        HDC hDC = GetDC( NULL );
        ..........
        ..........  // 获取 bits 的代码,除了颜色位那里,其它未作任何修改
        ..........
        GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);
        // 监视此处 GetDIBits() 返回的扫描行是 768,正常!    return;   // 执行到 return 会抛出个异常,
                  // 内存错误之类的,用 Debug 捕获不到
    }测试环境如下:
        XP Sp2,
        VS.Net 2005,
        Win32 Console Project [C++]
        颜色: 16, 32 位模式分别测试
    ==============================================================================另外 bh.bmiHeader.biBitCount 如果为 16 和 32,nBitClrUsed 应该是几呢?
    初学 GDI,见笑了...
      

  10.   

    执行到 return 会抛出个异常估计是写stack变量时越界,覆盖了返回地址。检查你对局部变量的写入操作。
      

  11.   

    void TestRGB( void )
    {
        HDC hScreen = GetDC(NULL);
        HBITMAP hBmp = (HBITMAP) GetCurrentObject (hScreen, OBJ_BITMAP);    BITMAPINFO bh = {0};
        bh.bmiHeader.biSize = sizeof(bh.bmiHeader);
        GetDIBits(hScreen, hBmp, 0, 0, NULL, &bh, DIB_RGB_COLORS);    int nBitClrUsed = 0;
        if (bh.bmiHeader.biBitCount == 24)
            nBitClrUsed = 3;
        else if(bh.bmiHeader.biBitCount == 16)
            nBitClrUsed = 3;
        else if(bh.bmiHeader.biBitCount == 32)
            nBitClrUsed = 4;    BYTE * bits =new BYTE[ bh.bmiHeader.biWidth * bh.bmiHeader.biHeight * nBitClrUsed ];
        GetDIBits(hScreen, hBmp, 0, bh.bmiHeader.biHeight, bits, &bh, DIB_RGB_COLORS);    return;
    }这就是那个函数,有什么地方会操作了 stack 呢?
      

  12.   

    if(bh.bmiHeader.biBitCount == 16)
            nBitClrUsed = 2;自己在单步调试的时候监视&hScreen之前的几个字节就可以看到
      

  13.   

    改成if(bh.bmiHeader.biBitCount == 16)
            nBitClrUsed = 2;
    ...可问题依旧...  应该如何解决呢?