万花筒

简要介绍一下调用Win API实现万花筒的过程:
首先假想一个圆,在其边界上有25个等分点,将其坐标存进数组,等分点的数据结构如下:

typedef struct DOT
{
	POINT point[DOTNUM];	//存储点的x,y坐标
	COLORREF color[DOTNUM];	//每个点的颜色,假设第1个点向第2个点划线,则这条线的颜色是第2个点的颜色
}DOT;

可以看到每个点还有对应的一个颜色,这是因为我们的万花筒是由各种颜色不一的线绘制出来的,因此给每个点设置了一个颜色。假设从a点向b点画一条直线,那么这条直线的颜色就是b点存储的颜色。
代码如下:

#include <Windows.h>
#include <math.h>

#define PI 3.1415926
#define DOTNUM 25			//等分点的个数
#define R 200				//半径

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

BOOL InitWindowsClass(HINSTANCE);

BOOL InitWindows(HINSTANCE, int);

TCHAR lpszClassName[] = L"作业";
TCHAR sizeTitle[] = L"万花筒";

//-------等分点的结构体-------//
typedef struct DOT
{
	POINT point[DOTNUM];	//存储点的x,y坐标
	COLORREF color[DOTNUM];	//每个点的颜色,假设第1个点向第2个点划线,则这条线的颜色是第2个点的颜色
}DOT;

DOT dot;
int j = 0;		//画线时用到
int WINAPI WinMain(
	_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPSTR lpCmdLine,
	_In_ int nCmdShow
)
{
	MSG Msg;
//--------------------设置25个等分点的坐标和每个点的颜色--------------------//
	for (int i = 0; i < DOTNUM; ++i)
	{
		dot.point[i].x = (long)(R * cos((360.0 / DOTNUM) * i * PI / 180.0));
		dot.point[i].y = (long)(R * sin((360.0 / DOTNUM) * i * PI / 180.0));
		switch (i % 4)
		{
		case 0:
			dot.color[i] = RGB(255, 0, 0);
			break;
		case 1:
			dot.color[i] = RGB(0, 255, 0);
			break;
		case 2:
			dot.color[i] = RGB(0, 0, 255);
			break;
		case 3:
			dot.color[i] = RGB(0, 0, 0);
			break;
		}
	}
//-----------------------------------------------------------------------//

	if (!InitWindowsClass(hInstance))
		return 1;
	if (!InitWindows(hInstance, nCmdShow))
		return 1;
	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;
	HPEN hPen;
	PAINTSTRUCT ps;
	switch (message)
	{
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		SetWindowOrgEx(hdc, -400, -250, NULL);//设置原点坐标
//-----------------------------画图---------------------------------------//
		for (int k = 0; k < DOTNUM; ++k)
		{
			for (int i = j; i < DOTNUM; ++i)
			{
				hPen = CreatePen(PS_SOLID, 1, dot.color[i]);//颜色是终点坐标的颜色
				SelectObject(hdc, hPen);
				MoveToEx(hdc, dot.point[j].x, dot.point[j].y, NULL);//画笔放到第1个点
				LineTo(hdc, dot.point[i].x, dot.point[i].y);		//画向第2个点
				DeleteObject(hPen);
				Sleep(10);
			}
			j++;
		}
//-------------------------------两种画法---------------------------------//
		//for (int i = j; i < DOTNUM; ++i)
		//{
		//	hPen = CreatePen(PS_SOLID, 1, dot.color[i]);//颜色是终点坐标的颜色
		//	SelectObject(hdc, hPen);
		//	MoveToEx(hdc, dot.point[j].x, dot.point[j].y, NULL);
		//	LineTo(hdc, dot.point[i].x, dot.point[i].y);
		//	DeleteObject(hPen);
		//	Sleep(100);
		//	InvalidateRect(hWnd, NULL, TRUE);
		//}
		//j++;
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
		break;
	}
	return 0;
}

BOOL InitWindowsClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;
	wcex.cbClsExtra = 0;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.cbWndExtra = 0;
	wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
	wcex.hInstance = hInstance;
	wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
	wcex.lpfnWndProc = WndProc;
	wcex.lpszClassName = lpszClassName;
	wcex.lpszMenuName = NULL;
	wcex.style = 0;
	return RegisterClassEx(&wcex);
}

BOOL InitWindows(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;
	hWnd = CreateWindowEx(
		WS_EX_OVERLAPPEDWINDOW,
		lpszClassName,
		sizeTitle,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
	);
	if (!hWnd)
		return FALSE;
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);
	return TRUE;
}

结果图:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值