设为首页 加入收藏

TOP

14.4.3 使用鼠标绘图(5)
2013-10-07 16:12:23 来源: 作者: 【 】 浏览:72
Tags:14.4.3 使用 鼠标 绘图

14.4.3  使用鼠标绘图(5)

调用继承的CreatePen()函数,会在aPen中建立钢笔。将钢笔选择到设备上下文中后,就把当前位置移动到直线的起点,这个点定义在m_StartPoint数据成员中,然后从这个点将直线绘制到m_EndPoint。最后在设备上下文中还原旧钢笔,绘图到此结束。

创建边界矩形

乍一看,获得一个形状的边界矩形好像很简单。例如,直线始终是封闭矩形的对角线,圆由它的封闭矩形定义,但还是有一些稍微复杂的问题。形状必须完全在封闭矩形的内部;否则,部分形状可能无法绘制出来,所以在创建边界矩形时,必须考虑形状如何相对于其定义参数来绘制,以及绘图时使用的线宽度。此外,如何调整定义边界矩形的坐标取决于映射模式,所以也必须考虑这个方面。

在计算不同映射模式中边界矩形的坐标时,计算方法之间的区别只与y坐标有关;x坐标的计算对于所有映射模式都一样:都是从矩形左上角的x坐标中减去线宽,再将它加到矩形右下角的x坐标中。在MM_TEXT映射模式中,要从定义矩形的左上角的y坐标中减去线宽,但是在MM_LOENGLISH映射模式(以及其他所有映射模式)中,由于y轴在相反的方向上增大,因此需要在定义矩形的左上角的y坐标中加上线宽。下面要在每种形状的构造函数中创建该形状的边界矩形。

需要提醒的是,CRect对象的各个数据成员是left和top (分别存储左上角的x和y坐标)以及right和bottom (分别存储右下角的x和y坐标)。这些数据成员都是公共成员,所以可以直接访问它们。一个常见的错误是把坐标对写成(top, left),而不是正确的顺序(left, top)。

规范化的矩形

规范化矩形的left值小于right值,top值小于bottom值。如果矩形不是规范化的,在CRect对象上执行的函数就不会正确执行。例如,CRect类的InflateRect()成员函数从矩形的top和left成员中减去参数值,给bottom和right成员加上这些值。这意味着,如果矩形不是规范化的,对它应用InflateRect(),矩形实际上有可能缩小。只要矩形是规范化的,则无论在什么映射模式中,InflateRect()函数都可以正常工作。通过调用CRect对象的NormalizeRect()成员,可以确保这个对象是规范化的。

5. 计算直线的封闭矩形

现在,在CLine构造函数内编写计算封闭矩形的代码:

  1. CLine::CLine(const CPoint& start, const CPoint& end, COLORREF color):  
  2. CElement(start, color), m_EndPoint(end)  
  3. {  
  4. // Define the enclosing rectangle  
  5. m_EnclosingRect = CRect(start, end);  
  6. m_EnclosingRect.NormalizeRect();  
  7. m_EnclosingRect.InflateRect(m_PenWidth, m_PenWidth);  
  8. }  

调用m_EnclosingRect对象的NormalizeRect()成员,则无论直线的起点和终点的相对位置如何,都能确保边界矩形的left和top值分别小于right和bottom值。调用InflateRect(),使边界矩形的尺寸增大一个线宽。第一个参数是左边和右边的调整量,第二个参数是顶部和底部的调整量。InflateRect()的一个重载版本只有一个SIZE类型的参数,它也接受CSize对象,该对象封装了SIZE结构。CSize对象通过long类型的公共成员cx和cy定义了大小。

6. CRectangle类

在定义矩形对象时使用的数据和定义直线时相同-- 矩形对角点,可以把CRectangle类定义为:

  1. class CRectangle: public CElement  
  2. {  
  3. public:  
  4. virtual ~CRectangle(void);  
  5. virtual void Draw(CDC* pDC) override;   // Function to display a rectangle  
  6. // Constructor for a rectangle object  
  7. CRectangle(const CPoint& start, const CPoint& end, COLORREF color);  
  8. protected:  
  9. CPoint m_BottomRight;                                                           // Bottom-right point for the rectangle  
  10. CRectangle(void);                                                                       // Default constructor - should not be used  
  11. };  

无参数构造函数现在是protected类型,以防止外界使用它。这个矩形的定义非常简单,只包括一个构造函数、一个虚函数Draw()和这个类的protected部分中的一个无参数构造函数。

CRectangle类构造函数

新的CRectangle类构造函数的代码比Cline复杂一些:

  1. // CRectangle constructor  
  2. CRectangle:: CRectangle (  
  3. const CPoint& start, const CPoint& end, COLORREF color) :  
  4. CElement(start, color)  
  5. {  
  6. // Normalize the rectangle defining points  
  7. m_StartPoint = CPoint((std::min)(start.x, end.x),(std::min)(start.y, end.y));  
  8. m_BottomRig ht = CPoint((std::max)(start.x, end.x), (std::max)(start.y, end.y));  
  9. // Ensure width and height between the points is at least 2  
  10. if((m_BottomRight.x - m_StartPoint.x) < 2)  
  11. m_BottomRight.x = m_StartPoint.x + 2;  
  12. if((m_BottomRight.y - m_StartPoint.y) < 2)  
  13. m_BottomRight.y = m_StartPoint.y + 2;  
  14. // Define the enclosing rectangle  
  15. m_EnclosingRect = CRect(m_StartPoint, m_BottomRight);  
  16. m_EnclosingRect.InflateRect(m_PenWidth, m_PenWidth);  
  17. }  

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇14.4.3 使用鼠标绘图(4) 下一篇14.4.3 使用鼠标绘图(6)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·数据库:推荐几款 Re (2025-12-25 12:17:11)
·如何最简单、通俗地 (2025-12-25 12:17:09)
·什么是Redis?为什么 (2025-12-25 12:17:06)
·对于一个想入坑Linux (2025-12-25 11:49:07)
·Linux 怎么读? (2025-12-25 11:49:04)