我需要写一些生成图片显示图片的MFC代码。比较简单,但在网上没有找到完整的例子。
我整理了一些代码,现实了此功能。共享之。
1.在内存DC上画图然后保存成BMP文件
#pragma once
#include <Windows.h>
class ForceCanvas
{
public:
ForceCanvas(int canvasWithd, int canvasHeight);
~ForceCanvas();
void DrawLine(int x1, int y1, int x2, int y2, COLORREF penColor, int penWidth);
void SetBackgroundColor(COLORREF backgroundColor);
bool SaveBMP(const char * fileName);
protected:
HDC memDc;
HDC dc;
HBITMAP hBitmap;
HGDIOBJ hOldBm;
int myCanvasWithd;
int myCanvasHeight;
};
ForceCanvas::ForceCanvas(int canvasWithd, int canvasHeight)
:myCanvasWithd(canvasWithd),
myCanvasHeight(canvasHeight)
{
memDc = ::CreateCompatibleDC(NULL); //创建一个兼容dc
dc = ::GetDC(NULL);
hBitmap = ::CreateCompatibleBitmap(dc, canvasWithd, canvasHeight);
hOldBm = ::SelectObject(memDc, hBitmap); //选入设备 保存老的设备以便恢复
}
ForceCanvas::~ForceCanvas()
{
DeleteObject(hBitmap);
DeleteDC(memDc);
::ReleaseDC(NULL, dc);
}
void ForceCanvas::DrawLine(int x1, int y1, int x2, int y2, COLORREF penColor, int penWidth)
{
HGDIOBJ hPen = ::CreatePen(PS_SOLID, penWidth, penColor);
::SelectObject(memDc, hPen);
::MoveToEx(memDc, x1, y1, NULL);
::LineTo(memDc, x2, y2);
::DeleteObject(hPen);
//MoveToEx最后一个参数的意思
//Pointer to a POINT structure that receives the previous current position.
//If this parameter is a NULL pointer, the previous position is not returned.
}
bool ForceCanvas::SaveBMP(const char * fileName)
{
WORD wBitCount;//位图中每象素所占字节数
DWORD dwPaletteSize=0;//定义调色板大小
DWORD dwBmBitsSize=0;//位图中像素字节大小
DWORD dwDIBSize=0;//位图文件大小
DWORD dwWritten=0;//写入文件字节数
BITMAP Bitmap;//位图属性结构
BITMAPFILEHEADER bmfHdr;//位图文件头结构
BITMAPINFOHEADER bi;//位图信息头结构
LPBITMAPINFOHEADER lpbi;//指向位图信息头结构
//定义文件,分配内存句柄,调色板句柄
HANDLE fh=NULL;
HANDLE hDib=NULL;
HANDLE hPal=NULL;
HANDLE hOldPal=NULL;
wBitCount = 24;
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.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
//处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
HDC hDC;
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
else
{
return false;
}
// 获取该调色板下新的像素值
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(fileName, 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;
}
void ForceCanvas::SetBackgroundColor(COLORREF backgroundColor)
{
HBRUSH brush = CreateSolidBrush(backgroundColor);
RECT rect={0, 0, myCanvasWithd, myCanvasHeight};
HGDIOBJ oldBrush = SelectObject(memDc, brush);
FillRect(memDc, &rect, brush);
SelectObject(memDc, oldBrush);
DeleteObject(brush);
}
void main()
{
ForceCanvas canvas(500, 500);
canvas.SetBackgroundColor(RGB(255,255,255));
canvas.DrawLine(100,100,500,100, RGB(0,255,0),3);
canvas.SaveBMP("c:\\t.bmp");
}
2.读入Bmp文件,显示在对话框的静态控件上
void DrawPictureFromBmpFile(CDialog * dlg, int pictureCtrlID, const char * fileName)
{
CStatic *pWnd = (CStatic *)dlg->GetDlgItem(pictureCtrlID);
if (pWnd == 0)
return;
HANDLE filehandle=::LoadImage(NULL, fileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if(filehandle!=NULL)
{
CBitmap bmp;
if(bmp.Attach(filehandle))
{
CDC * pDC = pWnd->GetDC();
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
dcMemory.SelectObject(&bmp);
pDC->SetStretchBltMode(HALFTONE);
//获取Static控件的大小范围
CRect rect;
pWnd->GetClientRect(&rect);
pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dcMemory,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY);
bmp.Detach();
}
}
}