事实上,仅使用SetPixel和GetPixel函数,确实可以绘制几乎所有需要的图形。也可以在这些函数的基础上设计一个简洁好用的结构良好的图形程序系统。唯一的问题是性能。 如果一个函数需要多次调用SetPixel函数,那么它执行起来会非常慢。如果一个图形系统是建立在设备驱动程序的层次上进行画线操作和其他复杂图形操作,它就会有效得多。因为设备驱动程序对完成实际操作的程序代码进行了最优化处理。更不用说一些显卡还包含允许视频硬件直接进行绘图的图形处理器。
本节必须掌握的知识点:
点和直线
第23练:绘制正玄波曲线
第24练:绘制矩形、椭圆和圆角矩形
第25练:绘制贝塞尔曲线
画笔
背景模式和绘图模式
4.3.1 点和直线■像素点绘图函数
在Windows程序中设置像素点需要使用SetPixel和GetPixel函数(虽然很少会用)。
●SetPixel函数是GDI(图形设备接口)中的一个函数,用于在设备上下文(Device Context)中设置指定坐标处的像素颜色。
函数的原型如下:
COLORREF SetPixel(
HDC hdc, //设备上下文句柄,指定了要进行绘制的设备上下文。
int x, //指定要设置像素的横坐标。
int y, //指定要设置像素的纵坐标。
COLORREF color//所设置像素的颜色,使用COLORREF类型表示,可以通过RGB值或
系统定义的颜色常量指定。
);
该函数会将指定坐标处的像素颜色修改为指定的颜色,并返回先前的颜色值(COLORREF类型)。如果函数调用失败,则返回CLR_INVALID。
需要注意的是,SetPixel函数由于每次只能修改一个像素的颜色,所以在大量绘制像素时可能会比较慢,不适合对整个图形进行绘制,或者需要高效绘制的场景。在需要绘制大量像素的情况下,使用 SetPixel 函数效率较低。通常,绘制大规模图像或复杂图形时,更推荐使用其他更高效的方式,如使用位图、图形路径、图形对象等。
如果你需要在设备上下文中进行大规模像素操作,可以考虑使用以下方法之一:
1.使用 BITMAP 和图形对象:可以创建一个位图(Bitmap),利用图形对象进行绘制。首先,创建一个与设备上下文兼容的位图,并使用 SelectObject 函数将其选择到设备上下文中。然后,可以使用位图的绘图函数,如 SetPixel, SetDIBitsToDevice 或者 StretchDIBits来进行绘制。这样可以实现对大量像素的高效操作。我们将在第十四章详细讲述位图。
2.使用缓冲区:可以使用内存缓冲区作为临时存储来进行像素计算和绘制操作,然后将绘制结果一次性地复制到设备上下文中。这种方式可以避免频繁的像素操作,提高绘制效率。
使用 GDI :GDI 是 Windows 提供的一个高级图形库,它提供了更多灵活和高效的图像处理功能。通过使用 GDI ,可以使用其提供的图形对象和方法来进行高效的图像绘制和处理。这些方法可以根据具体的需求按照情况选择,以实现绘制大量像素时的高效操作。
●GetPixel 函数是 Windows GDI 的一部分,用于获取设备上下文(Device Context, DC)中指定坐标点的颜色值。
函数的原型如下:
COLORREF GetPixel(
HDC hdc, //指定设备上下文句柄。
int nXPos,// 指定要检查的点的 X 坐标(水平位置)。
int nYPos //指定要检查的点的 Y 坐标(垂直位置)。
);
返回值:
如果函数调用成功,返回值是该点的COLORREF颜色值,该颜色值包含了 RGB (红绿蓝) 成分。
如果函数调用失败,返回值是 CLR_INVALID。
GetPixel 可以用来读取屏幕上任意点的颜色值或者设备上下文(比如内存DC)中的颜色值。这个功能在图形软件开发中常常用来进行颜色拾取、屏幕取色等操作。然而,由于 GetPixel 需要在调用时进行设备上下文的交互来获取单独的像素信息,频繁使用这一函数可能会影响应用的性能。在处理大量像素点的情况下,通常会采用更复杂但效率较高的方法,比如直接读取位图数据等。
■直线绘图函数
在Windows平台上,可以使用GDI(图形设备接口)函数来进行直线绘图。以下是一些常用的用于绘制直线的GDI函数:
●MoveToEx(移动到指定点):将绘图设备的当前位置移动到指定点。
BOOL MoveToEx(
HDC hdc, // 绘图设备的句柄
int X, // 目标点的X坐标
int Y, // 目标点的Y坐标
LPPOINT lpPoint // 可选参数,用于获取移动前的当前位置
);
函数的返回值为非零表示成功,零表示失败。
当你在画直线或者其他形状的时候,首先使用 MoveToEx 设定起始点,然后使用类似 LineTo 的函数去绘制到目标位置。这样就形成了一次从起始点到结束点的绘制过程。
●LineTo(绘制直线):从当前位置绘制一条直线到指定点。
BOOL LineTo(
HDC hdc, // 绘图设备的句柄
int X, // 目标点的X坐标
int Y // 目标点的Y坐标
);
返回值:如果函数成功,返回非零值;如果失败,返回零。
●Polyline是Windows平台上用于绘制一系列相连线段的GDI函数。它会连接给定的一组点,绘制相邻点之间的线段,最后一个点不会与下一个点连接。
以下是Polyline函数的函数原型:
BOOL Polyline(
HDC hdc, // 绘图设备的句柄
const POINT* lppt, // 包含点坐标的数组指针
int cPoints // 点的数量
);
●PolylineTo函数则是在当前位置和指定点之间绘制一段连续的线段。它会从当前位置开始,绘制连接当前位置和每个指定点的线段。函数原型如下:
BOOL PolylineTo(
HDC hdc, // 绘图设备的句柄
const POINT* lppt, // 包含点坐标的数组指针
DWORD cPoints // 点的数量
);
该函数的返回值为BOOL,当函数成功时返回非零值,失败时返回零。
PolylineTo和MoveToEx一起使用可以绘制一系列的连线。使用MoveToEx设定起始点,然后PolylineTo绘制从当前位置到每个POINT所定义的点的连续线段。使用PolylineTo的优势在于,你不需要在每两个点之间重复调用MoveToEx和LineTo来绘制线段,因此可以提高程序的效率。
在绘制操作结束后,当前位置会更新为PolylineTo函数最后一个点的位置。
●PolyPolyline函数可以用于绘制由多个不同点数的多段连续直线组成的复杂图形。
以下是PolyPolyline函数的函数原型:
BOOL PolyPolyline(
HDC hdc, // 绘图设备的句柄
const POINT* apt, // 包含所有线段端点坐标的数组指针
const DWORD* adwPolyPoints, // 包含每个多段连续直线的点数的数组指针
DWORD cCount // 多段连续直线的数量
);
函数返回非零表示成功,返回零表示失败。
●Arc函数是Windows平台上的一个GDI函数,用于绘制圆弧或椭圆弧。
以下是Arc函数的函数原型:
BOOL Arc(
HDC hdc, // 绘图设备的句柄
int nLeftRect, // 弧的左上角矩形的左边界坐标
int nTopRect, // 弧的左上角矩形的上边界坐标
int nRightRect, // 弧的左上角矩形的右边界坐标
int nBottomRect, // 弧的左上角矩形的下边界坐标
int nXStartArc, // 弧的起点的 x 坐标
int nYStartArc, // 弧的起点的 y 坐标
int nXEndArc, // 弧的终点的 x 坐标
int nYEndArc // 弧的终点的 y 坐标
);
函数返回非零表示成功,返回零表示失败。 这个函数在绘制一段椭圆弧时非常有用,例如绘制饼图时。但需要注意的是,这个弧是在由 nLeftRect,nTopRect,nRightRect,nBottomRect 定义的矩形框内绘制的,因此可能不是完全的圆弧。
●ArcTo函数用于在设备上下文中绘制一个弧。相比 Arc 函数,ArcTo 函数更灵活,可以用来创建更复杂的路径。其函数原型如下:
BOOL ArcTo(
HDC hdc, // 绘图设备的句柄
int nLeftRect, // 弧线段所在椭圆的左上角矩形的左边界坐标
int nTopRect, // 弧线段所在椭圆的左上角矩形的上边界坐标
int nRightRect, // 弧线段所在椭圆的左上角矩形的右边界坐标
int nBottomRect, // 弧线段所在椭圆的左上角矩形的下边界坐标
int x1, // 弧线段的起点的 x 坐标
int y1, // 弧线段的起点的 y 坐标
int x2, // 弧线段的终点的 x 坐标
int y2 // 弧线段的终点的 y 坐标
);
ArcTo函数用于绘制从当前位置到指定点的弧线段,弧线段位于指定椭圆的边界上。当前位置是通过之前的绘图操作确定的。ArcTo函数会自动将当前位置移动到弧线段的终点。
●AngleArc是用来绘制圆弧的函数,这个函数可以设置弧度的大小,使得绘制的线条更具灵活性。其函数原型如下:
BOOL AngleArc(
HDC hdc, // 绘图设备的句柄
int x, // 椭圆的中心点的 x 坐标
int y, // 椭圆的中心点的 y 坐标
DWORD dwRadius, // 椭圆的半径
FLOAT eStartAngle, // 起始角度(度数,逆时针方向为正)
FLOAT eSweepAngle // 弧线的角度范围(度数,逆时针方向为正)
);
函数返回非零表示执行成功,返回零表示执行失败。
●AngleArc 函数鉴于其灵活性,经常用于绘制如刻度盘、时钟等应用中,需要根据角度进行细致控制的场景。
PolyBezier 是 Windows GDI (图形设备接口) 中用来绘制贝塞尔曲线的函数。贝塞尔曲线是一种非常流行的平滑曲线,广泛应用于计算机图形学中。其函数原型如下:
BOOL PolyBezier(
HDC hdc, // 绘图设备的句柄
const POINT *lppt, // 包含贝塞尔曲线顶点的数组指针
DWORD cPoints // 贝塞尔曲线顶点的数量
);
如果函数执行成功,返回非零;如果执行失败,返回零。
这个函数可以帮你创建很多复杂和平滑的图形,比如字型设计、动画制作和矢量图形等领域经常用到。
可以使用 MoveToEx 函数设置起始点,然后使用 PolyBezier 函数绘制贝塞尔曲线。
●PolyBezierTo用于绘制一系列的贝塞尔曲线。它和 PolyBezier 函数类似,不过 PolyBezierTo 的初点是当前的位置点。其函数原型如下:
BOOL PolyBezierTo(
HDC hdc, // 绘图设备的句柄
const POINT *lppt, // 包含贝塞尔曲线顶点的数组指针
DWORD cCount // 贝塞尔曲线顶点的数量
);
如果函数执行成功,返回非零;如果函数执行不成功,返回值为零。
使用 PolyBezierTo 函数能够创建连续且平滑的曲线,它被广泛应用于动画制作,字体设计,矢量图形设计等计算机图形领域。
●PolyDraw用于一次绘制一在设备上下文中绘制一系列的线段和贝塞尔曲线的函数。其中每一段和每一条曲线可以是闭合的也可以是打开的。其函数原型如下:
BOOL PolyDraw(
HDC hdc, // 绘图设备的句柄
const POINT *lppt, // 包含线段顶点的数组指针
const BYTE *lpbTypes, // 包含线段类型的数组指针
int cCount // 顶点和类型的数量
);
如果函数执行成功,返回非零;如果函数执行失败,返回值为零。
这个函数允许在一个操作中绘制一系列复杂的图形,可以同时包括直线和曲线,大大提高了绘制的效率和灵活性,常用于复杂图形的绘制。
提示
上述GDI绘图函数通常会有两个版本,一个版本是“To”结尾的函数,一个没有“To”结尾。它们的区别是“To”结尾的函数会改变绘图的起始坐标,将起始坐标改为绘图结束后的最后一个位置。而不带“To”结尾的函数则不会改变绘图的起始坐标。显然,如果连续绘图,使用“To”结尾的函数不需要重新设定起始坐标,更为方便灵活。
■边框绘图函数
●Rectangle函数用于在设备上下文中绘制一个矩形。其函数原型如下:
BOOL Rectangle(
HDC hdc, // 绘图设备的句柄
int left, // 矩形左上角的 x 坐标
int top, // 矩形左上角的 y 坐标
int right, // 矩形右下角的 x 坐标
int bottom // 矩形右下角的 y 坐标
);
如果函数执行成功,返回非零;如果函数执行失败,返回值为零。
Rectangle 函数是 GDI 中最常用的绘图函数,它可以在图形绘制中快速的创建一个矩形形状。
●Ellipse函数用于在设备上下文中绘制一个椭圆形。其函数原型如下:
BOOL Ellipse(
HDC hdc, // 绘图设备的句柄
int left, // 椭圆的左上角的 x 坐标
int top, // 椭圆的左上角的 y 坐标
int right, // 椭圆的右下角的 x 坐标
int bottom // 椭圆的右下角的 y 坐标
);
如果函数执行成功,返回非零;如果函数执行失败,返回值为零。
Ellipse 函数可以在图形界面中快速绘制一个椭圆形,当需要绘制圆形时,只需确保包含椭圆的矩形是正方形(即宽和高相等)就可以了。
●RoundRect函数主要用于绘制带有圆角的矩形。其函数原型如下:
BOOL RoundRect(
HDC hdc, // 绘图设备的句柄
int left, // 矩形左上角的 x 坐标
int top, // 矩形左上角的 y 坐标
int right, // 矩形右下角的 x 坐标
int bottom, // 矩形右下角的 y 坐标
int width, // 圆角的宽度
int height // 圆角的高度
);
如果函数执行成功,返回非零;如果函数执行失败,返回值为零。
RoundRect 函数可以绘制带有圆角的矩形,这在绘制用户界面,如按钮等组件时很有用。如果你希望绘制的圆角是一个正圆,那么你需要让 width 和 height 相等。
●Pie函数主要用于绘制一个饼图形。其函数原型如下:
BOOL Pie(
HDC hdc, // 绘图设备的句柄
int left, // 扇形或椭圆弧的外接矩形的左上角的 x 坐标
int top, // 扇形或椭圆弧的外接矩形的左上角的 y 坐标
int right, // 扇形或椭圆弧的外接矩形的右下角的 x 坐标
int bottom, // 扇形或椭圆弧的外接矩形的右下角的 y 坐标
int xRadial1, // 扇形或椭圆弧的起点与椭圆中心的连线与 x 轴的夹角度数
int yRadial1, // 扇形或椭圆弧的起点与椭圆中心的连线与 y 轴的夹角度数
int xRadial2, // 扇形或椭圆弧的终点与椭圆中心的连线与 x 轴的夹角度数
int yRadial2 // 扇形或椭圆弧的终点与椭圆中心的连线与 y 轴的夹角度数
);
如果函数执行成功,返回非零;如果函数执行失败,返回值为零。
Pie 函数可以绘制一个饼图形,其填充使用当前的刷子,边缘线采用当前的画笔。在绘制统计图表或者需要部分椭圆形的场合中,该函数非常有用。
●Chord函数用于绘制一个弦图,即一个由线段和弧线段组成的闭合图形。其函数原型如下:
void drawChord(
SDL_Renderer* renderer, // 渲染器对象,用于绘制图形的画布
int centerX, // 和弦图的中心点横坐标
int centerY, // 和弦图的中心点纵坐标
int radius, // 和弦图的半径
int* connections, // 和弦图的节点之间的连接关系数组
int numNodes, // 节点数量
SDL_Color* colors // 节点颜色数组
);
如果函数成功,返回非零;若失败,则返回零。
Chord 函数在绘制物理图像,如科学图表和统计图表,或游戏中的图像素材等场合特别有用。通过控制其参数,可以构造出各种形状的图形。
提示
所有的GDI绘图函数都需要一个绘图设备的句柄(HDC)作为参数,可以通过调用GetDC函数获取窗口的绘图设备句柄。
本文摘自编程达人系列教材《Windows API每日一练》。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved