现在的位置: 首页 > 综合 > 正文

Windows程序中DC的介绍

2013年10月21日 ⁄ 综合 ⁄ 共 7085字 ⁄ 字号 评论关闭

Windows程序中DC的介绍

 

装置内容(简称为「DC」)实际上是GDI内部保存的资料结构。装置内容与特定的显示设备(如视讯显示器或印表机)相关。

视讯显示器,装置内容总是与显示器上的特定视窗相关。

 

装置内容中的有些值是图形「属性」,这些属性定义了GDI绘图函式工作的细节。例如,对TextOut,装置内容的属性确定

了文字的颜色、文字的背景色、x座标y座标映射到视窗的显示区域的方式,以及显示文字时Windows使用的字体。

 

MSDN的解释:

 

Device Contexts

A device context is a structure that defines a set of graphic objects and their associated attributes, as well as the graphic modes that affect

output. The graphic objects include a pen for line drawing, a brush for painting and filling, a bitmap for copying or scrolling parts of the

screen, a palette for defining the set of available colors, a region for clipping and other operations, and a path for painting and drawing

operations. The remainder of this section is divided into the following three areas.

 

About Device Contexts

Device independence is one of the chief features of Microsoft Windows. Applications can draw and print output on a variety of devices.

The software that supports this device independence is contained in two dynamic-link libraries. The first, Gdi.dll, is referred to as the

graphics device interface (GDI); the second is referred to as a device driver. The name of the second depends on the device where the

application draws output. For example, if the application draws output in the client area of its window on a VGA display, this library is

Vga.dll; if the application prints output on an Epson FX-80 printer, this library is Epson9.dll.

 

An application must inform GDI to load a particular device driver and, once the driver is loaded, to prepare the device for drawing

operations (such as selecting a line color and width, a brush pattern and color, a font typeface, a clipping region, and so on). These tasks

are accomplished by creating and maintaining a device context (DC). A DC is a structure that defines a set of graphic objects and their

associated attributes, and the graphic modes that affect output. The graphic objects include a pen for line drawing, a brush for painting and

filling, a bitmap for copying or scrolling parts of the screen, a palette for defining the set of available colors, a region for clipping and other

operations, and a path for painting and drawing operations. Unlike most of the structures, an application never has direct access to the DC;

instead, it operates on the structure indirectly by calling various functions.

 

 

取得DC的各种方式

 

SDK's way:

 

1.       BeginPaint

 

case WM_PAINT:

    HDC hdc = BeginPaint(hwnd, &ps);

    EndPaint(hwnd, &ps);

 

MSDN的解释:

 

The BeginPaint function automatically sets the clipping region of the device context to exclude any area outside the update region. The update

region is set by the InvalidateRect or InvalidateRgn function and by the system after sizing, moving, creating, scrolling, or any other operation

that affects the client area. If the update region is marked for erasing, BeginPaint sends a WM_ERASEBKGND message to the window.

 

An application should not call BeginPaint except in response to a WM_PAINT message. Each call to BeginPaint must have a corresponding call

to the EndPaint function.

 

其中给出了本次重绘的Clip   Rectangle,所有在这个rectangle之外的绘制操作都不会显示。

这两个BeginPaintEndPaint呼叫之间中没有任何叙述,仅仅使先前无效区域变为有效。

但以下方法是错误的:

 

case WM_PAINT:

       return 0 ;   // WRONG !!!

 

 

Windows将一个WM_PAINT讯息放到讯息伫列中,是因为显示区域的一部分无效。如果不呼叫BeginPaintEndPaint(或者

ValidateRect),则Windows不会使该区域变为有效。相反,Windows将发送另一个WM_PAINT讯息,且一直发送下去。

 

 

2.       GetDC

 

MSDN的解释:

 

The GetDC function retrieves a handle to a display device context (DC) for the client area of a specified window or for the entire screen. You

can use the returned handle in subsequent GDI functions to draw in the DC.

BeginPaintEndPaint一样,GetDCReleaseDC函式必须成对地使用。如果在处理某讯息时呼叫GetDC,则必须在退出视窗讯息

处理程式之前呼叫ReleaseDC。不要在一个讯息中呼叫GetDC却在另一个讯息呼叫ReleaseDC

 

与从BeginPaint传回装置内容代号不同,GetDC传回的装置内容代号具有一个剪取矩形,它等整个显示区域。可以在显示区域的某

一部分绘图,而不只是在无效矩形上绘图(如果确实存在无效矩形)。与BeginPaint不同,GetDC不会使任何无效区域变为有效。如

果需要使整个显示区域有效,可以呼叫

 

ValidateRect (hwnd, NULL) ;

 

一般可以呼叫GetDCReleaseDC来对键盘讯息(如在字处理程式中)和滑鼠讯息(如在画图程式中)作出反应。此时,程式可以

立刻根据使用者的键盘或滑鼠输入来更新显示区域,而不需要考虑为了视窗的无效区域而使用WM_PAINT讯息。不过,一旦确实收

到了WM_PAINT讯息,程式就必须要收集足够的资讯才能更新显示。

GetDC相似的函式是GetWindowDCGetDC传回用於写入视窗显示区域的装置内容代号,而GetWindowDC传回写入整个视窗的

装置内容代号。例如,您的程式可以使用从GetWindowDC传回的装置内容代号在视窗的标题列上写入文字。然而,程式同样也应该

处理WM_NCPAINT (「非显示区域绘制」)讯息

 

 

3.       CreateDC

 

MSDN的解释:

 

HDC CreateDC(

  LPCTSTR lpszDriver,        // driver name

  LPCTSTR lpszDevice,        // device name

  LPCTSTR lpszOutput,        // not used; should be NULL

  CONST DEVMODE* lpInitData  // optional printer data

);

 

 

MFC's way

 

1.       CDC

 

HDC的包装,类似CWndHWND的包装.CDC的构造函数里面并没有对m_hDC进行初始化.

 

MSDN的解释:

 

class CDC : public CObject

 

Defines a class of device-context objects.

 

Remarks

The CDC object provides member functions for working with a device context, such  as a display or printer, as well as members

for working with a display context  associated with the client area of a window.

 

Do all drawing through the member functions of a CDC object. The class provides member functions for device-context operations,

working with drawing tools, type-safe graphics device interface (GDI) object selection, and working with colors and palettes. It also

provides member functions for getting and setting drawing attributes, mapping, working with the viewport, working with the window

extent, converting coordinates, working with regions, clipping, drawing lines, and drawing simple shapes, ellipses, and polygons.

Member functions are also provided for drawing text, working with fonts, using printer escapes, scrolling, and playing metafiles.

 

To use a CDC object, construct it, and then call its member functions that parallel Windows functions that use device contexts.

 

For specific uses, the Microsoft Foundation Class Library provides several classes derived from CDC . CPaintDC encapsulates calls to

BeginPaint and EndPaint. CClientDC manages a display context associated with a window's client area. CWindowDC manages a display

context associated with an entire window, including its frame and controls. CMetaFileDC associates a device context with a metafile.

 

MFC中的代码实现:

 

CDC::CDC()

{

       m_hDC = NULL;

       m_hAttribDC = NULL;

       m_bPrinting = FALSE;

}

 

CDC::~CDC()

{

       if (m_hDC != NULL)

              ::DeleteDC(Detach());

}

 

 

BOOL CDC::Attach(HDC hDC)

{

       ASSERT(m_hDC == NULL);      // only attach once, detach on destroy

       ASSERT(m_hAttribDC == NULL);    // only attach to an empty DC

 

       if (hDC == NULL)

              return FALSE;

 

       CHandleMap* pMap = afxMapHDC(TRUE); // create map if not exist

       ASSERT(pMap != NULL);

       pMap->SetPermanent(m_hDC = hDC, this);

 

       SetAttribDC(m_hDC);     // Default to same as output

       return TRUE;

}

 

HDC CDC::Detach()

{

       HDC hDC = m_hDC;

       if (hDC != NULL)

       {

              CHandleMap* pMap = afxMapHDC(); // don't create if not exist

              if (pMap != NULL)

                     pMap->RemoveHandle(m_hDC);

       }

 

       ReleaseAttribDC();

       m_hDC = NULL;

       return hDC;

}

 

 

2. CPaintDC

 

BeginPaint的包装

 

MSDN的解释:

 

class CPaintDC : public CDC

 

It performs a CWnd::BeginPaint at construction time and CWnd::EndPaint at destruction time.

 

A CPaintDC object can only be used when responding to a WM_PAINT message, usually in your OnPaint message-handler

member function.

 

MFC中的代码实现:

 

CPaintDC::CPaintDC(CWnd* pWnd)

{

       ASSERT_VALID(pWnd);

       ASSERT(::IsWindow(pWnd->m_hWnd));

 

       if (!Attach(::BeginPaint(m_hWnd = pWnd->m_hWnd, &m_ps)))

              AfxThrowResourceException();

}

 

CPaintDC::~CPaintDC()

{

       ASSERT(m_hDC != NULL);

       ASSERT(::IsWindow(m_hWnd));

 

       ::EndPaint(m_hWnd, &m_ps);

       Detach();

}

 

3. CClientDC

 

GetDC的包装

 

MSDN的解释:

 

class CClientDC : public CDC

 

This means that the device context associated with a CClientDC object is the client area of a window.

 

MFC中的代码实现:

 

CClientDC::CClientDC(CWnd* pWnd)

{

       ASSERT(pWnd == NULL || ::IsWindow(pWnd->m_hWnd));

 

       if (!Attach(::GetDC(m_hWnd = pWnd->GetSafeHwnd())))

              AfxThrowResourceException();

}

 

 

CClientDC::~CClientDC()

{

       ASSERT(m_hDC != NULL);

       ::ReleaseDC(m_hWnd, Detach());

}

 

 

4. CWindowDC

 

抱歉!评论已关闭.