在上一篇中,作者详细介绍了GDI+中坐标系的概念,并以示例的方式进行了解释。
以下代码,是根据作者的示例,编写的VC++代码:
2.在app的InitInstance()函数中编写以下代码,进行Gdiplus的初始化
5.重载CGDIManDlg的OnSize函数,主要是为了获取当前对话框的区域值m_Rect
6.在CGDIManDlg的OnPaint函数中绘制上一篇示例:
以我个人的理解,graphi.TranslateTransform(pRightLeg.X,pRightLeg.Y);的作用简单说来就是将(pRightLeg.X,pRightLeg.Y)作为graphi下面绘制的world坐标系的原点,
graphi.RotateTransform(-45);意思是在绘制的基础上逆时针旋转45度,而每次利用graphi.DrawXXX绘制完图形后,需要进行重置Gdiplus的page坐标系:graphi.ResetTransform();
如不重置,下面的绘制将无法进行。
以下代码,是根据作者的示例,编写的VC++代码:
1.首先新建一个基于对话框的MFC程序项目名称GDIMan,在其app的头文件中声明Gdiplus的令牌,用于Gdiplus的初始化
ULONG_PTR m_gdiplusToken;
2.在app的InitInstance()函数中编写以下代码,进行Gdiplus的初始化
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
3.重载app的ExitInstance()虚函数,释放Gdiplus资源
int CGDIManApp::ExitInstance()
{
// TODO: 在此添加专用代码和/或调用基类
Gdiplus::GdiplusShutdown(m_gdiplusToken);
return CWinApp::ExitInstance();
}
private:
PointF pHead;
PointF pBody;
PointF pLeftArm;
PointF pRightArm;
PointF pLeftLeg;
PointF pRightLeg;
SizeF sHead;
SizeF sBody;
SizeF sArm;
SizeF sLeg;
CRect m_Rect;//当前对话框的区域
并在cpp文件中在CGDIManDlg的构造函数中对其赋值:
CGDIManDlg::CGDIManDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CGDIManDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
sHead.Width=30;
sHead.Height=30;
sBody.Width=50;
sBody.Height=70;
sArm.Width=10;
sArm.Height=60;
sLeg.Width=20;
sLeg.Height=70;
}
5.重载CGDIManDlg的OnSize函数,主要是为了获取当前对话框的区域值m_Rect
void CGDIManDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
GetWindowRect(&m_Rect);
}
6.在CGDIManDlg的OnPaint函数中绘制上一篇示例:
void CGDIManDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
Graphics graphi(GetDC()->m_hDC);
Pen pen(Color(255,0,0,255));
pHead=PointF(m_Rect.Width()/2.0,100.0);
graphi.TranslateTransform(pHead.X,pHead.Y);
graphi.DrawEllipse(&pen,-sHead.Width/2.0,-sHead.Height/2.0,sHead.Width,sHead.Height);
graphi.ResetTransform();
pBody=PointF(pHead.X-sBody.Width/2,pHead.Y+sHead.Height/2.0);
graphi.TranslateTransform(pBody.X,pBody.Y);
graphi.DrawRectangle(&pen,(REAL)0,(REAL)0,sBody.Width,sBody.Height);
graphi.ResetTransform();
pLeftArm=PointF(pBody.X,pBody.Y);
graphi.TranslateTransform(pLeftArm.X,pLeftArm.Y);
graphi.RotateTransform(45);
graphi.DrawRectangle(&pen,(REAL)0,(REAL)0,sArm.Width,sArm.Height);
graphi.ResetTransform();
pRightArm=PointF(pLeftArm.X+sBody.Width,pLeftArm.Y);
graphi.TranslateTransform(pRightArm.X,pRightArm.Y);
graphi.RotateTransform(-45);
graphi.DrawRectangle(&pen,(REAL)0-sArm.Width,(REAL)0,sArm.Width,sArm.Height);
graphi.ResetTransform();
pLeftLeg=PointF(pBody.X,pBody.Y+sBody.Height);
graphi.TranslateTransform(pLeftLeg.X,pLeftLeg.Y);
graphi.RotateTransform(45);
graphi.DrawRectangle(&pen,(REAL)0,(REAL)0,sLeg.Width,sLeg.Height);
graphi.ResetTransform();
pRightLeg=PointF(pLeftLeg.X+sBody.Width,pLeftLeg.Y);
graphi.TranslateTransform(pRightLeg.X,pRightLeg.Y);
graphi.RotateTransform(-45);
graphi.DrawRectangle(&pen,(REAL)0-sLeg.Width,(REAL)0,sLeg.Width,sLeg.Height);
graphi.ResetTransform();
}
以我个人的理解,graphi.TranslateTransform(pRightLeg.X,pRightLeg.Y);的作用简单说来就是将(pRightLeg.X,pRightLeg.Y)作为graphi下面绘制的world坐标系的原点,
graphi.RotateTransform(-45);意思是在绘制的基础上逆时针旋转45度,而每次利用graphi.DrawXXX绘制完图形后,需要进行重置Gdiplus的page坐标系:graphi.ResetTransform();
如不重置,下面的绘制将无法进行。