vc句柄,对象,实例差异 设备DC何时使用

来源:百度文库 编辑:神马文学网 时间:2024/04/28 18:27:06

微软喜欢将内核对象标识,称为句柄。应该都是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();


CDC是进行设备环境处理的类,GDI和GDI+显示类库需要这个设备显示对象(包括图像,画笔,线条,画刷等)

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类的函数        
   }