最近开始学习MFC自绘,自绘要有比较好的效果需要支持图像绘制,那就从图像类开始,那就用GDI+弄一个图像类。GDI(Graphics Device Interface)图形设备接口,处理所有Windows程序的图形输出。GDI+是以前版本GDI的继承者,对GDI进行了优化并添加了许多新的功能,只需调用GDI+库输出的类的一些方法即可完成图形操作。
头文件:
#include <GdiPlus.h>
class CWzdImage
{
protected:
Gdiplus::Image* m_pImage; // 图片对象
TCHAR m_strImageName[MAX_PATH]; // 图片名称
public:
CWzdImage(); // 构造函数
virtual ~CWzdImage(); // 析构函数
bool IsNull(); // 是否加载
int GetWidth(); // 获取宽度
int GetHeight(); // 获取高度
bool DestroyImage(); // 销毁图片
// 加载图片
bool LoadImage(LPCTSTR pszFileName);
bool LoadImage(HINSTANCE hInstance, LPCTSTR pszResourceName);
// 绘画图像
bool DrawImage(CDC* pDC, int nWndX, int nWndY);
bool DrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth, int nWndHeight);
bool DrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth, int nWndHeight,
int nImgX, int nImgY);
bool DrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth, int nWndHeight,
int nImgX, int nImgY, int nImgWidth, int nImgHeight);
// 透明绘画
bool AlphaDrawImage(CDC* pDC, int nWndX, int nWndY, BYTE cbAlphaDepth);
bool AlphaDrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight, BYTE cbAlphaDepth);
bool AlphaDrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight,int nImgX, int nImgY, BYTE cbAlphaDepth);
bool AlphaDrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight,int nImgX, int nImgY, int nImgWidth, int nImgHeight, BYTE cbAlphaDepth);
};
使用GDI+必须包含GdiPlus.h头文件,同时必须添加Gdiplus.lib静态库。另外初始化过程:
GdiplusStartupInput input;
GdiplusStartup(&m_GdiplusToken,&input,NULL);
释放过程都是必要的。
GdiplusShutdown(m_GdiplusToken);
Gdiplus::Image* m_pImage:保存图像信息。
IsNull():判断是否有图像信息。
LoadImage():两种加载图片方式:
- 一种调用Gdiplus::Image::FromFile()。
- 一种调用了FindResource()系列函数。再通过Gdiplus::Image::FromStream()读入数据。
DrawImage():四种普通画图方式:
- 在图片指定点开始(nWndX, nWndY)画一次图。
- 在窗口指定区域(nWndX, nWndY,nWndWidth, nWndHeight)画整幅图。
- 在窗口指定区域(nWndX, nWndY,nWndWidth, nWndHeight)从图片的指定点(nImgX, nImgY)画一次图。
- 在窗口指定区域(nWndX, nWndY,nWndWidth, nWndHeight)用图片的指定区域(nImgX, nImgY,nImgWidth, nImgHeight)画一次图。
AlphaDrawImage():四种透明绘图方式(必须在有背景的情况下):
- 从窗口指定点(nWndX, nWndY)开始以透明度(cbAlphaDepth)画一次图
- 在窗口指定区域(nWndX, nWndY,nWndWidth, nWndHeight)以透明度(cbAlphaDepth)画整幅图。
- 在窗口指定区域(nWndX, nWndY,nWndWidth, nWndHeight)从图片的指定点(nImgX, nImgY)以透明度(cbAlphaDepth)画一次图。
- 在窗口指定区域(nWndX, nWndY,nWndWidth, nWndHeight)用图片的指定区域(nImgX, nImgY,nImgWidth, nImgHeight)以透明度(cbAlphaDepth)画一次图。
实现代码:
#include "stdafx.h"
#include "WzdImage.h"
// 构造函数
CWzdImage::CWzdImage()
: m_pImage(NULL)
{
memset(m_strImageName, 0 ,sizeof(m_strImageName));
}
// 析构函数
CWzdImage::~CWzdImage()
{
DestroyImage();
}
// 是否加载
bool CWzdImage::IsNull()
{
if (NULL == m_pImage) return true;
if (m_pImage->GetLastStatus() != Gdiplus::Ok) return true;
return false;
}
// 获取宽度
int CWzdImage::GetWidth()
{
if (IsNull()) return 0;
return m_pImage->GetWidth();
}
// 获取高度
int CWzdImage::GetHeight()
{
if (IsNull()) return 0;
return m_pImage->GetHeight();
}
// 销毁图片
bool CWzdImage::DestroyImage()
{
if (m_pImage!=NULL)
{
delete m_pImage;
m_pImage = NULL;
}
return true;
}
// 加载图片
bool CWzdImage::LoadImage(LPCTSTR pszFileName)
{
if (NULL != m_pImage) return false;
// 加载文件
CT2CW strFileName(pszFileName);
m_pImage = Gdiplus::Image::FromFile((LPCWSTR)strFileName);
if ((NULL == m_pImage) || (Gdiplus::Ok != m_pImage->GetLastStatus()))
{
DestroyImage();
return false;
}
return true;
}
// 加载图片
bool CWzdImage::LoadImage(HINSTANCE hInstance, LPCTSTR pszResourceName)
{
if (NULL != m_pImage) return false;
// 查找资源
HRSRC hResource = FindResource(hInstance, pszResourceName, _T("IMAGE"));
if (NULL == hResource) return false;
// 读取资源
DWORD dwImageSize = SizeofResource(hInstance, hResource);
LPVOID pImageBuffer = LoadResource(hInstance, hResource);
IStream * pIStream = NULL;
if (S_OK != CreateStreamOnHGlobal(NULL, TRUE, &pIStream))
{
return false;
}
// 写入数据
pIStream->Write(pImageBuffer, dwImageSize, NULL);
m_pImage= Gdiplus::Image::FromStream(pIStream);
pIStream->Release();
if ((NULL == m_pImage) || (Gdiplus::Ok != m_pImage->GetLastStatus()))
{
return false;
}
return true;
}
// 绘画图像: 从窗口指定点(nWndX,nWndY)开始画一次图
bool CWzdImage::DrawImage(CDC* pDC, int nWndX, int nWndY)
{
int nImageWidth = m_pImage->GetWidth();
int nImageHeight = m_pImage->GetHeight();
return DrawImage(pDC, nWndX, nWndY, nImageWidth,
nImageHeight, 0, 0, nImageWidth, nImageHeight);
}
// 绘画图像: 在窗口指定区域(nWndX,nWndY,nWndWidth,nWndHeight)画整幅图
bool CWzdImage::DrawImage( CDC* pDC, int nWndX, int nWndY, int nWndWidth, int nWndHeight)
{
return DrawImage(pDC, nWndX, nWndY, nWndWidth,
nWndHeight, 0, 0, GetWidth(), GetHeight());
}
// 绘画图像: 在窗口指定区域(nWndX,nWndY,nWndWidth,nWndHeight)从图片的指定点
// (nImgX,nImgY)画一次图
bool CWzdImage::DrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight, int nImgX, int nImgY)
{
return DrawImage(pDC, nWndX, nWndY, nWndWidth,
nWndHeight, nImgX, nImgY, nWndWidth, nWndHeight);
}
// 绘画图像: 在窗口指定区域(nWndX,nWndY,nWndWidth,nWndHeight)用图片的指定区域
// (nImgX,nImgY,nImgWidth,nImgHeight)画一次图
bool CWzdImage::DrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight, int nImgX, int nImgY, int nImgWidth, int nImgHeight)
{
if (NULL == m_pImage || NULL == pDC) return false;
//创建屏幕
Gdiplus::Graphics graphics(pDC->GetSafeHdc());
//构造位置
Gdiplus::RectF rcDrawRect;
rcDrawRect.X = (Gdiplus::REAL)nWndX;
rcDrawRect.Y = (Gdiplus::REAL)nWndY;
rcDrawRect.Width = (Gdiplus::REAL)nWndWidth;
rcDrawRect.Height = (Gdiplus::REAL)nWndHeight;
//绘画图像
graphics.DrawImage(m_pImage, rcDrawRect, (Gdiplus::REAL)nImgX, (Gdiplus::REAL)nImgY,
(Gdiplus::REAL)nImgWidth, (Gdiplus::REAL)nImgHeight, Gdiplus::UnitPixel);
return true;
}
// 透明绘画: 从窗口指定点(nWndX,nWndY)开始以透明度(cbAlphaDepth)画一次图
bool CWzdImage::AlphaDrawImage(CDC* pDC, int nWndX, int nWndY, BYTE cbAlphaDepth)
{
int nImageWidth = m_pImage->GetWidth();
int nImageHeight = m_pImage->GetHeight();
return AlphaDrawImage(pDC, nWndX, nWndY, nImageWidth,
nImageHeight, 0, 0, nImageWidth, nImageHeight, cbAlphaDepth);
}
// 透明绘画: 在窗口指定区域(nWndX,nWndY,nWndWidth,nWndHeight)以透明度
//(cbAlphaDepth)画整幅图
bool CWzdImage::AlphaDrawImage( CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight, BYTE cbAlphaDepth)
{
return AlphaDrawImage(pDC, nWndX, nWndY, nWndWidth,
nWndHeight, 0, 0, GetWidth(), GetHeight(), cbAlphaDepth);
}
// 透明绘画: 在窗口指定区域(nWndX,nWndY,nWndWidth,nWndHeight)从图片的指定点
// (nImgX,nImgY)以透明度(cbAlphaDepth)画一次图
bool CWzdImage::AlphaDrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight, int nImgX, int nImgY, BYTE cbAlphaDepth)
{
return AlphaDrawImage(pDC, nWndX, nWndY, nWndWidth, nWndHeight,
nImgX, nImgY, nWndWidth, nWndHeight, cbAlphaDepth);
}
// 透明绘画: 在窗口指定区域(nWndX,nWndY,nWndWidth,nWndHeight)用图片的指定区域
// (nImgX,nImgY,nImgWidth,nImgHeight)以透明度(cbAlphaDepth)画一次图
bool CWzdImage::AlphaDrawImage(CDC* pDC, int nWndX, int nWndY, int nWndWidth,
int nWndHeight, int nImgX, int nImgY, int nImgWidth, int nImgHeight, BYTE cbAlphaDepth)
{
//加载判断
ASSERT(m_pImage!=NULL);
if (m_pImage==NULL) return false;
//创建屏幕
ASSERT(pDC!=NULL);
Gdiplus::Graphics graphics(pDC->GetSafeHdc());
//构造位置
Gdiplus::RectF rcDrawRect;
rcDrawRect.X=(Gdiplus::REAL)nWndX;
rcDrawRect.Y=(Gdiplus::REAL)nWndY;
rcDrawRect.Width=(Gdiplus::REAL)nWndWidth;
rcDrawRect.Height=(Gdiplus::REAL)nWndHeight;
//透明矩阵
Gdiplus::ColorMatrix Matrix=
{
1.0f,0.0f,0.0f,0.0f,0.0f,
0.0f,1.0f,0.0f,0.0f,0.0f,
0.0f,0.0f,1.0f,0.0f,0.0f,
0.0f,0.0f,0.0f,cbAlphaDepth/255.0f,0.0f,
0.0f,0.0f,0.0f,0.0f,1.0f
};
//设置属性
Gdiplus::ImageAttributes Attributes;
Attributes.SetColorMatrix(&Matrix,Gdiplus::ColorMatrixFlagsDefault,
Gdiplus::ColorAdjustTypeBitmap);
//绘画图像
graphics.DrawImage(m_pImage,rcDrawRect,(Gdiplus::REAL)nImgX,(Gdiplus::REAL)nImgY,
(Gdiplus::REAL)nImgWidth,(Gdiplus::REAL)nImgHeight,Gdiplus::UnitPixel,&Attributes);
return true;
}