例:绘制一条由点连起的曲线(简单图形)
新建一个MFC SDI应用程序,工程名为DrawGraph;
添加菜单命令:绘图和设置;
绘图子菜单项为绘制图形的类型。包含如下类型:
绘图类型:
菜单项名称 | Caption | 菜单项ID |
点 | Dot | IDM_DOT |
直线 | Line | IDM_LINE |
折线 | BrokenLine | IDM_BRONKENLINE |
矩形 | Rectangle | IDM_RECTANGLE |
圆角矩形 | Rounded Rectangle | DM_ROUNDEDRECTANGLE |
多边形 | Polygon | IDM_POLYGON |
圆弧 | Arc | IDM_ARC |
椭圆 | ellipse | IDM_ELLIPSE |
弧形 | camber | IDM_CAMBER |
扇形 | sector | IDM_SECTOR |
Bezier曲线 | Bezier | IDM_BEZIER |
在程序运行后,当用户点击某个菜单项时,应该把用户的选择保存起来,以便随后的绘图操作中使用。在头文件 DrawGraphView.h 中添加一个私有成员变 m_uiDrawType 用于保存用户选择的结果。
UINT m_uiDrawType;
在构造函数中将其初始化为0
当用户选择【绘图】菜单下的不同子菜单项时,将变量 m_uiDrawType 设置为不同的值,下表所示
表1-2 m_uiDrawType变量的取值
菜单项名称 | m_uiDrawType变量的取值 |
点 | 1 |
直线 | 2 |
折线 | 3 |
矩形 | 4 |
圆角矩形 | 5 |
多边形 | 6 |
圆弧 | 7 |
椭圆 | 8 |
弧形 | 9 |
扇形 | 10 |
Bezier曲线 | 11 |
在对应的菜单项消息响应函数按照表中的数值中给m_uiDrawType 赋值
对于直线、矩形和椭圆,在绘图时都可以用两个点来确定其图形。鼠标左键按下的一个点(绘图原点)和鼠标左键弹起的那个点(绘图终点)。这样就需要为视类(CDrawGraphView)分别捕获鼠标左键按下和弹起这两个消息。另外还需要将绘图原点保存下来,这样还需要在在头文件 DrawGraphView.h 中添加一个CPoint类型的私有成员变量 m_ptOrigin 用于保存绘图原点。
CPoint m_ptOrigin;
同样,还需要在构造函数中对其初始化。将该变量的值设置为0,即将原点设置为(0,0)。
然后,在鼠标左键按下消息响应函数中,保存当前的点。
void CDrawGraphView::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptOrigin=point;
CView::OnLButtonDown(nFlags, point);
}
在鼠标左键弹起的消息响应函数中添加绘制图形的响应:
代码如下:
void CDrawGraphView::OnLButtonUp(UINT nFlags, CPoint point)
{
//进行绘图操作首先需要DC对象
CClientDC dc(this);
//由用户指定的颜色来绘图
//pen 的第一个参数是线形状 第二个参数是线宽 均可以当做一个变量来设置
CPen pen(PS_SOLID,5,RGB(255,0,0));
dc.SelectObject(&pen);
//将DC中的画刷设置为透明的,这样就不会出现先绘制的图形被后面绘制的图形压盖
CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
dc.SelectObject(pBrush);
//折线
CPoint ptsPoly[4]={CPoint(100,50),CPoint(200,300),CPoint(400,150),CPoint(400,450)};
//圆角矩形
CRect RndRC(20,100,80,160);
//多边形
CPoint pts[6] = {CPoint(300,50),CPoint(400,50),CPoint(450,100),CPoint(400,150),CPoint(300,150),CPoint(250,100)};
//圆弧
CRect RndAre(40,200,160,320);
//画弧线相关
CRect rectArc(500,50,600,100);
CBrush brushArc(RGB(255,0,0));
//Bezier曲线
CPoint ptsBezier[4]={CPoint(100,50),CPoint(200,300),CPoint(400,150),CPoint(400,450)};
//为避免图形 之间形成遮盖,可以看到图形内部的内容 可以把DC中的画刷设置为透明
CBrush *pBush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
dc.SelectObject(pBush);
switch (m_uiDrawType)
{
//点
case 1:
dc.SetPixel(point,RGB(255,0,0));
break;
//直线
case 2:
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
break;
//折线
case 3:
dc.Polyline(ptsPoly,4);
break;
//矩形
case 4:
dc.Rectangle(CRect(m_ptOrigin,point));
break;
//圆角矩形
case 5:
dc.RoundRect(RndRC,CPoint(10,10));
break;
//多边形
case 6:
dc.Polygon(pts,6);
break;
//圆弧
case 7:
dc.Chord(RndAre,m_ptOrigin,point);
break;
//椭圆
case 8:
dc.Ellipse(CRect(m_ptOrigin,point));
//dc.Arc(RndAre,m_ptOrigin,point);//画圆
break;
//弧形
case 9:
dc.Arc(500,50,600,100,520,70,560,30);
break;
//扇形
case 10:
dc.Pie(RndAre,m_ptOrigin,point);
break;
//Bezier曲线
case 11:
dc.PolyBezier(ptsBezier,4);
break;
default:
break;
}
前面绘制的图形在界面遮盖或隐藏后绘制的结果就不能显示了 还在实现中
//CGraph graph(m_uiDrawType,m_ptOrigin,point);
//m_ptrArray.Add(graph);
CView::OnLButtonUp(nFlags, point);
}
注:这里绘制的图形在切换界面或隐藏当前的绘制界面后都会出现绘制的内容清空的情况。红色划线部分涉及到图像的重绘和保存,后面再做介绍。
小结:上面的绘制方法都是静态的操作再运用MFC封装好的绘制图形的函数,实现显得低级,这里只是简要地复习一下这些绘制图形的函数的用法。