CDC,CClientDC,CPaintDC,CWindowDC 比较区别

CDC,CClientDC,CPaintDC,CWindowDC 比较区别windows

MFC中的CDC,CClientDC,CPaintDC,CWindowDC的区别异步

CDCWindows绘图设备的基类。函数

CClientDC
(1)
(客户区设备上下文)用于客户区的输出,与特定窗口关联,可让开发者访问目标窗口中客户区,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC优化

CPaintDC
(1)
用于响应窗口重绘消息(WM_PAINT)是的绘图输出。
(2)CPaintDC
在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。 EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。所以,在处理窗口重画时,必须使用CPaintDC,不然 WM_PAINT消息没法从消息队列中清除,将引发不断的窗口重画。
(3)CPaintDC
也只能用在WM_PAINT消息处理之中。this

CWindowDC
(1)
可在非客户区绘制图形,而CClientDCCPaintDC只能在客户区绘制图形。
(2)
坐标原点是在屏幕的左上角,CClientDCCPaintDC下坐标原点是在客户区的左上角。
(3)
关联一特定窗口,容许开发者在目标窗口的任何一部分进行绘图,包含边界与标题,这种DCWM_NCPAINT消息一块儿发送。spa

===========code

CPaintDC用于响应窗口重绘消息(WM_PAINT)是的绘图输出。CPaintDC在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。EndPaint()除了释放设备上下文外,还负责从消息队列中清除 WM_PAINT消息。所以,在处理窗口重画时,必须使用CPaintDC,不然WM_PAINT消息没法从消息队列中清除,将引发不断的窗口重画。 CPaintDC也只能用在WM_PAINT消息处理之中。对象

系统什么时候发送WM_PAINT消息?队列

系统会在多个不一样的时机发送WM_PAINT消息:当第一次建立一个窗口时,当改变窗口的大小时,当把窗口从另外一个窗口背后移出时,当最大化或最小 化窗口时,等等,这些动做都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操做;大多数的时候应用也须要可以主动引起窗口中的绘制 操做,好比当窗口显示的数据改变的时候,这通常是经过InvalidateRectInvalidateRgn函数来完成的。 InvalidateRectInvalidateRgn把指定的区域加到窗口的Update Region中,当应用的消息队列没有其余消息时,若是窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。ci

系统为何不在调用Invalidate时发送WM_PAINT消息呢?又为何非要等应用消息队列为空时才发送WM_PAINT消息 呢?这是由于系统把在窗口中的绘制操做看成一种低优先级的操做,因而尽量地推后作。不过这样也有利于提升绘制的效率:两个WM_PAINT消息之间经过 InvalidateRectInvaliateRgn使之失效的区域就会被累加起来,而后在一个WM_PAINT消息中一次获得更新,不只能避免屡次 重复地更新同一区域,也优化了应用的更新操做。像这种经过InvalidateRectInvalidateRgn来使窗口区域无效,依赖于系统在合适 的时机发送WM_PAINT消息的机制其实是一种异步工做方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的;有时候这种延迟 并非咱们但愿的,这时咱们固然能够在无效化窗口区域后利用SendMessage 发送一条WM_PAINT消息来强制当即重画,但不如使用Windows GDI为咱们提供的更方便和强大的函数:UpdateWindowRedrawWindowUpdateWindow会检查窗口的Update Region,当其不为空时才发送WM_PAINT消息;RedrawWindow则给咱们更多的控制:是否重画非客户区和背景,是否老是发送 WM_PAINT消息而无论Update Region是否为空等。

说明:在绘图时推荐使用CClientDC,CPaintDCCWindowDC对象,而不推荐直接使用CDC对象。

创建项目,采用单文档结构

HDC:

首先在CYourClassView类中add windows message handler, 一个是LButtonDown, 另外一个是LButtonUp.添加成员变量:m_ptOrigin用来记录初始点位置。

view结构体中初始化m_ptOrigin变量:

CYourClassView:: CYourClassView ()

{

       // TODO: add construction code here

       m_ptOrigin=0;

}

LButtonDown函数里面添加代码:

void CYourClassView::OnLButtonDown(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       m_ptOrigin=point;

       CView::OnLButtonDown(nFlags, point);

}

LButtonUp中添加代码,首先使用HDC:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       HDC hdc;

       hdc=::GetWindowDC(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:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CDC *pdc=GetDC();

       pdc->MoveTo(m_ptOrigin);

       pdc->LineTo(point);

       ReleaseDC(pdc);


CView::OnLButtonUp(nFlags, point);

}

使用CClientDC:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CClientDC dc(this);

       dc.MoveTo(m_ptOrigin);

       dc.LineTo(point);


CView::OnLButtonUp(nFlags, point);

}

使用CWindowDC:

void CYourClassView::OnLButtonUp(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler code here and/or call default

       CWindowDC dc(this);

       dc.MoveTo(m_ptOrigin);

       dc.LineTo(point);

CView::OnLButtonUp(nFlags, point);

相关文章
相关标签/搜索