vc++如何将客户区存为bmp和VC实现自绘图形输出到bmp文件
3,556 views
0
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文件
版权所有: 本文系米扑博客原创、转载、摘录,或修订后发表,最后更新于 2017-11-18 22:02:27
侵权处理: 本个人博客,不盈利,若侵犯了您的作品权,请联系博主删除,莫恶意,索钱财,感谢!