下面是我做的一个位图程序,它能够对当前可视部分进行抓屏保存,但是我改了很长时间始终无法使它对客户区的其他图形进行保存,基类是CScrollView,望高手指点!
//
int CBittestView::GetDIBPixelSize(const BITMAPINFOHEADER &bmih)
{
if ( bmih.biSizeImage )
return bmih.biSizeImage;
else
return ( bmih.biWidth * bmih.biBitCount + 31 ) / 32 * 4 * bmih.biPlanes * abs(bmih.biHeight);
}
//
int CBittestView::GetDIBColorCount(const BITMAPINFOHEADER & bmih)
{
if ( bmih.biBitCount <= 8 )
if ( bmih.biClrUsed )
return bmih.biClrUsed;
else
return 1 << bmih.biBitCount;
else if ( bmih.biCompression==BI_BITFIELDS )
return 3 + bmih.biClrUsed;
else
return bmih.biClrUsed;
}
//
BOOL CBittestView::SaveDIBToBmp(const char* pFileName, const BITMAPINFO *pBMI, const BYTE *pBits)
{
if(pFileName==NULL)
{
return FALSE;
}
HANDLE handle = CreateFile(pFileName, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BITMAPFILEHEADER bmFH;
int nHeadSize = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * GetDIBColorCount(pBMI->bmiHeader);
bmFH.bfType = 0x4D42;
bmFH.bfSize = nHeadSize + GetDIBPixelSize(pBMI->bmiHeader);
bmFH.bfReserved1 = 0;
bmFH.bfReserved2 = 0;
bmFH.bfOffBits = nHeadSize + sizeof(BITMAPFILEHEADER);
DWORD dwRead = 0;
WriteFile(handle, & bmFH, sizeof(bmFH), & dwRead, NULL);
if(pBits==NULL) // packed DIB
pBits = (BYTE *) pBMI + nHeadSize;
WriteFile(handle, pBMI, nHeadSize,& dwRead, NULL);
WriteFile(handle, pBits, GetDIBPixelSize(pBMI->bmiHeader), & dwRead, NULL);
CloseHandle(handle);
return TRUE;
}
//
BITMAPINFO* CBittestView::BitmapToDIB(HPALETTE hPal, // palette for color conversion
HBITMAP hBmp, // DDB for convert
int nBitCount, int nCompression,CDC *pDC) // format wanted
{
typedef struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256+3];
} DIBINFO;
BITMAP ddbinfo;
DIBINFO dibinfo;
// retrieve DDB information
if ( GetObject(hBmp, sizeof(BITMAP), & ddbinfo)==0 )
return NULL;
// fill out BITMAPINFOHEADER based on size and required format
memset(&dibinfo, 0, sizeof(dibinfo));
dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dibinfo.bmiHeader.biWidth = ddbinfo.bmWidth;
dibinfo.bmiHeader.biHeight = ddbinfo.bmHeight;
dibinfo.bmiHeader.biPlanes = 1;
dibinfo.bmiHeader.biBitCount = nBitCount;
dibinfo.bmiHeader.biCompression = nCompression;
HDC hDC =::GetWindowDC(NULL); // screen DC
// HDC hDC=pDC->GetSafeHdc();
HGDIOBJ hpalOld;
if ( hPal )
hpalOld = SelectPalette(hDC, hPal, FALSE);
else
hpalOld = NULL;
// query GDI for image size
GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS);
int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader);
int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader);
BYTE * pDIB = new BYTE[nTotalSize];
if ( pDIB )
{
memcpy(pDIB, & dibinfo, nInfoSize);
if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) )
{
delete [] pDIB;
pDIB = NULL;
}
}
if ( hpalOld )
SelectObject(hDC, hpalOld);
DeleteDC(hDC);
return (BITMAPINFO *) pDIB;
}
//
HBITMAP CBittestView::CaptureWindow(CDC *pDC)
{
// HDC hDC = pDC->m_hDC;
HDC hDC = pDC->GetSafeHdc();
HBITMAP hBmp = CreateCompatibleBitmap(hDC,bitmappoint.x,bitmappoint.y);
if ( hBmp )
{
HDC hMemDC = CreateCompatibleDC(hDC);
HGDIOBJ hOld = SelectObject(hMemDC, hBmp);
BitBlt(hMemDC, 0, 0,this->GetTotalSize().cx, this->GetTotalSize().cy,
hDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteObject(hMemDC);
}
DeleteDC(hDC);
return hBmp;
}
//
void CBittestView::SaveWindowToFile(CDC *pDC,const char *filename,int nBitCount,int nCompression)
{
HBITMAP hBmp=CaptureWindow(pDC);
if(hBmp)
{
BITMAPINFO *pDIB = (BITMAPINFO*)BitmapToDIB(NULL, hBmp, nBitCount, nCompression,pDC);
if(pDIB)
{
SaveDIBToBmp(filename, pDIB, NULL);
delete [](BYTE *) pDIB;
}
DeleteObject(hBmp);
}
}
//void CBittestView::bitmapsave(CDC *pDC)
{
CRect rect;
GetClientRect(&rect);
bitmappoint.x=rect.Width();
bitmappoint.y=rect.Height();
TCHAR szFilters[]=_T("BMP位图(*.bmp)|*.bmp|所有文件(*.*)|*.*|");
CString filename;
CFileDialog dlg(false,_T("BMP"),_T("*.BMP"),OFN_HIDEREADONLY,szFilters);
if(dlg.DoModal()==IDOK)
{
filename=dlg.GetPathName();
SaveWindowToFile(pDC,filename,32,0);
}
}
//
int CBittestView::GetDIBPixelSize(const BITMAPINFOHEADER &bmih)
{
if ( bmih.biSizeImage )
return bmih.biSizeImage;
else
return ( bmih.biWidth * bmih.biBitCount + 31 ) / 32 * 4 * bmih.biPlanes * abs(bmih.biHeight);
}
//
int CBittestView::GetDIBColorCount(const BITMAPINFOHEADER & bmih)
{
if ( bmih.biBitCount <= 8 )
if ( bmih.biClrUsed )
return bmih.biClrUsed;
else
return 1 << bmih.biBitCount;
else if ( bmih.biCompression==BI_BITFIELDS )
return 3 + bmih.biClrUsed;
else
return bmih.biClrUsed;
}
//
BOOL CBittestView::SaveDIBToBmp(const char* pFileName, const BITMAPINFO *pBMI, const BYTE *pBits)
{
if(pFileName==NULL)
{
return FALSE;
}
HANDLE handle = CreateFile(pFileName, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BITMAPFILEHEADER bmFH;
int nHeadSize = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * GetDIBColorCount(pBMI->bmiHeader);
bmFH.bfType = 0x4D42;
bmFH.bfSize = nHeadSize + GetDIBPixelSize(pBMI->bmiHeader);
bmFH.bfReserved1 = 0;
bmFH.bfReserved2 = 0;
bmFH.bfOffBits = nHeadSize + sizeof(BITMAPFILEHEADER);
DWORD dwRead = 0;
WriteFile(handle, & bmFH, sizeof(bmFH), & dwRead, NULL);
if(pBits==NULL) // packed DIB
pBits = (BYTE *) pBMI + nHeadSize;
WriteFile(handle, pBMI, nHeadSize,& dwRead, NULL);
WriteFile(handle, pBits, GetDIBPixelSize(pBMI->bmiHeader), & dwRead, NULL);
CloseHandle(handle);
return TRUE;
}
//
BITMAPINFO* CBittestView::BitmapToDIB(HPALETTE hPal, // palette for color conversion
HBITMAP hBmp, // DDB for convert
int nBitCount, int nCompression,CDC *pDC) // format wanted
{
typedef struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256+3];
} DIBINFO;
BITMAP ddbinfo;
DIBINFO dibinfo;
// retrieve DDB information
if ( GetObject(hBmp, sizeof(BITMAP), & ddbinfo)==0 )
return NULL;
// fill out BITMAPINFOHEADER based on size and required format
memset(&dibinfo, 0, sizeof(dibinfo));
dibinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dibinfo.bmiHeader.biWidth = ddbinfo.bmWidth;
dibinfo.bmiHeader.biHeight = ddbinfo.bmHeight;
dibinfo.bmiHeader.biPlanes = 1;
dibinfo.bmiHeader.biBitCount = nBitCount;
dibinfo.bmiHeader.biCompression = nCompression;
HDC hDC =::GetWindowDC(NULL); // screen DC
// HDC hDC=pDC->GetSafeHdc();
HGDIOBJ hpalOld;
if ( hPal )
hpalOld = SelectPalette(hDC, hPal, FALSE);
else
hpalOld = NULL;
// query GDI for image size
GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, NULL, (BITMAPINFO *) & dibinfo, DIB_RGB_COLORS);
int nInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * GetDIBColorCount(dibinfo.bmiHeader);
int nTotalSize = nInfoSize + GetDIBPixelSize(dibinfo.bmiHeader);
BYTE * pDIB = new BYTE[nTotalSize];
if ( pDIB )
{
memcpy(pDIB, & dibinfo, nInfoSize);
if ( ddbinfo.bmHeight != GetDIBits(hDC, hBmp, 0, ddbinfo.bmHeight, pDIB + nInfoSize, (BITMAPINFO *) pDIB, DIB_RGB_COLORS) )
{
delete [] pDIB;
pDIB = NULL;
}
}
if ( hpalOld )
SelectObject(hDC, hpalOld);
DeleteDC(hDC);
return (BITMAPINFO *) pDIB;
}
//
HBITMAP CBittestView::CaptureWindow(CDC *pDC)
{
// HDC hDC = pDC->m_hDC;
HDC hDC = pDC->GetSafeHdc();
HBITMAP hBmp = CreateCompatibleBitmap(hDC,bitmappoint.x,bitmappoint.y);
if ( hBmp )
{
HDC hMemDC = CreateCompatibleDC(hDC);
HGDIOBJ hOld = SelectObject(hMemDC, hBmp);
BitBlt(hMemDC, 0, 0,this->GetTotalSize().cx, this->GetTotalSize().cy,
hDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteObject(hMemDC);
}
DeleteDC(hDC);
return hBmp;
}
//
void CBittestView::SaveWindowToFile(CDC *pDC,const char *filename,int nBitCount,int nCompression)
{
HBITMAP hBmp=CaptureWindow(pDC);
if(hBmp)
{
BITMAPINFO *pDIB = (BITMAPINFO*)BitmapToDIB(NULL, hBmp, nBitCount, nCompression,pDC);
if(pDIB)
{
SaveDIBToBmp(filename, pDIB, NULL);
delete [](BYTE *) pDIB;
}
DeleteObject(hBmp);
}
}
//void CBittestView::bitmapsave(CDC *pDC)
{
CRect rect;
GetClientRect(&rect);
bitmappoint.x=rect.Width();
bitmappoint.y=rect.Height();
TCHAR szFilters[]=_T("BMP位图(*.bmp)|*.bmp|所有文件(*.*)|*.*|");
CString filename;
CFileDialog dlg(false,_T("BMP"),_T("*.BMP"),OFN_HIDEREADONLY,szFilters);
if(dlg.DoModal()==IDOK)
{
filename=dlg.GetPathName();
SaveWindowToFile(pDC,filename,32,0);
}
}
本代码类似于spy++,可以自动锁定窗口区域进行抓图,并具有保存功能。