专栏导航
上一篇:第5章,[Win32 章节] :边框绘制函数(五)
回到目录
下一篇:第5章,[Win32 章节] :边框绘制函数的教材案例
本节前言
对于本节所讲解的知识,有可能,你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点,请你自行查阅。
我呢,也会提到一部分的参考课节。但是呢,你不应该依赖于我的主动提及。最好呢,你自己能够多去了解和查看本专栏目录。
想要学习本节,请先确认你已经学完并基本掌握了以下的几个参考课节的内容。
参考课节:第5章,[Win32 章节] :边框绘制函数(一)
参考课节:第5章,[Win32 章节] :边框绘制函数(二)
参考课节:第5章,[Win32 章节] :边框绘制函数(三)
参考课节:第5章,[Win32 章节] :边框绘制函数(四)
参考课节:第5章,[Win32 章节] :边框绘制函数(五)
本节,我们一口气来讲解三个函数,它们分别是 Arc、Chord 和 Pie 函数。
其中,Arc 函数绘制的是弧线,Chord 绘制的是弓形。Pie 绘制的图是饼形图,或者我们也可以将其称作扇形图。
我们开始。
一. 函数讲解
首先呢,我们来展示三个讲解示意图。
图1,Arc 函数讲解图
图2,Chord 函数降解图
图3,Pie 函数讲解图
使用 Arc 函数绘制的图形,如图1 的红线部分所示,它就是一条弧线。这个弧线,它是椭圆圆周上的一段曲线。
使用 Chord 函数绘制的图形,如图2 的红线部分所示。它在弧线的基础上,连接弧线的两端点,而形成一个封闭图形,弓形。
使用 Pie 函数绘制的图形,如图3 的红线部分所示。它是在弧线的基础上,由椭圆圆心分别连接弧线的两端点,形成一个封闭图形。我们将这个封闭图形称作饼形或者扇形。
接下来呢,我们来展示三个函数的使用方法。
Arc (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);
Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);
Pie (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);
可以看到,三个函数使用相同的参数。
三个函数的前五个参数与 Rectangle 和 Ellipse 函数相同。我们还是来重复一下这五个参数的含义。
首先呢,hdc 是设备环境句柄。
接下来,是 hdc 参数之后的四个参数,它的含义与 Rectangle 和 Ellipse 函数相同。不过呢,对于本节的三个函数,我们还得来讲解一下这四个坐标参数的特殊含义。
Arc、Chord 和 Pie 函数所绘制出来的图形,它们都拥有一段弧线,这个弧线,它是椭圆圆周上的一部分曲线。弧线所在的椭圆的外接矩形,便是 hdc 之后的四个坐标参数所描述的矩形了。
这个外接矩形的概念,请大家关注一下。
我们将这四个坐标参数单提出来,它们是(xLeft, yTop, xRight, yBottom)。
我们若以客户区内部的最左侧的一列像素为 0 列像素,则再往右一列是 1 号列像素,再往右一列是 2 号列像素,等等。在这种规定之下,则 xLeft 是弧线所在的椭圆圆周的外接矩形的左边的起始像素的列号,xRight 是弧线所在的椭圆圆周的外接矩形的右边的结束像素的右边一列像素的列号。也就是,弧线所在的椭圆圆周的外接矩形的 x 坐标的范围,是 xLeft <= x <= (xRight – 1),xRight 是弧线所在的椭圆圆周的外接矩形达不到的像素列号。
讲完了xLeft 和 xRight,我们再来看一看 yTop 和 yBottom 。
我们若以客户区内部最上边的一行像素为 0 行像素,则此行像素再往下一行为 1 号行像素,再往下一行为 2 号行像素,等等。在这种规定之下,则 yTop 是弧线所在的椭圆圆周的外接矩形的上边的起始像素的行号,而 yBottom 是弧线所在的椭圆圆周的外接矩形的下边的结束像素的下一行像素的行号。也就是,弧线所在的椭圆圆周的外接矩形的 y 坐标的范围,是 yTop <= y <= (yBottom – 1),yBottom 是弧线所在的椭圆圆周的外接矩形达不到的像素行号。
稍微有点绕嘴。但是,慢点看,多看看,应该还能看懂吧?
到了这里呢,hdc 之后的前四个坐标,我们就讲完了。我们再来讲最后四个坐标参数,(xStart, yStart, xEnd, yEnd)。
它们用来定义弧线的起点与终点。如何定义的呢?
Arc、Chord 和 Pie 函数绘制的图形都包含一段弧线,这个弧线是椭圆圆周上的一段曲线。我们将这几个函数图形所在的椭圆给提取出来。我们将其称作概念椭圆吧。
Windows 使用一条虚构的线来连接(xStart, yStart)和概念椭圆的圆心,这条虚构的线与概念椭圆的交点,为弧线的起点。Windows 使用另一条虚构的线来连接(xEnd, yEnd)和概念椭圆的圆心,这条虚构的线与概念椭圆的交点,为弧线的终点。
从弧线的起点开始,逆时针绘制曲线,绘制到弧线的终点,则起点与终点之间的弧线,就是 Arc、Chord 和 Pie 函数绘制的图形中的弧线部分。
这种绘制方法,似乎有些奇怪。为啥不是指定起始椭圆圆周的起始与结束角度,或者是起始与结束弧度呢?再或者,也可以由程序员来直接指定起点与终点啊。
如果是由程序员直接来指定起点与终点的话,那就需要由程序员来亲自计算弧线的起点与终点坐标了。Windows 不希望程序员亲自来进行这种精确的计算,而是用一种更为简单直观的计算方法。
至于说弧度和角度,如果是这么来指定,也会涉及浮点数了。Windows 还是希望程序员所使用的参数,尽量地都是整型数,而不要使用复杂的浮点数。
在以后学习计算字体等等的章节内容的时候,我们也会发现,Windows 依然是倾向于让我们指定整型数,而不是指定浮点数作为参数。
还有一点,是很重要的。Arc 函数绘制出来的,仅仅是一个弧线,它不存在封闭图形,所以不涉及采用当前画刷来填充封闭图形内部区域的问题。
而 Chord 和 Pie 函数,它们所绘制出来的图形都是封闭图形。除了外侧的边框曲线之外,还有内部的封闭区域。Windows 在绘制它们的时候,会采用当前画刷来填充其内部封闭区域。
当前画刷,大家还记得吗?我们在第三章有讲过,就是窗口类变量 wndclass 中的 hbrBackground 成员变量所加载的画刷句柄,它被用来绘制客户区的背景填充色。
到了这里,我想,本节的三个函数,我们就算是讲完了。
在下一分节,我们来给出一个简单的示例程序。
二. 本节程序示例
代码如下。
/*————————————————————
HELLOWIN.C — 在窗口客户区显示 "Hello, Windows Program"
改编自佩措尔德的 HelloWin 程序
————————————————————*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Arc_Chord_Pie_Lx");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("注册窗口类失败!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, // window class name
TEXT("The Arc_Chord_Pie_Lx Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
int xLeft, xRight, yTop, yBottom;
int xStart, yStart, xEnd, yEnd;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
xLeft = 100;
xRight = 300;
yTop = 100;
yBottom = 260;
xStart = (xLeft + xRight) / 2;
yStart = yTop – 30;
xEnd = xLeft – 30;
yEnd = yBottom – 30;
Arc(hdc, xLeft, yTop, xRight, yBottom,
xStart, yStart, xEnd, yEnd);
xLeft += 300;
xRight += 300;
xStart = (xLeft + xRight) / 2;
yStart = yTop – 30;
xEnd = xLeft – 30;
yEnd = yBottom – 30;
Chord(hdc, xLeft, yTop, xRight, yBottom,
xStart, yStart, xEnd, yEnd);
yTop += 300;
yBottom += 300;
xStart = (xLeft + xRight) / 2;
yStart = yTop – 30;
xEnd = xLeft – 30;
yEnd = yBottom – 30;
Pie(hdc, xLeft, yTop, xRight, yBottom,
xStart, yStart, xEnd, yEnd);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
程序应该是不难看懂的。
编译过程我就不详细写了。如果你忘了如何编译和运行程序,请参考下述课节。
参考课节:使用 VS2010 编写 C语言程序
参考课节:用 VS2019 编写C语言程序
程序的运行结果如下。
图4
结束语
本节课程,到这里就结束了。
专栏导航
上一篇:第5章,[Win32 章节] :边框绘制函数(五)
回到目录
下一篇:第5章,[Win32 章节] :边框绘制函数的教材案例




