GDI/GDI+ 绘制网站流量统计报表 总结(1)

来源:互联网 发布:技术导航网源码 编辑:程序博客网 时间:2024/05/01 23:52

第一讲:GDI编程的基本概念

图形设备接口:是一个抽象的接口,是一个关于图形显示的函数库。通过这个接口可以实现对图形的颜色、线条的粗细等属性的控制。通过GDI,可以进行设备无关性操作。所有的GDI函数中必须带有设备环境这个参数。设备环境DCDevice Context 又称为设备上下文,也称为设备描述表),它是一个关于如何绘制突袭的方法的集合,它既可以绘制各种图形,也可以确定在应用窗口中绘制图形的方式,就是绘图模式和映射模式。在Win32编程中,设备环境是用HDC来标识的。H的意思就是Handle句柄的意思。

如何在DC上绘制呢?就是用GDI函数来对DC进行操作。而GDI函数的声明是包含在WinGDI.h文件中的。DC好比一块画布,所有东西都是画在画布上的。所以在绘制图形之前就是要先获得画布DC,那么有这么几种方法可以来获得相应的HDC

第一种:通过GetDC函数来获得相应的窗口的HDCGetDC函数适合在需要窗口在现有图形的基础上进行绘制时,用来获取HDC

代码段:

        HDC hDC = ::GetDC(hWnd);

        //其它的绘图操作代码

……

 

::ReleaseDC(hWnd,hDC);

注:GetDC中传入的参数是hWnd,即窗口的句柄,它返回和这个窗口相关的DC

   GetDC(hWnd)用完之后,一定要记得用ReleaseDC(hWnd,hDC)来释放,否则会造成内存泄露,过多的内存泄露可能会使GetDC申请不到DC而导致窗口黑屏。

第二种方法:通过BeginPaint函数来获取所在窗口的HDC

BeginPaint函数是将窗口上所有内容清除干净,然后在上面绘制。

代码段:

{

        PAINTSTRUCT ps;

        HDC hDC = ::BeginPaint(hWnd,&ps);

        //其它绘制操作代码

 

        ::EndPaint(hWnd,&ps);

}

注意:在调用BeginPaint(hWnd,&ps)来获取hDC用完之后,一定要记得调用EndPaint(hWnd,&ps)来释放这个hDC,同时也提交绘图,最终显示在显示器上面.(hWnd是窗口句柄)

 

PAINTSTRUCT结构:

typedef struct tagPAINTSTRUCT{

        HDC hdc; //显示器的设备环境句柄

        BOOL fErase; //是否擦除背景

        RECT rcPaint; //指定了需要绘图的窗口区域

        BOOL fRestore; //是否需要恢复

        BOOL fIncUpdate; //更新

        BYTE rgbReserved[32]

}PAINTSTRUCT;

调用EndPaint函数可以只更新工作区域中的部分区域,这个比重绘整个屏幕要快。因此BeginPaintEndPaint总是被用来响应WM_PAINT消息。

 

第三种方法:通过CreateCompatibleDC函数来创建兼容内存DC

通过调用CreateCompatibleDC函数来创建与目标DC兼容的内存DC,然后可以在内存DC上进行各种各样的操作,需要注意的是这里的绘制不会直接显示到显示器上去,那要等到什么时候才会显示上去呢?只有等到BitBlt把内存DC上的内容拷贝到目标DC上来以后,才会被显示到显示器上,当然这里的目标DC,假定就是窗口DC,最后不要忘了调用DeleteDC来释放hMemDC其中这个hDest就是窗口的目标DC。其它的绘制操作代码都是基于内存DC,hMemDC的,那么要把在内存中绘制的结果,呈现在目标DC上的话,需要调用BitBlt将内存DC中的图像拷贝到目标DC上来。一般用于解决界面闪烁问题。

代码段:

{

        HDC hMemDC = ::CreateCompatibleDC(hDest);

        //其它绘制操作代码

        ……

        ::DeleteDC(hMemDC);

}

常用的GDI对象:

画笔Pen:

GDI中,用HPEN来表示画笔,H是代表句柄的意思。

GDI中,画线,画边框(如矩形边框,圆边框,饼边框)都是采用画笔来操作的。

GDI默认的画笔是黑色,宽度为1,样式为实线的画笔。

 

画刷Brush:

GDI中,填充矩形,填充圆,填充饼等以及刷窗口背景都是通过画刷来操作的。

GDI中,默认的画刷是白色的画刷。

 

字体Font:

GDI中,用HFONT来表示字体。

GDI中,所有文本绘制,都是要基于具体的字体对象来绘制的。GDI中默认的字体,是系统等宽字体,比如对话框标题一般就采用这个字体。

 

区域Region:

GDI中,用HRGN来表示区域。在窗口中,一个区域可以是椭圆形,多边形,或是矩形等。

 

位图Bitmap:

GDI中,用HBITMAP来表示位图。

GDI的绘制,从大体上,分为图形绘制和图像绘制。对于线,矩形,圆,饼等的绘制是属于图形绘制。而对于位图的绘制则是属于图像绘制。

 

如何来使用这些对象?使用SelectObject函数将这些对象选入到DC中,就可以用了。

SelectObject原型:

HGDIOBJ WINAPI SelectObject(HDC hdc, HGDIOBJ h);

第一个参数是设备DC

第二个参数是HGDIOBJ其实就是一个void*。这个函数传入一个新的GDI对象到第一个参数的DC中,并返回该DC的老的相同类型的GDI对象。

返回值为一个HGDIOBJ,是所有GDI对象的共同基类的一个类型。

WINAPI表示是系统API函数。

 

下面是一个完整的使用GDI对象的例子代码:

        LOGFONT if={0};

        lf.lfWidth = 16;

        lf.lfHeight = 40;

        lf.lfCharSet = GB2312_CHARSET;

        HFONT hOldFont = ::SelectObject(hDC,hFont);

        DrawText(hDC,_T(“abc”),3,&rect,DT_LEFT);

        //其它绘制操作代码

        ……

        ::SelectObject(hDC,hOldFont);

        ::DeleteObject(hFont);

LOGFONT这个其实就是字体的逻辑结构,把它初始化为0.然后把lf地址传入CreateFontIndirect(),CreateFontIndirect()就根据lf初始化的字体的逻辑结构信息来创建字体,并返回一个HFONT句柄。创建完之后,用SelectObejct来将其选入到HDC中来,但是这里我们把之前的老的hOldFont先保存起来,待用完之后,再将这个老的选入到HDC中来,最后调用DeleteOject(hFont);来删除这个用完的hFont对象。

 

创建GDI对象,把新的对象选入HDC,把老的保存起来,然后进行绘制,最后把老的对象再选入,最后删除这个用完的GDI对象。

 

如果要用的对象是windows能够默认提供的,也就是所谓的库存的对象,那么我们就不需要动态的去创建和销毁这些对象了,只需要直接使用就可以了。这样就可以提高程序运行的效率。

库存GDI对象,例如:

画刷

#define WHITE_BRUSH 0 //白色画刷

#define LTGRAY_BRUSH 1 //亮灰色画刷

#define GRAY_BRUSH 2 //灰色画刷

#define DKGRAY_BRUSH 3 //暗灰色画刷

#define BLACK_BRUSH 4 //黑色画刷

#define NULL_BRUSH 5 //空画刷

#define HOLLOW_BRUSH NULL_BRUSH

 

画笔

#define WHITE_PEN 6 //白色画笔

#define BLACK_PEN 7 //黑色画笔

#define NULL_PEN 8 //空画笔

 

字体

#define OEM_FIXED_FONT 10

#define ANSI_FIXED_FONT 11

#define ANSI_VAR_FONT 12

#define SYSTEM_FONT 13

#define DEVICE_DEFAULT_FONT 14

#define DEFAULT_PALETTE 15

#define SYSTEM_FIXED_FONT 16

#define DEFAULT_GUI_FONT 17

 

用的最多的是DEVICE_DEFAULT_FONT字体

可以通过调用对象的ID号来获得库存的GDI对象的函数如下:

HGDIOBJ GetStockObject(int i);

Stock即库存的意思

返回对应的GDI句柄,库存的对象是不需要你创建,也不需要你来销毁

除了对GDI进行选入之外,有时候还需要获得GDI的一些信息,那么获得对象的一些信息可以通过调用GetObject函数来实现。

int WINAPI GetObject(HANDLE h , int c , LPVOID pv);

第一个参数填入GDI对象的句柄

第二个参数填入结构的大小

第三个参数填入结构的指针,这里的结构是对应相应的GDI对象的。

 

比如:位图HBITMAP对象的结构是BITMAP画刷HBRUSH的对象结构是LOGBRUSH。现在以获得位图对象的信息为例:得到位图的宽度和高度。

BITMAP bm;

::GetObject(hBitmap,sizeof(BITMAP),&bm);

 

GDI对象的信息获取

typedef struct tagBITMAP

{

        LONG bmType;

        LONG bmWidth;

        LONG bmHeight;

        LONG bmWidthBytes;

        LONG bmPlanes;

        LONG bmBitsPixel;

        LPVOID  bmBits;

}BITMAP,*PBITMAP,NEAR *NPBITMAP,FAR *LPBITMAP;

 

DCGDI设备之间的关系,DC主要描述绘图的状态和方式,GDI设备主要描述了采用什么样的绘图工具来绘制。前者就像是一块白板,后者就好像是各种的画笔和画刷。

 

图片和颜色的关系

RGB格式中,R(0~255)红色分量,G(0~255)绿色分量,B(0~255)蓝色分量。没有透明信息。通常RGB三个分量各占一个字节,所以RGB实际占用的是三个字节。

ARGB格式中,A(0~255)代表Alpha,代表透明度信息。后面的RGB就是红、绿、蓝分量。通常ARGB四个分量各占一个字节,所以ARGB实际占用的是四个字节。

 

 

 

原创粉丝点击