GDI与DX截屏API操作

LPDIRECTDRAW lpDD      = NULL;
LPDIRECTDRAWSURFACE lpDDSPrime   = NULL;
LPDIRECTDRAWSURFACE lpDDSBack   = NULL;
LPDIRECTDRAWSURFACE lpDDSGdi   = NULL;

LPDIRECTDRAWSURFACE lpSurf    = NULL;

DDSURFACEDESC DDSdesc;
BOOL m_b24=TRUE;
//rfbServerInitMsg m_scrinfo;
RECT    m_bmrect;

struct _BMInfo {
BITMAPINFO   bmi;
BOOL    truecolour;
RGBQUAD    cmap[256];
} m_bminfo; // 用来保存位图信息的结构

 


// DirectX初始化。返回当前表面获取一张屏幕位图的存储空间大小
int DX_Init()
{
HRESULT hr;
// 初始化directX
hr = DirectDrawCreate(0, &lpDD, 0);
if (FAILED(hr))
   return FALSE;

hr = lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
if (FAILED(hr))
   return FALSE;

ZeroMemory(&DDSdesc, sizeof(DDSdesc));
DDSdesc.dwSize = sizeof(DDSdesc);
DDSdesc.dwFlags = DDSD_CAPS;
DDSdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = lpDD->CreateSurface(&DDSdesc, &lpDDSPrime, 0);
if (FAILED(hr))
   return FALSE;

hr = lpDD->GetGDISurface(&lpDDSGdi);
if (FAILED(hr))
   return FALSE;

ZeroMemory(&DDSdesc, sizeof(DDSdesc));
DDSdesc.dwSize = sizeof(DDSdesc);
DDSdesc.dwFlags = DDSD_ALL;
hr = lpDDSPrime->GetSurfaceDesc(&DDSdesc);
if (FAILED(hr))
   return FALSE;

// 初始化位图信息
if ((DDSdesc.dwFlags & DDSD_WIDTH) && (DDSdesc.dwFlags & DDSD_HEIGHT))
{
   m_bmrect.left = m_bmrect.top = 0;
   m_bmrect.right = DDSdesc.dwWidth;
   m_bmrect.bottom = DDSdesc.dwHeight;
}
else
   return FALSE;

m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;//BI_BITFIELDS;
m_bminfo.bmi.bmiHeader.biBitCount = DDSdesc.ddpfPixelFormat.dwRGBBitCount;

//m_bminfo.truecolour = DDSdesc.ddpfPixelFormat.dwFlags & DDPF_RGB;
if(m_bminfo.bmi.bmiHeader.biBitCount > 8)
   m_bminfo.truecolour = TRUE;
else
   m_bminfo.truecolour = FALSE;

ZeroMemory(&DDSdesc, sizeof(DDSdesc));
DDSdesc.dwSize = sizeof(DDSdesc);
DDSdesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
DDSdesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
DDSdesc.dwHeight = m_bmrect.bottom - m_bmrect.top;
DDSdesc.dwWidth   = m_bmrect.right - m_bmrect.left;
hr = lpDD->CreateSurface(&DDSdesc, &lpDDSBack, 0);
if (FAILED(hr))
   return FALSE;
//hr = lpDDSPrime->QueryInterface( IID_IDirectDrawSurface3, (LPVOID *)&lpSurf);
//if (FAILED(hr))
// return FALSE;

switch (m_bminfo.bmi.bmiHeader.biBitCount)
{
case 32:
case 24:
   // Update the bitmapinfo header
   m_b24 = TRUE;
   m_bminfo.bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
   m_bminfo.bmi.bmiHeader.biWidth = 1024;
   m_bminfo.bmi.bmiHeader.biHeight = 768;
   m_bminfo.bmi.bmiHeader.biPlanes = 1;
//   m_bminfo.bmi.bmiHeader.biBitCount = 24;
   m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;
   m_bminfo.bmi.bmiHeader.biSizeImage =
    abs((m_bminfo.bmi.bmiHeader.biWidth *
     m_bminfo.bmi.bmiHeader.biHeight *
     m_bminfo.bmi.bmiHeader.biBitCount)/ 8);
   m_bminfo.bmi.bmiHeader.biXPelsPerMeter = (1024*1000)/1024;
   m_bminfo.bmi.bmiHeader.biYPelsPerMeter = (768*1000)/768;
   m_bminfo.bmi.bmiHeader.biClrUsed   = 0;
   m_bminfo.bmi.bmiHeader.biClrImportant = 0;
   break;
}

return m_bminfo.bmi.bmiHeader.biSizeImage;
}
// 捕捉屏幕。rect: 区域。scrBuff: 输出缓冲。scrBuffSize: 缓冲区大小
BOOL CaptureScreen(RECT &rect, BYTE *scrBuff, UINT scrBuffSize)
{
HRESULT hr=0;

hr = lpDDSBack->BltFast(rect.left,rect.top,lpDDSPrime,&rect,DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
if (FAILED(hr))
{  
   return FALSE;
}

DDSURFACEDESC surfdesc;
ZeroMemory(&surfdesc, sizeof(surfdesc));
surfdesc.dwSize = sizeof(surfdesc);

hr   = lpDDSBack->Lock(&rect, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL);
//hr   = lpDDSPrime->Lock(&rect, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL);
if (FAILED(hr))
   return FALSE;

// copy the data into our buffer
BYTE * destbuffpos, * srcbuffpos;
// m_scrinfo.format.bitsPerPixel = 24;
srcbuffpos = (BYTE *) surfdesc.lpSurface;  
destbuffpos = scrBuff;

memcpy( destbuffpos, srcbuffpos,m_bminfo.bmi.bmiHeader.biSizeImage);

// unlock the primary surface
//lpDDSPrime->Unlock(surfdesc.lpSurface);
lpDDSBack->Unlock(surfdesc.lpSurface);
return TRUE;
}


int SaveBitmapToFile(BITMAP *bitmap, LPSTR lpFileName,char *lpBuf)
{
   DWORD dwWritten;
   BITMAPFILEHEADER   bmfHdr;
   BITMAPINFOHEADER   bi;           
   HANDLE          fh=NULL;
   bi.biSize = sizeof(BITMAPINFOHEADER);
   bi.biWidth= bitmap->bmWidth;
   bi.biHeight = bitmap->bmHeight;
   bi.biPlanes = 1;
   bi.biBitCount         =bitmap->bmBitsPixel*8;
   bi.biCompression      = BI_RGB;
   bi.biSizeImage        = 0;
   bi.biXPelsPerMeter     = 0;
   bi.biYPelsPerMeter     = 0;
   bi.biClrUsed         = 0;
   bi.biClrImportant      = 0;
   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"
   bmfHdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel;
   bmfHdr.bfReserved1 = 0;
   bmfHdr.bfReserved2 = 0;
   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
   WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
   WriteFile(fh, (char *)&bi,sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
   WriteFile(fh, (char *)lpBuf,bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel, &dwWritten, NULL);
   FlushFileBuffers(fh);
   CloseHandle(fh);
   return true;
}

int GetBitmapFromScreen(char *lpFileName)
{
char *lpBuf;
HBITMAP hBitmap,hOld ;
HDC hDC,hcDC;
BITMAP bb;BITMAPINFO b;
HANDLE hp,fh=NULL;
DWORD dwX,dwY;
//***************
dwX=GetSystemMetrics(SM_CXSCREEN);
dwY=GetSystemMetrics(SM_CYSCREEN);
hDC=GetDC(NULL);
hcDC=CreateCompatibleDC(hDC);
hBitmap=CreateCompatibleBitmap(hDC,dwX,dwY);
hOld=(HBITMAP)SelectObject(hcDC,hBitmap);
BitBlt(hcDC,0, 0,dwX,dwY, hDC, 0, 0, SRCCOPY);
bb.bmWidth=dwX;
bb.bmHeight =dwY;
bb.bmPlanes = 1;
bb.bmWidthBytes=bb.bmWidth*3;
bb.bmBitsPixel=3;
bb.bmType=0;
b.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
b.bmiHeader.biWidth=dwX;
b.bmiHeader.biHeight =dwY;
b.bmiHeader.biPlanes = 1;
b.bmiHeader.biBitCount        =3*8;
b.bmiHeader.biCompression      = BI_RGB;
b.bmiHeader.biSizeImage        = 0;
b.bmiHeader.biXPelsPerMeter     = 0;
b.bmiHeader.biYPelsPerMeter     = 0;
b.bmiHeader.biClrUsed         = 0;
b.bmiHeader.biClrImportant      = 0;
b.bmiColors[0].rgbBlue=8;
b.bmiColors[0].rgbGreen=8;
b.bmiColors[0].rgbRed=8;
b.bmiColors[0].rgbReserved=0;
hp=GetProcessHeap();
lpBuf=(char *)HeapAlloc(hp,HEAP_ZERO_MEMORY,bb.bmHeight*bb.bmWidth*4);
GetDIBits(hcDC,hBitmap,0,dwY,lpBuf,&b,DIB_RGB_COLORS);
SaveBitmapToFile(&bb,lpFileName,lpBuf);
ReleaseDC(NULL,hDC);
DeleteDC(hcDC);
DeleteObject(hBitmap);
DeleteObject(hOld);
HeapFree(hp,0,lpBuf);
return true;
}

---------------------------

思路:
(1)获取屏幕绘图设备
(2)创建一个与屏幕绘图设备相兼容的内存绘图设备
(2)在内存中创建一个与屏幕绘图设备相兼容的图像对象
(3)将屏幕设备中的图像复制到内存绘图设备中
(4)将内存图像保存到文件中

相关函数:
GetDIBits:按位的方式返回指定的BITMAP,并按指定的格式存储到内存中

代码:

int GetBitmapFromScreen( char * lpFileName)
{
    
char *lpBuf;
     HBITMAP hBitmap;
     HBITMAP hOld ;
     HDC hDC;
     HDC hcDC;
     BITMAP bb;
     BITMAPINFO b;
     HANDLE hp;
     HANDLE fh
= NULL;
     DWORD dwX;
     DWORD dwY;
    
     dwX
= GetSystemMetrics(SM_CXSCREEN);
     dwY
= GetSystemMetrics(SM_CYSCREEN);
     hDC
= GetDC(NULL);
     hcDC    
= CreateCompatibleDC(hDC);
     hBitmap
= CreateCompatibleBitmap(hDC,dwX,dwY);
     hOld    
= (HBITMAP)SelectObject(hcDC,hBitmap);
     BitBlt(hcDC,
0, 0,dwX,dwY, hDC, 0, 0, SRCCOPY);
     bb.bmWidth        
= dwX;
     bb.bmHeight        
= dwY;
     bb.bmPlanes        
= 1;
     bb.bmWidthBytes    
= bb.bmWidth*3;
     bb.bmBitsPixel    
= 3;
     bb.bmType        
= 0;
     b.bmiHeader.biSize        
= sizeof(BITMAPINFOHEADER);
     b.bmiHeader.biWidth        
= dwX;
     b.bmiHeader.biHeight    
= dwY;
     b.bmiHeader.biPlanes    
= 1;
     b.bmiHeader.biBitCount    
= 3*8;
     b.bmiHeader.biCompression    
= BI_RGB;
     b.bmiHeader.biSizeImage        
= 0;
     b.bmiHeader.biXPelsPerMeter    
= 0;
     b.bmiHeader.biYPelsPerMeter    
= 0;
     b.bmiHeader.biClrUsed        
= 0;
     b.bmiHeader.biClrImportant    
= 0;
     b.bmiColors[
0].rgbBlue        = 8;
     b.bmiColors[
0].rgbGreen        = 8;
     b.bmiColors[
0].rgbRed        = 8;
     b.bmiColors[
0].rgbReserved    = 0;
     hp        
= GetProcessHeap();
     lpBuf    
= (char *)HeapAlloc(hp,HEAP_ZERO_MEMORY,bb.bmHeight*bb.bmWidth*4);

     GetDIBits(hcDC,hBitmap,
0,dwY,lpBuf,&b,DIB_RGB_COLORS);
     SaveBitmapToFile(
&bb,lpFileName,lpBuf);
     ReleaseDC(NULL,hDC);
     DeleteDC(hcDC);
     DeleteObject(hBitmap);
     DeleteObject(hOld);
     HeapFree(hp,
0,lpBuf);
    
return true;
}

截图并保存位图的代码:  http://hi.baidu.com/%B4%F3%D5%AC%C0%C7/blog/item/4e313589ec49659da4c27292.html

如何抓取视频画面和游戏画面(一):  http://hi.baidu.com/%B4%F3%D5%AC%C0%C7/blog/item/78b69e1fee6becfd1bd57694.html

如何抓取视频画面和游戏画面(二):  http://hi.baidu.com/%B4%F3%D5%AC%C0%C7/blog/item/4724acc33a12673ce5dd3b95.html

Window Contents Capturing using WM_PRINT Message:  http://www.fengyuan.com/article/wmprint.html

  • 0
    点赞
  • 2
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值