14.4.3 使用鼠标绘图(4)
4. CLine类
可以把CLine类的定义修改为:
- class CLine: public CElement
- {
- public:
- virtual ~CLine(void);
- virtual void Draw(CDC* pDC) override; // Function to display a line
- // Constructor for a line object
- CLine(const CPoint& start, const CPoint& end, COLORREF aColor);
- protected:
- CPoint m_EndPoint; // End point of line
- protected:
- CLine(void); // Default constructor should not be used
- };
直线用两个点定义,分别是继承自CElement的m_StartPoint和m_EndPoint。这个类有一个public构造函数,它的参数值将定义直线,而无参数的默认构造函数已移动到这个类的protected部分,以防从外部使用它。构造函数的前两个参数是const引用,以免在创建CLine对象时复制CPoint对象。OnDraw()成员声明中使用override,是为了确保编译器可验证,它正确覆盖了基类函数。
实现CLine类
把CLine成员函数的实现添加到由Class Wizard创建的Line.cpp文件中。stdafx.h文件已经包括在这个文件中,从而使得标准系统头文件在这个文件中可用,并预编译stdafx.h文件的内容。预计不会修改的头文件可以包含在stdafx.h文件中,使它们也预编译。现在就可以在Line.cpp文件中添加CLine构造函数的基本代码了。
CLine类构造函数
CLine类构造函数的代码是:
- // CLine class constructor
- CLine::CLine(const CPoint& start, const CPoint& end, COLORREF color) :
- CElement(start, color), m_EndPoint(end) {}
首先调用CElement类的构造函数,初始化继承来的m_StartPoint和m_Color成员。在这个构造函数中忽略了第三个参数,定义钢笔宽度默认设置为1,而Cline的m_EndPoint成员在构造函数的初始化列表中初始化,以后会添加更多的代码。
绘制直线
绘制直线所需的CPen对象对所有元素而言都是相同的,在CElement类的定义中可以添加一个函数来创建它:
- // Create a pen
- void CreatePen(CPen& aPen)
- {
- if(!aPen.CreatePen(PS_SOLID, m_PenWidth, m_Color))
- {
- // Pen creation failed
- AfxMessageBox(_T("Pen creation failed."), MB_OK);
- AfxAbort();
- }
- }
只有派生类对象才调用这个函数,所以可以把这个函数定义放在类的protected部分。在类定义中定义该函数,会使它成为内联函数。引用参数允许函数修改在调用函数中定义的aPen对象。给CPen对象调用CreatePen(),会创建一个钢笔,并把它关联到对象上。
创建合适颜色的新钢笔,直线宽度由m_PenWidth指定,只不过这次要保证它能使用。在钢笔不能使用这种不大可能发生的情况中,最可能的原因是内存耗尽,这是一个严重的问题。这几乎总是由程序中的错误引起的,所以应首先编写调用AfxMessageBox()的函数(它是一个显示消息框的MFC全局函数),然后调用AfxAbort()终止这个程序。AfxMessageBox()的第一个参数指定要出现的消息,第二个参数指定消息框应当有一个OK按钮。要获得有关这两个函数的详细信息,可以在Editor窗口中把光标放在函数名内,然后按F1键。
如果基类中没有这个函数,就必须在每个派生类的Draw()函数中重复这些代码。
设备上下文、钢笔、画笔、字体和其他用于在窗口中绘图的对象都是GDI对象。不能复制或指定GDI对象,否则,代码就不会编译。这表示,不能将GDI对象按值传递给另一个函数。
尽管在绘制直线时需要考虑使用的颜色,但是CLine类的Draw()函数也不是太难:
- // Draw a CLine object
- void CLine::Draw(CDC* pDC)
- {
- // Create a pen for this object and initialize it
- CPen aPen;
- CreatePen(aPen);
- CPen* pOldPen = pDC->SelectObject(&aPen); // Select the pen
- // Now draw the line
- pDC->MoveTo(m_StartPoint);
- pDC->LineTo(m_EndPoint);
- pDC->SelectObject(pOldPen); // Restore the old pen
- }