当获得了DC的句柄,如何把DC上的区域保存到一个位图文件中?谢谢
解决方案 »
- 使用CTypedPtrArray参数不能转换的问题
- 在界面上画方框中的一个问题.
- 关于全屏显示的过程中,移动鼠标到上方,出现菜单,移开鼠标,菜单消失的问题,高手请进!
- 为什么我的句柄是“无效的窗口句柄”?
- 从VB6.0中调用Vc++编写的Dll文件,出现错误,请各位大侠指正!(急,急,急!!!!!)
- sqlserver中存储的韩文,用ADO读出后全是“???”,怎么解决?
- 如何返回字符串数组,通过后马上给分!!
- 关于《windows程序设计》一书
- 求救 Winsock2
- jjww,我想向你请教一个Minix的问题,请看我写的《Minix进程管理部分的问题》
- 关于DISPID_NAVIGATECOMPLETE2 and DISPID_NAVIGATECOMPLETE
- 不让 ,非模态对话框,始终在顶层显示。
HBITMAP hMemBmp = CreateCompatibleBitmap(); //创建内存位图
SelectObject(hMemDC, hMemBmp); //将位图选入内存DC
StretchBlt(hMemDC,... hYourDC, ..); //把你得到的DC复制到内存DC
下一步就是保存这个内存位图hMemBmp
Storing an Image
//其中hScrDC为你的DC句柄,nx,ny为区域矩形的起点,nWidth,nHeight为长宽,
hMemDC = CreateCompatibleDC(hScrDC);
hBitmap = CreateCompatibleBitmap
(hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);//创建军兼容DC,当bSave为中时把开始保存的全屏位图,按截取矩形大小保存
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(CDC::FromHandle(hMemDC));
dcCompatible.SelectObject(m_pBitmap);
BitBlt(hMemDC, 0, 0, nWidth, nHeight,dcCompatible, nX, nY, SRCCOPY);
BeginPaint
GetClientRect(GetWindowRect)
CreateCompatibleBitmap -> 获得HBITMAP
位图写文件
EndPaint对于获得的句柄操作也类似,楼主略作修改就可以将以下二个方法选一个使用。(要作小修改,因为这是将窗口存为BMP的)方法一:
----------------------------------------------LPTSTR CRemoteC::CopyScreenToBitmap(LPRECT lpRect)
{
HDC hScrDC, hMemDC; // 屏幕和内存设备描述表
HBITMAP hBitmap,hOldBitmap; // 位图句柄
int nX, nY, nX2, nY2; // 选定区域坐标
int nWidth, nHeight; // 位图宽度和高度
int xScrn, yScrn; // 屏幕分辨率
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect)) return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
// 获得屏幕分辨率
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//确保选定区域是可见的
if (nX < 0) nX = 0;
if (nY < 0) nY = 0;
if (nX2 > xScrn) nX2 = xScrn;
if (nY2 > yScrn) nY2 = yScrn;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
int *temp=new int(m_szResolution.Find("*"));
char *pWidth=new char[10];
char *pHeight=new char[10];
strcpy(pWidth,m_szResolution.Mid(0,*temp));
strcpy(pHeight,m_szResolution.Mid(*temp+1));
delete temp;
int nDestResWidth=atoi(pWidth);
int nDestResHeight=atoi(pHeight);
delete pWidth;
delete pHeight;
hBitmap = CreateCompatibleBitmap(hScrDC, nDestResWidth, nDestResHeight);
// 把新位图选到内存设备描述表中
hOldBitmap=(HBITMAP)::SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
StretchBlt(hMemDC, 0, 0, nDestResWidth, nDestResHeight,hScrDC, nX, nY,nWidth,nHeight,SRCCOPY);
//得到屏幕位图的句柄
hBitmap =(HBITMAP) ::SelectObject(hMemDC, hOldBitmap);
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
char tmppath[MAX_PATH];
char *tmpname=new char[MAX_PATH];
GetTempPath(MAX_PATH,tmppath);
GetTempFileName(tmppath,"AnyServer",0,tmpname);//获得一个唯一的临时文件名
SaveBitmapToFile(hBitmap,tmpname);
return tmpname;
}
int CRemoteC::SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName)
{
//我们也可以把屏幕内容以位图格式存到磁盘文件上.
//lpFileName 为位图文件名
HDC hDC; //设备描述表
int iBits; //当前显示分辨率下每个像素所占字节数
WORD wBitCount; //位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小,位图文件大小,写入文件字节数
DWORD dwPaletteSize=0,
dwBmBitsSize,
dwDIBSize, dwWritten;
BITMAP Bitmap; //位图属性结构
BITMAPFILEHEADER bmfHdr; //位图文件头结构
BITMAPINFOHEADER bi; //位图信息头结构
LPBITMAPINFOHEADER lpbi; //指向位图信息头结构
HANDLE fh, hDib, hPal,hOldPal=NULL;
//定义文件,分配内存句柄,调色板句柄
//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL)*GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else if (iBits <= 32)
wBitCount = 24;
//计算调色板大小
if (wBitCount <= 8)
dwPaletteSize = (1 << wBitCount) *
sizeof(RGBQUAD);
//设置位图信息头结构
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((Bitmap.bmWidth*wBitCount+31)/32)* 4*Bitmap.bmHeight ;
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));//为位图内容分配内存
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
hPal=(HPALETTE)::GetStockObject(DEFAULT_PALETTE);// 处理调色板
if (hPal)
{
hDC = GetDC(NULL);
hOldPal = SelectPalette(hDC,(HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize,
(BITMAPINFO *)
lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
SelectPalette(hDC,(HPALETTE) hOldPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
}
//创建位图文件
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"
dwDIBSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
+ dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof
(BITMAPFILEHEADER)
+ (DWORD)sizeof(BITMAPINFOHEADER)
+ dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof
(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize,
&dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
取rect的话只要GetWindowRect就行了-------------------------------------------------------------
-------------------------------------------------------------写窗口图像到BMP位图文件
WINDOWS的窗口图像从本质上来说,是WINDOWS在内存DC上绘制的一幅图像,
我们要将此图像存储起来,首先要获得WINDOWS窗口的区域大小,然后将区域中的图像
存在一内存DC中,由于内存DC是与设备相关的位图,所以将它存储起来还要用DDBTODIB
函数转换成DIB位图,最后再用WriteDIB函数转储成BMP文件。
BOOL WriteWindowToDIB( LPTSTR szFile, CWnd *pWnd )
{
CBitmap bitmap;
CWindowDC dc(pWnd);
CDC memDC;
CRect rect;
memDC.CreateCompatibleDC(&dc);
pWnd->GetWindowRect(rect);
//用窗口区域大小定义一个内存DC ,并将窗口图像暂存其中
bitmap.CreateCompatibleBitmap(&dc, rect.Width(),rect.Height() );
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
memDC.BitBlt(0, 0, rect.Width(),rect.Height(), &dc, 0, 0, SRCCOPY);
// 如果设备支持调色板,创建调色板
CPalette pal;
if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries =
GetSystemPaletteEntries( dc, 0, 255, pLP->palPalEntry );
// Create the palette
pal.CreatePalette( pLP );
delete[] pLP;
}
memDC.SelectObject(pOldBitmap);
// 转换 bitmap 到 a DIB
HANDLE hDIB = DDBToDIB( bitmap, BI_RGB, &pal );
if( hDIB == NULL )
return FALSE;
// Write it to file
WriteDIB( szFile, hDIB );
// Free the memory allocated by DDBToDIB for the DIB
GlobalFree( hDIB );
return TRUE;
}
-------------------------------------------------------------
#define WIDTHBYTES(w,b) ((((w)*(b)+31)/32)*4)
BOOL Save( LPCTSTR lpszFileName, HDC saveDC, RECT rc ) //文件名/dc/保存的矩形
{
BITMAPFILEHEADER bf = { 0 };
BITMAPINFOHEADER bi = { 0 };
HDC hMemDC;
HBITMAP hBitmap;
LPBYTE lpBits; bi.biSize = sizeof( BITMAPINFOHEADER );
bi.biBitCount = 24; // 保存为true color
bi.biWidth = rc.right - rc.left;
bi.biHeight = rc.bottom - rc.top;
bi.biPlanes = 1;
bi.biCompression = BI_RGB;
bi.biSizeImage = WIDTHBYTES( bi.biWidth, bi.biBitCount ) * bi.biHeight; HDC hdc = GetDC( NULL );
if( !hdc )
return FALSE;
hBitmap = CreateDIBSection( hdc, ( CONST BITMAPINFO * )&bi, DIB_RGB_COLORS,
( VOID ** )&lpBits, NULL, 0 );
if( !hBitmap ){
ReleaseDC( NULL, hDC );
return FALSE;
} hMemDC = CreateCompatibleDC( hdc );
HBITMAP hOldBmp = ( HBITMAP )SelectObject( hBitmap );
BitBlt( hMemDC, 0, 0, bi.biWidth, bi.biHeight, saveDC, 0, 0, SRCCOPY );
SelectObject( hMemDC, hOldBmp );
ReleaseDC( NULL, hDC );
DeleteDC( hMemDC ); bf.bfType = 0x4d42;
bf.bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER )
+ bi.biSizeImage;
bf.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER );
CFile file( lpszFileName, CFile::modeCreate|CFile::modeWrite );
file.Write( &bf, sizeof( BITMAPFILEHEADER ) );
file.Write( &bi, sizeof( BITMAPINFOHEADER ) );
file.WriteHuge( lpBits, bi.biSizeImage );
DeleteObject( hBitmap );
return TRUE;
}
BitBlt( hMemDC, 0, 0, bi.biWidth, bi.biHeight, saveDC, rc.left, rc.top, SRCCOPY );才对.
CFile file( lpszFileName, CFile::modeCreate|CFile::modeWrite );
file.Write( &bf, sizeof( BITMAPFILEHEADER ) );
file.Write( &bi, sizeof( BITMAPINFOHEADER ) );
file.WriteHuge( lpBits, bi.biSizeImage );
把这几句替换成writefile..
DWORD dwWrite;
HANDLE fh = CreateFile( lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL );
WriteFile( fh, ( LPBYTE )&bf, sizeof( BITMAPFILEHEADER ), &dwWrite, NULL );
WriteFile( fh, ( LPBYTE )&bi, sizeof( BITMAPINFOHEADER ), &dwWrite, NULL );
WriteFile( fh, ( LPBYTE )lpBits, bi.biSizeImage, &dwWrite, NULL );汗...
1>c:\documents and settings\cx\桌面\textusenglish\textusenglish\textusenglish\textusenglish.cpp(38) : error C2660: “SelectObject”: 函数不接受 1 个参数
1: #define WIDTHBYTES(w,b) ((((w)*(b)+31)/32)*4)
#define WIDTHBYTES(w,b) ((((w)*(b)+31)/32)*4)
BOOL Save( LPCTSTR lpszFileName, HDC saveDC, RECT rc )
{
BITMAPFILEHEADER bf = { 0 };
BITMAPINFOHEADER bi = { 0 };
HDC hMemDC;
HBITMAP hBitmap;
LPBYTE lpBits; bi.biSize = sizeof( BITMAPINFOHEADER );
bi.biBitCount = 24; // 保存为true color
bi.biWidth = rc.right - rc.left;
bi.biHeight = rc.bottom - rc.top;
bi.biPlanes = 1;
bi.biCompression = BI_RGB;
bi.biSizeImage = WIDTHBYTES( bi.biWidth, bi.biBitCount ) * bi.biHeight; HDC hdc = GetDC( NULL );
if( !hdc )
return FALSE;
hBitmap = CreateDIBSection( hdc, ( CONST BITMAPINFO * )&bi, DIB_RGB_COLORS,
( VOID ** )&lpBits, NULL, 0 );
if( !hBitmap ){
ReleaseDC( NULL, hdc );
return FALSE;
} hMemDC = CreateCompatibleDC( hdc );
HBITMAP hOldBmp = ( HBITMAP )SelectObject( hMemDC, hBitmap );
BitBlt( hMemDC, 0, 0, bi.biWidth, bi.biHeight, saveDC, 0, 0, SRCCOPY );
SelectObject( hMemDC, hOldBmp );
ReleaseDC( NULL, hdc );
DeleteDC( hMemDC ); bf.bfType = 0x4d42;
bf.bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER )
+ bi.biSizeImage;
bf.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ); DWORD dwWrite;
HANDLE fh = CreateFile( lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL );
WriteFile( fh, ( LPBYTE )&bf, sizeof( BITMAPFILEHEADER ), &dwWrite, NULL );
WriteFile( fh, ( LPBYTE )&bi, sizeof( BITMAPINFOHEADER ), &dwWrite, NULL );
WriteFile( fh, ( LPBYTE )lpBits, bi.biSizeImage, &dwWrite, NULL );
DeleteObject( hBitmap );
return TRUE;
}
还有没?估计这个没有了.因为是随手写的.哈哈~
BitBlt( hMemDC, 0, 0, bi.biWidth, bi.biHeight, saveDC, 0, 0, SRCCOPY );
这个又不记得改回:
BitBlt( hMemDC, 0, 0, bi.biWidth, bi.biHeight, saveDC, rc.left, rc.top, SRCCOPY );-_-"..good luck~不搞了..哈哈
#include <ocidl.h>
#include <olectl.h>
// ////////////////////////////////////////
// 函数名称:DC2File
// 函数功能:将指定DC中的位图保存为BMP文件
// ////////////////////////////////////////
BOOL DC2File(HDC hDC,LPCSTR szFileName,UINT nLeft=0,UINT nTop=0,UINT nWidth=0,UINT nHeight=0)
{
HDC hMemDC;
BITMAP bmp;
HBITMAP hSrcBmp,hMemBmp,hOldBmp;
BOOL retVal=FALSE; hSrcBmp=(HBITMAP)GetCurrentObject(hDC,OBJ_BITMAP);
if(hSrcBmp==NULL)return FALSE; GetObject(hSrcBmp,sizeof(BITMAP),&bmp);
if(nWidth>(UINT)bmp.bmWidth)nWidth=(UINT)bmp.bmWidth;
if(nHeight>(UINT)bmp.bmHeight)nHeight=(UINT)bmp.bmHeight;
if( nWidth<nLeft || nHeight<nTop)return 0; hMemDC = CreateCompatibleDC(hDC);
hMemBmp = CreateCompatibleBitmap(hDC,(nWidth-nLeft),(nHeight-nTop));
hOldBmp = (HBITMAP)SelectObject(hMemDC,hMemBmp);
BitBlt(hMemDC,nLeft,nTop,(nWidth-nLeft),(nHeight-nTop),hDC,nLeft,nTop,SRCCOPY); PICTDESC ps;
IPicture* pIPic=NULL;
ps.cbSizeofstruct = sizeof(PICTDESC);
ps.picType = PICTYPE_BITMAP;
ps.bmp.hbitmap = hMemBmp;
ps.bmp.hpal = NULL;
if(OleCreatePictureIndirect(&ps,IID_IPicture,TRUE,(LPVOID*)&pIPic)==ERROR_SUCCESS)
{
LONG lSize = 0;
IStream* pIStm = NULL;
CreateStreamOnHGlobal(NULL,TRUE,&pIStm);
if(pIPic->SaveAsFile(pIStm,TRUE,&lSize) == ERROR_SUCCESS)
{
LARGE_INTEGER li;
li.HighPart = 0;
li.LowPart = 0;
ULARGE_INTEGER uli;
uli.HighPart = 0;
uli.LowPart = 0;
pIStm->Seek(li, STREAM_SEEK_SET, &uli); char buffer[1024];
HANDLE hFile = CreateFile(szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL);
DWORD dwRead = 1,dwWrite=0;
while(dwRead>0)
{
pIStm->Read(buffer, 1024, &dwRead);
if(dwRead > 0)WriteFile(hFile, buffer, dwRead, &dwWrite, NULL);
}
CloseHandle(hFile);
retVal=TRUE;
}
pIPic->Release();
pIStm->Release();
}
DeleteObject(SelectObject(hMemDC,hOldBmp));
DeleteDC(hMemDC);
return retVal;
}
Save((LPCTSTR)"c:\\jk.bmp",hdc,*t);HWND是你的窗口的句柄,而不是DC句柄.
GetWindowRect()需要的是程序窗口句柄吧.
GetClientRect()是客户区窗口句柄.
HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
HDC hDesktopDC=GetDC(NULL);
DC2File(hDesktopDC,"c:\\temp.bmp",0,0,800,500);
ReleaseDC(NULL,hDesktopDC);
MessageBox(NULL,"保存完毕!","",MB_OK);
return 0;
}
报编译错误,error C2660: 'ReleaseDC' : function does not take 2 parameters
请问怎么回事?
没有GetDC()就不需要ReleaseDC(),成对使用.