第5章,[Win32 章节] :边框绘制函数(五)
专栏导航上一篇第5章[Win32 章节] 边框绘制函数四回到目录下一篇第5章[Win32 章节] 边框绘制函数六本节前言对于本节所讲解的知识有可能你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点请你自行查阅。我呢也会提到一部分的参考课节。但是呢你不应该依赖于我的主动提及。最好呢你自己能够多去了解和查看本专栏目录。想要学习本节请先确认你已经学完并基本掌握了以下的几个参考课节的内容。参考课节第5章[Win32 章节] 边框绘制函数一参考课节第5章[Win32 章节] 边框绘制函数二参考课节第5章[Win32 章节] 边框绘制函数三参考课节第5章[Win32 章节] 边框绘制函数四本节我们要来讲解一个比较麻烦的形状那就是圆角矩形。学习过 3ds max 软件等等的三维软件的同学可能会对这个形状有所了解。我们开始。一. RoundRect 函数的讲解我们来看一张图。图1图1 所示的平面图形就是圆角矩形。一般的矩形其四个角都是直角而圆角矩形的四个角则是一段圆弧。除去四个圆角其余的部分与矩形还是比较像的。我们再来看下一张图。图2图2 则是更为详细地展示了圆角矩形的结构。在图2 里面最外边是一个矩形。然后呢在矩形内部的四个角的位置放置着四个一模一样的椭圆形这四个椭圆均与矩形的相邻两个边相切。然后呢去掉矩形的原本的四个直角而代之以椭圆与矩形的两个切点之间的椭圆弧线如此一来所形成的便是圆角矩形了。在 Windows API 里面用来绘制圆角矩形的函数叫做 RoundRect 。它的用法如下。RoundRect (hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse);此函数中的 hdc依然是 GDI 函数中经常会有的设备环境句柄。hdc 右边的前四个参数与 Rectangle 函数和 Ellipse 函数一样都是xLeft, yTop, xRight, yBottom。它们的含义我们之前讲过几次了。在这里呢我就再来重复一遍。在复习这四个坐标之前我们还是将圆角矩形的详细讲解图示画在下面。图3接下来呢我们来讲解 RoundRect 函数的参数列表中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 是圆角矩形所在的外接矩形达不到的像素行号。应该还能看懂吧接下来呢我们来讲 RoundRect 函数的最后两个参数xCornerEllipse 和 yCornerEllipse 。xCornerEllipse 是圆角矩形的圆角部分所在的椭圆的宽度也就是椭圆的左右极限点的距离是椭圆的横向的直径。同理yCornerEllipse 是圆角矩形的圆角部分所在的椭圆的高度也就是椭圆的上下极限点的距离是椭圆的纵向的直径。概念上应该是清楚了吧还有一点它是很重要的。RoundRect 函数它所绘制出来的图形是封闭图形。除了外侧的边框曲线之外还有内部的封闭区域。Windows 在绘制它的时候会采用当前画刷来填充其内部封闭区域。当前画刷大家还记得吗我们在第三章有讲过就是窗口类变量 wndclass 中的 hbrBackground 成员变量所加载的画刷句柄它被用来绘制客户区的背景填充色。图1 到图3 中我们所展示的圆角矩形其宽度和高度并不一致。经验上用宽度和高等相等的椭圆也就是正圆来作为圆角矩形的圆角会更加地美观一些。所以呢一般来讲在绘制圆角矩形时一般都让圆角部分所在的椭圆用正圆来绘制。到了这里基础概念部分我想你大概是能懂了。那么我们接下来还是要写一个练习程序。二. 案例程序程序代码如下。/*------------------------------------------------------------ 练习绘制圆角矩形RoundRect_Lx ------------------------------------------------------------*/ #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(RoundRect_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 RoundRect_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, yTop, xRight, yBottom; int xCornerEllipse, yCornerEllipse; switch (message) { case WM_CREATE: return 0; case WM_PAINT: hdc BeginPaint(hwnd, ps); xLeft 60; yTop 60; xRight 360; yBottom 260; xCornerEllipse 60; yCornerEllipse 50; RoundRect(hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse); xLeft 360; yTop 100; xRight 360; yBottom 100; xCornerEllipse 100; yCornerEllipse 100; RoundRect(hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse); EndPaint(hwnd, ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }程序应该是不难看懂的。编译过程我就不详细写了。如果你忘了如何编译和运行程序请参考下述课节。参考课节使用 VS2010 编写 C语言程序参考课节用 VS2019 编写C语言程序程序的运行结果如下。图4结束语总算是写完了本节。在绘制圆角矩形讲解示意图的时候我还是花费了一点功夫的。讲完了本节接下来呢在边框绘制函数里面我们还剩下三个函数PieChord 和 Arc 。这三个函数我们打算一起来讲解。本章内容还是比较重要的它算是上是一个重头戏了。大家务必要学好本章。另外呢本章结束以后我们暂且阁下 Windows API 部分不往下讲。我们接着要去讲的是 MFC 知识。也就是在我这里我打算将 Windows API 和 MFC 穿插着来讲解。本节结束。专栏导航上一篇第5章[Win32 章节] 边框绘制函数四回到目录下一篇第5章[Win32 章节] 边框绘制函数六