Windows编程(一)画一只哆啦A梦

 本文为一Windows编程API绘图实战小例子,学习自哔哩哔哩小甲鱼的《Windows程序设计SDK》。最终效果展示:

Windows编程(一)画一只哆啦A梦_第1张图片

源码在最后,跟着小甲鱼老师敲一遍代码,这些API能记住不少。 

一、大体脉络

Windows编程(一)画一只哆啦A梦_第2张图片

Windows编程(一)画一只哆啦A梦_第3张图片

Windows编程(一)画一只哆啦A梦_第4张图片

Windows编程(一)画一只哆啦A梦_第5张图片

Windows编程(一)画一只哆啦A梦_第6张图片

Windows编程(一)画一只哆啦A梦_第7张图片

Windows编程(一)画一只哆啦A梦_第8张图片

Windows编程(一)画一只哆啦A梦_第9张图片

Windows编程(一)画一只哆啦A梦_第10张图片

Windows编程(一)画一只哆啦A梦_第11张图片

Windows编程(一)画一只哆啦A梦_第12张图片

二、相关知识细则(来自鱼C工作室)

1.WM_SIZE 消息

  • 消息含义:
  1. 当主窗口的客户区部分大小改变时,操作系统将给应用程序发送 WM_SIZE 消息
  2. 应用程序通过窗口过程接收该消息
  • 消息定义:
#define WM_SIZE                         0x0005
  • 参数解析:
  1. wParam:指出窗口的新状态
  2. wParam 参数可以是下列值之一:
含义
SIZE_MAXHIDE(4) 当该应用程序的其他窗口被最大化的时候,消息被发送往所有的弹出窗口
SIZE_MAXIMIZED(2) 该窗口被最大化
SIZE_MAXSHOW(3) 当该应用程序的其他窗口已经恢复到原来大小的时候,消息被发送往所有的弹出窗口
SIZE_MINIMIZED(1) 该窗口被最小化
SIZE_RESTORED(0) 该窗口的大小发生变化,但不是最大化(SIZE_MAXIMIZED)或最小化(MINIMIZED)
  • lParam:指出当前客户区的大小(宽度和高度)
  1. lParam 参数的低 16 位指定了新窗口的宽度;
  2. lParam 参数的高 16 位制定了新窗口的高度。
  • 温馨提醒:可以通过 LOWORD 宏和 HIWORD 宏来获取 lParam 参数的低 16 位和高 16 位。
  • 返回值:如果窗口过程响应该消息,必须返回 0。

2.RGB宏

  • 宏功能:
  1. RGB 宏有三个参数(byRed, byGreen, byBlue),功能是将这三个参数转换为 COLORREF 颜色值。
  2. 注释:COLORREF 颜色被定义为 DWORD 类型(4 个字节),用于表示 RGB 颜色。
  • 宏原型:
COLORREF RGB(
   BYTE byRed,
   BYTE byGreen,
   BYTE byBlue
);
  • 参数解析:
参数 含义
byRed 红色的颜色值
byGreen 绿色的颜色值
byBlue 蓝色的颜色值
  • 小甲鱼忍不住罗嗦补充一句:色彩中不能再分解的基本色称之为原色,红绿蓝即三原色,将它们按照不同比例混合,可以搭配出所有的颜色。
  • 返回值:返回三个参数转换后的 COLORREF 颜色值
  • 备注:
  1. 每个颜色可以指定的颜色值是 0 ~ 255,三个参数同时为 0,即黑色,同时为 255 即白色。
  2.  通过 GetRValue、GetGValue 和 GetBValue 宏可以分别从 COLORREF 颜色值中获得红色、绿色、蓝色的颜色值。

3.LOWORD 和 HIWORD 宏

  • 宏功能:
  1. 获得指定 32 位数据的低 16 位数据和高 16 位数据。
  2. 小甲鱼温馨提醒:不要使用 LOWORD 和 HIWORD 宏去获取鼠标的坐标,因为在多显示器的情况下会得到错误的坐标。应该使用 GET_X_LPARAM 和 GET_Y_LPARAM 宏来获取。
  • 宏定义:
WORD LOWORD(
   DWORD dwValue
);
……
WORD HIWORD(
   DWORD dwValue
);
  • 参数解析:
参数 含义
lParam 32 位的目标数据
  • 返回值:
  1. LOWORD(lParam) 返回 lParam 的低 16 位数据;
  2. 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 轴坐标,按逻辑单位表示坐标
lpPoint 1. 一个 POINT 结构的指针,用于获得之前位置的坐标
2. 如果这个值是 NULL,则不会获得之前位置的坐标
  • 返回值:
  1. 如果函数调用成功,返回值是非 0;
  2. 如果函数调用失败,返回值是 0。
  • 备注:
  1. MoveExTo 函数将影响所有的绘图函数。
  2. 在默认的设备环境中,点 (0, 0) 为最初设定的当前位置。

6.LineTo

  • 函数功能:
  1. LineTo 函数使用当前画笔绘制一条线,线段从当前位置连到一个指定的点 (x, y)。
  2. 当这个函数调用完毕后,当前位置变成 (x, y)。
  3. 小甲鱼提示:所绘制的线段并不包含指定的点 (x, y)。
  • ​​​​​​API 函数原型:注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。
BOOL LineTo(
  _In_  HDC hdc,
  _In_  int nXEnd,
  _In_  int nYEnd
);
  • 参数解析:
参数 含义
hdc 指定设备环境句柄
nXEnd 1. 线段终点X坐标位置,采用逻辑坐标表示。
2. 这个点不会实际画出来,因为它不属于线段的一部份
nYEnd 1. 线段终点Y坐标位置,采用逻辑坐标表示。
2. 这个点不会实际画出来,因为它不属于线段的一部份
  • 返回值:
  1. 如果函数调用成功,返回值是非 0;
  2. 如果函数调用失败,返回值是 0。

7.Rectangle

  • 函数功能:
  1. Rectangle 函数用于绘制一个矩形。
  2. 该矩形用当前画笔绘制轮廓,用当前画刷填充。

Windows编程(一)画一只哆啦A梦_第13张图片

  • 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 坐标
  • 返回值:
  1. 如果函数调用成功,返回值是非 0;
  2. 如果函数调用失败,返回值是 0。
  • 备注:
  1.  该函数既不使用当前位置,也不修改当前位置。
  2. 写过图形程序的程序员通常熟悉边界偏差(off-by-one)的问题:一些图形程序系统画出的图形包含了右坐标和底坐标表示的点,一些则只画到右坐标和底坐标表示的点之前的一点。Windows 使用后一种方法。
  3. 如果使用 PS_NULL 画笔,则矩形的尺寸高和宽比实际少一个像素。

8.Ellipse

  • 函数功能:
  1. Ellipse 函数用于绘制一个椭圆,椭圆的中心是限定矩形的中心。
  2. 该椭圆用当前画笔绘制轮廓,用当前画刷填充。

Windows编程(一)画一只哆啦A梦_第14张图片

  •  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 坐标
  • 返回值:
  1. 如果函数调用成功,返回值是非 0;
  2. 如果函数调用失败,返回值是 0。
  • 备注:该函数既不使用当前位置,也不修改当前位置。

9.RoundRect 

  • 函数功能:
  1. RoundRect 函数用于绘制一个带圆角的矩形。
  2. 该矩形用当前画笔绘制轮廓,用当前画刷填充。

Windows编程(一)画一只哆啦A梦_第15张图片

  • 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 指定用来画圆角的椭圆的高
  • 返回值:
  1. 如果函数调用成功,返回值是非 0;
  2. 如果函数调用失败,返回值是 0。
  • 备注:该函数既不使用当前位置,也不修改当前位置。

10.Arc 

  • 函数功能:Arc 函数用于绘制一个椭圆的圆弧。

Windows编程(一)画一只哆啦A梦_第16张图片

  • 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 坐标
  • 返回值:
  1. 如果函数调用成功,返回值是非 0;
  2. 如果函数调用失败,返回值是 0。
  • 备注:
  1. 点 (xLeft, yTop) 和点 (xRight, yBottom) 指定限定矩形的位置。
  2. 由指定的限定矩形形成的椭圆定义弧的曲线。
  3. 弧的起始点 (xStart, yStart) 开始和终点 (xEnd, yEnd) 并不在椭圆上,而是定义为在椭圆的中心的延长线上(不懂的鱼油请看上图)。
  4. 如果椭圆的起始点和终点是同一个点,那么将绘制整个椭圆。

11.Pie

  • 函数功能:
  1. Pie 函数绘制一个由弧以及椭圆中心构成的扇形。
  2. 该扇形用当前画笔绘制轮廓,用当前画刷填充。

Windows编程(一)画一只哆啦A梦_第17张图片

  • 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 坐标
  • 返回值:
  1. 如果函数调用成功,返回值是非 0;
  2. 如果函数调用失败,返回值是 0。
  • 备注:
  1. 扇形对应的曲线(弧)由限定矩形画出的椭圆所指定。
  2. 曲线(弧)的起始点 (xStart, yStart) 开始和终点 (xEnd, yEnd) 并不在椭圆上,而是定义为在椭圆的中心的延长线上(不懂的鱼油请看上图)。
  3. 该函数既不使用当前位置,也不修改当前位置。

三、程序源码

#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);
}

 

你可能感兴趣的:(C/C++)