下面是将窗口内的图像采集生成一个BITMAP文件的过程,只要在去掉存储的过程,在修改一下采集的范围就可以使用,在类似于ONTIME之类的过程中调用,就可以实时处理了
  m_hMciWnd  是播放窗口的句柄
HDC hdcDC = ::GetDC(m_hMciWnd);
RECT rcRect;
::GetClientRect(m_hMciWnd ,&rcRect);
HDC memDC;
memDC = ::CreateCompatibleDC(hdcDC);
HBITMAP hbitmap = ::CreateCompatibleBitmap(hdcDC, rcRect.right,rcRect.bottom);
HBITMAP holdbitmap = (HBITMAP)::SelectObject(memDC, hbitmap); ::ShowWindow(m_hMciWnd, SW_HIDE);
Sleep(500);
::ShowWindow(m_hMciWnd, SW_SHOWNA);
::SetWindowPos(m_hMciWnd, NULL, rcRect.left, rcRect.right, (rcRect.right - rcRect.left)/2,
(rcRect.bottom - rcRect.top)/2, SWP_NOMOVE);
::SetWindowPos(m_hMciWnd, NULL, rcRect.left, rcRect.right, rcRect.right - rcRect.left,
rcRect.bottom - rcRect.top, SWP_NOMOVE); int b = ::BitBlt(memDC, rcRect.left,rcRect.top,rcRect.right,rcRect.bottom,
hdcDC,0,0, SRCCOPY);
if(strFileName.IsEmpty())
{
CFileDialog BmpFile(FALSE,"BMP",strFileName,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
"BMP图像文件 (*.bmp)|*.bmp||");
if(BmpFile.DoModal() != IDOK)
{
::SelectObject(memDC,holdbitmap);
::DeleteDC(hdcDC);
::DeleteDC(memDC);
if(result == MCI_MODE_PLAY)
MCIWndPlay(m_hMciWnd);
return FALSE;
}
strFileName = BmpFile.GetFileName();
}
CBitmap *bitmap = CBitmap::FromHandle(hbitmap);
BITMAP bitmapinfo;
bitmap->GetBitmap(&bitmapinfo);
WORD    cClrBits; 
cClrBits = (WORD)(bitmapinfo.bmPlanes * bitmapinfo.bmBitsPixel); 
if (cClrBits == 1) 
        cClrBits = 1; 
else if (cClrBits <= 4)   
cClrBits = 4; 
else if (cClrBits <= 8)  
cClrBits = 8; 
else if (cClrBits <= 16) 
cClrBits = 16;   
else if (cClrBits <= 24)    
cClrBits = 24; 
else cClrBits = 32; 
PBITMAPINFO pbmi; 
if (cClrBits != 24)       
pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                    sizeof(BITMAPINFOHEADER) + 
                    sizeof(RGBQUAD) * (1<< cClrBits)); 
else 
         pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                    sizeof(BITMAPINFOHEADER));  pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
pbmi->bmiHeader.biWidth = bitmapinfo.bmWidth; 
pbmi->bmiHeader.biHeight = bitmapinfo.bmHeight; 
pbmi->bmiHeader.biPlanes = bitmapinfo.bmPlanes; 
pbmi->bmiHeader.biBitCount = bitmapinfo.bmBitsPixel;  
if (cClrBits < 24) 
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);  pbmi->bmiHeader.biCompression = BI_RGB; 
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                  * pbmi->bmiHeader.biHeight; 
pbmi->bmiHeader.biClrImportant = 0; 
PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbmi;  
LPBYTE lpBits;     
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
::GetDIBits(memDC, hbitmap, 0, (WORD) pbih->biHeight, lpBits, pbmi, 
DIB_RGB_COLORS);
BITMAPFILEHEADER fiHead;
fiHead.bfType = 0x4d42;
fiHead.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
 pbih->biSize + 
 pbih->biClrUsed* sizeof(RGBQUAD) + 
 pbih->biSizeImage);
fiHead.bfReserved1 = 0;
fiHead.bfReserved2 = 0;
fiHead.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
pbih->biSize + 
pbih->biClrUsed* sizeof (RGBQUAD); 
CFile file(strFileName,CFile::modeCreate | CFile::modeWrite);
file.WriteHuge(&fiHead, sizeof(BITMAPFILEHEADER));
file.WriteHuge((LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
                  + pbih->biClrUsed * sizeof (RGBQUAD)) ;
DWORD dwTotal;
DWORD cb;
BYTE *hp;
dwTotal = cb = pbih->biSizeImage;     
hp = lpBits; 
file.WriteHuge((LPSTR) hp, (int) cb);
file.Close();
GlobalFree((HGLOBAL)lpBits);
::SelectObject(memDC,holdbitmap);
::DeleteDC(hdcDC);
::DeleteDC(memDC);
if(result == MCI_MODE_PLAY)
MCIWndPlay(m_hMciWnd);
Invalidate();

解决方案 »

  1.   

    先谢谢这位兄台了!不过你的代码和平常的屏幕抓图是一样的,还是不能截AVI的图像啊?
      

  2.   

    我也需要关于截取当前播放的AVI影片的图片参考代码。关注ing……
      

  3.   

    To ndugu:
    我想是否可以用内嵌汇编语言直接读取显卡内容?《Windows图形编程》有这个例程,我还没试的。
      

  4.   

    呵呵,我都忘了这回事了,后来我改用usb摄像头来拍,通过vfw来取dib数据
    ,已经搞定了。
    后来我发现其实只要不是使用directDraw来播放的AVI窗口,通常的屏幕捕捉代码都可以实现的。
    如果没什么其他问题,这个帖子近日内可以结掉了,谢谢。