当前位置: 首页 > news >正文

MFC 一个简单的绘图程序

MFC 一个简单的绘图程序

转自:http://hi.baidu.com/orchard/item/860eb5c067bce82847d5c0f5

 首先本文的代码来自《visual c++面向对象编程教程第2版》,本人拿来练手,并稍加总结,整理,评述,以飨读者。

   涉及到的知识点:

     1.鼠标信息的处理

     2.深刻理解文档和视图的关系

     3.新建一个类及其使用方法的技巧。

     4.改变窗口大小或者刷新窗口后原来所绘制的图形没有显示出来的问题。

  程序软件:VC++6.0

      绘制图形的原理:鼠标被用作画笔,绘图过程中要进行不同的鼠标消息的处理,如按下鼠标,移动鼠标和释放鼠标。当用户按下鼠标左键是必须记录鼠标当前的位置,并捕获鼠标,设置光标形状;当移动鼠标时,先判断鼠标左键是否同时被按住,如果是则从上一个鼠标位置到当前鼠标位置绘制一条直线。并保存当前鼠标位置点,供绘制下一段直线用,当释放鼠标左键时将鼠标释放给系统。

 程序实现:

  1.使用MFC AppWizard 应用程序向导创建一个SDI应用程序MyDraw,在视图类CMyDrawView.h中添加如下代码:

protected: // create from serialization only
 CMyDrawView();
 DECLARE_DYNCREATE(CMyDrawView)
 CPoint m_ptOrigin;   //起始点坐标
 bool m_bDragging;  //鼠标是否处于拖拽状态标记
 HCURSOR m_hCross;//拖拽状态时鼠标的样

2.在构造函数中对拖拽标记和鼠标样式进行初始化

 

CMyDrawView::CMyDrawView()
{
 // TODO: add construction code here
 m_bDragging=false;//初始化为false
 m_hCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);//十字光标

}

 3 。使用类向导 为视图类添加按下鼠标左键,移动鼠标,释放鼠标左键等消息处理函数。代码分别为:

 

void CMyDrawView::OnLButtonDown(UINT nFlags, CPoint point) //按下鼠标左键
{
 // TODO: Add your message handler code here and/or call default
 
 CView::OnLButtonDown(nFlags, point);
 SetCapture();
 ::SetCursor(m_hCross);

 m_ptOrigin=point;
 m_bDragging=true;
}

void CMyDrawView::OnLButtonUp(UINT nFlags, CPoint point) //释放鼠标左键
{
 // TODO: Add your message handler code here and/or call default
 
// CView::OnLButtonUp(nFlags, point);
 if(m_bDragging)
 {
  m_bDragging=false;
  ReleaseCapture();//  教程上此句有误,Release Capture()中间不能有空格
 }
}

void CMyDrawView::OnMouseMove(UINT nFlags, CPoint point)   //移动鼠标
{
 // TODO: Add your message handler code here and/or call default
 
 CView::OnMouseMove(nFlags, point);
 if(m_bDragging)
 {
  CMyDrawDoc * pDoc=GetDocument();
  ASSERT_VALID(pDoc);
 // pDoc->AddLine(m_ptOrigin,point);
  CClientDC dc(this);
  dc.MoveTo(m_ptOrigin);
  dc.LineTo(point);
  m_ptOrigin=point;
 }

}

4.在MyDraw.CPP中设置窗口标题

 m_pMainWnd->SetWindowText("雪豹出击-----简单的绘图程序");

此后,编译、链接,运行程序后可以将鼠标当作一个画笔绘制曲线了。如图所示:



但是,当你打开了其他任何窗口,在显示此窗口,或者将此窗口进行任何大小变化时,“雪豹出击”四个字就没有了。其原因:

此时调用的是视图类的刷新函数OnDraw(),而在该函数中并没有实现图形绘制功能,为了解决此缺陷必须在OnDraw()函数中重新绘制以前用鼠标所绘制的线段,在利用鼠标绘制时必须将线段的坐标数据保存起来。

 

二 功能的修补

     为线段定义一个CLine的类,线段的起点和终点坐标作为类的成员变量,并定义相应的成员函数。在文档类中为线段选择一个合适的动态数据结构,用于保存大量的且数目不确定的直线图形对象。

 在CLine.h中定义:

 private:
 CPoint m_pt1;//两个私有数据成员 分别表示一条线段的起点和终点。
 CPoint m_pt2;
public:
 CLine(CPoint pt1,CPoint pt2);//自定义构造函数
 void DrawLine(CDC *pDC);//声明绘制线段的成员函数。

在CLine.cpp中:

CLine::CLine(CPoint pt1,CPoint pt2)//使用自定义构造函数初始化起点和终点
{
 m_pt1=pt1;
 m_pt2=pt2;
}

void CLine::DrawLine ( CDC *pDC)//绘制线段
{
 pDC->MoveTo(m_pt1);
 pDC->LineTo(m_pt2);
}
2  文档类主要是用来保存数据的,那么在文档类CMyDrawDoc文档类中定义

#include"Line.h"//包含CLine类头文件

#include <afxtempl.h>//使用模板来需要包含此头文件

protected: // create from serialization only
 CMyDrawDoc();
 DECLARE_DYNCREATE(CMyDrawDoc)
 CPtrArray m_LineArray;  //存放线段对象指针的动态数组

// Attributes
public:
   CLine * GetLine( int nIndex);   //获取指定序号线段对象的指针
   void AddLine(CPoint pt1,CPoint pt2);//向动态数组中添加新的线段对象的指针
   int GetNumLines();//获取线段的向量

成员函数的实现:

void CMyDrawDoc::AddLine (CPoint pt1,CPoint pt2)
{
 CLine *pLine=new CLine(pt1,pt2);
 m_LineArray.Add(pLine);
}
CLine * CMyDrawDoc::GetLine(int nIndex)
{
 if( nIndex<0||nIndex>m_LineArray.GetUpperBound())
  return NULL;
 return (CLine *)m_LineArray.GetAt (nIndex);
}
int CMyDrawDoc::GetNumLines()
{
 return  m_LineArray.GetSize();
}

3.当移动鼠标时,除了绘制,还要保存当前线段的起点和终点坐标,代码如下:

void CMyDrawView::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 
 CView::OnMouseMove(nFlags, point);
 if(m_bDragging)
 {
  CMyDrawDoc * pDoc=GetDocument();
  ASSERT_VALID(pDoc);
  pDoc->AddLine(m_ptOrigin,point);//加入线段到指针数组
  CClientDC dc(this);
  dc.MoveTo(m_ptOrigin);
  dc.LineTo(point);
  m_ptOrigin=point;
 }

}

4.在改变程序窗口大小或重新打开窗口时显示这些窗口中的原有图形,必须在OnDraw()函数中重新绘制前面利用鼠标所绘制的线段,这些线段的坐标为CLine类的成员变量,所有的CLine对象的指针已保存在动态数组m_LineArray中。

void CMyDrawView::OnDraw(CDC* pDC)
{
 CMyDrawDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 // TODO: add draw code for native data here
 int  nIndex=pDoc->GetNumLines();
 while(nIndex--)
 {
  pDoc->GetLine(nIndex)->DrawLine(pDC);
 }

}

至此程序完整了。

 在第一阶段的时候,由于视图的OnDraw()函数里面没有实现绘图的函数,在改变窗口大小后,程序刷新重画窗口,也就什么东东都没有了。修补程序后,OnDraw()函数取得线段的数量nIndex,然后用一个while循环,GetLine(nIndex)取得指定序号线段对象的指针,它是一个CLine类型的对象。然后调用CLine类的DrawLine()绘制已保存的所有线段。

 


相关文章:

  • Linux 系统设置静态 IP
  • CString及Char指针和数组的问题(转)
  • 首尾相连的跑马灯效果(在IE Firefox Opera Safari中均已测试)
  • 多线程技术
  • CentOS-6.4 下成功安装openvswitch
  • 一个简单的端口扫描程序
  • 《BREW进阶与精通——3G移动增值业务运营、定制与开发》一书的网店地址
  • apue.h
  • Linux 临时mount 移动设备
  • 文件描述符、文件表项、V节点表项、dup
  • linux 第一个内核模块Hello World
  • Linux 根据端口查找进程
  • tshark命令行的使用
  • 联通iPhone,真的是狼来了?
  • GCC -L-l -D -I 参数的用法
  • Java编程基础24——递归练习
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • node 版本过低
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • TCP拥塞控制
  • ucore操作系统实验笔记 - 重新理解中断
  • Vue2.x学习三:事件处理生命周期钩子
  • 给初学者:JavaScript 中数组操作注意点
  • 关于for循环的简单归纳
  • 基于Android乐音识别(2)
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 译有关态射的一切
  • 怎么把视频里的音乐提取出来
  • Java性能优化之JVM GC(垃圾回收机制)
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • $refs 、$nextTic、动态组件、name的使用
  • (floyd+补集) poj 3275
  • (二)斐波那契Fabonacci函数
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • ***利用Ms05002溢出找“肉鸡
  • .NET 8.0 发布到 IIS
  • .NET Framework与.NET Framework SDK有什么不同?
  • .NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 WeakDictionary)
  • .NET下ASPX编程的几个小问题
  • ;号自动换行
  • @在php中起什么作用?
  • [ Algorithm ] N次方算法 N Square 动态规划解决
  • [Android]使用Git将项目提交到GitHub
  • [BetterExplained]书写是为了更好的思考(转载)
  • [BUG] Hadoop-3.3.4集群yarn管理页面子队列不显示任务
  • [BZOJ 1032][JSOI2007]祖码Zuma(区间Dp)
  • [C++]unordered系列关联式容器
  • [Java][方法引用]构造方法的引用事例分析