读书人

mfc 怎么把当前窗口的内容保存到图片

发布时间: 2012-02-17 17:50:42 作者: rapoo

mfc 如何把当前窗口的内容保存到图片
使用GDI
在网上找了些方法可以对屏幕进行截图。
但是我需要截图的窗口有被遮挡的时候。所有没有达到预期的效果
HBITMAP FSPictureBox::CopyScreenToBitmap()
{
HDC hScrDC,hMemDC;//屏幕和内存设备描述表
HBITMAP hBitmap,hOldBitmap;//位图句柄
if(IsRectEmpty(rect)) return NULL;
//为屏幕创建设备描述表
//hScrDC=CreateCompatibleDC(NULL);
//hScrDC=::GetDC(this->m_hWnd);
hScrDC=GetWindowDC()->GetSafeHdc();
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC=CreateCompatibleDC(hScrDC);
//创建一个与屏幕设备描述表兼容的位图
hBitmap=CreateCompatibleBitmap(hScrDC,rect.Width(),rect.Height());
//把新位衅选到内存设备描述表中
hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
//把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC,-2,-2,rect.Width(),rect.Height(),hScrDC,0,0,SRCCOPY);
//得到屏幕位图句柄
hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
DeleteDC(hScrDC);
DeleteDC(hMemDC);
return hBitmap;
}
请问有什么办法只得到窗口的内容,不管是否遮挡。
(我写的是个类,继承于Static)

[解决办法]
请问有什么办法只得到窗口的内容,不管是否遮挡。 //获得窗口的HDC,然后把你原来源码里屏幕的HDC换成那个窗口的HDC
[解决办法]
接分去散
[解决办法]
不懂
学习去了
[解决办法]

C/C++ code
//////////////////////////////////////////////////////////////////Function Name :BOOL WndToBmpFile(CDC *pDC, CString szFile)Parameters:  CDC *pDC: is pointer to window DC whose image should be    captured.  CString szFile : is null terminated string with that name Bmp    file should be saved.////////////////////////////////////////////////////////////////////it will capture a wnd image and save it into a bmp fileBOOL WndToBmpFile(CDC *pDC, CString szFile){//it will capture a wnd image and save it into a bmp file  CString fname=szFile;  CBitmap bmp,*pOldBmp;  CRect rect;  CWnd *pWnd;  BOOL flg=0;  CPalette pal;  LOGPALETTE *pLp;  if(pDC==NULL)               //if pDC is NULL return    {    return FALSE;    }  pWnd=pDC->GetWindow();      //Get Window of PDC  pWnd->GetClientRect(&rect); //Get dimension of Window  if(fname.IsEmpty())    return FALSE;  CDC memdc;  memdc.CreateCompatibleDC(pDC);  //Make Compatible DC for memdc  bmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());    //Create Compatible DDB  pOldBmp=memdc.SelectObject(&bmp);  memdc.BitBlt(0,0,rect.Width(),rect.Height(),pDC,0,0,SRCCOPY);//The following code will detect whether the BMP uses a Raster//palette or not.  if(pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)  {    int nSize;    nSize=sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256;    pLp=(LOGPALETTE*) new BYTE[nSize];    pLp->palVersion=0x300;    pLp->palNumEntries=GetSystemPaletteEntries(         pDC->m_hDC,0,255,pLp->palPalEntry);    pal.CreatePalette(pLp);    delete [] pLp;  }  memdc.SelectObject(pOldBmp);//will convert bitmap from DDB to DIB see DDBToDIB()// See DDBToDIB function for more..  HANDLE hDIB=DDBToDIB(bmp,BI_RGB,&pal);  if(hDIB==NULL)    return FALSE;//*************************************//This code writes the BMP file  CFile m_file;  if(!m_file.Open(fname,CFile::modeWrite |                  CFile::modeCreate,NULL))    return FALSE;  BITMAPFILEHEADER hdr;  LPBITMAPINFOHEADER lpbi;  lpbi=(LPBITMAPINFOHEADER ) hDIB;  int nColors= 1 << lpbi->biBitCount;  hdr.bfType= ((WORD) ('M' << 8) | 'B');  hdr.bfSize=sizeof(hdr) + GlobalSize(hDIB);  hdr.bfReserved1=0;  hdr.bfReserved2=0;  hdr.bfOffBits=(DWORD) sizeof(hdr) + nColors * sizeof(RGBQUAD);  m_file.Write(&hdr,sizeof(hdr));  m_file.Write(lpbi,GlobalSize(hDIB));  m_file.Close();//**************************************//This is the tricky part of the code. It will open the BMP file//again, but in Binary Mode. Then, it will read the first 14//bytes from the bitmap file.//It will change the 11th byte from 11 to 36.//It will change the 14th byte from 4 to 0 because this is the//basic requirement for the bitmap format.//So, it will support all PaintBrush Tools and thumbnail views//of Windows Explorer.  CBinFile  m_tempFile;    //CBinFile is derived from CFile  BYTE dummy=0;//14        //14  BYTE pBuf[14];           //11  BOOL fres=m_tempFile.Open(fname,CFile::modeReadWrite |                                  CFile::typeBinary);  if(fres==0)    return FALSE;  UINT tt=m_tempFile.Read(pBuf,14);  pBuf[13]=dummy;//will replace from 04 to 00  m_tempFile.SeekToBegin();  m_tempFile.Write(pBuf,14);  m_tempFile.Close();  return flg;//it will capture wnd and save into a bmp file//End of the code}//////////////////////////////////////////////////////////////////Function Name :HANDLE DDBToDIB(CBitmap &bitmap,                               DWORD dwCompression,                               CPalette *pPal)Parameters:  CBitmap &bitmap : Compatible Device Dependent Bitmap  DWORD dwCompression : Compression format for Bitmap must not be  BI_BITFIELDS in this case.  CPalette *pPal : Pointer to Palette. If this is NULL, the  default system palette will be used.//////////////////////////////////////////////////////////////////HANDLE DDBToDIB(CBitmap &bitmap, DWORD dwCompression,                CPalette *pPal){  BITMAP              bm;  BITMAPINFOHEADER    bi;  LPBITMAPINFOHEADER  lpbi;  DWORD               dwLen;  HANDLE              hDIB;  HANDLE              handle;  HDC                 hDC;  HPALETTE            hPal;  ASSERT( bitmap.GetSafeHandle() );  // The function has no arg for bitfields  if( dwCompression == BI_BITFIELDS )    return NULL;  // If a palette has not been supplied, use default palette  hPal = (HPALETTE) pPal->GetSafeHandle();  if (hPal==NULL)    hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);  // Get bitmap information  bitmap.GetObject(sizeof(bm),(LPSTR)&bm);  // Initialize the bitmap infoheader  bi.biSize          = sizeof(BITMAPINFOHEADER);  bi.biWidth         = bm.bmWidth;  bi.biHeight        = bm.bmHeight;  bi.biPlanes        = 1;  bi.biBitCount      = bm.bmPlanes * bm.bmBitsPixel;    //bm.bmPlanes    * bm.bmBitsPixel;  bi.biCompression   = dwCompression;  bi.biSizeImage     = 0;  bi.biXPelsPerMeter = 0;  bi.biYPelsPerMeter = 0;  bi.biClrUsed       = 0;  bi.biClrImportant  = 0;  // Compute the size of the infoheader and the color table  int nColors = (1 << bi.biBitCount);  if( nColors > 256 )    nColors = 0;  dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);  // We need a device context to get the DIB from  hDC = ::GetDC(NULL);  hPal = SelectPalette(hDC,hPal,FALSE);  RealizePalette(hDC);  // Allocate enough memory to hold bitmap infoheader and  // color table  hDIB = GlobalAlloc(GMEM_FIXED,dwLen);  if (!hDIB){    SelectPalette(hDC,hPal,FALSE);    ::ReleaseDC(NULL,hDC);    return NULL;  }  lpbi = (LPBITMAPINFOHEADER)hDIB;  *lpbi = bi;  // Call GetDIBits with a NULL lpBits param, so the device  // driver will calculate the biSizeImage field  GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L,                 (DWORD)bi.biHeight,                 (LPBYTE)NULL, (LPBITMAPINFO)lpbi,                 (DWORD)DIB_RGB_COLORS);  bi = *lpbi;  // If the driver did not fill in the biSizeImage field, then  // compute it  // Each scan line of the image is aligned on a DWORD (32bit)  // boundary  if (bi.biSizeImage == 0){    bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31)                        & ~31) / 8) * bi.biHeight;    // If a compression scheme is used, the result may in fact    // be larger    // Increase the size to account for this.    if (dwCompression != BI_RGB)      bi.biSizeImage = (bi.biSizeImage * 3) / 2;  }  // Realloc the buffer so that it can hold all the bits  dwLen += bi.biSizeImage;  if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))    hDIB = handle;  else{    GlobalFree(hDIB);    // Reselect the original palette    SelectPalette(hDC,hPal,FALSE);    ::ReleaseDC(NULL,hDC);    return NULL;  }  // Get the bitmap bits  lpbi = (LPBITMAPINFOHEADER)hDIB;  // FINALLY get the DIB  BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),        0L,                        // Start scan line        (DWORD)bi.biHeight,        // # of scan lines        (LPBYTE)lpbi               // address for bitmap bits        + (bi.biSize + nColors * sizeof(RGBQUAD)),        (LPBITMAPINFO)lpbi,        // address of bitmapinfo        (DWORD)DIB_RGB_COLORS);    // Use RGB for color table  if( !bGotBits )  {    GlobalFree(hDIB);    SelectPalette(hDC,hPal,FALSE);    ::ReleaseDC(NULL,hDC);    return NULL;  }  SelectPalette(hDC,hPal,FALSE);  ::ReleaseDC(NULL,hDC);  return hDIB;//End of the function} 


[解决办法]
如果是自己的窗口,只要调用SetWindowLong和SetLayeredWindowAttributes就可以了.但如果是别人的窗口,唔,还是等高手来解答吧.
顺便说一下,看了下WndToBmpFile代码,似乎有些错误(或者与楼主的要求不符).比如:
pWnd->GetClientRect(&rect); 应该改为pWnd->GetWindowRect(&rect);
bi.biHeight = bm.bmHeight应该改为bi.biHeight = -bm.bmHeight.
[解决办法]
获得当前窗口DC就不能避免“不管是否遮挡”的问题了,应该获取指定窗口句柄的DC
[解决办法]
在被遮盖前用一个CDC 变量吧内容保存下来。

读书人网 >C++

热点推荐