关于设备描述表

来源:互联网 发布:淘宝网如何提高排名 编辑:程序博客网 时间:2024/05/21 17:37

设备环境是一个结构,它定义了一系列图形对象及其相关的属性,以及会影响输出结果的绘图方式。这些图形对象包括:画笔(用于画直线),笔刷(用于绘图和填充),位图(用于屏幕的拷贝或滚动),调色板(用于定义可用的颜色集),剪裁区(用于剪裁和其他操作),路径(用于绘图和画图操作)。设备环境函数用于对设备环境进行创建、删除或获取信息。


device context 设备描述表   
设备描述表是一个Windows数据结构,它包含了一个设备(比如显示器和打印机)绘图属性的相关信息。所有的绘图操作的调用都是通过一个设备描述表类型的对象来实现,这个类对象封装了Windows API(Application Programming Interface,应用程序编程接口)函数中关于划线、作图和输入输出文本的的相关操作。设备描述表允许在窗口上进行与设备无关的绘图操作,设备描述表可以用在往屏幕、打印机或者图元文件的绘图操作。   设备描述表旗下有4个常用DC类,他们分别是CPaintDC,CClientDC,CWindowDC和CMetaFileDC.


绘图时都需要一个DC对象,DC(Device Context设备环境)对象是一个抽象的作图环境,可能是对应屏幕,也可能是对应打印机或其它。这个环境是设备无关的,所以你在对不同的设备输出时只需要使用不同的设备环境就行了,而作图方式可以完全不变。这也就是Windows耀眼的一点设备无关性。

 


绘图是通过设备环境实现的,设备环境是图形设备接口的重要基元,它代表了具体的物理设备,隐藏了设备的差异性,例如打印机和显示器间的差异,设备无关性使得用户不必关心具体的物理设备的显示,只需要去调用具体的函数去显示就可以了。
设备环境包含了被绘制的设备的信息,例如显示器、打印机等,利用GDI可以方便的处理来自程序的图形绘制的函数调用,然后把这些调用传递给合适的设备驱动程序,由设备驱动程序来进行硬件的操作,绘制相应的图形并显示。

在利用GDI进行操做时需要得到具体的设备环境,使得GDI可以明确具体的设备。
同时设备环境还包括了绘图所需要的数据结构,例如颜色、画笔、字体等,

应用程序-----》设备环境和GDI------》设备驱动---》设备硬件

在MFC中,利用类CDC封装了设备环境和GDI,它封装了绘图所需要的所有数据成员,它定义了一般物理设备的设备环境,为了可以使用具体的物理设备,CDC派生了几个类
1:CPaintDC
这是一个专门用来显示的类,在实际的应用中只要用到相关的CDC指针,就可以将它当成任何设备的指针使用

2:CClientDC
CClientDC是表示在窗口的客户区内进行画图,这个区域不包括标题栏、菜单栏、窗口的边框和状态栏。绘图时客户区的左上角的坐标是(0,0)。CClientDC的构造函数调用GetDC()数调用ReleaseDC()

3:CWindowDC
CWindowDC类的设备环境是表示整个窗口(包括客户区和非客户区),它运行在窗口的任何位置绘图,它定义的窗口的左上角坐标为(0,0),CWindowDC的构造函数调用GetDC()数调用ReleaseDC()

4:CMetaFileDC
CMetaFileDC类封装了在Windows图元文件中绘图的方法。图元文件是一系列与设备无关的图片集,一个图元文件包括了设备接口,可以通过重放命令来创建图形
此类的使用方法入下
(1) 定义CMetaFileDC类对象
(2)
调用CMetaFileDC的Create方法初始化对象

(3)
发送CDC GDI命令道该对象

 

(4)
调用CMetaFileDC的Close()方法关闭元文件

调用CMetaFileDC的PlayMetaFile()方法来回放文件
在如MS-DOS的单任务系统里面,正在运行的应用程序可以自由的做它想做的事情,无论是在屏幕上画线还是重新编写调色板。但是在windows下的多任务环境下,程序却没有如此的自由,A程序的输出是不可以影响B程序的输出的,所以每个程序都被严格的限制于它本身的窗口。GDI用简单的机制确保每个程序的绘制在上面的规则下执行,这个机制就是Device Context(DC)

    当一个windows程序向屏幕,打印机等输出设备绘制时,它不是直接在设备绘制的,而是绘制在一个由DC(Device Context)表示的“Display Surface”上面的。

在现实生活中我们要显示一张图像, 是一件很简单的事情. 投射到计算机中, 则要复杂得多, 因为计算机不是现实世界, 但为了真实地反映现实世界, 走更多的弯路是必然的. 在计算机中, 一张图像的实质只是数据, 很多的0和1的组合. 它只是数据, 至于如何显示它呢, 毫无疑问, 这涉及到硬件设备, 即显示器\打印机等. 那么现在的问题是我有表示图像的数据流, 如何将这些数据流代表的图像描绘出来, 即将这些数据流解释为图像而不是其他的什么东西呢?.

如果我们能直接控制硬件, 那么我们可以将这些数据流塞给显示器或打印机, 然后让它们进行解释. 如果真的这么简单就好了, 我可以任意构造一串数据流, 然后命令显示设备进行解释, 至于解释成什么那我们不要管了, 美女或俊男这都不在我们掌握之内, 因为数据流是我们任意构造的吗!

问题是我们不能直接控制, 结果是我们只能间接控制. 对应于数据结构, 微软就搞了一个Device Context, 它能映射到显示设备, 即它代表了真正的硬件. 如果我们能控制好Device Context, 那么我们也就能控制好真正的硬件.比如说, 我们拥有一些数据流, 我们也知道它代表了一张比较好看的图像. 现在想将它显示在电脑屏幕上, 该如何做呢?

直觉思维告诉我们: 将数据流交给电脑屏幕的Device Context, 显示的细节叫给它了. 但是微软没有提供如此简洁的直觉性操作, 在微软看来, 图像的显示是该图像的数据流从一个设备到另一个设备的过程. 我们看看这意味着什么? 即我们在做显示图像这么简单的操作时, 我们不得不创建一个临时的设备, 将其作为数据流到达目标设备的过渡, 在此之前还必须将图像和临时设备进行关联.

HBITMAP hBitmap = LoadBitmap(...);

// 创建临时设备, 即通常说的内存DC, 而这个设备要与目标设备兼容

// "兼容"就是指两个设备在特性上面要吻合, 不能冲突, 说白了就是

// 属性相同.

HDC pCurrentDC = CreateDC(...);

HDC hTmpDC = CreateCompatibleDC(pCurrentDC);

// 将Bitmap和临时设备进行关联, 假设hbitmap已经成功加载

HBITMAP hOldBitmap = reinterpret_cast<HBITMAP>SelectObject(hTmpDC,

                                                            hBitmap);

// 从临时设备到目标设备, 如果这个目标设备是显示器就是显示图像

BitBlt(hCurrentDC, 0, 0, nWidth, nHeight, &hTmpDC, 0, 0, SRCCOPY);

// 断开临时设备和Bitmap的关联

SelectObject(hTmpDC, hOldBitmap);

// 释放临时设备

ReleaseDC(hTmpDC);

 

以上代码做解释用, 从中可以看出Device Context最大的特点是SelectObject,

而这个Object是Device Context的属性之一, 同时有时必须的, 为什么这样讲呢?

因为每个Device Context创建后都有一系列默认的属性Object. 选进了新的Object,

操作完了还要将原来的属性Object再设定回去.

 

Device context

设备上下文(我更喜欢称作 设备相关性)

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.

DC是一个包含了一系列图形对象(及属性)和影响图形输出模式的结构。

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,而是通过调用各式各样函数来间接进行操作。

现在就明白了,什么是DC了!原来就是那些映象模式和画笔什么的啊。

再来看看Graphic objects究竟含有哪些东西。说实话我真不记得有哪些了。

位图、画刷、调色板、字体、路径、画笔、区域——7种

看起来都理所当然,呵呵。

Device independence

设备无关性

Device independence is one of the chief features of Microsoft? Windows?.

这个特性是MS 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);

实现设备无关性第一个需要的DLL是GDI.dll

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;

如果是在VGA显示器上的客户区域里做图形输出的话,就调用的是Vga.dll的设备驱动

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

如果是在爱普生的FX-80打印机上,就是调用的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).

程序必须通知GDI调用专属的设备驱动,一旦设备驱动加载完毕,就可以进行作图了。

These tasks are accomplished by creating and maintaining a device context (DC).

通过创建并保存DC就可以实现上述操作。

    一个DC是在windows底层下的结构体,包含了GDI需要知道“display surface”的所有东西,包括和它相关的物理设备。当要在屏幕绘制时,应用程序需要从GDI获得一个DC句柄,然后当要调用GDI的输出函数时,就把这个句柄传递给它。通过DC,GDI可以保证程序的所有绘制都限制在屏幕的指定区域。

    在mfc下应用程序可以通过CWnd::GetDC来获得一个DC,然后应该用CWnd::ReleaseDC来释放DC,具体的使用如下:

    CDC* pDC = GetDC();

    // Do some drawing

    ReleaseDC(pDC)

    当处理WM_PAINT消息时,要用到CWnd::BeginPain 和CWnd::EndPaint 来代替上面的函数。使用如下:

    PAINTSTRUCT ps;

    CDC* pDC = BeginPain(&ps);

    //Do some drawing

    EndPaint(&ps);

    Special-Purpose Device Context Classes

    CpaintDC            For drawing in a window’s client area(OnPaint handles only)

    CclientDC            For drawing in a window’s client area(anywhere but OnPain)

    CwindowDC               For drawing anywhere in a window, including the nonclient area

    CmetaFileDc        For drawing to a GDI metafile

    这些类的构造函数和释构函数在获取和释放DC的时候会调用合适的函数,所以就可以直接这样用了,不用象上面很复杂的用法了。

    CpaintDC dc(this); //传递的指针可以确定DC所属的窗口

    //Do some drawing

    ClientDC & CwindowDC

    è当你需要处理一个鼠标的单击,然后马上画出一个圆,你不能等到下一个WM_PAINT的消息到来才画图,而是马上,这是就需要CclientDC了。它可以在OnPaint的外面创建一个客户区域的device context

    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);
    }
    当你不仅仅是想绘制客户区域时,还包括标题栏,窗口边框等,就需要CwindowDC类了。你可以捕获WM_NCPAINT消息,重载OnNcPaint函数来重绘NcClient区域。

    当你想在整个屏幕绘制时,可以创建一个CclientDC或CwindowDC对象,然后给他的构造函数传递一个NULL指针。如下:

    CclientDC dc(NULL);

    dc.Ellipse(0,0,100,100);