计算机图形学__第二章_MFC交互绘图基础(4)

1970-01-01 08:00

//鼠标绘图时鼠标移动处理函数

void CDrawMapView::DrawMouseMove(UINT nFlags, CPoint point) {

SetCursor(m_Cursor);//设置使用光标资源 CClientDC dc(this);//构造设备环境对象

//判断鼠标移动的同时鼠标左键按下,并且要绘制的是直线段 if (m_LButtonDown && m_DrawType == 1) { dc.SetROP2(R2_NOT);//设置绘图模式为R2_NOT //重新绘制前一个鼠标移动消息处理函数绘制的直线段 //因为绘图模式的原因,结果是擦除了该线段 dc.MoveTo(m_StartPoint); dc.LineTo(m_EndPoint); //绘制新的直线段 dc.MoveTo(m_StartPoint); dc.LineTo(point); //保存新的直线段终点 m_EndPoint = point; } }

//鼠标绘图时鼠标左键抬起处理函数

void CDrawMapView::DrawLButtonUp(UINT nFlags, CPoint point) {

SetCursor(m_Cursor);//设置使用光标资源 ReleaseCapture();//释放鼠标

CClientDC dc(this);//构造设备环境对象

//绘制的是直线段 if (m_DrawType == 1) { //绘制最终要绘制的直线段 dc.MoveTo(m_StartPoint); dc.LineTo(m_EndPoint); } }

在处理函数中用到的变量m_StartPoint和m_EndPoint用于存放所要绘制的直线段的起始点坐标和终止点坐标。这两个变量是CDrawMapView的成员变量,所以我们要在CDrawMapView类中添加这两个变量,其类型是CPoint:

CPoint m_EndPoint;//鼠标绘图终止点坐标 CPoint m_StartPoint;//鼠标绘图开始点坐标

变量m_LButtonDown是一个布尔型变量,该变量用于标识绘图的时候鼠标左键是否按下,因为要求绘图过程中要一直按住鼠标左键。在CDrawMapView

类中要添加这个变量:

BOOL m_LButtonDown;//鼠标左键是否按下

并且在CDrawMapView类的构造函数中初始化该变量,添加如下代码: m_LButtonDown = false;

现在分别看一下在三个鼠标消息处理函数中我们都做了哪些工作。

(1) 鼠标左键按下处理函数。在函数中先设置了鼠标使用的光标资源,并捕捉鼠标。然后设置了m_StartPoint和m_EndPoint的初始值,此时鼠标左键刚刚按下,所以这两个点相同。最后设置m_LButtonDown为true,表示鼠标左键已经按下。

(2) 鼠标移动处理函数,主要在该函数中完成橡皮线的绘制。先在函数中设置鼠标使用的光标资源,再构造设备环境对象,以便进行绘图。if条件判断在鼠标左键按下并且要绘制的图形是直线段时,执行绘制直线段橡皮线的代码。绘制直线段橡皮线的代码就是if条件句内的代码。代码设置绘图模式为R2_NOT,就是在这个绘图模式下才产生了橡皮线的效果。接下来,首先绘制m_StartPoint和m_EndPoint之间的直线段,再绘制m_StartPoint和产生鼠标移动消息时鼠标光标所在位置point之间的直线段,最后将point赋值给m_EndPoint。因为m_EndPoint中存放的一直是上次调用鼠标移动消息处理函数时鼠标光标所处的位置,所以绘制m_StartPoint和m_EndPoint之间的直线段时,该直线段已经存在了,因为绘图模式的关系,本次绘图就起到了将原来的线段擦除的功能。在m_StartPoint和point之间绘制直线段,此时point点是新的位置,所以原来视图区中不会有该直线段存在,则此时绘图实际在视图区中绘制了一条从m_StartPoint到point的直线段。最后将m_EndPoint赋值为point,保证下一次执行鼠标移动消息处理函数时可以正确的将本次执行时绘制的直线段擦除掉。可以看到m_StartPoint点在鼠标左键按下时进行赋值之后就一直没有改变,因为在当前鼠标绘图方式中,起始点是一直不变的,鼠标移动所改变的是终止点。

(3) 鼠标左键抬起处理函数,此时表示本次鼠标绘制图形完毕。在函数中设置了鼠标使用的光标资源,并释放鼠标。然后构造设备环境对象,用于绘制最终的图形。if条件句判断当前绘制的是直线段,就调用相应的绘图函数将直线段绘制出来。实际上此处应该使用用户设定的画笔和画刷来绘制图形,并且需要将绘制的图形储存起来以便应用程序可以进行重画,在后面介绍到相关部分时将修改此处代码,现在只是把图形简单地绘制出来。代码最后将m_LButtonDown设置为false,表示鼠标左键处于抬起状态。

现在我们在系统的鼠标消息处理函数中调用我们所编写的函数,代码如下: //鼠标左键按下处理函数

void CDrawMapView::OnLButtonDown(UINT nFlags, CPoint point) {

// TODO: Add your message handler code here and/or call default //处于绘图状态时调用鼠标绘图时鼠标左键按下处理函数 if (m_isDraw) this->DrawLButtonDown(nFlags,point); CView::OnLButtonDown(nFlags, point); }

//鼠标移动处理函数

void CDrawMapView::OnMouseMove(UINT nFlags, CPoint point) {

// TODO: Add your message handler code here and/or call default //处于绘图状态时调用鼠标绘图时鼠标移动处理函数 if (m_isDraw) this->DrawMouseMove(nFlags,point); CView::OnMouseMove(nFlags, point); }

//鼠标左键抬起处理函数

void CDrawMapView::OnLButtonUp(UINT nFlags, CPoint point) {

// TODO: Add your message handler code here and/or call default //处于绘图状态时调用鼠标绘图时鼠标左键抬起处理函数 if (m_isDraw) this->DrawLButtonUp(nFlags,point); CView::OnLButtonUp(nFlags, point); }

调用我们编写的函数之前先判断当前是否处于绘图状态,如果是则调用我们编写的绘图状态下对应的鼠标消息处理函数。现在运行应用程序,就可以使用鼠标绘制直线段了,我们可以看一下橡皮线的具体效果。 2.2.3 用鼠标绘制椭圆和椭圆区域

使用鼠标绘制椭圆和椭圆区域类似于绘制直线段,差别在于要绘制的橡皮线是不同的,而且绘图完毕时最终绘制的图形分别为椭圆和椭圆区域。对于绘制椭圆和椭圆区域来说,使用的橡皮线都是相同的,即为椭圆的边界线。这里要注意不能使用设备环境的Ellipse函数来绘制椭圆边界线,因为Ellipse函数绘制的是填充的椭圆区域,填充的区域内部将产生覆盖效果,不能满足橡皮线的要求。这里我们调用设备环境的Arc函数来分别绘制椭圆的两段首尾相接的椭圆弧,从而合成一个椭圆。

DrawLButtonDown函数不需要修改,因为在鼠标左键按下时进行的初始设置是相同的。在DrawMouseMove中添加如下代码,完成椭圆和椭圆区域的橡皮线绘制:

//判断鼠标移动的同时鼠标左键按下,并且要绘制的是椭圆或椭圆区域 if (m_LButtonDown && (m_DrawType == 2 || m_DrawType ==3)) {

dc.SetROP2(R2_NOT);//设置绘图模式为R2_NOT //擦除前一次函数调用时绘制的椭圆边界线

dc.Arc(m_StartPoint.x,m_StartPoint.y,m_EndPoint.x,m_EndPoint.y, m_StartPoint.x,m_StartPoint.y,m_EndPoint.x,m_EndPoint.y); dc.Arc(m_StartPoint.x,m_StartPoint.y,m_EndPoint.x,m_EndPoint.y, m_EndPoint.x,m_EndPoint.y,m_StartPoint.x,m_StartPoint.y); //绘制新的椭圆边界线

dc.Arc(m_StartPoint.x,m_StartPoint.y,point.x,point.y, m_StartPoint.x,m_StartPoint.y,point.x,point.y);

dc.Arc(m_StartPoint.x,m_StartPoint.y,point.x,point.y, point.x,point.y,m_StartPoint.x,m_StartPoint.y); //保存新的终止点 m_EndPoint = point; }

将该段代码添加到绘制直线段橡皮线代码后面。代码中Arc函数以m_StartPoint和m_EndPoint点(或者point点)为椭圆弧所在椭圆的外接矩形的左上角点和右下角点。然后先以m_StartPoint和m_EndPoint点(或者point点)作为椭圆弧的起始点和终止点,再以m_StartPoint和m_EndPoint点(或者point点)作为椭圆弧的终止点和起始点,就正好画出一个完整的椭圆。

在DrawLButtonUp函数中添加如下代码,完成椭圆或椭圆区域的绘制工作: //绘制的是椭圆 if (m_DrawType == 2) {

//绘制椭圆边界线

dc.Arc(m_StartPoint.x,m_StartPoint.y,m_EndPoint.x,m_EndPoint.y, m_StartPoint.x,m_StartPoint.y,m_EndPoint.x,m_EndPoint.y); dc.Arc(m_StartPoint.x,m_StartPoint.y,m_EndPoint.x,m_EndPoint.y, m_EndPoint.x,m_EndPoint.y,m_StartPoint.x,m_StartPoint.y); }

//绘制的是椭圆区域 if (m_DrawType == 3) {

//绘制椭圆区域

dc.Ellipse(m_StartPoint.x,m_StartPoint.y, m_EndPoint.x,m_EndPoint.y); }

绘制椭圆因为绘制的只是椭圆的边界线,所以采用了与绘制椭圆橡皮线相同的方法来完成。而绘制椭圆区域时则直接调用了Ellipse函数进行绘制。

现在运行应用程序,我们可以通过点击工具条按钮来选择绘制直线段、椭圆或者椭圆区域。

2.2.4 用鼠标绘制矩形区域

绘制矩形区域橡皮线时,和绘制椭圆和椭圆区域的橡皮线一样,不能使用Rectangle函数来进行绘制。同样,DrawLButtonDown函数不需要修改。在DrawMouseMove函数中添加如下代码,完成矩形区域的橡皮线的绘制:

//判断鼠标移动的同时鼠标左键按下,并且要绘制的是矩形区域 if (m_LButtonDown && m_DrawType == 4) {

dc.SetROP2(R2_NOT);//设置绘图模式为R2_NOT //擦除前一次函数调用时绘制的矩形边界线 dc.MoveTo(m_StartPoint);

dc.LineTo(m_StartPoint.x,m_EndPoint.y); dc.LineTo(m_EndPoint);

dc.LineTo(m_EndPoint.x,m_StartPoint.y); dc.LineTo(m_StartPoint); //绘制新的矩形边界线 dc.MoveTo(m_StartPoint);

dc.LineTo(m_StartPoint.x,point.y); dc.LineTo(point);

dc.LineTo(point.x,m_StartPoint.y); dc.LineTo(m_StartPoint); //保存新的终止点 m_EndPoint = point; }

矩形边界线是通过分别绘制矩形的四个边界完成的。

在鼠标绘制矩形完成后,要绘制最终的矩形区域时,处理稍微有些复杂。这是因为用Rectangle绘制矩形区域的特性决定的。在绘制椭圆区域时,调用Arc函数绘制的椭圆边界线和调用Ellipse函数绘制的椭圆区域的边界线是完全重合的。不论m_StartPoint点和m_EndPoint点是否是椭圆所在的外接矩形的左上角点和右下角点(因为鼠标移动的关系,可能导致这两点并不是最终绘制的椭圆的外接矩形的左上角点和右下角点),Arc函数和Ellipse函数绘制出的图形都是相同的,因为真正起作用的是两点的x坐标和y坐标,它们分别指定了椭圆外接矩形的上边界、下边界、左边界和右边界。所以在绘制最终的椭圆区域时,直接调用Ellipse函数即可,无需对m_StartPoint点和m_EndPoint点的坐标进行修正。但是在绘制矩形区域时就需要对这两点的坐标进行修改,以保证m_StartPoint点和m_EndPoint确实是绘制的矩形区域的左上角点和右下角点,即在默认逻辑坐标系中,m_StartPoint的x坐标值应小于m_EndPoint的x坐标值,m_StartPoint的y坐标值应小于m_EndPoint的y坐标值。并且在最后绘制的时候要给m_EndPoint的x和y坐标值分别加1,Rectangle函数绘制出的矩形区域的边界才与通过分别绘制矩形区域边界的四个直线段所形成的矩形区域边界线重合。在DrawLButtonUp函数中添加如下代码:

//绘制的是矩形区域 if (m_DrawType == 4) {

int c;

//确保m_StartPoint确实为矩形区域的左上角 //m_EndPoint确实是矩形区域的右下角 if (m_StartPoint.x > m_EndPoint.x) { c = m_StartPoint.x; m_StartPoint.x = m_EndPoint.x; m_EndPoint.x = c; }

if (m_StartPoint.y > m_EndPoint.y) { c = m_StartPoint.y; m_StartPoint.y = m_EndPoint.y;


计算机图形学__第二章_MFC交互绘图基础(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:青春驿站广播稿

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: