下面以一个应用为例说明该操作:
应用:画线,可以选择先粗细和颜色
首先我创建一个名字为wd的单文档MFC工程
1.在wdDoc.h中定义线的结构体:
struct CLine
{
CPoint start; //起始点坐标
CPoint end; //结束点坐标
COLORREF color; //线条颜色
int thick; //粗细
int style; //线条样式
}
2.在文档类中加入链表类型,通过它来保存视图中绘制的所有的直线
class CWdDoc : public CDocument
{
protected: // create from serialization only
CWdDoc();
DECLARE_DYNCREATE(CWdDoc)
// Attributes
public:
CObList list; //注意这里的数据类型是MFC封装好的链表类CObList
3.在视图类中添加鼠标按下和鼠标抬起的事件
这里的视图类为CWdView
加入消息响应,为鼠标左键按下和鼠标左键抬起,以WM开头,看单词可以知道意思
并在视图类中加入两个变量
public:
Cline l;
bool isFinished; //直线是否画完
在鼠标按下事件中
void CWdView::OnLButtonDown(UINT nFlags, CPoint point) //鼠标按下
{
// TODO: Add your message handler code here and/or call default
l.start=point; //记录落点
isFinished=false;
CView::OnLButtonDown(nFlags, point);
}
void CWdView::OnLButtonUp(UINT nFlags, CPoint point) //抬起
{
// TODO: Add your message handler code here and/or call default
l.end=point;
isFinished=true;
Invalidate(); //通知视图类重绘
CView::OnLButtonUp(nFlags, point);
}
4.在OnDraw中增加重绘制
void CWdView::OnDraw(CDC* pDC)
{
CWdDoc* pDoc = GetDocument(); //自动生成的文档指针
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CPen pen,*oldpen; //定义画笔
CObList *list=&pDoc->list; //定义链表
if(isFinished)
list->AddTail((CObject*)new CLine(l)); //如果已经画结束,把线条压入链表尾部
POSITION p=list->GetHeadPosition(); //定义POSITION指针位置结构,指向表头
CLine *t; //定义线指针
while(p){ //循环直到表尾
t=(CLine*)list->GetNext(p); //得到当前直线指针,注意类型转换
pen.CreatePen(t->style,t->thick,t->color); //设置当前画笔
oldpen=pDC->SelectObject(&pen); //选择画笔,同时将现在的画笔保存至oldpen指针
pDC->MoveTo(t->start); //画线
pDC->LineTo(t->end); //画线
pDC->SelectObject(oldpen); //选择oldpen画笔,然并软
pen.DeleteObject(); //撤销画笔部件,这一步必须
}
isFinished=false; //画完避免重复
}
5.增加菜单中的画笔选项
在菜单视图中创建并绘好如下几个选项
对于每一个选项,增加处理函数,这里只列举一个,其它类比
void CWdView::OnBlack()
{
// TODO: Add your command handler code here
l.color=0;
}
void CWdView::OnUpdateBlack(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
pCmdUI->SetCheck(l.color==0);
}
前面一个是选WM_COMMAND,当点击时,选中颜色
后面一个的效果是如果SetCheck的返回是true,则菜单框处于选中状态,不能再按下
6.文件的打开与保存
void CWdDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
CLine *t;
POSITION p=list.GetHeadPosition();
ar<<list.GetCount(); //先保存线个数
while(p)
{
t=(CLine*)list.GetNext(p); //注意,这个p的头指针(表头)为空
ar<<t->start<<t->end<<t->color<<t->style<<t->thick;
}
}
else
{
// TODO: add loading code here
CLine *t;
int n,i;
ar>>n;
for(i=0;i<n;i++)
{
t=new CLine;
ar>>t->start>>t->end>>t->color>>t->style>>t->thick;
list.AddTail((CObject*)t);
}
}
}
下面为效果