MFC之绘制线条

前言


我们首先建立MFC单文档工程,利用编辑器向导工具,自动在view类中完成WM_LButtonUp和WM_LButtonDown两个消息的添加,添加完成后将自动出现如下两个函数:

//nFlags:Indicates whether the user pressed modifier keys(Alt,Shift,Ctrl..)
//point: specify current cursor the position when left button down
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    CView::OnLButtonDown(nFlags, point);
}


//nFlags:Indicates whether the user pressed modifier keys(Alt,Shift,Ctrl..)
//point: specify current cursor the position when left button up
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
   // TODO: 在此添加消息处理程序代码和/或调用默认值
   
   CView::OnLButtonUp(nFlags, point);
}

背景知识:

       DC(Device Context,设备描述表)是一个包含设备(物理输出设备,比如显示器, 设备驱动程序)信息的结构体。在Windows平台下,所有的图形操作都是利用DC完成的,想要完成绘图功能,只需要得到DC句柄即可。其次,DC是一种资源,在完成图形操作后,需要调用ReleaseDC函数来完成DC所占用的资源释放,否则会引起内存泄漏


画线思路:

      我们两点成一线,利用鼠标左键按下和弹起时可以分别确定起点和终点,利用Moveto和Lineto完成画线功能。


函数接口和功能描述:

//Remarks:
//Moves the current position to the point specified by x and y (or by point). 
CPoint MoveTo(int x,int y);
CPoint MoveTo(POINT point);

//Remarks:
//Draws a line from the current position up to, but not including, the point specified by x and y (or point). 
//If LineTo succeeds, the current position is set to the specified ending point. 
BOOL LineTo(int x,int y);
BOOL LineTo(POINT point);

利用SDK全局函数实现画线


//起点位置

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    //保存起点位置
    m_ptBeginPos = point;
    CView::OnLButtonDown(nFlags, point);
}

//终点位置

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
    //获得窗口的设备描述表
    HDC hdc;
    hdc = ::GetDC(m_hWnd);

    //移动到线条的起点位置
    MoveToEx(hdc, m_ptOrigin.x, m_ptOrigin.y,NULL);

    //划线,
    LineTo(hdc, point.x, point.y);
    
    //释放设备描述表,全局函数
    ::ReleaseDC(m_hWnd, hdc);
   
   CView::OnLButtonUp(nFlags, point);
}

运行效果:



利用CDC类实现画线


MFC为我们提供了一个设备描述表的封装类CDC,该类封装了所有与绘图相关的操作,该类提供一个数据成员m_hDC,用来保存与CDC类相关的DC句柄。关于CDC类的绘图相关成员函数见博文CDC详解一文。

具体代码实现如下:

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
    CDC* pDC = GetDC();
	//起点
    pDC->MoveTo(m_ptOrigin);
	//划线,终点
    pDC->LineTo(point);
    ReleaseDC(pDC);
   
   CView::OnLButtonUp(nFlags, point);
}

利用CClientDC类实现画线


CClientDC 类派生于CDC类,CClientDC 对象的构造时,会调用GetDC函数,在析构对象时调用ReleaseDC函数,因此CClientDC类对象生命周期结束后,有程序就自动完成资源释放,就不需要显示调用DC资源相关函数了。实现程序如下:

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
	//创建DC
	CClientDC dc(this);
	dc.MoveTo(m_ptOrigin);
	dc.LineTo(point);
	CView::OnLButtonUp(nFlags, point);
}

利用CWindowDC类实现画线


CWindowDC类也派生于CDC类,并且在构造时调用GetWindowDC函数获得相应的设备描述表对象,在析构时调用ReleaseDC函数释放占用的资源。

CWindowDC对象存在以下好处:

     该对象可以访问整个窗口区域,包括框架窗口的非客户区和客户区。如果要构造一个与视类窗口相关的DC,则可以利用视类对象的指针来构造整个CWindowDC对象,如果想在非客户区画图,则需要传递指向视类父窗口的指针。代码实现如下:

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
	//创建DC
    CWindowDC dc(GetParent());
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);
	CView::OnLButtonUp(nFlags, point);
}

运行效果:


绘制彩色线条


以上各种画线的实现方法,绘制的都是黑色线条。这是因为DC中有一个默认的黑色画笔,因此绘制的线条都是黑色的,想要完成其他颜色的画线功能,需要以下几个步骤:

1.创建一个特性颜色的画笔

2.将此画笔选入到DC中

3.画线


MFC提供了CPen类来创建画笔对象,该类封装了和画笔相关的操作,其中一个的构造函数原型声明如下:

CPen(int nPenStyle, int nWidth, COLORREF crColor)
其中nPenStyle指定了线型(实线、虚线、点线等) ,nWidth指定了线的宽度,crColor指定笔的颜色,该参数可以由RGB宏来构建,具体信息参加MSDN。

另外,在程序中,当构造一个GDI对象(CPen,CBrush...)时,该对象只有被选人设备DC后,它才会在以后的绘图操作中生效。SelectObject函数可以实现将GDI对象选人设备描述表中,该函数会返回旧的GDI对象指针。

其次,在完成绘图操作后,都需要利用SelectObject函数把先前的GDI对象选人设备描述表,以便还原先前的状态

具体代码实现如下:

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
	//创建画笔,红色的虚线
    CPen pen(PS_DASH,1, RGB(255, 0,0));
	//创建DC
    CClientDC dc(this);
	//GDI对象选入DC
    CPen* pOldPen = dc.SelectObject(&pen);
	//移动起点
    dc.MoveTo(m_ptOrigin);
	//画线 
    dc.LineTo(point);
	//还原DC
    dc.SelectObject(pOldPen);
	CView::OnLButtonUp(nFlags, point);
}

运行效果:



转载于:https://www.cnblogs.com/jinxiang1224/p/8468383.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值