vc++如何将客户区存为bmp

在view类中添加以下三个函数:

BOOL CTestestView::WriteWindowToDIB(LPTSTR szFile, CWnd *pWnd)
{
   CBitmap bitmap;
   CWindowDC dc(pWnd);
   CDC memDC;
   CRect rect;
   memDC.CreateCompatibleDC(&dc);
   pWnd->GetWindowRect(rect);
   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);
      pal.CreatePalette(pLP);
      delete[] pLP;

   }
   memDC.SelectObject(pOldBitmap);
   HANDLE hDIB=DDBToDIB(bitmap,BI_RGB,&pal);
   if(hDIB==NULL)
          return FALSE;
   WriteDIB(szFile,hDIB);
   GlobalFree(hDIB);
   return TRUE;
 
}
 
HANDLE CTestestView::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());
   if(dwCompression==BI_BITFIELDS)
		return NULL;
   hPal=(HPALETTE)pPal->GetSafeHandle();
   if(hPal==NULL)
		hPal=(HPALETTE)GetStockObject(DEFAULT_PALETTE);
   bitmap.GetObject(sizeof(bm),(LPSTR)&bm);
   bi.biSize=sizeof(BITMAPINFOHEADER);
   bi.biWidth=bm.bmWidth;
   bi.biHeight=bm.bmHeight;
   bi.biPlanes=1;
   bi.biBitCount=bm.bmPlanes*bm.bmBitsPixel;
   bi.biCompression=dwCompression;
   bi.biSizeImage=0;
   bi.biXPelsPerMeter=0;
   bi.biYPelsPerMeter=0;
   bi.biClrImportant=0;
   bi.biClrUsed=0;

   int nColors=(1<<bi.biBitCount);
   if(nColors>256)
		nColors=0;
   dwLen=bi.biSize+nColors*sizeof(RGBQUAD);
   hDC=::GetDC(NULL);
   hPal=SelectPalette(hDC,hPal,FALSE);
   RealizePalette(hDC);
   hDIB=GlobalAlloc(GMEM_FIXED,dwLen);
   if(!hDIB)
   {
      SelectPalette(hDC,hPal,FALSE);
             ::ReleaseDC(NULL,hDC);
      return NULL;

   }
  
   lpbi=(LPBITMAPINFOHEADER)hDIB;
   *lpbi=bi;
   GetDIBits(hDC,(HBITMAP)bitmap.GetSafeHandle(),0L,(DWORD)bi.biHeight,(LPBYTE)NULL,(LPBITMAPINFO)lpbi,(DWORD)DIB_RGB_COLORS);
   bi=*lpbi;
   if(bi.biSizeImage==0)
   {
      bi.biSizeImage=((((bi.biWidth*bi.biBitCount)+31)& ~31)/8)*bi.biHeight;
      if(dwCompression!=BI_RGB)
      	bi.biSizeImage=(bi.biSizeImage*3)/2;
   }

   dwLen+=bi.biSizeImage;
   if(handle=GlobalReAlloc(hDIB,dwLen,GMEM_MOVEABLE))
     	hDIB=handle;
   else
   {
      GlobalFree(hDIB);
      SelectPalette(hDC,hPal,FALSE);
      ::ReleaseDC(NULL,hDC);
      return NULL;
   }
   lpbi=(LPBITMAPINFOHEADER)hDIB;
   BOOL bGotBits=GetDIBits(hDC,(HBITMAP)bitmap.GetSafeHandle(),0L,(DWORD)bi.biHeight,(LPBYTE)lpbi+(bi.biSize+nColors*sizeof(RGBQUAD)),
          (LPBITMAPINFO)lpbi,(DWORD)DIB_RGB_COLORS);
   if(!bGotBits)
   {
      GlobalFree(hDIB);
      SelectPalette(hDC,hPal,FALSE);
      ::ReleaseDC(NULL,hDC);
      return NULL;
   }
   SelectPalette(hDC,hPal,FALSE);
   ::ReleaseDC(NULL,hDC);
   return hDIB;
}
 
BOOL CTestestView::WriteDIB(LPTSTR szFile, HANDLE hDIB)
{
   BITMAPFILEHEADER hdr;
   LPBITMAPINFOHEADER lpbi;
   if(!hDIB)
          return FALSE;
   CFile file;
   if(!file.Open(szFile,CFile::modeWrite|CFile::modeCreate))
          return FALSE;
   lpbi=(LPBITMAPINFOHEADER)hDIB;
   int nColors=1<<lpbi->biBitCount;
   hdr.bfType=((WORD)('M'<<8)|'B');
   hdr.bfSize=::GlobalSize(hDIB)+sizeof(hdr);
   hdr.bfReserved1=0;
   hdr.bfReserved2=0;
   hdr.bfOffBits=(DWORD)(sizeof(hdr)+lpbi->biSize+nColors*sizeof(RGBQUAD));
   file.Write(&hdr,sizeof(hdr));
   file.Write(lpbi,GlobalSize(hDIB));
   return TRUE;
 
}
 在保存时调用函数WriteWindowToDIB()
void CTestestView::OnFileSave()
{
   // TODO: Add your command handler code here
   WriteWindowToDIB("D://My.bmp",this);    
}

本人测试过,确实直接加上就可以了,但是注意类名要改为和你的一致的

 

VC实现自绘图形输出到bmp文件

在用vc做程序时候,经常需要把输出的文本和图形保存到位图文件,

当然可以有现成的控件来实现,但总不能如自己所愿,还是自己动手写吧!

 

一、实现方法

要把文本和图形保存到位图文件,只要对掌握位图结构有一定的了解,一切都ok呢。先必须要创建内存设备环境,然后内存设备环境创建的DIB区域,别忘了还要创建个CBitmap对象,CBitmap对象必须和DIB区域关联起来,把CBitmap对象选择到当前设备环境,然后在当前设备环境输出文本和图形就可以了。

 

二、具体实现代码如下

void CTestSaveBmpView::SaveAsBmp(CString filename) {
	 //定义图形大小
	 int iWidth = 800;
	 int iHeight = 600;
	 int iPixel = 16;

	 //图形格式参数
	 LPBITMAPINFO lpbmih = new BITMAPINFO;
	 lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	 lpbmih->bmiHeader.biWidth = iWidth;
	 lpbmih->bmiHeader.biHeight = iHeight;
	 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;
	 
	 //创建位图数据
	 HDC hdc,hdcMem;
	 HBITMAP hBitMap = NULL;
	 CBitmap *pBitMap = NULL;
	 CDC *pMemDC = NULL;
	 BYTE *pBits;
	 
	 hdc = CreateIC(TEXT("DISPLAY"),NULL,NULL,NULL);
	 hdcMem = CreateCompatibleDC(hdc);
	 hBitMap = CreateDIBSection(hdcMem,lpbmih,DIB_PAL_COLORS,(void **)&pBits,NULL,0);
	 pBitMap = new CBitmap;
	 pBitMap->Attach(hBitMap);
	 pMemDC = new CDC;
	 pMemDC->Attach(hdcMem);
	 pMemDC->SelectObject(pBitMap);

	 CRect rc(0,0,iWidth,iHeight);
	 pMemDC->SetBkMode(TRANSPARENT);

	 //添加自绘图形 
	 DrawCurve(pMemDC,rc);

	 //保存到文件并创建位图结构
	 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 + (iWidth * iHeight) * iPixel / 8;
	 
	 TCHAR szBMPFileName[128];
	 int iBMPBytes = iWidth * iHeight * iPixel / 8;
	 strcpy(szBMPFileName,filename);
	 CFile file;
	 if(file.Open(szBMPFileName,CFile::modeWrite | CFile::modeCreate)) {
		file.Write(&bmfh,sizeof(BITMAPFILEHEADER));
		file.Write(&(lpbmih->bmiHeader),sizeof(BITMAPINFOHEADER));
		file.Write(pBits,iBMPBytes);
		file.Close();
	 }
	 
	 pMemDC->DeleteDC();
	 delete pMemDC; pMemDC = NULL;
	 delete pBitMap; pBitMap = NULL;
	 delete lpbmih; lpbmih = NULL;
}

//输出文本和图形
void CTestSaveBmpView::DrawCurve(CDC *pDC, CRect rcClient) {
	//页面背景色
	CBrush brushCtl;
	brushCtl.CreateSolidBrush(RGB(255,255,255));
	pDC->Rectangle(rcClient);
	pDC->FillRect(rcClient,&brushCtl) ;
	brushCtl.DeleteObject();

	CPen pen;
	pen.CreatePen(PS_SOLID, 1, RGB(255,0,0));
	CPen *oldPen = pDC->SelectObject(&pen); 

	double xMin = 10.00f, xMax = 100.00f;
	double yMin = 10.00f, yMax = 200.00f;

	double dbX1 = (xMax- xMin)/100 + xMin;
	double dbY1 = 600/dbX1 ;
	for (int i=1; i<100; i++) //曲线
	{
		double dbX2 = (xMax- xMin)*i/100 + xMin;
		double dbY2 = 600/dbX2 ;

		pDC->MoveTo(int(rcClient.left+(dbX1 - xMin)*rcClient.Width()/(xMax- xMin)), 
		int(rcClient.bottom-(dbY1- yMin)*rcClient.Height()/(yMax- yMin)));
		pDC->LineTo(int(rcClient.left+(dbX2 - xMin)*rcClient.Width()/(xMax- xMin)), 
		int(rcClient.bottom-(dbY2- yMin)*rcClient.Height()/(yMax- yMin))); 

		dbX1=dbX2;
		dbY1=dbY2;
	}
	pDC->SelectObject(oldPen); 
	pen.DeleteObject();
	oldPen = NULL;
}

//保存的实现
void CTestSaveBmpView::OnRButtonDown(UINT nFlags, CPoint point) {
	CFileDialog dlg(false,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
	"位图文件(*.bmp)|*.bmp|",
	NULL);
	if (dlg.DoModal()!= IDOK) return;
	
	CString filename = dlg.GetFileName() + ".bmp";
	SaveAsBmp(filename); 

	CView::OnRButtonDown(nFlags, point);
}

 

原文 vc++如何将客户区存为bmp和VC实现自绘图形输出到bmp文件