您的位置:首页 > 编程语言 > C语言/C++

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

2009-12-12 13:20 591 查看
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);
}

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

转载声明: 本文转自http://wmnmtm.blog.163.com/blog/static/38245714200963032449/
==================================================================

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);
}



转载声明: 本文转自http://wmnmtm.blog.163.com/blog/static/38245714200963005616282/
==================================================================
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: