14.4.3 使用鼠标绘图(7)
要使用sqrt()函数,必须在Circle.cpp文件的开始处给cmath头文件添加一个#include指令。最大坐标值是32位,CPoint成员x和y声明为long型,所以把sqrt()函数返回的值转换为long类型会得到准确的结果。平方根计算的结果是double型,由于想把它作为整数使用,因此要把它强制转换成long型。半径至少应是1,否则CDC的Ellipse()函数就什么都不绘制。
在m_StartPoint中存储CPoint对象和边界矩形左上角的坐标,该坐标是从圆心坐标中减去radius得到的。m_BottomRight点则是给圆心坐标加上radius得到的。
绘制圆
Draw()函数在CCircle类中的实现如下所示:
- // Draw a circle
- void CCircle::Draw(CDC* pDC)
- {
- // Create a pen for this object and initialize it
- CPen aPen;
- CreatePen(aPen);
- CPen* pOldPen = pDC->SelectObject(&aPen); // Select the pen
- // Select a null brush
- CBrush* pOldBrush = dynamic_cast<CBrush*>(pDC->SelectStockObject(NULL_BRUSH));
- // Now draw the circle
- pDC->Ellipse(m_StartPoint.x, m_StartPoint.y,
- m_BottomRight.x, m_BottomRight.y);
- pDC->SelectObject(pOldPen); // Restore the old pen
- pDC->SelectObject(pOldBrush); // Restore the old brush
- }
在设备上下文中选择了具有适当颜色的钢笔和空画笔以后,将通过调用Ellipse()函数绘制圆。参数是边界矩形的角点坐标。Ellipse()函数的一个重载版本接受CRect参数。
8. CCurve类
CCurve类不同于其他类,因为它必须能够处理数量可变的定义点。曲线由两个或多个点来定义,这些点可以存储在STL容器中。不需要删除曲线上的点,所以vector<CPoint>容器是存储这些点的一个不错的候选。第10章介绍了vector<T>模板,但是,在完成CCurve类的定义之前,需要更详细地探讨一下用户如何创建和绘制曲线。
绘制曲线
绘制曲线与绘制直线、矩形或圆并不相同。当绘制这些形状时,按下鼠标左键并移动光标时,就在创建一系列不同的元素,它们具有一个相同的参考点--即按下鼠标左键时的那个点。而当绘制曲线时,情况就不同了,如图14-16所示。

当移动光标来绘制一条曲线时,并不是在创建一系列新的曲线,而是在延伸同一条曲线,因此后续的每个新光标位置都向曲线添加另一个线段。因此,一旦从WM_LBUTTONDOWN消息和第一条WM_MOUSEMOVE消息获得两个点,就需要创建一个CCurve对象。随后的鼠标移动消息所定义的点则向已有的CCurve对象定义其他线段。为此,需要向CCurve类添加一个函数AddSegment(),用来对曲线进行延伸。
需要考虑的另一要点是如何计算封闭矩形。定义封闭矩形时,需要从所有定义点中获得(最小x, 最小y)对,以便建立矩形的左上角;再从所有定义点中获得(最大x, 最大y)对,以便建立矩形的右下角。生成封闭矩形的最简单的方法是,在构造函数中根据前两个点来计算它,然后向曲线添加点时,在AddSegment()函数中以增量方式重新计算它。
在Curve.h文件中,给vector头文件添加一个#include指令。可以将CCurve类定义修改为:
- class CCurve: public CElement
- {
- public:
- virtual ~CCurve(void);
- virtual void Draw(CDC* pDC) override; // Function to display a curve
- // Constructor for a curve object
- CCurve(const CPoint& first, const CPoint& second, COLORREF color);
- void AddSegment(const CPoint& point); // Add a segment to the curve
- protected:
- std::vector<CPoint> m_Points; // Points defining the curve
- CCurve(void); // Default constructor - should not be used
- };