本文为一Windows编程API绘图实战小例子,学习自哔哩哔哩小甲鱼的《Windows程序设计SDK》。最终效果展示:
![](https://img-blog.csdnimg.cn/20181115183443684.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
源码在最后,跟着小甲鱼老师敲一遍代码,这些API能记住不少。
一、大体脉络
![](https://img-blog.csdnimg.cn/20181118215731187.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/2018111822174218.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118215807281.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118215833984.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118215903160.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118215922635.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118215942979.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118215958845.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118220018820.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118220039533.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20181118220057471.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQwODE4Nzk4,size_16,color_FFFFFF,t_70)
二、相关知识细则(来自鱼C工作室)
1.WM_SIZE 消息
消息含义:
当主窗口的客户区部分大小改变时,操作系统将给应用程序发送 WM_SIZE 消息应用程序通过窗口过程接收该消息
消息定义:
#define WM_SIZE 0x0005
参数解析:
wParam:指出窗口的新状态wParam 参数可以是下列值之一:
值含义SIZE_MAXHIDE(4)当该应用程序的其他窗口被最大化的时候,消息被发送往所有的弹出窗口SIZE_MAXIMIZED(2)该窗口被最大化SIZE_MAXSHOW(3)当该应用程序的其他窗口已经恢复到原来大小的时候,消息被发送往所有的弹出窗口SIZE_MINIMIZED(1)该窗口被最小化SIZE_RESTORED(0)该窗口的大小发生变化,但不是最大化(SIZE_MAXIMIZED)或最小化(MINIMIZED)
lParam:指出当前客户区的大小(宽度和高度)
lParam 参数的低 16 位指定了新窗口的宽度;lParam 参数的高 16 位制定了新窗口的高度。
温馨提醒:可以通过 LOWORD 宏和 HIWORD 宏来获取 lParam 参数的低 16 位和高 16 位。返回值:如果窗口过程响应该消息,必须返回 0。
2.RGB宏
宏功能:
RGB 宏有三个参数(byRed, byGreen, byBlue),功能是将这三个参数转换为 COLORREF 颜色值。注释:COLORREF 颜色被定义为 DWORD 类型(4 个字节),用于表示 RGB 颜色。
宏原型:
COLORREF RGB(
BYTE byRed,
BYTE byGreen,
BYTE byBlue
);
参数解析:
参数含义byRed红色的颜色值byGreen绿色的颜色值byBlue蓝色的颜色值
小甲鱼忍不住罗嗦补充一句:色彩中不能再分解的基本色称之为原色,红绿蓝即三原色,将它们按照不同比例混合,可以搭配出所有的颜色。返回值:返回三个参数转换后的 COLORREF 颜色值备注:
每个颜色可以指定的颜色值是 0 ~ 255,三个参数同时为 0,即黑色,同时为 255 即白色。 通过 GetRValue、GetGValue 和 GetBValue 宏可以分别从 COLORREF 颜色值中获得红色、绿色、蓝色的颜色值。
3.LOWORD 和 HIWORD 宏
宏功能:
获得指定 32 位数据的低 16 位数据和高 16 位数据。小甲鱼温馨提醒:不要使用 LOWORD 和 HIWORD 宏去获取鼠标的坐标,因为在多显示器的情况下会得到错误的坐标。应该使用 GET_X_LPARAM 和 GET_Y_LPARAM 宏来获取。
宏定义:
WORD LOWORD(
DWORD dwValue
);
……
WORD HIWORD(
DWORD dwValue
);
参数解析:
参数含义lParam32 位的目标数据
返回值:
LOWORD(lParam) 返回 lParam 的低 16 位数据;HIWORD(lParam) 返回 lParam 的高 16 位数据。
4.POINT 结构
POINT 结构定义了一个点的 x 坐标和 y 坐标。结构原型:
typedef struct tagPOINT {
LONG x;
LONG y;
} POINT, *PPOINT;
成员解析:
成员含义x被定义的点的 x 坐标y被定义的点的 y 坐标
5.MoveToEx
函数功能:MoveToEx 函数将当前绘图位置移动到某个具体的点,同时也可获得之前位置的坐标。API 函数原型:注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。
BOOL MoveToEx(
_In_ HDC hdc,
_In_ int X,
_In_ int Y,
_Out_ LPPOINT lpPoint
);
参数解析:
参数含义hdc指定设备环境句柄X指定新位置的 X 轴坐标,按逻辑单位表示坐标Y指定新位置的 Y 轴坐标,按逻辑单位表示坐标lpPoint1. 一个 POINT 结构的指针,用于获得之前位置的坐标 2. 如果这个值是 NULL,则不会获得之前位置的坐标
返回值:
如果函数调用成功,返回值是非 0;如果函数调用失败,返回值是 0。
备注:
MoveExTo 函数将影响所有的绘图函数。在默认的设备环境中,点 (0, 0) 为最初设定的当前位置。
6.LineTo
函数功能:
LineTo 函数使用当前画笔绘制一条线,线段从当前位置连到一个指定的点 (x, y)。当这个函数调用完毕后,当前位置变成 (x, y)。小甲鱼提示:所绘制的线段并不包含指定的点 (x, y)。
API 函数原型:注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。
BOOL LineTo(
_In_ HDC hdc,
_In_ int nXEnd,
_In_ int nYEnd
);
参数解析:
参数含义hdc指定设备环境句柄nXEnd1. 线段终点X坐标位置,采用逻辑坐标表示。 2. 这个点不会实际画出来,因为它不属于线段的一部份nYEnd1. 线段终点Y坐标位置,采用逻辑坐标表示。 2. 这个点不会实际画出来,因为它不属于线段的一部份
返回值:
如果函数调用成功,返回值是非 0;如果函数调用失败,返回值是 0。
7.Rectangle
函数功能:
Rectangle 函数用于绘制一个矩形。该矩形用当前画笔绘制轮廓,用当前画刷填充。
![](https://xxx.ilovefishc.com/forum/201410/22/154918ybnkxynfiyxi144k.jpg)
API 函数原型:注释:_In_ 说明该参数是输入的。
BOOL Rectangle(
_In_ HDC hdc,
_In_ int xLeft,
_In_ int yTop,
_In_ int xRight,
_In_ int yBottom
);
参数解析:
参数含义hdc指定设备环境句柄xLeft指定矩形左上角的逻辑 x 坐标yTop指定矩形左上角的逻辑 y 坐标xRight指定矩形右下角的逻辑 x 坐标yBottom指定矩形右下角的逻辑 y 坐标
返回值:
如果函数调用成功,返回值是非 0;如果函数调用失败,返回值是 0。
备注:
该函数既不使用当前位置,也不修改当前位置。写过图形程序的程序员通常熟悉边界偏差(off-by-one)的问题:一些图形程序系统画出的图形包含了右坐标和底坐标表示的点,一些则只画到右坐标和底坐标表示的点之前的一点。Windows 使用后一种方法。如果使用 PS_NULL 画笔,则矩形的尺寸高和宽比实际少一个像素。
8.Ellipse
函数功能:
Ellipse 函数用于绘制一个椭圆,椭圆的中心是限定矩形的中心。该椭圆用当前画笔绘制轮廓,用当前画刷填充。
![](https://xxx.ilovefishc.com/forum/201410/22/155009psvv3pnvf3cnx83q.jpg)
API 函数原型:注释:_In_ 说明该参数是输入的。
BOOL Ellipse(
_In_ HDC hdc,
_In_ int xLeft,
_In_ int yTop,
_In_ int xRight,
_In_ int yBottom
);
参数解析:
参数含义hdc指定设备环境句柄xLeft指定椭圆限定矩形左上角的逻辑 x 坐标yTop指定椭圆限定矩形左上角的逻辑 y 坐标xRight指定椭圆限定矩形右下角的逻辑 x 坐标yBottom指定椭圆限定矩形右下角的逻辑 y 坐标
返回值:
如果函数调用成功,返回值是非 0;如果函数调用失败,返回值是 0。
备注:该函数既不使用当前位置,也不修改当前位置。
9.RoundRect
函数功能:
RoundRect 函数用于绘制一个带圆角的矩形。该矩形用当前画笔绘制轮廓,用当前画刷填充。
![](https://xxx.ilovefishc.com/forum/201410/22/162725bi2cy5293rp99ry3.jpg)
API 函数原型:注释:_In_ 说明该参数是输入的。
BOOL RoundRect(
_In_ HDC hdc,
_In_ int xLeft,
_In_ int yTop,
_In_ int xRight,
_In_ int yBottom,
_In_ int xCornerEllipse,
_In_ int yCornerEllipse
);
参数解析:
参数含义hdc指定设备环境句柄xLeft指定限定矩形的左上角的逻辑 x 坐标yTop指定限定矩形的左上角的逻辑 y 坐标xRight指定限定矩形的右下角的逻辑 x 坐标yBottom指定限定矩形的右下角的逻辑 y 坐标xCornerEllipse指定用来画圆角的椭圆的宽yCornerEllipse指定用来画圆角的椭圆的高
返回值:
如果函数调用成功,返回值是非 0;如果函数调用失败,返回值是 0。
备注:该函数既不使用当前位置,也不修改当前位置。
10.Arc
函数功能:Arc 函数用于绘制一个椭圆的圆弧。
![](https://xxx.ilovefishc.com/forum/201410/22/171525e6ds6ofpuy4zuuw1.jpg)
API 函数原型:注释:_In_ 说明该参数是输入的。
BOOL Arc(
_In_ HDC hdc,
_In_ int xLeft,
_In_ int yTop,
_In_ int xRight,
_In_ int yBottom,
_In_ int xStart,
_In_ int yStart,
_In_ int xEnd,
_In_ int yEnd
);
参数解析:
参数含义hdc指定设备环境句柄xLeft指定限定矩形的左上角的逻辑 x 坐标yTop指定限定矩形的左上角的逻辑 y 坐标xRight指定限定矩形的右下角的逻辑 x 坐标yBottom指定限定矩形的右下角的逻辑 y 坐标xStart指定圆弧开始的逻辑 x 坐标yStart指定圆弧开始的逻辑 y 坐标xEnd指定圆弧结束的逻辑 x 坐标yEnd指定圆弧结束的逻辑 y 坐标
返回值:
如果函数调用成功,返回值是非 0;如果函数调用失败,返回值是 0。
备注:
点 (xLeft, yTop) 和点 (xRight, yBottom) 指定限定矩形的位置。由指定的限定矩形形成的椭圆定义弧的曲线。弧的起始点 (xStart, yStart) 开始和终点 (xEnd, yEnd) 并不在椭圆上,而是定义为在椭圆的中心的延长线上(不懂的鱼油请看上图)。如果椭圆的起始点和终点是同一个点,那么将绘制整个椭圆。
11.Pie
函数功能:
Pie 函数绘制一个由弧以及椭圆中心构成的扇形。该扇形用当前画笔绘制轮廓,用当前画刷填充。
![](https://xxx.ilovefishc.com/forum/201410/22/203952vbkfy2rk4iiv2mq7.jpg)
API 函数原型:注释:_In_ 说明该参数是输入的。
BOOL Pie(
_In_ HDC hdc,
_In_ int xLeft,
_In_ int yTop,
_In_ int xRight,
_In_ int yBottom,
_In_ int xStart,
_In_ int yStart,
_In_ int xEnd,
_In_ int yEnd
);
参数解析:
参数含义hdc指定设备环境句柄xLeft指定限定矩形的左上角的逻辑 x 坐标yTop指定限定矩形的左上角的逻辑 y 坐标xRight指定限定矩形的右下角的逻辑 x 坐标yBottom指定限定矩形的右下角的逻辑 y 坐标xStart指定圆弧开始的逻辑 x 坐标yStart指定圆弧开始的逻辑 y 坐标xEnd指定圆弧结束的逻辑 x 坐标yEnd指定圆弧结束的逻辑 y 坐标
返回值:
如果函数调用成功,返回值是非 0;如果函数调用失败,返回值是 0。
备注:
扇形对应的曲线(弧)由限定矩形画出的椭圆所指定。曲线(弧)的起始点 (xStart, yStart) 开始和终点 (xEnd, yEnd) 并不在椭圆上,而是定义为在椭圆的中心的延长线上(不懂的鱼油请看上图)。该函数既不使用当前位置,也不修改当前位置。
三、程序源码
#include
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hprevInstance,PSTR szCmdLine,int iCmdShow)
{
static TCHAR szAppName[] = TEXT("MyWindows");
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("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, // window class name
TEXT("哆啦A梦"), // 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;
HPEN hPen, hOldPen;
HBRUSH hBlueBrush, hOldBrush, hRedBrush, hYellowBrush;
POINT apt[128];
static int cxClient, cyClient;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
//辅助线
hPen = CreatePen(PS_DOT, 1, RGB(192, 192, 192));
hOldPen = SelectObject(hdc, hPen);
MoveToEx(hdc, cxClient / 2, 0, NULL);
LineTo(hdc, cxClient / 2, cyClient);
MoveToEx(hdc, 0, cyClient / 2, NULL);
LineTo(hdc, cxClient, cyClient / 2);
SelectObject(hdc, hOldPen);
//头 直径240
hBlueBrush = CreateSolidBrush(RGB(0, 159, 232)); //借
hOldBrush = SelectObject(hdc, hBlueBrush);
Ellipse(hdc, cxClient / 2 - 120, cyClient / 2 - 200, cxClient / 2 + 120, cyClient / 2 + 40);
SelectObject(hdc, hOldBrush); //还
//脸 直径200
Ellipse(hdc, cxClient / 2 - 100, cyClient / 2 - 160, cxClient / 2 + 100, cyClient / 2 + 40);
//眼睛 长60 宽50
Ellipse(hdc, cxClient / 2 - 50, cyClient / 2 - 180, cxClient / 2, cyClient / 2 - 120);
Ellipse(hdc, cxClient / 2 + 50, cyClient / 2 - 180, cxClient / 2, cyClient / 2 - 120);
//眼珠
hOldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Ellipse(hdc, cxClient / 2 - 20, cyClient / 2 - 160, cxClient / 2 - 5, cyClient / 2 - 140);
Ellipse(hdc, cxClient / 2 + 20, cyClient / 2 - 160, cxClient / 2 + 5, cyClient / 2 - 140);
SelectObject(hdc, hOldBrush);
hOldBrush = SelectObject(hdc, GetStockObject(WHITE_BRUSH));
Ellipse(hdc, cxClient / 2 - 15, cyClient / 2 - 155, cxClient / 2 - 10, cyClient / 2 - 145);
Ellipse(hdc, cxClient / 2 + 15, cyClient / 2 - 155, cxClient / 2 + 10, cyClient / 2 - 145);
SelectObject(hdc, hOldBrush);
//鼻子
hRedBrush = CreateSolidBrush(RGB(255, 0, 0));
hOldBrush = SelectObject(hdc, hRedBrush);
Ellipse(hdc, cxClient / 2 - 10, cyClient / 2 - 135, cxClient / 2 + 10, cyClient / 2 -115);
SelectObject(hdc, hOldBrush);
MoveToEx(hdc, cxClient / 2, cyClient / 2 - 115, NULL);
LineTo(hdc, cxClient / 2, cyClient / 2 - 30);
//嘴巴
Arc(hdc, cxClient / 2 - 70, cyClient / 2 - 120, cxClient / 2 + 70, cyClient / 2 - 30,
cxClient / 2 - 60, cyClient / 2 - 50, cxClient / 2 + 60, cyClient / 2 - 50);
//胡须 中上下
MoveToEx(hdc, cxClient / 2 + 20, cyClient / 2 - 85, NULL);
LineTo(hdc, cxClient / 2 + 75, cyClient / 2 - 85);
MoveToEx(hdc, cxClient / 2 - 20, cyClient / 2 - 85, NULL);
LineTo(hdc, cxClient / 2 - 75, cyClient / 2 - 85);
MoveToEx(hdc, cxClient / 2 + 20, cyClient / 2 - 95, NULL);
LineTo(hdc, cxClient / 2 + 70, cyClient / 2 - 105);
MoveToEx(hdc, cxClient / 2 - 20, cyClient / 2 - 95, NULL);
LineTo(hdc, cxClient / 2 - 70, cyClient / 2 - 105);
MoveToEx(hdc, cxClient / 2 + 20, cyClient / 2 - 75, NULL);
LineTo(hdc, cxClient / 2 + 70, cyClient / 2 - 65);
MoveToEx(hdc, cxClient / 2 - 20, cyClient / 2 - 75, NULL);
LineTo(hdc, cxClient / 2 - 70, cyClient / 2 - 65);
//身体
hOldBrush = SelectObject(hdc, hBlueBrush);
Rectangle(hdc, cxClient / 2 - 100, cyClient / 2 - 10, cxClient / 2 + 100, cyClient / 2 + 150);
SelectObject(hdc, hOldBrush);
//肚皮
Ellipse(hdc, cxClient / 2 - 70, cyClient / 2 - 20, cxClient / 2 + 70, cyClient / 2 + 120);//圆
hPen = CreatePen(PS_DOT, 1, RGB(255, 255, 255));//擦除肚皮上面嘴巴下面的圆弧
hOldPen = SelectObject(hdc, hPen);
Arc(hdc, cxClient / 2 - 70, cyClient / 2 - 20, cxClient / 2 + 70, cyClient / 2 + 120,
cxClient / 2 + 60, cyClient / 2 - 10, cxClient / 2 - 60, cyClient / 2 - 10);
SelectObject(hdc, hOldPen);
//围脖
hOldBrush = SelectObject(hdc, hRedBrush);
RoundRect(hdc, cxClient / 2 - 102, cyClient / 2 - 12, cxClient / 2 + 102, cyClient / 2 + 5, 20,20);
SelectObject(hdc, hOldBrush);
//铃铛
hYellowBrush = CreateSolidBrush(RGB(255, 255, 0));
hOldBrush = SelectObject(hdc, hYellowBrush);
Ellipse(hdc, cxClient / 2 - 12, cyClient / 2 - 4, cxClient / 2 + 12, cyClient / 2 + 20);
RoundRect(hdc, cxClient / 2 - 12, cyClient / 2 + 3, cxClient / 2 + 12, cyClient / 2 + 6, 20, 20);
SelectObject(hdc, hRedBrush);
Ellipse(hdc, cxClient / 2 - 5, cyClient / 2 + 8, cxClient / 2 + 5, cyClient / 2 + 18);
SelectObject(hdc, hOldBrush);
//裤腿
Ellipse(hdc, cxClient / 2 - 20, cyClient / 2 + 130, cxClient / 2 + 20, cyClient / 2 + 170);//画圆
hPen = CreatePen(PS_DOT, 1, RGB(255, 255, 255)); //擦除肚皮下面嘴巴上面的圆弧
hOldPen = SelectObject(hdc, hPen);
Arc(hdc, cxClient / 2 - 20, cyClient / 2 + 130, cxClient / 2 + 20, cyClient / 2 + 170,
cxClient / 2 - 20, cyClient / 2 + 150, cxClient / 2 + 20, cyClient / 2 + 150);
SelectObject(hdc, hOldPen);
//口袋
Pie(hdc, cxClient / 2 - 50, cyClient / 2, cxClient / 2 + 50, cyClient / 2 + 100,
cxClient / 2 - 50, cyClient / 2 + 50, cxClient / 2 + 50, cyClient / 2 + 50);
/*Pie(hdc, cxClient / 2 - 50, cyClient / 2, cxClient / 2 + 50, cyClient / 2 + 100,
cxClient / 2 - 50, cyClient / 2 + 50, cxClient / 2 + 50, cyClient / 2 + 50);
画弧线时是逆时针的*/
//脚掌
/*Ellipse(hdc, cxClient / 2 - 100, cyClient / 2 + 130, cxClient / 2 - 20, cyClient / 2 + 170);
Ellipse(hdc, cxClient / 2 + 20, cyClient / 2 + 130, cxClient / 2 + 100, cyClient / 2 + 170);*/
Ellipse(hdc, cxClient / 2 - 110, cyClient / 2 + 135, cxClient / 2 - 10, cyClient / 2 + 165);
Ellipse(hdc, cxClient / 2 + 10, cyClient / 2 + 135, cxClient / 2 + 110, cyClient / 2 + 165);
//胳膊
hOldBrush = SelectObject(hdc, hBlueBrush);
apt[0].x = cxClient / 2 - 100;
apt[0].y = cyClient / 2;
apt[1].x = cxClient / 2 - 150;
apt[1].y = cyClient / 2 + 60;
apt[2].x = cxClient / 2 - 140;
apt[2].y = cyClient / 2 + 80;
apt[3].x = cxClient / 2 - 100;
apt[3].y = cyClient / 2 + 60;
//点是按顺序连接的,下面是错误用例
/*apt[0].x = cxClient / 2 - 100;
apt[0].y = cyClient / 2;
apt[1].x = cxClient / 2 - 150;
apt[1].y = cyClient / 2 + 60;
apt[3].x = cxClient / 2 - 140;
apt[3].y = cyClient / 2 + 80;
apt[2].x = cxClient / 2 - 100;
apt[2].y = cyClient / 2 + 60;*/
Polygon(hdc, apt, 4);
SelectObject(hdc, hOldBrush);
Ellipse(hdc, cxClient / 2 - 168, cyClient / 2 + 60, cxClient / 2 - 138, cyClient / 2 + 90); //左手掌
hOldBrush = SelectObject(hdc, hBlueBrush);
apt[0].x = cxClient / 2 + 100;
apt[0].y = cyClient / 2;
apt[1].x = cxClient / 2 + 150;
apt[1].y = cyClient / 2 + 60;
apt[2].x = cxClient / 2 + 140;
apt[2].y = cyClient / 2 + 80;
apt[3].x = cxClient / 2 + 100;
apt[3].y = cyClient / 2 + 60;
Polygon(hdc, apt, 4);
SelectObject(hdc, hOldBrush);
Ellipse(hdc, cxClient / 2 + 168, cyClient / 2 + 60, cxClient / 2 + 138, cyClient / 2 + 90); //右手掌
//去多余线,增强立体感
hPen = CreatePen(PS_SOLID, 2, RGB(0, 159, 232));
hOldPen = SelectObject(hdc, hPen);
MoveToEx(hdc, cxClient / 2 - 100, cyClient / 2, NULL);;
LineTo(hdc, cxClient / 2 - 100, cyClient / 2 + 50);;
MoveToEx(hdc, cxClient / 2 + 100, cyClient / 2, NULL);;
LineTo(hdc, cxClient / 2 + 100, cyClient / 2 + 50);
SelectObject(hdc, hOldPen);
EndPaint(hwnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
|