`
wo_deqing
  • 浏览: 64214 次
文章分类
社区版块
存档分类
最新评论

VC之GDI

 
阅读更多

以前在Delphi下用Canvas用惯了,很少直接使用GDI API,今天转换到VC下了,哪只有重新温习GDI了,首先先简单说说GDI体系结构。

GDI是微软设计的一套API,为应用程序提供设备无关的接口,包括视频显示、打印机、画图仪和传真机。GDI提供几百个Windows程序可以调用的函数。这些函数大多数是从Win32的子系统GDI32.DLL中导出。有兴趣的话找个工具看看GDI32.Dll的导出函数。

GDI的功能太多了,MSDN库就将GDI API分为17个领域(位图、画刷、剪裁、颜色、坐标和变换、设备上下文、填充形状、字体和文本、直线和曲线、元文件、多显示监视器、画图和绘图、路径、画笔、打印和打印池、矩形、区域)。除了这些分类外,还有一些没有文档记载的函数。有一些在DDK中说明,还有一些没文档但系统DLL使用的函数。

主要的Windows图形编程API就是GDI,这些API与设备无关,编写出来的程序可在不同的设备上运行。哪GDI怎样实现设备无关的呢?为了与图形设备驱动程序交互,windows图形系统采用了了称之为设备上下文的内部数据结构,是用指针链接在一起的结构和对象组成的网状结构。设备上下文有两个重要的作用,最主要的用途在于提供图形设备逻辑,使的设备驱动程序以上的事物,包括图形引挚、win32客户端以及用户应用程序都独立于设备。另一个用途是存储常用的绘图属性,比如前景色,画笔、刷子......,这样不同的绘图调用就不需要重复这些设置。Win32 GDI的客户端向用户应用程序屏蔽了真正的设备上下文,应用只得到了设备上下文的句柄,GDI在创建设备上下文时返回句柄,然后将句柄反馈给GDI,以查询新的绘图操作。

//通过使用指定的名字为一个设备创建设备上下文环境
/*

CreateDC(LPCTSTRpszDriver,只能是"DISPLAY"、NULL、"WINSPOOL"
LPCTSTRpszDevice,可以是EnumDisplayDevices返回的显示设备名,也可是打印名(如////.//DISPLAY1)或NULL
LPCTSTRpszOutput,用于可以接收打印作业的端口名,win32API使用新的函数调用StartDoc传递端口名,因此必须为NULL
CONSTDEVMODE*pdvmInit指向DEVMODE结构的指针,DocumentProperties函数检索指定设备获取已填充的结构,如果设备驱动程序使用用户指定的缺省初始化值。则lplnitData参数必须为Null
);
*/
HDChdc
=CreateDC(_T("DISPLAY"),NULL,NULL,NULL);//整个屏幕的设备上下文句柄
MoveToEx(hdc,0,0,NULL);
LineTo(hdc,
100,100);//绘制一条直线
DeleteDC(hdc);

//获取指定窗口客户区设备上下文句柄
/*

GetDC(HWNDhWnd);
*/

hdc
=::GetDC(this->m_hWnd);
MoveToEx(hdc,
0,0,NULL);
LineTo(hdc,
100,100);
::ReleaseDC(
this->m_hWnd,hdc);

//获取指定窗口设备上下文件句柄
/*

BeginPaint(HWNDhWnd,//窗口句柄
CONSTPAINTSTRUCT*lpPaint//获取显示参数
)

PAINTSTRUCT结构定义
typedefstructtagPAINTSTRUCT{
HDChdc;
BOOLfErase;
RECTrcPaint;
BOOLfRestore;
BOOLfIncUpdate;
BYTErgbReserved[32];
}PAINTSTRUCT,*PPAINTSTRUCT
*/

PAINTSTRUCTps;
hdc
=::BeginPaint(this->m_hWnd,&ps);
MoveToEx(hdc,
200,200,NULL);
LineTo(hdc,
1300,1300);
::EndPaint(
this->m_hWnd,&ps);

接着练

GDI对像

Windows的GDI对象类型是通过MFC中的类来表示的,而CGdiObject正是所有GDI对象类的抽象基类,即Windows的GDI对象是通过CGdiObject派生类的C++对象来表示的。如:CBitmap、CBrush、CFont、CPallete、CPen、CRgn.......

GDI对象存储在什么地方呢?GDI对象存储在系统范围内的固定大小的对象表中,称之为对象句柄表,GDI对象表是一个固定大小的表,在win2000/NT允许最多有16384个GDI句柄。GDI对象有许多专用的例程以创建该类型的一个新的GDI对象。一旦创建完成GDI对象,GDI将返回一个GDI对象句柄,当GDI对象不用时,要用DeleteObject函数删除哦,但要确保没该对象没有处在设备上下文中,不然会导致潜在的GDI对象泄露

HGDIOBJSelectObject(HDChdc,HGDIOBJhgdiobj);//将GDI对象和一个设备上下文相连接
BOOLDeleteObject(HGDIOBJhgdiobj);//删除GDI对象
DWORDGetObjectType(HGDIOBJh);//确定指定对象类型
intGetObject(HGDIOBJhgdiobj,intcbBuffer,LPVOIDlpvObject);//将指定对象的信息写入到缓冲区

下面以CPen对象来练练上面的四个函数。

//SelectObject和DeleteObject用法

CPenp,
*oldPen;
p.CreatePen(PS_SOLID,
1,RGB(255,255,0));
HDChdc
=::GetDC(this->m_hWnd);
oldPen
=(CPen*)SelectObject(hdc,p.GetSafeHandle());
MoveEx(hdc,
0,0,NULL);
LineTo(hdc,
100,100);
SelectObject(hdc,oldPen);
DeleteObject(p.GetSafehandle());
::ReleaseDC(
this->m_hWnd,hdc);

/*
DWORDGetObjectType(HGDIOBjh);
返回值:
OBJ_BITMAP(位图Bitmap)
OBJ_BRUSH(刷子Brush)
OBJ_PAL(调色版Palette)
OBJ_PEN(画笔Pen)
OBJ_EXTPEN(扩展画笔Extendedpen)
OBJ_REGION(区域Regioin)
OBJ_DC(设备上下文Devicecontext)
OBJ_MEMDC(存储设备上下文MemoryDC)
OBJ_METAFILE(元文件Metafile)
OBJ_METADC(元文件设备上下文MetafileDC)
OBJ_ENHMETAFILE(扩展元文件Enhancedmetafile)
OBJ_ENHMATADC(扩展元文件设备上下文EnhancedmetafileDC)
*/
CPenp;
p.CreatePen(PS_SOLID,
1,RGB(255,255,0));

if(OBJ_PEN==GetObjectType(p.GetSafeHandle()))
{
MessageBox(_T(
"CPen对象"),"信息");
}

p.DeleteObject();

GDI画笔对象

GDI中的画笔对象包含了直线和曲线的宽度、形式、颜色、端点形状、交点以及样式。你画出来的线是啥颜色,好宽,都由它决定的。

缺省的DC画笔是单个象素宽的黑色画笔。一旦画笔被选入设备上下文后,只有颜色是可以改变的,可通过下面两个函数来访问设置和得到DC画笔颜色。

COLORREFGetDCPenColor(HDChdc);
COLORREFSetDCPenColor(HDChdc,COLORREFcrColor);

GetDCPenColor函数获取设备上下文中DC画笔的当前颜色,SetDCPenColor函数设置一个新的颜色,并返回旧的颜色。

hdc=::GetDC(this->m_hWnd);
COLORREFcrCol;
crCol
=GetDCPenColor(hdc);//默认为黑色
MoveToEx(hdc,0,200,NULL);
LineTo(hdc,
100,200);//绘制一条黑色的直线
HGDIOBJhld=SelectObject(hdc,GetStockObject(DC_PEN));
SetDCPenColor(hdc,RGB(
255,0,0));
MoveToEx(hdc,
0,220,NULL);
LineTo(hdc,
100,220);//绘制一条红色的直线
SelectObject(hdc,hOld);
::ReleaseDC(
this->m_hWnd,hdc);

上面的GetStockObject是啥?

原来GDI定义了四种预定义的画笔对象,叫库存画笔,为了获取库存画笔,那就要用到GetStockObject这个函数了。GetStockObject(BLACK_PEN)黑色、GetStockObject(White_PEN)白色、GetStockObject(NULL_PEN)什么都不画、GetStockObject(DC_PEN)。

下面用下面两个函数来创建画笔。

HPENCreatePen(intfnPenStyle,intnwidth,COLORREFcrColor);
HPENCreatePenIndirect(CONSTLOGPEN
*lgPen);

fnPenStyle画笔样式有下面这些样式。

PS_SOLID---------------纯色,所有象素都画

PS_DASH---------------虚线

PS_DOT-----------------点画线

PS_DASHDOT---------虚线和点画线交替出现

PS_DASHDOTDOT---虚线和两交点画线交替出现

PS_NULL----------------不画线

PS_INSIDEFRAME----纯色,所有象素都画

hdc=::GetDC(this->m_hWnd);
HPENp_SOLID,p_DASH,p_DOT,p_DASHDOT,p_DASHDOTDOT;
p_SOLID
=CreatePen(PS_SOLID,1,RGB(255,0,0));
p_DASH
=CreatePen(PS_DASH,1,RGB(255,0,0));
p_DOT
=CreatePen(PS_DOT,1,RGB(255,0,0));
p_DASHDOT
=CreatePen(PS_DASHDOT,1,RGB(255,0,0));
p_DASHDOTDOT
=CreatePen(PS_DASHDOTDOT,1,RGB(255,0,0));
hOld
=SelectObject(hdc,p_SOLID);
MoveToEx(hdc,
0,10,NULL);
LineTo(hdc,
10,10);
SelectObject(hdc,p_DASH);
MoveToEx(hdc,
0,20,NULL);
LineTo(hdc,
0,20);
SelectObject(hdc,p_DOT);
MoveToEx(hdc,
0,30,NULL);
LineTo(hdc,
0,30);
SelectObject(hdc,p_DASHDOT);
MoveToEx(hdc,
0,40,NULL);
LineTo(hdc,
0,40);
SelectObject(hdc,p_DASHDOTDOT);
MoveToEx(hdc,
0,50,NULL);
LineTo(hdc,
0,50);
SelectObject(hdc,hOld);
DeleteObject(p_SOLID);
DeleteObject(p_DASH);
DeleteObject(p_DOT);
DeleteObject(p_DASHDOT);
DeleteObject(p_DASHDOTDOT);
::ReleaseDC(
this->m_hWnd,hdc);

CreatePenIndirect函数

结构LOGPEN存储了逻辑画笔的三个参数,画笔样式、宽度、颜色。

typedefstructtagLOGPEN{
UINTlopnStyle;
//样式
POINTlopnWidth;//宽度
COLORREFlopnColor;//颜色
}LOGPEN,*PLOGPEN;

LOGPENlogpen;
HPENp;
HGDIOBJhOld;
HDChdc
=::GetDC(this->m_hWnd);
logpen.lopnWidth.x
=1;
logpen.lopnColor
=RGB(255,0,0);
logpen.lopnStyle
=PS_SOLID;
p
=CreatePenIndirect(&logpen);
hOld
=SelectObject(hdc,p);
MoveToEx(hdc,
0,10,NULL);
LineTo(hdc,
50,10);
SelectObject(hdc,hOld);
DeleteObject(p);
::ReleaseDC(
this->m_hWnd,hdc);

ExtCreatePen函数

上面CreatePen和CreatePenIndirect(CreatePenIndirect也是调用的CreatePen函数)创建的画笔,当宽度大于一个象素时,画笔不能画真实形式的直线,例如虚线和点划线。绘制的直线画端是圆角的,这时这两个函数将不能满足需要了。这时就可用到ExtCreatePen函数。ExtCreaetPen可以创建几何画和装饰性画笔。

HPENExtCreatePen(DWORDdwPenStylek,
DWORDdwWidth,
CONSTLOGBRUSH
*lplb,
DWORDdwStyleCont,
CONSTDWORD
*lpStyle);

用ExtCreatePen创建装饰性画笔

dwPenStyle:为画笔类型和型式(类型包括PS_COSMETIC和PS_GEOMETRIC,PS_COSMETIC为装饰画笔,PS_GEOMETRIC为几何画笔,型式包括前面说的画笔的样式PS_SOLID....,在2000/nt以上还包括PS_USERSTYLE、PS_ALTERNATE)。

dwWidth:装饰性画笔只能画单个象素宽的线,因此dwWidth参数只能为1;

lplb:画笔的属性;

dwStyleCont:是自定义样式数组的个数。

lpStyle:自定义样式数组

LOGBRUSHlb;
HDChdc
=::GetDC(this->m_hWnd);
HGDIOBJhOld;

lb.lbStyle
=BS_SOLID;
lb.lbColor
=RGB(255,0,0);
lb.lbHatch
=0;
HPENp
=ExtCreatePen(PS_COSMETIC|PS_SOLID,1,&lb,0,NULL);
hOld
=SelectObject(hdc,p);
MoveToEx(hdc,
0,20,NULL);
LineTo(hdc,
100,20);
SelectObject(hdc,hOld);
DeleteObject(p);
::ReleaseDC(
this->m_hWnd,hdc);

下面使用PS_USERSTYLE来创建自定义的装饰性画笔,lpSyle数组中的第一个元素象素长度,第二个元素为间距长度,第三个元素为象素长度......,里面元素的单位为三个象素,例如{4,3,2,1}则绘出的线为12个象素的线,9象素的间距,6象素的线,3象素的间距。

LOGBRUSHlb;
HDChdc
=::GetDC(this->m_hWnd);
HGDIOBJhOld;
DWORDcy[
4]={4,3,2,1};

lb.lbStyle
=BS_SOLID;
lb.lbColor
=RGB(255,0,0);
lb.lbHatch
=0;
HPENp
=ExtCreatePen(PS_COSMETIC|PS_USERSTYLE,1,&lb,4,cy);
hOld
=SelectObject(hdc,p);
MoveToEx(hdc,
0,20,NULL);
LineTo(hdc,
100,20);
SelectObject(hdc,hOld);
DeleteObject(p);
::ReleaseDC(
this->m_hWnd,hdc);

使用ExtCreatePen建立几何画笔

LOGBRUSHlb;
HDChdc
=::GetDC(this->m_hWnd);
HGDIOBJhOld;
DWORDcy[
4]={4,3,2,1};

lb.lbStyle
=BS_SOLID;
lb.lbColor
=RGB(255,0,0);
lb.lbHatch
=0;
//创建一个平面端点几何画笔(PS_ENDCAP_FLAT平面端点,PS_ENDCAP_ROUND圆角端点)
HPENp=ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT,16,&lb,0,NULL);
hOld
=SelectObject(hdc,p);
MoveToEx(hdc,
0,20,NULL);
LineTo(hdc,
100,20);
SelectObject(hdc,hOld);
DeleteObject(p);
::ReleaseDC(
this->m_hWnd,hdc);

GDI画刷对象

GDI中的画刷对象的颜色决定了区域填充中前景色。

缺省的DC画刷是白色画刷。一旦画笔被选入设备上下文后,可通过下面两个函数来访问设置和得到DC画笔颜色。

GDI预定义了7个库存画刷,可以使用GetStockObject函数带入以下参数获取库存画刷。

BLACK_BRUSH---------------黑色画刷

DKGRAY_BRUSH-------------暗灰色画刷

GRAY_BRUSH----------------灰色画刷

LTGRAY_BRUSH-------------浅灰色画刷

WHITE_BRUSH--------------白色画刷

NULL_BRUSH----------------空画刷

DC_BRUSH------------------DC画刷

COLORREFGetDCBrushColor(HDChdc);
COLORREFSetDCBrushColor(HDChdc,COLORREFclColor);

GetDCBrushColor函数获取设备上下文中DC画刷的当前颜色,SetDCBrushColor函数为当关DC画刷设置一个新的颜色,并返回旧的颜色。

自定义画刷

HBRUSHCreateSolidBrush(COLORREFclColor);//创建纯色画刷
HBRUSHCreateHatchBrush(intfnStyle,COLORREFcrRef);//创建阴影画刷
HBRUSHCreatePatternBrush(HBITMAPhbmp);//创建位图画刷
HBRUSHCreateDIBPatternBrushPt(CONSTVOID*lpPackedDIB,UINTiUsage);//创建设备无关位图画刷
HBRUSHCreateDIBPatternBrush(HGLOBALhglbDIBPacked,UINTiUsage);//创建设备无关位图画刷
HBRUSHGetSysColorBursh(intnIndex);//创建系统颜色画刷
分享到:
评论

相关推荐

    VC使用GDI+的方法.

    在探讨如何在Visual C++(以下简称VC)环境中使用GDI+进行图形绘制之前,我们首先需要了解几个关键概念:GDI+是什么?它与传统的GDI(Graphics Device Interface)有何不同?以及如何在VC项目中集成GDI+库来实现更...

    vc 精通GDI+编程

    GDI+是Windows图形设备接口(Graphics Device Interface)的一个增强版本,主要在Microsoft Visual C++(简称VC)环境中被广泛使用,用于实现丰富的图形绘制、图像处理和文本渲染。GDI+提供了更多的图形功能和更现代...

    VC6.0GDI++

    在本主题“VC6.0 GDI++”中,我们将深入探讨如何在Visual C++ 6.0环境下利用GDI++进行图形界面的绘制。 首先,虽然VC6.0是一款较老的开发环境,但仍然被许多开发者所青睐,尤其是对于学习和理解底层Windows编程。...

    VC6使用GDI+

    在Microsoft Visual C++ 6.0(简称VC6)这个经典的开发环境中,使用GDI+进行图形绘制和处理是一项常见的任务。GDI+是Windows API的一个扩展,它提供了丰富的图形功能,包括2D图形绘制、图像操作、文本渲染等。在本文...

    VC6-GDI+.rar_GDI 双缓冲_MFC_MFC 读jpg_mfc 滚动条_璇诲彇 鍐呭瓨

    这段时间在研究GDI+双缓冲的方法,在网上找了很多时间都没有找到合适的示例,特别是针对VC6的。后来通过对网上资料的分析,和对SDK,MFC的学习,实现了VC6下GDI+双缓冲的效果,把它写出来与大家分享,希望可以找到更...

    vc_GDI+显示PNG图片

    ### VC与GDI+显示PNG图片详解 #### 一、GDI+简介 GDI+是微软为Windows XP及以上版本操作系统推出的一种图形设备接口技术,它作为GDI(Graphics Device Interface)的升级版,提供了更丰富的图形处理能力,特别是在...

    VC6下的GDI+双缓冲 解决闪烁问题

    在VC6下实现GDI+双缓冲,首先需要创建一个内存设备上下文,并且创建一个与窗口大小相同的位图,然后将内存设备上下文与这个位图关联。接着,开发者可以在内存设备上下文中使用GDI+的各种绘图函数进行图形绘制,如...

    Vc6.0中gdi+环境搭建

    对于使用Visual C++ 6.0(简称VC6.0)的老版本开发环境的程序员来说,尽管VC6.0本身并不直接支持GDI+,但通过特定的配置和安装步骤,我们仍然可以在VC6.0中使用GDI+进行图形编程。下面将详细介绍如何在VC6.0中搭建...

    VC6使用GDI+相关文件

    在Visual C++ 6.0(简称VC6)这个经典的开发环境中,使用GDI+进行图形绘制需要一些特定的文件,包括头文件、库文件和动态链接库(DLL)。以下是对这些知识点的详细说明: 1. **头文件(Include Files)**:GDI+的...

    VC6和VC2005中使用GDI+步骤

    在Microsoft Visual C++ 6.0 (VC6) 和Visual Studio 2005中使用GDI+(Graphics Device Interface Plus)是一项常见的图形处理任务,它扩展了传统的GDI功能,提供了更强大的图形绘制和图像处理能力。GDI+允许开发者...

    VC6.0中用GDI+加载动态gif图片示例

    在VC6.0环境下,利用GDI+加载动态GIF图片是一个常见的图形处理任务,尤其在开发具有图形界面的应用程序时。GDI+是Windows API的一个扩展,它提供了丰富的绘图功能,包括对矢量图形、位图以及动画的支持。在本示例中...

    VC中GDI方法在Picture控件中显示PNG、bmp、jpg图片

    在VC++开发环境中,使用GDI(Graphics Device Interface)来在Picture控件中显示PNG、BMP、JPG等图片是一项常见的任务。GDI是Windows操作系统内核的一部分,提供了丰富的图形绘制功能。以下是对这个主题的详细阐述:...

    vc6下gdi打开png文件的设置

    在VC6环境下,使用GDI(Graphics Device Interface)来打开PNG文件并不是一件直截了当的事情,因为GDI原生并不支持PNG这种现代的、基于压缩的图像格式。PNG(Portable Network Graphics)文件通常需要像libpng这样的...

    vc mtc GDI+ 双缓存画图板

    在VC++编程环境中,"vc mtc GDI+ 双缓存画图板"是一个涉及到图形用户界面(GUI)开发的技术点。这个标题暗示我们将会讨论如何使用Microsoft的多线程类库(MTL,Multithreaded Apartment)以及GDI+图形库来实现一个双...

    VC-GDI泄漏查找工具.

    **VC-GDI泄漏查找工具详解** 在Windows操作系统中,GDI(Graphics Device Interface)是图形设备接口,它为应用程序提供了一种与硬件无关的方式来进行图形处理。然而,不当的GDI资源管理可能导致GDI资源泄漏,进而...

    VC GDI+绘制渐灭的文字

    GDI+绘制文字使用Graphics::DrawString函数,其中的brush参数可以使用透明度,通过控制该透明度(逐渐减少从而增加透明度),实现文字的透明度逐渐增加,最终融入到背景中,达到渐变消失的效果。具体实现上,设置...

    VC 用GDI与PNG图片实现半透明桌面时钟

    在Windows编程领域,Visual C++(简称VC)是一款强大的开发工具,它允许程序员利用Microsoft的图形设备接口(GDI)来创建丰富的用户界面。在这个特定的项目中,“VC用GDI与PNG图片实现半透明桌面时钟”,我们将探讨...

    vc 画线 GDI

    当我们需要在应用程序中实现动态画线,比如模拟“橡皮筋”效果,即用户在画布上拖动鼠标时能实时看到线条的变化,GDI是常用的技术之一。本篇将详细介绍如何使用VC++和GDI来实现这种画线功能,特别是橡皮筋画直线的...

    使用vc和gdi+开发图形界面

    在本文中,我们将深入探讨如何使用Visual C++ 6(简称VC6)和GDI+技术来开发图形用户界面(GUI)。GDI+是Windows API的一个扩展,它为开发者提供了更强大、更灵活的图形绘制功能,使得创建美观且功能丰富的用户界面...

    VC调用GDI显示不同类型的图片

    在Windows编程领域,Visual C++(简称VC)是一种常用的开发工具,它允许程序员利用Microsoft的图形设备接口(GDI)来实现丰富的图形绘制和显示功能。本篇文章将深入探讨如何在VC项目中调用GDI来显示不同类型的图片,...

Global site tag (gtag.js) - Google Analytics