首页 > 其他分享 >MFC中绘图类总结

MFC中绘图类总结

时间:2023-02-04 21:33:41浏览次数:71  
标签:总结 MFC 窗口 CDC DC HDC 绘图 hDC pDC

绘图一般在视图类的(屏幕/打印机)绘图消息响应函数OnDraw中进行,例如:

void CTestView::OnDraw(CDC* /*pDC*/) {
         CTestDoc* pDoc = GetDocument();
         ASSERT_VALID(pDoc);
         if (!pDoc)
                return;
         // TODO: 在此处为本机数据添加绘制代码

}
每次需要重绘窗口时(程序启动/窗口大小改变/全部或部分窗口重现/程序员调用RedrawWindow或UpdateWindow),应用程序框架都会调用该CWnd的消息响应成员函数(的覆盖)来绘制窗口客户区。
在Windows中,绘图一般在视图窗口的客户区进行,使用的是MFC的设备上下文(DC = Device-Context)类CDC中各种绘图函数。
在绘图前,必须先得到客户区大小和DC、设置绘图颜色,然后再根据文档数据或用户操作来绘制图形。

1.CDC *pDC和HDC hdc有什么不同,类似的有CWnd *pWnd和HWnd?

pDC是CDC类指针,HDC是对应windows句柄

通过pDC可以获得win句柄hdc:
HDC hdc=pDC->GetSafeHdc();
反过来也可以通过win句柄hdc获得pDC:
CDC *pDC=new CDC;
pDC->Attach(hdc);

2.hDC和CDC有本质区别

HDC是WINDOWS的一种数据类型,是设备描述句柄。而CDC是MFC里的一个类,它封装了几乎所有的关于HDC的操作。也可以这样说,HDC定义的变量指向一块内存,这内存用来描述一个设备的相关的内容,所以也可以认为HDC定义的是一个指针;而CDC类定义一个对象,这个对象拥有HDC定义的一个设备描述表,同时也包含与HDC相关的操作的函数。这与HPEN和CPen,POINT与CPoint之间的差别是一样的。

CDC是对hDC的相关操作进行封装,CDC 是CObject的直接派生类,CDC类自己也有若干派生类,其中包括窗口客户区DC所对应的CClientDC类、OnPaint和OnDraw消息响 应函数的输入参数中使用的CPaintDC类、图元文件对应的CMetaFileDC类和整个窗口所对应的CWindowDC类。CDC类中有许多成员函数,可以用来设置各种绘图环境、属性和参数,以及绘制各种图形和图像等

例如CDC的一个TextOut函数隐去其错误检测,完全可以简化到这样程度CDC:TextOut( int x, int y, const CString& str )
{
   TextOut( m_hDC, x, y, (LPCTSTR)str, str.GetLength() );
}

m_hDC就是CDC的成员变量HDC m_hDC;
CDC有一个operator HDC() const { return m_hDC; }  
你可以把它当成一个HDC使用

3.this是dc输出目标窗口的指针,通过它可以得到窗口句柄,对象带参构造这有什么奇怪的呢?  

   CPaintDC        无效区dc,相当于BeginPaint,    EndPaint  
   CClientDC       客户区dc,相当于GetDC,         ReleaseDC  
   CWindowDC       整窗口dc, 相当于GetWindowDC,   ReleaseDC  
   CDC             任何dc,   相当于CreateDC,      DeleteDC

 

4.获得CDC *
CDC* pDC
pDC=GetDC();

获得hdc
HDC hDC;
hDC=GetDC(pCxp->hWnd);
pDC->m_hDC;


MEMDCXP Mdcxp;
GetMemDCXP(&Mdcxp);
hDC = Mdcxp.hMemDC;
hDC=::GetDC(HWND handle)

转换
CDC* pDC
HDC hDC;
pDC=Attach(hDC);
hDC=GetSafeHDC(pDC);
pDC->m_hDC==hDC

 

5.客户区大小和DC

DC:在Windows中,绘图使用的是MFC的DC(Device-Context, 设备上下文)类CDC中各种绘图函数。

每次从OnDraw函数的输入参数或调用GetDC所获得的DC,都是一个全新的临时缺省DC。它不能用类变量来长期保存,而且原来选入的各种GDI对象全都被作废,必须从头再来。为了使选入的各种GDI对象一直有效,必须在视图类的PreCreateWindow函数中调用CWnd类的成员函数AfxRegisterWndClass:

LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0,
HBRUSH hbrBackground = 0, HICON hIcon = 0 );
来修改窗口类的风格属性中的DC为类DC:CS_CLASSDC。如
BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs) {
      cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW |
CS_VREDRAW | CS_CLASSDC, 0,
::CreateSolidBrush(RGB(255, 255, 255)));
         return CView::PreCreateWindow(cs);
}

 

安全DC句柄
也可以用CDC类的成员函数:
HDC GetSafeHdc();
来 获取CD所对应窗口(如客户区)的安全DC句柄,该句柄在窗口存在期间一直是有效的。例如,可先定义类变量HDC m_hDC;,再在适当的地方给它赋值m_hDC = GetDC()->GetSafeHdc();,然后就可以放心地使用了。例如,可以使用CDC类的成员函数
BOOL Attach(HDC hDC); // 成功返回非0
来将CDC对象与DC句柄连接在一起。

 

在绘图前,必须先得到客户区大小和设备上下文DC。
获得客户区:
绘图一般都是在视图窗口的客户区进行,而客户区的大小在运行时可由用户改变,为了使绘制的图形能随窗口大小自动改变,必须先得到当前客户区大小的数据(宽w和高h)。
获取客户区大小的方法有如下两种:
1)在消息响应函数OnSize中获得
利用属性窗口的信息页,在视图类中添加WM_SIZE消息的响应函数OnSize。该函数在窗口第一次显示或窗口大小被改变时会被Windows系统调用。其输入参数中的cx和cy就是客户区大小的宽和高,可将它们赋值给类变量(如m_iW和m_iH)供绘图时使用。例如
void CDrawView::OnSize(UINT nType, int cx, int cy) {
        CView::OnSize(nType, cx, cy);

        // TODO: 在此处添加消息处理程序代码
        m_iW = cx;    m_iH = cy;
}
其中,nType的值为:
l           SIZE_MAXIMIZED(窗口已被最大化)
l           SIZE_MINIMIZED(窗口已被最小化)
l           SIZE_RESTORED(窗口已被改变大小)
l           SIZE_MAXHIDE(其他窗口被最大化)
l           SIZE_MAXSHOW(其他窗口从最大化还原)
2)调用成员函数GetClientRect得到
可在绘图前,定义一个矩形变量rect,然后再调用CWnd类的成员函数GetClientRect:
void GetClientRect( LPRECT lpRect ) const;
得到当前客户区矩形的数据,其中的右(right)与底(bottom)就是客户区的宽与高(其左left与顶top都为0)。例如:
         RECT rect;
         GetClientRect(&rect);
         int w = rect.right, h = rect.bottom;

获得DC:
可以从OnDraw函数的输入参数pDC或调用CWnd的成员函数GetDC:
CDC* GetDC( );
来获得DC的指针。
释放DC:
因为Windows限制可用DC的数量,所以DC属于稀缺的公用资源。因此,对每次获得的DC,在使用完成后必须立即释放。
从OnDraw函数的输入参数pDC获得的DC,在该函数运行结束后,系统会自动释放。但由GetDC所获得的DC,必须自己来释放,这可以通过调用CWnd的成员函数ReleaseDC来完成:
int ReleaseDC( CDC* pDC ); // 成功返回非0
例如:
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
         ReleaseCapture();
         if (m_bLButtonDown) {
                CDC* pDC = GetDC();
                pDC->SelectObject(new CPen(PS_SOLID, 0, RGB(255, 0, 0)));
                pDC->SelectStockObject(NULL_BRUSH);
                pDC-> Ellipse (rect);
                ReleaseDC(pDC);
                m_bLButtonDown = FALSE;
         }
         CView::OnLButtonUp(nFlags, point);
}

 

标签:总结,MFC,窗口,CDC,DC,HDC,绘图,hDC,pDC
From: https://www.cnblogs.com/Groot3377/p/17092445.html

相关文章

  • 19-逻辑门电路知识点总结
    逻辑门电路知识点总结门电路注意事项传输高低电压的问题上一级输出为0,下一级的输入也要认为是0逻辑0和逻辑1都是有范围或区间的,逻辑0有最大值,逻辑1有最小值上一级输......
  • 第二周总结
    目录一、数据类型元组集合布尔值二、用户交互1、input()2、print()三、格式化输出四、运算符号1、基本运算符之数学运算符2、基本运算符之比较运算符3、赋值符号及用法1.链......
  • 第一周总结回顾
    目录一、计算机基础知识1、计算机的本质2、计算机五大组成部分3、计算机三大核心硬件4、路径5、计算机操作系统6、计算机系统的三层结构二、typora软件1、typora的安装2、t......
  • 2023/2/4 考试总结
    树形数据结构专场也就是我的大型GG专场题单贴贴T1.P4587[FJOI2016]神秘数主席树/可持久化线段树;考试的时候怕调不出来,不是很敢写,然后还有性质分析得不是......
  • QML(14)——QML与C++交互方式总结1/3(qml调用C++的public函数)
    一、效果qml文件中,可以调用C++类的公共函数   二、步骤1、C++类文件创建C++文件时,一定要勾选下面3项 MyQmlClass.h #ifndefMYQMLCLASS_H#defineMYQMLCL......
  • MySql 误操作回滚方法总结
    drop是直接删除表信息,速度最快,但是无法找回数据 truncatetabletruncate是删除表数据,不删除表的结构,速度排第二,但不能与where一起使用 deletefromdelete是删......
  • 第十届ACM山东省赛总结
    省赛结束了,排名打铁,只出了四题。前三个小时只出了一道题。M题很简单,我第一次循环做的直接超时,没想到怎么优化,然后误以为有公式,推了半个小时的公式,测试都对,提交一直wa,然后考......
  • 总结
    关于DP专题:这几天主要收获是数位dp和斜率优化的具体模板,期望:数位dpdfs(数的最后若干位,各种限制条件,当前第几位) if最后一位 return各种限制条件下的返回值......
  • misc之压缩包总结------2023.2.3
    1,ZIP伪加密 ZIP文件格式一个ZIP文件由三个部分组成:压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志压缩源文件数据区:504B0304:这是头文件标记(0x040......
  • 2023.2.3 寒假集训二阶段总结
    2023.2.3寒假集训二阶段总结新内容与课堂这几天都在讲解有关dp的优化策略以及各种dp等有关知识,其中在计数dp、数位dp、概率与期望dp,数据结构优化dp(斜率优化版题qwq)上......