• CClientDC 解说及举例


    CClientDC 解说及举例

     

    -

    -

     

    类CClientDC派生于CDC,在构造时调用了Windows函数GetDC,在析构时调用了ReleaseDC。这意味着和CClientDC对象相关的设备上下文是窗口的客户区。

    #include <afxwin.h>
    请参阅   CDC
    CClientDC类的成员
    构造函数
    CClientDC构造一个连接到CWnd上的CClientDC对象
    数据成员
    m_hWnd CClientDC所在的有效窗口的HWND
    成员函数
    CClientDC::CClientDC
    CClientDC(CWnd* pWnd );
    throw( CResourceException );
    参数
    pWnd设备上下文将要存取的客户区所在的窗口。
    说明
    本函数构造一个CClientDC对象,它将存取pWnd指向的CWnd的客户区。此构造函数调用了Windows函数GetDC。如果Windows函数GetDC调用失败,则产生一个CResourceException类型的异常。如果Windows已经分配出了所有可用的设备上下文,则没有新的设备上下文可用。无论何时,应用总在竞争使用Windows提供的五个公共显示上下文。
    数据成员
    CClientDC::m_hWnd
    说明
    m_hWnd是一个保护的变量,是用来构造m_hWnd对象的CWnd指针的HWND。  

    ==============================================================  

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

    CClientDC::CClientDC(CWnd* pWnd)
    {
         ...
         if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))
             AfxThrowResourceException();
    }

    CClientDC::~CClientDC()
    {
         ...
         ::ReleaseDC(m_hWnd, Detach());
    }
    用法是:
    CClientDC dc(this);//this一般指向本窗口或当前活动视图
    dc.TextOut(10,10,str,str.GetLength());//利用dc输出文本,如果是在CScrollView中使用,还要注意调用OnPrepareDC(&dc)调整设备上下文的坐标。
    CPaintDC用于响应窗口重绘消息(WM_PAINT)是的绘图输出。CPaintDC在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。因此,在处理窗口重画时,必须使用CPaintDC,否则WM_PAINT消息无法从消息队列中清除,将引起不断的窗口重画。CPaintDC也只能用在WM_PAINT消息处理之中。
    CPaintDC::CPaintDC(CWnd* pWnd)
    {
         ...
         if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))
             AfxThrowResourceException();
    }

    CPaintDC::~CPaintDC()
    {
         ...
         ::EndPaint(m_hWnd, &m_ps);
         Detach();
    }
    CWindowDC:关联一特定窗口,允许开发者在目标窗口的任何一部分进行绘图,包含边界与标题,这种DC同WM_NCPAINT消息一起发送

    CWindowDC与CClientDC,CPaintDC的区别:
    CWindowDC可在非客户区绘制图形,而CClientDC,CPaintDC只能在客户区绘制图形。
    CWindowDC下坐标原点是在屏幕的左上角,CClientDC,CPaintDC下坐标原点是在客户区的左上角。
    CClientDC与CPaintDC的区别:

    CPaintDC的对象一般用在OnPaint内以响应Windows消息WM_PAINT,自动完成绘制,在整个窗口内进行重画,
    维持原有窗口完整性。
    CClientDC应用在非响应Windows消息WM_PAINT的情况下,进行实时绘制,绘制的区域内被重画。

    ====================================================================
    All Rights Reserved!

    首先我们说下通过鼠标的移动来绘制直线。
    这里要捕获到鼠标的两个消息:WM_LBUTTONDOWN, WM_LBUTTONUP
    响应WM_LBUTTONDOWN消息记录直线的起始点,响应WM_LBUTTONUP消息记录直线的终点并绘制直线。
    好了,我们看看怎么响应。
    void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
    {
    //MessageBox("Left Button Clicks DrawView");
    m_ptOrigin = point ;         //这里先定义了一个内部变量保存直线的起始点
    CView::OnLButtonDown(nFlags, point);
    }
    下面看看响应WM_LBUTTONUP消息记录直线的终点并绘制直线。

    //方法一
    void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
    {
    HDC hdc;
    hdc = ::GetDC(m_hWnd); //调用全局函数
    MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,0);
    LineTo(hdc,point.x,point.y);
    ::ReleaseDC(m_hWnd,hdc);
    CView::OnLButtonUp(nFlags, point);
    }
    //方法二
    void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
    {
    CDC *pDC = GetDC();
    pDC->MoveTo(m_ptOrigin);
    pDC->LineTo(point);
    ReleaseDC(pDC);
    }
    //方法三
    void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
    {
    CClientDC dc(this) ;    //CClientDC对象构造的时候就调用了GetDC,析构的时候调用

    ReleaseDC ,只能访问客户区
    CClientDC dc(GetParent());
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);
    }
    //方法四
    void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
    {
    CWindowDC dc(this) ;   //CWindowDC可以访问客户区和非客户区
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);
    }
    void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
    {
    CWindowDC dc(GetDesktopWindow()) ;   //现在可以访问桌面
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);
    }
    连续线绘图:
    思路:鼠标移动的信号被捕捉到,然后随时响应该信号,绘制图线
    这里要设置一个BOOL变量 m_bDraw 来判断是否鼠标左键按下了。
    //画连续的线条
    void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
    {
    if ( m_bDraw )
    {
       CClientDC dc(this) ;
       dc.MoveTo(m_ptOrigin);   //移动到原来的点
       dc.LineTo(point); //绘制直线
       m_ptOrigin = point ; //将现在的点赋值给原来的坐标,以便下次调用
    }
    CView::OnMouseMove(nFlags, point);
    }

    //改变画笔的颜色
    void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
    {
    if ( m_bDraw )
    {
       CClientDC dc(this) ;
       CPen pen( PS_SOLID , 1 , RGB(255,128,128) );
       CPen *pOldPen = dc.SelectObject(&pen);
       dc.MoveTo(m_ptOrigin);
       dc.LineTo(point);
       m_ptOrigin = point ;
       dc.SelectObject(pOldPen);
    }
    CView::OnMouseMove(nFlags, point);
    }

    //画扇型
    void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
    {
    if ( m_bDraw )
    {
       CClientDC dc(this) ;
       CPen pen( PS_SOLID , 1 , RGB(255,128,128) );
       CPen *pOldPen = dc.SelectObject(&pen);
       dc.MoveTo(m_ptOrigin);
       dc.LineTo(m_ptOld);
       dc.MoveTo(m_ptOrigin);
       dc.LineTo(point);
       m_ptOld = point ;
       dc.SelectObject(pOldPen);
    }
    CView::OnMouseMove(nFlags, point);
    }
    //画带边线的扇型
    void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
    {
    if ( m_bDraw )
    {
       CClientDC dc(this) ;
       CPen pen( PS_SOLID , 1 , RGB(255,128,128) );
       CPen *pOldPen = dc.SelectObject(&pen);
       dc.MoveTo(m_ptOrigin);
       dc.LineTo(m_ptOld);
       dc.MoveTo(m_ptOrigin);
       dc.LineTo(point);
       dc.MoveTo(m_ptOld);
       dc.LineTo(point);
       m_ptOld = point ;
       dc.SelectObject(pOldPen);
    }
    CView::OnMouseMove(nFlags, point);
    }

    //看看绘图的模式设置方法
    void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
    {
    if ( m_bDraw )
    {
       CClientDC dc(this) ;
       dc.SetROP2(R2_BLACK);   //绘图的模式设置,始终绘制黑色图形
       CPen pen( PS_SOLID , 1 , RGB(255,128,128) );
       CPen *pOldPen = dc.SelectObject(&pen);
       dc.MoveTo(m_ptOrigin);
       dc.LineTo(m_ptOld);
       dc.MoveTo(m_ptOrigin);
       dc.LineTo(point);
       dc.MoveTo(m_ptOld);
       dc.LineTo(point);
       m_ptOld = point ;
       dc.SelectObject(pOldPen);
    }

    CView::OnMouseMove(nFlags, point);
    }

    到此,我们知道了一般地绘图方法了。

    ==============================================
    显示一张位图:

    int CThreadPoolDlg::ShowFace(int xPos, int yPos, CString FilePath)
    {
    // TODO: Add your control notification handler code here
    CClientDC *pDC = new CClientDC(this);
    CBitmap Bitmap;
    HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,FilePath,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
    Bitmap.Attach(hBitmap);
    CDC DCCompatible;
    DCCompatible.CreateCompatibleDC(pDC);
    DCCompatible.SelectObject(&Bitmap);
    BITMAP bmInfo;
    Bitmap.GetObject(sizeof(bmInfo),&bmInfo);
    pDC->BitBlt(xPos,yPos,bmInfo.bmWidth,bmInfo.bmHeight,&DCCompatible,0,0,SRCCOPY);
    return 1;

  • 相关阅读:
    制作自适应布局的模块及框架(转载)
    从今天起开始写博了
    工作中碰到的css问题解决方法
    标题写个什么好呢
    快速编写HTML(Zen conding)
    2013年1月21日记事
    opc 方面研究
    关于 部署方面研究 Visual Studio 2013
    intel AVX指令集
    关于 返回数据类型 后 加& 的作用
  • 原文地址:https://www.cnblogs.com/sunliming/p/1892305.html
Copyright © 2020-2023  润新知