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

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/

==================================================================

你可能感兴趣的:(vc++)