PersonalCorpus 版 (精华区)


    前两天,老板突然发现视频分析系统的合同上有要求分析网络媒体流的条款,小组
里几个人说用RealPlay和MidiaPlayer播放视频的时候不能得到帧信息,然后老板就说,
那就抓图吧,把屏幕抓下来存成bmp图像,然后再分析。这样,我就做了一些抓图的程序
。但后来才发现RealPlay和MidiaPlay以及解霸2001都是用DirectX写的,用GDI的函数很
难抓下来,大多数情况只能抓到一个黑框。

    后来偶师兄xp用DirectX的方法做了一次,还是不能保证正确的抓取,后来来就只有
自己做了个可以播放网络视频的媒体播放器嵌入到系统中(算通公司一个姓张的人做的
,不是我)。

    但这样一来,对Windows抓屏的方法倒是了解了不少。现在将代码都贴出来,一来为
了大家方便,二来自己将来要再用到的时候就免得到处去找了。

设定成员变量 HWND m_hwndFoundWindow; 该变量为要抓取的窗口的句柄

第一步,获得被抓取区域的句柄:
    1,抓取屏幕:

HWND GetScreenHandle()
{
    return  GetDesktopWindow();
}
    
    2,抓取当前激活状态的程序窗口区域:
HWND GetActiveWindowHandle()
{
    return  GetForegroundWindow();
}

    3,抓取指定程序窗口:
可用Spy++工具先获得程序主窗口类名,比如我用的视频采集的程序窗口的类名为:
“#1000”
HWND GetTheWindowHandle()
{
    return FindWindow("#1000",NULL);
          
}

如果还要找到其子窗口
HWND GetTheWindowHandle()
{
    HWND  hParentWnd = FindWindow("#1000",NULL);
    if(hParentWnd)
    {
        return FindWindowEx(hWndMDP,NULL,"VideoRenderer",NULL);
            //VideoRenderer为Spy++探测到的子窗口类名
    }
    
}

第二步,创立抓屏函数
CaptureWindow(HWND hWnd,BOOL FullWnd)
{
    CWnd *wnd = (CWnd *)CWnd::FromHandle (hWnd);
     CDC *dc;
    CMainFrame* pAppFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
    ASSERT_KINDOF(CMainFrame, pAppFrame);
    CClientDC pDC(pAppFrame);

    if(FullWnd)
    { // 抓取整个窗口
        dc = new CWindowDC(wnd);
     } // 抓取整个窗口
     else
     { // 仅抓取客户区时
         dc = new CClientDC(wnd);
      } // 仅抓取客户区时
     CDC memDC;
     memDC.CreateCompatibleDC(dc);
     CBitmap bm;
     CRect r;
     if(FullWnd)
        wnd->GetWindowRect(&r);
     else
         wnd->GetClientRect(&r);
     CString s;
     wnd->GetWindowText(s);
     CSize sz(r.Width(), r.Height());
     bm.CreateCompatibleBitmap(dc, sz.cx, sz.cy);
     CBitmap * oldbm = memDC.SelectObject(&bm);
     pDC.BitBlt(0,45, sz.cx, sz.cy, dc, 0, 0, SRCCOPY);
     pDC.TextOut(0,0,m_strCount+".bmp");
     //直接调用OpenClipboard(),而不用wnd->GetParent()->OpenClipboard();
    wnd->OpenClipboard();
     ::EmptyClipboard();
     ::SetClipboardData(CF_BITMAP, bm.m_hObject);
     CloseClipboard();
    //恢复原始环境
     memDC.SelectObject(oldbm);
     bm.Detach();
    delete dc;
}

第三步,保存位图
aveImg()
{
    //获取选中图像窗口的位图句柄
    CDC dc;
    HDC hdc = ::GetWindowDC(m_hwndFoundWindow);
    dc.Attach(hdc);
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);

    CBitmap bm;
    CRect r;
    CString strFileName ="D:\\test\\test.bmp"; 自定义文件名
    ((CWnd *)CWnd::FromHandle(m_hwndFoundWindow))->GetWindowRect(&r);

    CSize sz(r.Width(), r.Height());
    bm.CreateCompatibleBitmap(&dc, sz.cx, sz.cy);
    CBitmap * oldbm = memDC.SelectObject(&bm);
    memDC.BitBlt(0, 0, sz.cx, sz.cy, &dc, 0, 0, SRCCOPY);

    //保存为指定位图文件
    if(!SaveImgtoFile((HBITMAP)bm.m_hObject,strFileName))
    {
         MessageBox(NULL,"位图保存失败!",NULL,MB_OK);
        return ;
    }

    //恢复原始环境
    memDC.SelectObject(oldbm);
    bm.Detach();
}


第四步,保存位图文件
SaveImgtoFile(HBITMAP hBitmap , CString lpFileName)
{
    HDC    hDC;       //设备描述表
    int    iBits;       //当前显示分辨率下每个像素所占字节数
    WORD            wBitCount;      //位图中每个像素所占字节数
    DWORD           dwPaletteSize=0,    //定义调色板大小, 位图中像素字节大小 ,
                                        //位图文件大小 , 写入文件字节数
    dwBmBitsSize,
    dwDIBSize, dwWritten;
    BITMAP          Bitmap;
    BITMAPFILEHEADER   bmfHdr;      //位图属性结构
    BITMAPINFOHEADER   bi;       //位图文件头结构
    LPBITMAPINFOHEADER lpbi;      //位图信息头结构
    HANDLE          fh, hDib, hPal,hOldPal=NULL; //指向位图信息头结构,定义文
                                               // 件,分配内存句柄,调色板句柄
   //计算位图文件每个像素所占字节数
   hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
   iBits = GetDeviceCaps(hDC, BITSPIXEL) *  GetDeviceCaps(hDC, PLANES);
   DeleteDC(hDC);
   if (iBits <= 1)
      wBitCount = 1;
   else if (iBits <= 4)
      wBitCount = 4;
   else if (iBits <= 8)
      wBitCount = 8;
   else if (iBits <= 24)
      wBitCount = 24;
   else if(iBits <= 32)
    wBitCount = 32;
   //计算调色板大小
   if (wBitCount <= 8)
      dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);
   //设置位图信息头结构
   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
   bi.biSize            = sizeof(BITMAPINFOHEADER);
   bi.biWidth           = Bitmap.bmWidth;
   bi.biHeight          = Bitmap.bmHeight;
   bi.biPlanes          = 1;
   bi.biBitCount         = wBitCount;
   bi.biCompression      = BI_RGB;
   bi.biSizeImage        = 0;
   bi.biXPelsPerMeter     = 0;
   bi.biYPelsPerMeter     = 0;
   bi.biClrUsed         = 0;
   bi.biClrImportant      = 0;
   dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32)* 4
  *Bitmap.bmHeight ;
   //为位图内容分配内存
   hDib  = GlobalAlloc(GHND,dwBmBitsSize+
 dwPaletteSize+sizeof(BITMAPINFOHEADER));
   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
   *lpbi = bi;
   // 处理调色板
   hPal = GetStockObject(DEFAULT_PALETTE);
   if (hPal)
   {
    hDC  = ::GetDC(NULL);
    hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
       RealizePalette(hDC);
   }
   // 获取该调色板下新的像素值
   GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
  (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
  (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
   //恢复调色板
   if (hOldPal)
   {
      SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
      RealizePalette(hDC);
      ::ReleaseDC(NULL, hDC);
   }
   //创建位图文件
 fh = CreateFile(lpFileName, GENERIC_WRITE,
   0, NULL, CREATE_ALWAYS,
         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
   if (fh == INVALID_HANDLE_VALUE)
      return FALSE;
   // 设置位图文件头
   bmfHdr.bfType = 0x4D42;  // "BM"
   dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPa
letteSize + dwBmBitsSize;
   bmfHdr.bfSize = dwDIBSize;
   bmfHdr.bfReserved1 = 0;
   bmfHdr.bfReserved2 = 0;
   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)
      + (DWORD)sizeof(BITMAPINFOHEADER)
     + dwPaletteSize;
   // 写入位图文件头
   WriteFile(fh, (LPSTR)&bmfHdr, sizeof
 (BITMAPFILEHEADER), &dwWritten, NULL);
   // 写入位图文件其余内容
   WriteFile(fh, (LPSTR)lpbi, dwDIBSize,
   &dwWritten, NULL);
   //消除内存分配
   GlobalUnlock(hDib);
   GlobalFree(hDib);
   CloseHandle(fh);
   return TRUE;
}

第五步,抓取窗口并保存位图
以抓取全屏为例
Void OnCapture()
{
    m_hwndFoundWindow = GetScreenHandle();
    if(m_hwndFoundWindow)
    {
        CaptureWindow(m_hwndFoundWindow);
    }
    SaveImg();
}
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.051毫秒