CDC与HDC的区别以及二者之间的转换

VC中CDC与 HDC 的区别以及二者之间的转换
微软喜欢将内核对象标识,称为句柄。应该都是32位或者64位整数
HINSTANCE :进程实例或者句柄
HANDLE :       文件句柄
HWND :        窗口的句柄,用来标识窗口对象
HPEN :         画笔句柄,用来标识画笔对象
HBITMAP :      位图句柄
HDC :          设备环境句柄  
CWnd:      是提供窗口处理的一个MFC封装基类,
             一般都和一个窗口句柄 HWND 绑定,有 HWND m_hWnd成员
CDC:       是进行设备环境处理的一个MFC封装类,
             一般都和一个设备环境句柄 HDC 绑定,有 HDC m_hDC
句柄和类可以相互构造:
1.从已知句柄构造设备类
假定知道了hDC或者hBitmap,想构造CDC类进行窗口操作。
1.1 临时使用,用完不用删除
CDC *pDC = CDC::FromHandle(hDC); //MFC不保证什么时候删除DC
CBitmap *pBmp = CBitmap::FromHandle(hBitmap)
1.2 永久使用,用完需要删除GDI对象一定要释放内存并删除对象
    CDC dc;
    dc.Attach(hDC);  //窗口绑定,永久的,一直到你删除它
    //..........//  
    dc.Detach(hDC);  //当不用的时候要销毁
2.从类得到句柄
    CDC  dc;
    HDC  hDC;
    hDC = dc.GetSafeHdc();
 
3.由 HDC 转为CDC
HDC   hDC   =   GetDC(hWnd); 
    CDC   *pDC   =   CDC::FromHandle(hDC); 
http: //blog.csdn.net/loop_k/article/details/4476797
 
CDC是进行设备环境处理的类,GDI和GDI+显示类库需要这个设备显示对象(包括图像,画笔,线条,画刷等)
 
     CPaintDC        无效区dc,相当于BeginPaint,    EndPaint  
     CClientDC        客户区dc,相当于GetDC,         ReleaseDC  
     CWindowDC      整窗口dc, 相当于GetWindowDC,   ReleaseDC  
     CDC             任何dc,   相当于CreateDC,      DeleteDC
CDC类下面有4个子类
1.  CPaintDC  
// For drawing in a window’s client area(OnPaint handles only)
     在构造时自动调用CWnd::BeginPaint,
     析构时调用CWnd::EndPaint。
     通常 CPaintDC用来响应WM_PAINT消息。一般应用在OnPaint函数。窗口在很多时候能被绘制或重新绘制,如在窗口创建、大小变更、从其他窗口后面移出窗口、最大或最小化等的时候。在窗口内容因某项操作改变时,系统将向程序发出WM_PAINT消息,通知程序作出相应的绘制工作
 
2.  CClientDC 
//For drawing in a window’s client area(anywhere but OnPain)
      客户区窗口DC
      构造时自动调用GetDC函数,
      析构时自动调用ReleaseDC函数.一般应用于客户区窗口的绘制
      当需要处理一个鼠标的单击,然后马上画出一个圆,你不能等到下一个WM_PAINT的消息到来才画图,而是马上,这是就需要CclientDC了。它可以在OnPaint的外面创建一个客户区域DC
     void CMainWindow::OnLButtonDown ( UINT nFlags, CPoint point)
     {
         CRect rect;
         GetClientRect (&rect);
         CClientDC dc ( this );
         dc.MoveTo (rect.left, rect.top);
         dc.LineTo (rect.right, rect.bottom);
         dc.MoveTo (rect.right, rect.top);
         dc.LineTo (rect.left, rect.bottom);
     }
3.   CWindowDC    
//For drawing anywhere in a window, including the nonclient area
不仅是客户区,还包括窗口客户区以外的部分(如窗口标题栏、菜单栏等)需要需要重画时,系统向程序发出WM_NCPAINT消息。因标准窗口的客户区以外部分为窗口必需部分,因而WM_NCPAINT消息将默认被发送到DefWindowProc函数进行默认处理。程序可通过截获该消息来实现窗口其他部分的自定义绘制。使用的是CWindowDC
4.  CMetaFileDC   //For drawing to a GDI metafile
上面这4个子类由于构造和析构函数在获取和释放DC的时候会调用合适的函数,所以可以直接使用,不用释放DC,而CDC就要释放资源RealseDC()
    如果想在整个屏幕绘制时,可以创建一个CclientDC或CwindowDC对象,然后给他的构造函数传递一个NULL指针。如下:
     CClientDC dc(NULL);
     dc.Ellipse(0,0,100,100);
  
实例1:
  HWND hWnd;
   hWnd = ::GetTopWindow(NULL);
   hWnd = ::GetSafeHwnd();
实例2:
void draw()  
    {  
      CWnd*   pWnd = GetDlgItem(IDC_PICTURE);   // 获取绘图的标签  
      CDC*   pDC   =   pWnd->GetDC();   //获取设备上下文  
      int nOldDrawMode = pDC->SetROP2(R2_XORPEN); //设置绘制方式为异或模式  
      pDC->SetBkMode(TRANSPARENT);  
      pDC->MoveTo(,);  
            ....  
      pWnd->ReleaseDC(pDC)
//注:CreateDC()     对应   DeleteDC()    都是CDC类的函数  
     //注:GetDC()   对应   ReleaseDC()       都是CWnd类的函数       
    }  
CDC是MFC的DC的一个类
HDC 是DC的句柄,API中的一个类似指针的数据类型.
MFC类的前缀都是C开头的 ——API中的类呢!!!!!!!!!!!!!!!!!
H开头的大多数是句柄
这是为了助记,是编程读写代码的好的习惯.
CDC中所有MFC的DC的基类.常用的CClientDC dc( this );就是CDC的子类(或称派生类).
CDC等设备上下分类,都含有一个类的成员变量:m_nHdc;即 HDC 类型的句柄.
记住下面的一句话,会有助于你的理解.
MFC的类,是在用window API语句开发出来的有一定功能的小程序.(也可称为类).使用它的默认方法,就是,记住它的名字与参数(可以用笔记,代替脑记).
如果将window api比做汇编语言
那么MFC就相当于Basic语言.
cdc是设备描述表的基类,clientDC指代客户区的设备描述表,PaintDC只用于OnPaint()函数中
 
HDC 是WINDOWS的一种数据类型,是设备描述句柄。  
   而CDC是MFC里的一个类,它封装了几乎所有的关于 HDC 的操作。  
   也可以这样说, HDC 定义的变量指向一块内存,这块  
   内存用来描述一个设备的相关的内容,所以也可以  
   认为 HDC 定义的是一个指针;而CDC类定义一个对象,  
   这个对象拥有 HDC 定义的一个设备描述表,同时也包  
   含与 HDC 相关的操作的函数。  
   这与 HPEN 和CPen,POINT与CPoint之间的差别是一样  
   的。
 
CDC 到 HDC 的转化:
2007-05-09 12:04
方法一: 此方法在设备结束时不会销毁原来的资源(即:hDC,hBitmap)
CDC *pDC = CDC::FromHandle(hDC);   
CBitmap *pBitmap = CBitmap::FromHandle(hBitmap);
 
方法二: 此方法在设备结束时会销毁原来的资源(即:hDC,hBitmap)
CDC dc; //因为是对象,所以有析构函数善后——如在结束的时候加dc.detach()则不会销毁原来资源
dc.Attach(hDC);
CBitmap bit;
bit.Attach(hBitmap);
 
 
回复于 2004-04-08 17:46:03 得分 20
 
HDC   hdc;  
   CDC   cdc;  
   cdc到hdc  
   hdc=cdc.GetSafeHdc();  
   hdc到cdc  
   cdc.Attach(hdc)  
     
回复于 2004-04-08 17:54:20 得分 20
 
CDC   cdc;  
   HDC   hDC=cdc.m_hDC  
   cdc.FromHandle(hDC); 
 
回复于 2004-04-08 18:02:47 得分 10
 
dc.FromHandle(hDC)产生一个dc,但是是临时的,mfc不保证系统在什么时候删除dc.  
   dc.Attach(hDC)是永久的,直到这个dc的生命正常结束。
 
回复于 2004-04-08 18:05:21 得分 5
 
以上的都很对。你就查找替换。将所有的(hdc,替换为pdc->(当然。前面声明个  
   pdc就可以了。
     
 
    HDC 与CDC相互转换
原文地址::http: //blog.csdn.net/loop_k/archive/2009/08/24/4476797.aspx首先说一下什么是DC(设备描述表):Windows应用程序通过为指定设备(屏幕,打印机等)创建一个设备描述表(Device Context, DC)在DC表示的逻辑意义的“画布”上进行图形的绘制。DC是一种包含设备信息的数据结构,它包含了物理设备所需的各种状态信息 。Win32程序在绘制图形之前需要获取DC的句柄HDC,并在不继续使用时释放掉。在c++ 编程中常会见到HDC,CDC,CClientDC,CPaintDC,CWindowDC这样的类
HDC 是DC的句柄,API中的一个类似指针的数据类型.
CDC是MFC的DC的一个类
CDC等设备上下分类,都含有一个类的成员变量:m_nHdc;即 HDC 类型的句柄.CDC及其派生类的继承视图:
CObject
public |------CDC
public |------|------CClientDC
public |------|------CPaintDC
public |------|------CWindowDC
public |------|------CMetaFileDC
(注意: 除CMetaFileDC以外的三个派生类用于图形绘制.)CDC类定义了一个设备描述表相关的类,其对象提供成员函数操作设备描述表进行工作,如显示器,打印机,以及显示器描述表相关的窗口客户区域。通过CDC的成员函数可进行一切绘图操作。CDC提供成员函数进行设备描述表的基本操作,使用绘图工具,选择类型安全的图形设备结构(GDI),以及色彩,调色板。除此之外还提供成员函数获取和设置绘图属性,映射,控制视口,窗体范围,转换坐标,区域操作,裁减,划线以及绘制简单图形(椭圆,多边形等)。成员函数也提供绘制文本,设置字体,打印机换码,滚动, 处理元文件。其派生类:1.PaintDC: 封装BeginPaint和EndPaint两个API的调用。
(1)用于响应窗口重绘消息(WM_PAINT)的绘图输出。
(2)CPaintDC在构造函数中调用BeginPaint()取得设备上下文,在析构函数中调用EndPaint()释放设备上下文。 EndPaint()除了释放设备上下文外,还负责从消息队列中清除WM_PAINT消息。因此,在处理窗口重画时,必须使用CPaintDC,否则 WM_PAINT消息无法从消息队列中清除,将引起不断的窗口重画。
(3)CPaintDC也只能用在WM_PAINT消息处理之中。
2.CClientDC(客户区设备上下文): 处理显示器描述表的相关的窗体客户区域。
用于客户区的输出,与特定窗口关联,可以让开发者访问目标窗口中客户区,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC。
3.CWindowDC: 处理显示器描述表相关的整个窗体区域,包括了框架和控 件(子窗体)。
(1)可在非客户区绘制图形,而CClientDC,CPaintDC只能在客户区绘制图形。
(2)坐标原点是在屏幕的左上角,CClientDC,CPaintDC下坐标原点是在客户区的左上角。
(3)关联一特定窗口,允许开发者在目标窗口的任何一部分进行绘图,包含边界与标题,这种DC同WM_NCPAINT消息一起发送。4.CMetaFileDC: 与元文件相关的设备描述表关联。CDC提供两个函数,GetLayout和SetLayout用于反转设备描述表的布局。用于方便阿拉伯,希伯来的书写文化习惯的设计,以及非欧洲表中的字体布局。CDC包含两个设备描述表,m_hDC和m_hAttribDC对应于相同的设备,CDC为m_hDC指定所有的输出GDI调用,大多数的GDI属性调用由m_hAttribDC控制。(如,GetTextColor是属性调用,而SetTextColor是一种输出调用。)下面用一些简单的代码看看如果使用这些类
HDC 使用, 每次画线等操作都比MFC封装的类多了个 HDC 的参数
执行在哪个设备描述表操作
HDC hdc=::GetDC(m_hWnd); //m_hWnd == this->m_hWnd 即当前窗口句柄
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
LineTo(hdc,point.x,point.y);
::ReleaseDC(m_hWnd,hdc); //必须和GetDC配对
可以看到 HDC 的使用较麻烦, 而且如果::GetDC和::ReleaseDC不配对的话,会造成错误CDC *pDC=GetDC();
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);CClientDC dc( this );
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);CWindowDC dc( this );
CWindowDC dc2(GetDesktopWindow()); //获得整个桌面的句柄, 一些桌面特效程序使用
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);CPaintDC dc( this );
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);可以看到 MFC 的类使用方便很多, 因为它们都在构造函数和析构函数调用了响应的函数进行DC的获取和释放.下面说下一些细点的知识点
CClientDC,CWindowDC 区别不大, 可以说 CWindowDC包含了CClientDC 就拿记事本来说
CClientDC 就只是白白的我们可以编辑文字的那个区域,是客户区
CWindowDC 除了上面说的白白区域, 还包括菜单栏和工具栏等CClientDC和CWindowDC 与 CPaintDC 的区别大点
在DC的获取方面 CClientDC和CWindowDC 使用的是并只能是 GetDC 和 ReleaseDC
CPaintDC 使用的是并只能是 BeginPaint 和 EndPaintCPaintDC 只能用在响应 WM_PAINT 事件
CClientDC,CWindowDC 只能用在响应非WM_PAINT 事件关于 WM_PAINT 事件
系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和InvalidateRgn函数来完成的。InvalidateRect和 InvalidateRgn把指定的区域加到窗口的Update Region中,当应用的消息队列没有其他消息时,如果窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做。不过这样也有利于提高绘制的效率:两个WM_PAINT消息之间通过 InvalidateRect和InvaliateRgn使之失效的区域就会被累加起来,然后在一个WM_PAINT消息中一次得到更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过InvalidateRect和InvalidateRgn来使窗口区域无效,依赖于系统在合适的时机发送WM_PAINT消息的机制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用SendMessage 发送一条WM_PAINT消息来强制立即重画,但不如使用Windows GDI为我们提供的更方便和强大的函数:UpdateWindow和RedrawWindow。UpdateWindow会检查窗口的Update Region,当其不为空时才发送WM_PAINT消息;RedrawWindow则给我们更多的控制:是否重画非客户区和背景,是否总是发送 WM_PAINT消息而不管Update Region是否为空等。相互转换:
方法一: 此方法在设备结束时不会销毁原来的资源(即:hDC,hBitmap)
CDC *pDC = CDC::FromHandle(hDC);方法二: 此方法在设备结束时会销毁原来的资源(即:hDC,hBitmap)
CDC dc;
dc.Attach(hDC);关于 HDC CDC
首先:CDC 不可以释放. FromHandle 是通过 HDC 来创建了一个CDC 对象,以方便操作,释放 DC 的操作应该针对于 HDC 而非此CDC , 如果释放了它   pDC->ReleaseDC,就会造成隐患. 
    
   HDC   hDC   =   GetDC(hWnd); 
   CDC   *pDC   =   CDC::FromHandle(hDC);  
     
这两者是指向的一个DC对象,只能释放一次,而这个释放应该针对 hDC 而非 pDC.   然后:GetDC和ReleaseDC的调用匹配,CreateDC和DeleteDC的调用匹配。
GetDC是从窗口获取現有的DC,而CreateDC是创建DC,所以ReleaseDC和DeleteDC的作用一个是释放,一个是销毁。
 
HWND hWnd_S2Done = ( HWND )pParam; //创建线程时传递过来的hwnd ,即是IDC_S2DONE的hWnd
// hWnd_S2Done是传入的Picture Control 的HWnd.
HDC Camera_S2Done_Video_hdc = ::GetDC( hWnd_S2Done ); //得到HDC,以便可以上其上"画图
CDC *pDC_S2Done= CDC::FromHandle(Camera_S2Done_Video_hdc); //得到HDC对应的CDC
CRect Camera2_Out_rc;
::GetClientRect(hWnd_S2Done, &Camera2_Out_rc);      // 获取显示区域hWnd
CDC          n_pMemDC;              //定义缓存CDC
CBitmap     m_pMemBmp;           // 缓存画布BMP
 
n_pMemDC.CreateCompatibleDC(pDC_S2Done);  //用上面得到的CDC,建立内存CDC,即准备实现内存画布
//建立CBitmap,否则无法实现对新画布的操作。(不建立,不报错,但没显示)
m_pMemBmp.CreateCompatibleBitmap(pDC_S2Done,Camera2_Out_rc.Width(),Camera2_Out_rc.Height());
n_pMemDC.SelectObject(&m_pMemBmp); //选择新建立的画布
 
     // 必须调用该语句,否则图像出现水纹--但好像没作用
     ::SetStretchBltMode(n_pMemDC.GetSafeHdc(), COLORONCOLOR);
     StretchDIBits(n_pMemDC.GetSafeHdc(), //Camera_S2Done_Video_hdc,
                     0,0,
                     Camera2_Out_rc.Width(), //Camera2_Out_rc.right - Camera2_Out_rc.left,
                     Camera2_Out_rc.Height(), //Camera2_Out_rc.top,
                     0,Camera2_Out_rc.Height(),
                     Camera2_Out_rc.Width(), -Camera2_Out_rc.Height(),
                     pDisplay_Out_Buffer,
                     BitMapInfo,   //m_bmphdr,
                     DIB_RGB_COLORS,
                     SRCCOPY); //实现缓冲区的数据写入新画布
     
     sprintf_s(PutStr, "fps:%.2f" ,pMyApp_Hwnd->MYsetVal.vSpeed);
     n_pMemDC.TextOut(100,40,PutStr); //在内存画布上操作,加入文字
     //这句很重要,注意是用屏显的CDC指针的BitBlt来写,调试时,写成了n_pMemDC. BitBlt,调了2小时也没找到原因。
     pDC_S2Done->BitBlt(  0,0,Camera2_Out_rc.Width(),Camera2_Out_rc.Height(),
                         &n_pMemDC,
                         0,0,
                         SRCCOPY); //将内存画布在显示画布上显示出来
     n_pMemDC.DeleteDC();  //释放资源
     m_pMemBmp.DeleteObject();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值