/*--------------------------------------------------------------------
【函数介绍】: 在客户端的平台截取屏幕
【入口参数】: hWnd 为要截的窗口句柄,filename为图片保存的路径
【出口参数】: (无)
【返回  值】: 没有返回值
---------------------------------------------------------------------*/
void OnScreenSave(HWND hWnd,const char *filename)
{

DWORD dwRest = GetTickCount();
HDC  hScrDC = NULL;
HDC  hMemDC = NULL; 
//矩形窗口的高和宽
int  width = 0;
int  height = 0; 
//客户的坐标
long   nStartX = 0;
long   nStartY = 0;

//定义指向DIB数据区的指针
BYTE  *lpBitmapBits = NULL; 

//定义图形色深32位
int iPixel = 32;

//桌面或是窗口
if(hWnd==HWND_DESKTOP) 

width     =   GetSystemMetrics(SM_CXSCREEN); 
height   =   GetSystemMetrics(SM_CYSCREEN); 

else 

RECT   rc; 
GetClientRect(hWnd,&rc);
// GetWindowRect(hWnd,&rc);
width     =   rc.right-rc.left; 
height   =   rc.top-rc.bottom;
//矩形窗口的左上角坐标(x,y)
nStartX = rc.left;
nStartY = rc.top;
}
// hScrDC = GetWindowDC(hWnd);

//创建获取窗口的DC
hScrDC = GetDC(hWnd);


//获取屏幕参数
// nStartX = GetDeviceCaps(hScrDC, HORZRES);
// nStartY = GetDeviceCaps(hScrDC, VERTRES);

//创建内存DC
hMemDC = CreateCompatibleDC(hScrDC);

//初始化位图结构描述信息
BITMAPINFO bitmapInfo; 
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = iPixel;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = 0;
bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
bitmapInfo.bmiHeader.biClrUsed = 0;
bitmapInfo.bmiHeader.biClrImportant = 0;
//创建位图
HBITMAP directBmp = CreateDIBSection(hMemDC, (BITMAPINFO*)&bitmapInfo, 
DIB_RGB_COLORS, (void **)&lpBitmapBits, NULL, 0);
HGDIOBJ previousObject = SelectObject(hMemDC, directBmp);

//拷贝源DC到内存DC中

BOOL beel = BitBlt(hMemDC, 0, 0, width, height, hScrDC, nStartX, nStartY, SRCCOPY);

//初始化位图文件头结构
BITMAPFILEHEADER bmBITMAPFILEHEADER;
ZeroMemory(&bmBITMAPFILEHEADER, sizeof(BITMAPFILEHEADER));
bmBITMAPFILEHEADER.bfType = 0x4d42;  //bmp  
bmBITMAPFILEHEADER.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmBITMAPFILEHEADER.bfSize = bmBITMAPFILEHEADER.bfOffBits + ((width*height)*4); //分辨率乘以占用字节数4=(32 / 8),图像体积

//准备写文件
FILE *mStream = NULL;
if((mStream = fopen(filename, "wb")))
{  
//写位图头
fwrite(&bmBITMAPFILEHEADER, sizeof(BITMAPFILEHEADER), 1, mStream);
//写位图描述信息
fwrite(&(bitmapInfo.bmiHeader), sizeof(BITMAPINFOHEADER), 1, mStream);
//写RGB数据
fwrite(lpBitmapBits, 4*width*height, 1, mStream);

fclose(mStream);
}

//资源释放
SelectObject(hMemDC,previousObject);
DeleteObject(directBmp);
directBmp = NULL;
DeleteObject(hMemDC);
hMemDC = NULL;
DeleteObject(hScrDC);
hScrDC = NULL;
// delete lpBitmapBits;
// lpBitmapBits = NULL;

RETAILMSG(1,(TEXT("Screenshot spend %d ms\r\n"),GetTickCount()-dwRest));
}

解决方案 »

  1.   

    拷贝pWnd指向窗口的lpRect部分 写成BMP文件
      

  2.   

    确认抓到内存的数据是正确的吗?
    不清楚你抓的窗口图是什么,如果是用DDRAW OVERLAY播放的
    视频图象的话,这么抓肯定是抓不到的.
      

  3.   

    我以前写的EVC代码:HBITMAP CopyScreenToBitmap(int &nWidth, int &nHeight)
    {
    // 屏幕和内存设备描述表
    HDC  hScrDC, hMemDC;      
    // 位图句柄
    HBITMAP  hBitmap, hOldBitmap;    
    // 屏幕分辨率
    int  xScrn, yScrn;         

    //为屏幕创建设备描述表
    hScrDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
    //为屏幕设备描述表创建兼容的内存设备描述表
    hMemDC = CreateCompatibleDC(hScrDC);
    // 获得屏幕分辨率
    xScrn = GetDeviceCaps(hScrDC, HORZRES);
    yScrn = GetDeviceCaps(hScrDC, VERTRES); //存储屏幕的长宽
    nWidth = xScrn;
    nHeight = yScrn;

    // 创建一个与屏幕设备描述表兼容的位图
    hBitmap = CreateCompatibleBitmap(hScrDC, xScrn, yScrn);
    // 把新位图选到内存设备描述表中
    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
    // 把屏幕设备描述表拷贝到内存设备描述表中
    BitBlt(hMemDC, 0, 0, xScrn,yScrn,hScrDC, 0, 0, SRCCOPY);

    SaveDCToBMP(hMemDC,0,0,nWidth,nHeight,_T("\\TheScreen.bmp")); //得到屏幕位图的句柄
    hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
    //清除 
    DeleteDC(hScrDC);
    DeleteDC(hMemDC);
    // 返回位图句柄
    return hBitmap;
    }BOOL SaveDCToBMP(HDC hDC,int nStartX,int nStartY,int nWidth,int nHeight,LPCTSTR szFileName)
    {
    //定义图形色深
    int iPixel = 32;
    //位图信息头
    LPBITMAPINFO lpbmih = new BITMAPINFO;
    lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    lpbmih->bmiHeader.biWidth = nWidth;
    lpbmih->bmiHeader.biHeight = nHeight;
    lpbmih->bmiHeader.biPlanes = 1;
    lpbmih->bmiHeader.biBitCount = iPixel;
    lpbmih->bmiHeader.biCompression = BI_RGB;
    lpbmih->bmiHeader.biSizeImage = 0;
    lpbmih->bmiHeader.biXPelsPerMeter = 0;
    lpbmih->bmiHeader.biYPelsPerMeter = 0;
    lpbmih->bmiHeader.biClrUsed = 0;
    lpbmih->bmiHeader.biClrImportant = 0;
    lpbmih->bmiColors[1].rgbBlue=8;
    lpbmih->bmiColors[1].rgbGreen =8;
    lpbmih->bmiColors[1].rgbRed =8;
    lpbmih->bmiColors[1].rgbReserved =8;

    //创建位图数据
    HDC hdcMem;
    HBITMAP hBitMap = NULL;
    CBitmap *pBitMap = NULL;
    CDC *pMemDC = NULL;
    //BYTE *pBits;
    //hBitMap = CreateDIBSection(hdcMem,lpbmih,DIB_PAL_COLORS,(void **)&pBits,NULL,0);
    LPVOID pBits;
    hdcMem = CreateCompatibleDC(hDC);
    hBitMap = CreateDIBSection(hdcMem,lpbmih,DIB_RGB_COLORS,&pBits,NULL,0);
    if(!hBitMap)
    {
    CString lpMsgBuf="init error str(frx savebmp)";
    FormatMessage( 
    FORMAT_MESSAGE_ALLOCATE_BUFFER | 
    FORMAT_MESSAGE_FROM_SYSTEM | 
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    GetLastError(),
    0, // Default language
    (LPTSTR)(LPCTSTR)lpMsgBuf,
    0,
    NULL 
    );
    AfxMessageBox((LPCTSTR)lpMsgBuf);
    // Free the buffer.
    return false;
    }
    pBitMap = new CBitmap;
    pBitMap->Attach(hBitMap);
    pMemDC = new CDC;
    pMemDC->Attach(hdcMem);
    pMemDC->SelectObject(pBitMap);

    pMemDC->BitBlt(0,0,nWidth,nHeight,CDC::FromHandle(hDC),nStartX,nStartY,SRCCOPY);
    BITMAPFILEHEADER bmfh;//位图文件头
    ZeroMemory(&bmfh,sizeof(BITMAPFILEHEADER));
    *((char *)&bmfh.bfType) = 'B';
    *(((char *)&bmfh.bfType) + 1) = 'M';
    bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    bmfh.bfSize = bmfh.bfOffBits + (nWidth * nHeight) * iPixel / 8;
    int iBMPBytes = nWidth * nHeight * iPixel / 8;
    CFile file;
    if(file.Open(szFileName,CFile::modeWrite | CFile::modeCreate))
    {
    file.Write(&bmfh,sizeof(BITMAPFILEHEADER));
    file.Write(&(lpbmih->bmiHeader),sizeof(BITMAPINFOHEADER));
    file.Write(pBits,iBMPBytes);
    file.Close();
    }
    else return false;
    DeleteObject(hBitMap);
    DeleteObject(hDC);
    pMemDC->DeleteDC();
    delete pMemDC; pMemDC = NULL;
    delete pBitMap; pBitMap = NULL;
    delete lpbmih; lpbmih = NULL;
    return true;
    }
      

  4.   

    CopyScreenToBitmap是将当前屏幕保存为图片的代码。
    SaveDCToBMP是将DC保存为图片文件的公用函数。