书接上回,上一篇用鼠标菜单响应,利用Bresenham画直线,但是画出直线后,放缩窗口之后就只保留啦最后一条直线.
本文将利用结构体PL和链表SavePoint存储鼠标响应得到的直线段点pointa,pointb.然后在OnDraw函数中遍历链表SavePoint画直线(仅以此文纪念被导导凶的两节课,真的把数据结构的东西都忘记啦呜呜呜).
1头文件中关于结构体和新变量,新函数的定义.在头文件中定义需要的结构体,由两个端点pointa, pointb和next指针构成.在类中定义需要的新变量和函数.
//结构体
struct PL
{
CPoint pointa;
CPoint pointb;
struct PL* next;
};
class CBresenhamlineView : public CView
{
protected: // 仅从序列化创建
CBresenhamlineView();
DECLARE_DYNCREATE(CBresenhamlineView)
// 特性
public:
CBresenhamlineDoc* GetDocument() const;
// 定义的新变量和需要用到的Bresenham函数
public:
void CBresenhamlineView::Bresenham_Line(int x0, int y0, int x1, int y1, int color);
struct PL *p;//辅助构建链表的指针
struct PL *SavePoint;//用来存储结构体的链表
bool flag;//判断point是pointa还是pointb的布尔变量
2在构造函数中进行变量和指针的初始化.flag为真,最先将point赋给pointa.SavePoint是有头指针的链表(也可以没有头指针,我习(只)惯(会)用头指针)
flag = true;
p = NULL;
SavePoint = (struct PL*)malloc(sizeof(PL));
SavePoint->next = NULL;
3利用鼠标响应建立链表(如何添加响应请看上一篇).(啰嗦一句,指针指向节点的首地址,NULL是个空地址)
void CBresenhamlineView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(flag)
{
p = (struct PL*)malloc(sizeof(PL));//开辟一段内存
p->pointa = point;//如果flag为正,将point赋值给p的pointa
}
else
{
p->pointb = point;//如果flag为反,将point赋给pointb
//将新p逆向串入SavePoint链表中
p->next = SavePoint->next;
SavePoint->next = p;
}
flag = !flag;//flag取反
CDC *pDC = GetDC();
OnDraw(pDC);
ReleaseDC(pDC);
CView::OnLButtonDown(nFlags, point);
}
4OnDraw函数中遍历链表画直线
void CBresenhamlineView::OnDraw(CDC* pDC)
{
CBresenhamlineDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
struct PL *traverse;
traverse = SavePoint->next;//SavePoint链表中有头节点
while(traverse)
{
Bresenham_Line(traverse->pointa.x, traverse->pointa.y, traverse->pointb.x, traverse->pointb.y, RGB(255,0,0));
traverse = traverse->next;
}
free(traverse);
}
5析构函数中遍历销毁
CBresenhamlineView::~CBresenhamlineView()
{
p = SavePoint;
while(SavePoint->next)
{
p = SavePoint->next;
SavePoint->next = p->next;
free(p);
}
free(SavePoint);
}