
绘图时使某一个颜色值透明 此示例是过滤纯白颜色
Private Declare Function GdiTransparentBlt Lib "gdi32" (ByVal hdc1 As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal W1 As Long, ByVal H1 As Long, ByVal Hdc2 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal W2 As Long, ByVal H2 As Long, ByVal Color As Long) As Long
Private Sub Command1_Click()
GdiTransparentBlt MehDC, 0, 0, Picture1ScaleWidth, Picture1ScaleHeight, _
Picture1hDC, 0, 0, Picture1ScaleWidth, Picture1ScaleHeight, RGB(255, 255, 255)
MeRefresh
End Sub
Private Sub Form_Load()
MeAutoRedraw = True
MeScaleMode = 3
Picture1AutoRedraw = True
Picture1ScaleMode = 3
End Sub
SelectObject的作用是将指定GDI对象选定进入指定的DC,并作为其绘画时使用的当前对象。
请仔细看下面这段话:
确保释放DC的时候DC中的各gdi对象都不是你自己创建的!!!!确保个gdi对象在释放的时候不被任何dc选中使用!!!!
假如我们要使用gdi函数画图,正确的步骤应该如下:
a创建一个内存兼容dc(CreateCompatibleDC)
b创建一个内存兼容bitmap(CreateCompatibleBitmap)
c关联创建的内存兼容dc和bitmap(SelectObject)
d画图
eBitBlt到目的dc上
f断开内存兼容dc和bitmap关联(SelectObject)
g销毁内存兼容bitmap
h销毁内存兼容dc
由于SelectObject在选入一个新的gdi对象的时候会返回一个原来的gdi对象(假如成功的话),所以需要在步骤c的时候保存返回值,在步骤f的时候当作入口参数使用还有,步骤g和步骤h实际上顺序可以随意,因为他们两个此刻已经没有关系了,但是为了结构清晰,我建议按照 "先Create的后释放,后Create的先释放 "的原则进行
关于步骤f,可能会有争议,因为即使省略这一步,步骤g和步骤h看起来照样可以返回一个成功的值但实际上可能并没有执行成功,至少boundschecker会报告有错,错误信息大致是说,在释放dc的时候还包含有非默认的gdi对象,在释放gdi对象的时候又说这个gdi对象还被一个dc在使用所以,我建议保留步骤f
WINDOWS图像编程
--------------------------------------------------------------------------------
图形设备接口(GDI,Graphics Device Interface)的主要目标之一是支持在输出设备(如视频显示器、打印机和绘图仪)上的与设备无关的图形。 GDI通过将应用程序与不同输出设备特性相隔离,使Windows应用程序能够毫无问题地在Windows支持的任何图形输出设备上运行。
Windows中的图形基本上是由从GDI.EXE模块中输出的函数处理的(尽管一些绘制函数实际上具有USER.EXE的入口点),GDI.EXE模块调用在不同驱动程序文件中的例程,其中有一个.DRV驱动程序文件用于控制显示屏幕,并且可能有一个或多个其他的.DRV驱动程序文件用来控制打印机或绘图仪。
Windows GDI使用两种坐标系统。使用虚拟坐标系统可以使程序不依赖于具体的硬件,使用设备坐标系统可以使程序和硬件紧密相联。
GDI含有在Windows应用程序内部执行、且与设备无关的图形 *** 作函数,这些函数可产生各种各样的线、正文和位图,它们可以输出到许多不同的输出设备上。GDI允许一个应用程序产生笔、刷子、字体和位图,以供特定的输出 *** 作使用。下面列出GDI中几组比较常用的函数:
·设备上下文函数
·椭圆和多边形函数
·绘图工具函数
·位图函数
·绘图属性函数
·正文函救
·映射函数。
·坐标函数
·元文件(metafile)函数
·区域函数
·裁剪(clipping)函数·
窗口应用程序输出图形的 *** 作步骤如下:
①取得指定窗口的当前显示设备上下丈,显示设备上下文实际上是一个数据结构,它包括该窗口的参数及各种图形、文字属性的现行设定值,它们对以后的图形、文字输 出命令起控制作用。
②选择用户坐标系及映射方式。
③设定用户坐标系中的观察窗口和设备坐标系中的显示视区。
④输出图形、文字和图象。
⑤释放所使用的显示设备上下文。
当想要在图形输出设备(例如屏幕或打印机)上绘制图形时,必须首先获得设备上下文的句柄。先给出这个句柄,Windows才允许程序使用设备,在GDI函数中将句柄作为一个参数传入,向Windows标明需要使用的设备。
设备上下文中包含许多属性,当GDI在不同的设备上工作时都要用到这些属性。使用这些属性可使GDI只关心起始和终止坐标的大小,而不必关心有关对象的其他属性,如颜色、背景等等,因为这些都是设备上下文的一部分。当需要修改这些属性时,只需调用一个修改设备上下文中属性的参数,以后的程序中都使用修改后的设备上下文属性。设备上下文是连接Windows应用程序、设备驱动程序以及输出设备的纽带。
获取设备上下文句柄有多种方法。最一般的方法是当处理一条消息时获得了设备上下文、并在退出窗口之前释放它。一般的处理方法如下:
在处理WM_PAINT消息时
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps)
EndPaint (hwnd,&ps);
其数据结构为:
HDC hWnd;
PAINTSTRUCT ps;
而在windows.h中定义了PAINTSTRUCT的数据结构。
type struct tagPAINTSTRUCT {
HDC hdC;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL flncUpdate;
BYTE rgbReserved[16];
}PAINTSTRUCT;
其中,hdc用于标识显式上下文,fErase指出背景是否重画,rcPaint是涂色矩形,其余的域均为保留。这里的hdc是BeginPaint返回的设备上下文句柄,有了从DeginPaint获取的设备上下文句柄,就可以也只能在ps指出的rcPaint的矩形内绘图,EndPaint调用使这一区域有效。
第二种方法如下所示,使用这种方法获取和释放设备上下文可以在整个用户区内画图,图形在整个用户区域内都有效:
hdC=GetDc (hwnd );
…画图 *** 作…
ReleaseDC (hwnd , hdc );
使用下面第三种方法获取和释放设备上下文,可以在整个窗口内画图,图形在整个窗口内有效:
hdC=GetWindowDc(hwnd);
…画图 *** 作…
ReleaseDc(hwnd,hdc);
使用下面第四种方法获取和释放设备上下文,可以在整个显示器区域内画图,图形在整个显示器区域内部有效:
hdc=CreateDC (lpszDriver ,lpszDevice ,lpszOutput , lpData);
…画图 *** 作…
ReleaseDC(hdc);
其中lpszDriver指向设备驱动程序的DOS文件名(不带扩展名),lpszDevice指向专用设备名(例如Epson Fx-80),lpszOutput指向物理输出介质(文件或输出端口)的DOS文件名或设备名,lpData指向含有设备驱动程序的设备专用的初始化数据的DEVMODE数据结构。例如:
hdc=CreateDC("DISPLAY",NULL,NULL,NULL);
使用屏幕画图,而:
hdc= CreateDC ("IBMGRX","IBM Graphics","LPT1",NULL );
在打印机上输出图形,这里的lpData置为默认值,可以在WIN.INI中找到初始化值。
如果不需要获取设备上下文,即不需要在设备上下文中 *** 作,只需了解有关设备上下文的信息,可以用如下语句:
hdcInfo = CreateDC (lpszDriver, lpszDevice,lpszOutput, lpData );
……
DeteteDC (hdcInfo);
另外,还可以使用设备上下文来对位图的内存进行控制,如下所示:
hdcMem = CreateCompatibleDC (hdc)
OeleteDc(hdcMem );
一个元文件是以二进制形式编码的GDI调用集合,可通过获取一个元文件设备上下文来建立一个文件:
hdcMeta=CreateMetaFile(lpszFilename);
……
hmf=CloseMetaFile(hdCMeta);
在元文件设备上下文有效期间,使用hdcMeta所进行的任何GDI调用都成为元文件的一部分,当调用CloseMetaFile时,设备上下文句柄变化无效,函数返回元文件(hmf)的句柄。
一个设备上下文通常涉及物理设备,如视频显示器、打印机等,所以需要获取有关该设备的信息,如显示器大小和彩色能力等。可以通过调用GetDeviceCaps函数来获取这样的信息:
nValue=GetDeviceCaps (hdc,nIndex);
这里的hdc标识设备上下文,nIndex确定返回值,它可以是window.h中所定义的28个标识符中的一个,例如nIndex=DRIVEVERSION,则该函数返回的是版本号。
真正影响在用户区域上绘制过程的设备上下文属性是“映射方式”,与映射方式属性密切相关的还有如下四个设备上下义属性:窗口原点、视窗原点、窗口范围和视窗范围。
Windows定义了八种映射方式,即:
这里的TWIP指的是1/1440英寸,in.代表英寸。
可以调用函数setMapMode(hdc,MapMode)来设置这八种映射方式中的一种。hdc用来标识设备上下文,nMapMode可以取MM_TEXT、MM_LOMETRIC、MM_HIMETRIC等八个值中的一个。在设置了映射方式之后,到下一次设置映射方式之前,Windows一直使用这种映射方式。如果想要获取当前的映射方式,可用:
nMapMode= GetMapMode (hdc)
在设置了映射方式之后,就规定了逻辑单位的大小和增量的方式,在GDI画图函数中,可以不必考虑这些内容而直接使用逻辑数字,如:
SetMapMode(hdc ,MM_TEXT);
TextOut(hdc,8 ,16,szBuffer ,nLength)
即正文从用户区域左起第八个象素,顶边起第16个象素的位置开始写 *** 作。不管映射方式如何,Windows函数中所有坐标规定为-32768 到 32767之间的带符号短整救。
注意映射方式只是一个设备上下文属性,因此映射方式唯一起作用的是将映射方式作为设备上下文句柄属性,而将该句柄当作参数的GDI函数,因此象GetSystemMetrics这样的非GDI函数,将继续以设备单位(象素值)返回尺寸值。
用GDI的SetPixel函数可以绘制一特定颜色的象素:
rgbActualColor =SetPixel (hdc,x,y,rgbColor);
这里hdc标识设备上下文,x ,y表示点坐标,rgbColor为一无符号的长整数,其结构为:
COLORREF rgbColor;
其中低位字节为红基色的相对亮度值,第二个字节包含绿基色的相对亮度值,第三个字节包含蓝基色的相对亮度值,高位字节必须为零。可以使用RGB函数来获取rgbColor。
rgbColor =RGB(byRed ,byGreen,byBlue);
这里的byRed、byGreen、byBlue取值范围为0~255,分别代表红色、绿色、蓝色的亮度。给出正确的参数之后,SetPixel返回的是调色板中最靠近所需彩色的颜色。还可以使用如下方法来取得一个特定象素的颜色:
rgbCotor= GetPixel(hdc,x,y);
画线函数主要有三种, LineTo、Polyline 和 Arc。还有五个设备上下文属性会影响这些函数画出的线的外观:笔的当前位置(仅对LineTo有影响)、笔、背景方式(对非实心笔有影响)、背景颜色(对 OPAQUE背景方式)以及绘制方式。
在这些设备上下文的属性中,笔的当前位置影响画线的起点,笔影响线的粗细等形状,背景方式影响非实心笔画出的线的模板图形,背景颜色影响线模板背景色,绘制方式影响实心线、虚线等线属性。
以下是典型的画线 *** 作步骤:
MoveTo(hdc,xStart,yStart);
LineTo(hdc ,xEnd ,yEnd);
上面两句画出一条从(xStart,yStart)到(xEnd,yEnd)的直线。
可以使用语句:
dwPoint = GetCurrentPosition (hdc);
获得笔的当前位置。这里,dwPoint返回值是一个无符号长整数(或双倍长字),其中低位字含有X坐标,高位字含有Y坐标。
可以使用MAKEPOINT函数将dwPoint转换为POINT结构;
point = MAKEPOINT (dwPoint);
point的类型为POINT:
typedef struct togPOINT {kk1}
int x;
int y;
}POINT;
Polyline用于绘制折线,例:
Polyline(hdc,&pt,5)
将数组pt中的5个点之间用线段相连。
Arc用于画椭圆的周边:
Arc (hdc,xLeft,yTop,xRight,yBottom,xStart,yStart,XEnd,yEnd );
画出的椭圆以左上角为(xLeft,yTop),右下角为(xRight,yBottom)的矩形为界,圆弧开始于椭圆和(xStart,yStart)与椭圆中心的连线的交点处,沿着椭圆周边的过时针方向绘制,并终止于椭圆和(xEnd,yEnd)与椭圆中小的连线的交点处。
当调用LineTo、Polyline和Arc时,Windows使用当前在设备上下文中选择的笔来画线,笔决定了线的颜色、密度和型式,而线型可以是实线、点线或短划(虚)线,缺省设备上下文中的笔叫做BLACK_PEN,不管映射方式如何选支笔以一个象素的宽度画黑色的实线, BLACK_PEN是Windows提供的三支“备用笔”之一,其他两支是WHITE_PEN和NULL_PEN,NULL_PEN是一支什么都不画的空笔,当然用户也可以自己建立定制的笔。
可以通过一个句柄来引用所需的笔:
HPEN hPen;
hPen =GetStockObject(WHITE_PEN);
SelectObjeCt (hdc ,hPen) ;
SelectObject (hdc , hBrush ) ;
将逻辑刷送入设备上下文中。如果使用结束,可以用:
DeletObject (hBrush ) ;
删除一把已建立的刷子,如果在程序中需要获取有关于刷子的信息,则可以调用:
3.像素格式结构
每个OpenGL显示设备都支持一种指定的像素格式。一般用一个名为PIXELFORMATDESCRIPTOR的结构来表示某个特殊的像素格式,这个结构包含26个属性信息。Win32定义PIXELFORMATDESCRIPTOR如下所示:
typedef struct tagPIXELFORMATDESCRIPTOR
{ kk1}
// pfd
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
DWORD dwLayerMask;
DWORD dwVisibleMask;
DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR;
4.初始化PIXELFORMATDESCRIPTOR结构
PIXELFORMATDESCRIPTOR中每个变量值的具体含义和设置可以参考有关资料,下面举出一个PIXELFORMATDESCRIPTOR初始化例子来简要说明相关变量的意义。定义PIXELFORMATDESCRIPTOR结构的pfd如下:
PIXELFORMATDESCRIPTOR pfd = { kk1}
sizeof(PIXELFORMATDESCRIPTOR), //size of this pfd 1
PFD_DRAW_TO_WINDOW| // support window
PFD_SUPPORT_OPENGL| // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0,0,0,0,0,0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buff
0,0,0,0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0,0,0 // layer masks ignored
};
在这个结构里,前两个变量的含义十分明显。第三个变量dwFlags的值是
PFD_DRAW_TO_WINDOW |PFD_SUPPORT_OPENGL ,
表明应用程序使用OpenGL函数来绘制窗口
第四个:
PFD_DOUBLEBUFFER,
表明当前采用RGBA颜色模式,第五个采用24位真彩色,既1.67千万种颜色,如果是256色系统则自动实现颜色抖动;因为没有使用alpha缓存和累计缓存,所以从变量cAlphaBits到cAccumAlphaBits都设置为0;深度缓存设置为32位,这个缓存能解决三维场景的消隐问题;变量cAuxBuffers设置为0,在Windows 95下不支持辅助缓存;Windows 95下针对OpenGL变量ilayerType只能设置为PFD_MAIN_PLANE,但在其它平台也许支持PFD_MAIN_PLANE或PFD_MAIN_UNDERLAYPLANE;接下来bReserved变量只能设为0,而最后三个变量Windows 95都不支持,故全设置为0。
对于各种各样应用日益广泛的嵌入式系统而言,除了应用功能强大外,人机界面的美观也是吸引用户的重要方面。因此,越来越多的嵌入式系统开发人员希望:LCD上除了显示图案固定的菜单以外,再添加适量的动画,使得整个界面屏幕更加活泼可人。用于动画设计的程序设计语言有多种,并且有多种方法,根据是否需要借助于其他应用软件和程序,可以将这些方法分成两大类:第一类是只使用各种编程语言及开发环境中包含的文件和框架实现的设计方法;第二类则是安装相关软件(诸如Flash、Di-rectDraw等),在相关语言的开发环境中将这些软件的功能文件包含进去,来共同实现动画设计的方法。而嵌入式系统由于其极强的专用性、实时性要求,传统采用的开发语言并不是很多,虽然动画界面在嵌入式系统应用中并非高优先级的程序,但开发人员在选取其设计方法时,也应该辨明利弊,灵活使用,这样才能看到更加赏心悦目的界面,而不是被LCD上凌乱不堪的显示内容所困扰。
1不需安装第三方软件的动画设计方法分析
(1)Logo适用于简易的嵌入式设备的动画设计
Logo语言的设计方法最为简单。它内置一套(TurtleGraphics)系统,其本身就是一种绘画语言,理论上可以加载到嵌入式系统中作动画开发;然而,因为一个嵌入式系统会有很多别的软件设计部分,其他功能都采用Logo显然并不合适,而要在一个嵌入式系统中安装两种开发环境更加不现实。所以,若在嵌入式系统开发中选用这种方法制作动画,应该只适合用于儿童用的复杂程度同等的简易的嵌入式设备。
(2)最适合嵌入式系统使用的擦除法
C语言是嵌入式系统开发使用最多的语言,并且高中低档的系统都可以用,因而采用C语言的所有动画设计方法,理论上均适用于嵌入式系统的屏幕动画开发。然而,诸如利用动态开辟图视口方法、利用显示页和编辑页交替变化、利用画面存储再重放的方法,以及直接对图像动态存储器进行 *** 作的方法等程序比较复杂,且要对图像不断进行存取 *** 作,这需要耗费大量内存资源;而擦除法动画设计则可以解决上述问题。其设计原理是:利用同色原理,当图形色与背景色相同时人眼不能感知。在动画设计中,当在一个位置画了一张图像时,使图像色与背景色相异,然后再到另一个位置画一张图像并使图像色与背景色也相异,此时将先画的图像在原位置再画一张,并使图像色与背景色相同,这样人眼只能看到新画的一张图像而看不到先前画的图像,从而先前画的图像感觉被擦除了。
这样连续画多张图像并在每画一张新的图像时将原来的图像擦除,从而在观察者看来就实现了动画的效果。综上所述,从耗费资源较少且执行速度较快的角度出发,笔者认为,采用C语言设计动画的常用方法中,最适合嵌入式系统使用的是首选擦除法。
(3)CBuilder语言本身不太适合嵌入式开发
采用CBuilder语言设计动画,可以方便地利用现成的组件产生图像及控制时间,从而解决了动画设计中两个非常重要的问题。然而CBuilder语言本身不太适合嵌入式开发,因为嵌入式开发对空间、效率都要求较高,而CB是针对高层的应用程序开发的工具。但是,有两点值得注意:首先,现在很多公司做嵌入式开发多是自己搞一套系统,使其适合使用CB完全可以做到;另外,Borland公司正在开发嵌入式的C,可以期待。
(4)Java语言非常适合嵌入式系统的屏幕动画设计Java语言是嵌入式系统开发经常采用的语言,在手机中更是应用良多。Java语言的动画设计方法通过定义线程的方法来控制动画时间;而使图像动的平滑的双缓冲方法需要很大内存,因而更常用的消除画面闪烁的办法是重载upGlate()。
(5)C语言方法均可用于嵌入式系统动画设计
面向对象的C语言中,可供选择的动画设计方法很多:简单的动态图像(如不断闪烁的星星)可以采用底色覆盖法;在屏幕的固定位置显示动态图像时,可以选择多切换法;利用异或方式进行绘图不会发生全屏幕闪动,通常效果较好,但若反复使用,在所清除图像处会产生闪烁,仍不是很完美;像素 *** 作一般和其他动态图像实现方法(如底色覆盖)相结合使用;多缓冲技术是将图形绘制在不同的帧中,通过将屏幕在这些不同的帧之间进行切换,来达到动画效果;具体的帧数目可以根据实际动画的需要自行确定。这类似于C语言中的双缓冲技术原理,只不过双缓冲只绘制一份备用图像作为离屏图像,而多缓冲则将图形绘制在多个不同帧中,将屏幕在这些帧之间进行切换。
因为工业方面大多用C/C作为嵌入式系统的开发语言,所以这些方法都可用于嵌入式系统动画设计。在Nord-TecSoftWare开发的Nord-TecSnowFlakes屏幕保护程序中,逼真的雪花动画便是利用多缓冲技术实现的。
(6)绘制复杂风格线条的方法
在GIS(地理信息系统)类软件设计中,经常需要在绘图时使用一些相对固定但又频繁使用的一些用以代表地理状态的符号,如河流、铁路、海岸线等等。显然,这些基本符号图形一般都是相对复杂的线条,在MFC提供的基本类库中并未提供可以直接使用的相关函数;即使是在绘图功能比较强大的CDC中,也仅仅提供了LineTo()、Set-Pixel()等一些通用的最基本的绘图函数。使用这些函数来绘制GIS基本符号是效率比较低的一种办法,这在大量的绘图 *** 作中将会表现得比较明显,因此不宜提倡。但是,可以通过WindowsNT3.1中首次出现的Win32.API函数LineDDA,来解决这一绘制复杂风格线条的问题。
(7)使用VC实现高速平滑的简单动画的方法
许多软件(特别是游戏软件)的开发中,实现高速平滑的动画需要比较深的技术,如OpenGL、DirectX,并且可能还要开发人员有深厚的数学功底。但是,如果只是在开发嵌入式系统过程中,想为应用程序的界面实现一些动画效果,就可能不用以上这些技术了,更多的是用WindowsAPI提供或MFC封装后的GDI绘图函数来实现。虽然所需动画的复杂程度不高,但作为开发人员,并不能为此就降低对动画效果的要求。因此,需要了解如何用GDI函数来开发平滑无闪、高速的动画。
该技术的关键就是在内存中创建一个与显示动画的窗口区域一样大的位图,先用GDI函数绘制位图,然后在适当的时候从内存中显示出来。因为位图已经绘制好,不象平时编程那样边绘制边显示,所以,显示一帧图形时便减少了闪烁,从而实现平滑动画;同时,由于图形是从内存中直接显示到当前窗体的,所以速度很快,从而实现高速动画。如果再创建一个线程后台绘制图形,将会实现很多特殊效果的动画,使嵌入式系统的用户界面收到意想不到的效果。
在此基础上,还可以在显示位图时作优化显示。例如:不是将位图全部显示出来,而是显示其中动画的一部分,因为BitBlt函数作位传输很慢。这样更符合嵌入式系统重视效率的特点。
2需要安装第三方软件的动画设计方法分析
(1)为教学研究开发的嵌入式设备可使用Ubigraph
graphviz和Ubigraph都是图论生成软件,但Ubig-raph功能更强,利用它可以快速生成图论模型的图形和动态图像,直观地展示出各种图论模型的三维结构,演示各种图论算法的过程。因为可以嵌入到Java、C、C等语言中,所以当然适合用于嵌入式系统的动画设计,尤其是一些专门为教学研究开发的嵌入式设备。
(2)Flash对嵌入式系统而言太过华丽
Flash是一种功能强大的矢量动画软件,但是所用到的高级技术比较多,不过为了能够做出精美的**特技效果的动画,还是值得对其进行深入研究的。然而,对于嵌入式系统开发而言,它实在是太过华丽了;如果不是特别需要突出游戏或者动画的精致效果,一般开发者应该不会舍本逐末以此来牺牲系统的速度和容量。
(3)DirectDraw方法对嵌入式系统的适用度
DirectDraw使用页面切换的方法实现图像动态。它不仅可以访问系统内存,还可以访问显示内存,实现图像动态的同时不会使得画面闪烁,是一种“完美切换”技术;因此DirectDraw技术很受程序员青睐,尤其在虚拟现实技术中应用广泛。但是,显而易见,该方法需要占用很大内存,安装所需的开发文件同样需要较大硬盘空间,应用到一般的嵌入式系统中,对反应速度等的限制将会比较明显。
其实,用DirectDraw编程的核心要点即“几个表面之间拷来拷去”。在对界面的动画复杂程度要求不高的嵌入式系统中,可以采用C程序作为开发语言,并且在动画实现方法上,利用前述C程序设计中显示页和编辑页交替变化的方法,来代替几个表面交替拷贝的DirectDraw方法。然而,如果是大型的嵌入式系统,并且重视界面动画效果,采用DirectDraw方法和面向对象开发语言,仍然是更好的选择。
当然,若对美术工艺有特殊要求,可以尝试将更专业的技术(如颜色锁结及用于3D效果的Z排序与视差)引入到嵌入式系统软件设计中——这种系统本身也应该是专业的、功能专用的,否则只能停留在理论上,难以实现!
3可用于嵌入式系统开发的脚本语言
当动画应用于网络时,可以选择直接使用脚本语言设计,譬如JSP、PHP等。当今的很多嵌入式系统都有连接网络的需求和相应功能,虽然大多数系统的屏幕动画都不涉及对外发布的问题,但在联网嵌入式系统的开发中直接使用脚本语言编写动画,也不啻为一个新的思路。
Python可作为嵌入式系统的开发语言(在Nokia智能手机所采用的Symbian *** 作系统上已得到证明)。它最大的优势是能够很轻松地把使用其他语言制作的各种模块(尤其是C/C)轻松地联结在一起。由此,既可以直接使用Py-thon编写简单的界面动画,也可以将对速度要求更高的复杂动画使用C语言编写后嵌入到Python程序中。
CurvePointF1[k2 - (ConvertToInt32(MathFloor(a)) + 1)] = new PointF((float)(cPtX + 45 + k2), (float)(cPtY - s2));
这句中的
k2 - (ConvertToInt32(MathFloor(a)) + 1)值超出CurvePointF1定义的范围了
MainFrame是框架窗口因此它是无效的窗口,你应该先让窗口有效,才可画图。AfxGetMainWnd()->ValidateRect(CRect(0,0,1000,1000));
图形和图像函数包含在graphicsh里面
(一) 像素函数
56 putpiel() 画像素点函数
57 getpixel()返回像素色函数
(二) 直线和线型函数
58 line() 画线函数
59 lineto() 画线函数
60 linerel() 相对画线函数
61 setlinestyle() 设置线型函数
62 getlinesettings() 获取线型设置函数
63 setwritemode() 设置画线模式函数
(三)、多边形函数
64 rectangle() 画矩形函数
65 bar() 画条函数
66 bar3d() 画条块函数
67 drawpoly() 画多边形函数
(四)、 圆、弧和曲线函数
68 getaspectratio()获取纵横比函数
69 circle()画圆函数
70 arc() 画圆弧函数
71 ellipse()画椭圆弧函数
72 fillellipse() 画椭圆区函数
73 pieslice() 画扇区函数
74 sector() 画椭圆扇区函数
75 getarccoords()获取圆弧坐标函数
(五)、 填充函数
76 setfillstyle() 设置填充图样和颜色函数
77 setfillpattern() 设置用户图样函数
78 floodfill() 填充闭域函数
79 fillpoly() 填充多边形函数
80 getfillsettings() 获取填充设置函数
81 getfillpattern() 获取用户图样设置函数
(六)、图像函数
82 imagesize() 图像存储大小函数
83 getimage() 保存图像函数
84 putimage() 输出图像函数
四、图形和图像函数
对许多图形应用程序,直线和曲线是非常有用的。但对有些图形只能靠 *** 作单个像素才能画出。当然如果没有画像素的功能,就无法 *** 作直线和曲线的函数。而且通过大规模使用像素功能,整个图形就可以保存、写、擦除和与屏幕上的原有图形进行叠加。
(一) 像素函数
56 putpixel() 画像素点函数
功能: 函数putpixel() 在图形模式下屏幕上画一个像素点。
用法: 函数调用方式为void putpixel(int x,int y,int color);
说明: 参数x,y为像素点的坐标,color是该像素点的颜色,它可以是颜色符号名,也可以是整型色彩值。
此函数相应的头文件是graphicsh
返回值: 无
例: 在屏幕上(6,8)处画一个红色像素点:
putpixel(6,8,RED);
57 getpixel()返回像素色函数
功能: 函数getpixel()返回像素点颜色值。
用法: 该函数调用方式为int getpixel(int x,int y);
说明: 参数x,y为像素点坐标。
函数的返回值可以不反映实际彩色值,这取决于调色板的设置情况(参见setpalette()函数)。
这个函数相应的头文件为graphicsh
返回值: 返回一个像素点色彩值。
例: 把屏幕上(8,6)点的像素颜色值赋给变量color。
color=getpixel(8,6);
(二) 直线和线型函数
有三个画直线的函数,即line(),lineto(),linerel()。这些直线使用整型坐标,并相对于当前图形视口,但不一定受视口限制,如果视口裁剪标志clip为真,那么直线将受到视口边缘截断;如果clip为假,即使终点坐标或新的当前位置在图形视口或屏幕极限之外,直线截断到屏幕极限。
有两种线宽及几种线型可供选择,也可以自己定义线图样。下面分别介绍直线和线型函数。
58 line() 画线函数
功能: 函数line()使用当前绘图色、线型及线宽,在给定的两点间画一直线。
用法: 该函数调用方式为void line(int startx,int starty,int endx,int endy);
说明: 参数startx,starty为起点坐标,endx,endy为终点坐标,函数调用前后,图形状态下屏幕光标(一般不可见)当前位置不改变。
此函数相应的头文件为graphicsh
返回值: 无
例: 见函数60linerel()中的实例。
59 lineto() 画线函数
功能: 函数lineto()使用当前绘图色、线型及线宽,从当前位置画一直线到指定位置。
用法: 此函数调用方式为void lineto(int x,int y);
说明: 参数x,y为指定点的坐标,函数调用后,当前位置改变到指定点(x,y)。
该函数对应的头文件为graphicsh
返回值: 无
例: 见函数60linerel()中的实例。
60linerel() 相对画线函数
功能: 函数linerel() 使用当前绘图色、线型及线宽,从当前位置开始,按指定的水平和垂直偏移距离画一直线。
用法: 这个函数调用方式为void linerel(int dx,int dy);
说明: 参数dx,dy分别是水平偏移距离和垂直偏移距离。
函数调用后,当前位置变为增加偏移距离后的位置,例如,原来的位置是(8,6),调用函数linerel(10,18)后,当前位置为(18,24)。
返回值:无
例: 下面的程序为画线函数调用实例:
#i nclude<graphicsh>
void main()
{
int driver,mode;
driver=DETECT;
mode=0;
initgraph(&driver,&mode,"");
setcolor(15);
line(66,66,88,88);
lineto(100,100);
linerel(36,64);
getch();
restorecrtmode();
}
61 setlinestyle() 设置线型函数
功能: setlinestyle() 为画线函数设置当前线型,包括线型、线图样和线宽。
用法: setlinestyle() 函数调用方式为void setlinestyle(int stly,unsigned pattern,int width);
说明: 参数style为线型取值,也可以用相应名称表示,如表1-10中所示。
参数pattern用于自定义线图样,它是16位(bit)字,只有当style=USERBIT_LINE(值为1)时,pattern的值才有意义,使用用户自定义线图样,与图样中“1”位对应的像素显示,因此,pattern=0xFFFF,则画实线;pattern=0x9999,则画每隔两个像素交替显示的虚线,如果要画长虚线,那么pattern的值可为0xFF00和0xF00F,当style不为USERBIT_LINE值时,虽然pattern的值不起作用,但扔须为它提供一个值,一般取为0。
参数wigth用来设定线宽,其取值见表1-11,表中给出了两个值,即1和3,实际上,线宽取值为2也是可以接受的。
若用非法参数调用setlinestyle()函数,那么graphresult()会返回错误代码,并且当前线型继续有效。
Turbo C提供的线型与线宽定义在头文件graphicsh中,表1-10和1-11分别列出了参数的取值与含义。
表1-10 线型
-----------------------------------------------------
名 称 取 值 含 义
-----------------------------------------------------
SOLID_LINE 0 实线
DOTTED_LINE 1 点线
CNTER_LINE 2 中心线
DASHED_LINE 3 虚线
USERBIT_LINE 4 用户自定义线型
-----------------------------------------------------
表1-11 线宽
-----------------------------------------------------------
名 称 取 值 说 明
-----------------------------------------------------------
NORM_WIDTH(常宽) 1 一个像素宽(缺省值)
THICK_WIDTH(加宽) 3 三个像素宽
-----------------------------------------------------------
这个函数的头文件是graphicsh
返回值: 无
例: 下面的程序显示了BC中所提供的线型图样:
#i nclude<graphicsh>
void main()
{
int driver,mode;
driver=DETECT;
mode=0;
initgraph(&driver,&mode,"");
for(i=0;i<4;i++)
{
setlinestyle(i,0,1);
line(i50,200,i50+60,200)
}
getch();
restorecrtmode();
}
62 getlinesettings() 获取线型设置函数
功能: 函数getlinesettings() 用当前设置的线型、线图样和线宽填 写linesettingstype型结构。
用法: 函数调用方式为void getlinesettings(struct linesettingstype info);
说明: 此函数调用执行后,当前的线型、线图样和线宽值被装入info指向的结构里,从而可从该结构中获得线型设置。
linesettingstype型结构定义如下:
struct linesettingstype {
int linestyle;
unsigned upattern;
int thickness;
};
其中linestyle用于存放线型,线型值为表1-10中的各值之一。
upattern用为装入用户自定义线图样,这是16位字,每一位等于一个像素,如果哪个位被设置,那么该像素打开,否则关闭。
thickness为线宽值存放的变量,可参见表1-11。
getlinesettings()函数对应的头文件为graphicsh
返回值: 返回的线型设置存放在info指向的结构中。
例: 把当前线型的设置写入info结构:
struct linesettingstype info;
getlinesettings(&info);
63setwritemode() 设置画线模式函数
功能: 函数setwritemode() 设置画线模式
用法: 函数调用方式为 void setwritemode()(int mode);
说明: 参数mode只有两个取值0和1,若mode为0,则新画的线将复盖屏幕上原有的图形,此为缺省画线输出模式。如果mode为1,那么新画的像素点与原有图形的像素点先进行异或(XOR)运算,然后输出到屏幕上,使用这种画线输出模式,第二次画同一图形时,将擦除该图形。调用setwritemode()设置的画线输出模式只影响函数line(),lineto(),linerel(),recangle()和drawpoly()。
setwritemode()函数对应的头文件是graphicsh
返回值: 无
例: 设置画线输出模式为0:
setwritemode(0);
(三)、多边形函数
对多边形,无疑可用画直线函数来画出它,但直接提供画多边形的函数会给用户很大方便。最常见的多边形有矩形、矩形块(或称条形)、多边形和多边形块,我们还把长方形条块也放到这里一起考虑,虽然它不是多边形,但它的特例就是矩形(块)。下面直接介绍画多边形的函数。
64 rectangle() 画矩形函数
功能: 函数rectangle() 用当前绘图色、线型及线宽,画一个给定左上角与右下角的矩形(正方形或长方形)。
用法: 此函数调用方式为void rectangle(int left,int top,int right,int bottom);
说明: 参数left,top是左上角点坐标,right,bottom是右下角点坐标。如果有一个以上角点不在当前图形视口内,且裁剪标志clip设置的是真(1),那么调用该函数后,只有在图形视口内的矩形部分才被画出。
这个函数对应的头文件为graphicsh
返回值: 无
例: 下面的程序画一些矩形实例:
#i nclude<graphicsh>
void main()
{
int driver,mode;
driver=DETECT;
mode=0;
initgrpah(&driver,&mode,"");
rectangle(80,80,220,200);
rectangle(140,99,180,300);
rectangle(6,6,88,88);
rectangle(168,72,260,360);
getch();
restorecrtmode();
}
65 bar() 画条函数
功能: 函数bar()用当前填充图样和填充色(注意不是给图色)画出一个指定上左上角与右下角的实心长条形(长方块或正方块),但没有四条边线)。
用法: bar()函数调用方式为void bar(int left,int top,int right,int bottom);
说明: 参数left,topright,bottom分别为左上角坐标与右下角坐标,它们和调用函数rectangle()的情形相同,调用此函数前,可用setfillstyle()或setfillpattern()设置当前填充图样和填充色。
注意此函数只画没有边线的条形,如果要画有边线的的条形,可调用下面的函数bar3d()来画,并将深度参数设为0,同时topflag参数要设置为真,否则该条形无顶边线。
这 应的头文件为graphicsh
返回值: 无
例: 见函数bar3d()中的实例。
66bar3d() 画条块函数
功能: 函数bar3d() 使用当前绘图色、线型及线宽画出三维长方形条块,并用当前填充图样和填 充色填充该三维条块的表面。
用法: 此函数调用方式为void bar3d(int left,int top,int right,int bottom,int depth,int topflag);
说明: 参数left,top,right,bottom分另为左上角与右下角坐标,这与bar()函数中的一样。参数depth为条块的深度,以像素为单位,通常按宽度的四分之一计算。深度方向通过屏显纵横比调节为约45度(即这时x/y比设置为1:1)。
参数topflag相当于一个布尔参数,如果设置为1(真)那么条块上放一顶面;若设置为0(假),则三维条形就没有顶面,这样可使多个三维条形叠加在一起。
要使图形更加美观,可利用函数floodfill()或setfillpattern()来选择填充图样和填充色(参见本小节(五)填充函数 )。
bar3d()函数对应的头文件为graphicsh
返回值: 无
例: 下面的程序画一个条形和条块:
#i nclude<graphicsh>
void main()
{
int driver,mode;
driver=DETECT;
mode=0;
initgraph(&driver,&mode,"");
setfillstyle(SOLID-FILL,GREEN);
bar(60,80,220,160);
setfillstyle(SOLID-FILL,RED);
bar3d(260,180,360,240,20,1);
getch();
restorecrtmode();
}
67 drawpoly() 画多边形函数
功能: 函数drawpoly() 用当前绘图色、线型及线宽,画一个给定若干点所定义的多边形。
用法: 此函数调用方式为void drawpoly(int pnumber,int points);
说明: 参数pnumber为多边形的顶点数;参数points指向整型数组,该数组中是多边形所有顶点(x,y)坐标值,即一系列整数对,x坐标值在前。显然整型数组的维数至少为顶点数的2倍,在定义了多边形所有顶点的数组polypoints时,顶点数目可通过计算sizeof(polypoints)除以2倍的sizeof(int)得到,这里除以2倍的原因是每个顶点有两个整数坐标值。另外有一点要注意,画一个n个顶点的闭合图形,顶点数必须等于n+1,并且最后一点(第n+1)点坐标必须等于第一点的坐标。
drawpoly()函数对应的头文件为grpahicsh
返回值: 无
例: 下面的程序画一个封闭星形图与一个不封闭星形图:
#i nclude<graphicsh>
void main()
{
int driver,mode;
static int polypoints1[18]={100,100,110,120,100,130,120,125,140,140,130,120,
140,110,120,115,100,100};
static int polypoints2[18]={180,100,210,120,200,130,220,125,240,140,230,120,
240,110,220,115,220,110};
driver=DETECT;
mode=0;
initgraph(&driver,&mode,"");
drawpoly(9,polypoints1);
drawpoly(9,polypoints2);
getch();
restorecrtmode();
}
(四)、 圆、弧和曲线函数
在一个屏幕上画得很圆的图形到另一个屏幕上可能被压扁或拉长,这是因为每一种显示卡与之相应的显示模式都有一个纵横比。纵横比是指像素的水平方向大小与垂直方向大小的比值。如VGA显示卡由于偈素基本上是正方形,所以纵横比为1000。
为了保证几何图形基本按预计情况显示在屏幕上,用屏显的纵横比来计算和纠正不同硬件及显示卡产生的畸变。计算纵横比所需要的水平方向和垂直方向的比例系数可调用函数getaspectratio()获得。
68 getaspectratio()获取纵横比函数
功能: 函数getaspectratio()返回x方向和y方向的比例系数,用这两个整型值可计算某一特定屏显的纵横比。
用法: 此函数调用方式为void getaspectratio(int xasp,int yasp);
说明: 参数xasp指向的变量存放返回的x方向比例系数;参数yasp指向的变量存放返回的y方向比例系数。通常y方向比例系数为10 000, x方向比例系数不大于10 000(这是因为大多数屏幕像素高比宽长)。
注意纵横比自动用作下面函数arc(),circle()和pieslice()中的标尺因子,使屏幕上圆或弧正常显示。但用ellipse()函数画椭圆必须调用本函数获取纵横比作为标尺因子,否则不予调整。纵横比可用于其它几何图形,目的是校正和显示图形。
getaspectratio()函数对应的头文件为graphicsh
返回值: 返回x与y方向比例系数分别存放在xasp和yasp所指向的变量中。
例: 下面的程序显示纵横比:
int xasp,yasp;
float aspectratio;
getaspectratio(&xasp,&yasp);
aspectratio=xasp/yasp;
printf("aspect ratio: %f",aspectratio);
69 circle()画圆函数
功能: 函数circle()使用当前绘图色并以实线画一个完整的圆。
用法:该函数调用方式为void circle(int x,int y,int radius);
说明: 参数x,y为圆心坐标,radius为圆半径,用像素个素表示。注意,调用circle()函数画圆时不用当前线型。
不同于ellipse()函数,只用单个半径radius参数调用circle()函数,故屏显纵横比可以自动调节,以产生正确的显示图。
此函数对应的头文件为graphicsh
返回值: 无
例: 画六个同心圆,圆心在(100,100)。
#i nclude<graphicsh>
void main()
{
int driver,mode;
driver=DETECT;
mode=0;
initgraph(&driver,&mode,"");
circle(100,100,10);
circle(100,100,20);
circle(100,100,30);
circle(100,100,40);
circle(100,100,50);
circle(100,100,60);
getch();
restorecrtmode();
}
70 arc() 画圆弧函数
功能: 函数arc()使用当前绘图色并以实线画一圆弧。
用法: 函数调用方式为void arc(int x,int y,int startangle,int endangle,int radius);
说明: 参数x,y为圆心坐标,startangle与endangle分别为起始角与终止角,radius为半径。圆心坐标和半径以像素个数给出,起始角和终止角以度为单位,0度位于右边,90度位于顶部,180度位于左边,底部是270度。同往常一样,360度与0度重合。角度按逆时针方向增加,但并不要求终止角一定比起始角大。例如指定300度和90度分别为起始角和终止角,与指定300度和450度分别为起始角和终止角可画出相同的弧。大于360度可作为参数,它将被化到0度 ̄360度范围里。函数arc()能画封闭圆,只要取起始角为0度,终止角为360度即可。此函数中,屏显纵横比可自动调节。
arc()函数对应的头文件为graphicsh
返回值: 无
例: 以(200,200)为圆心,100为半径,从0度到120度画圆弧:
#i nclude<graphicsh
void main()
{
int driver,mode;
driver=DETECT;
mode=0;
initgraph(&drivwer,&mode,"");
setcolor(WHITE);
arc(200,200,0,120,100);
getch();
restorecrtmode();
}
以上就是关于谁能说说在VB6.0中使用GdiTransparentBlt函数全部的内容,包括:谁能说说在VB6.0中使用GdiTransparentBlt函数、MFC初学,如图,请问这个程序的两处selectobject是做什么用的只用一处可以么谢谢、画点函数等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)