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
[解决办法]
接分去散
[解决办法]
不懂
学习去了
[解决办法]
//////////////////////////////////////////////////////////////////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 变量吧内容保存下来。