使用GDI分段填充三角形区域

之前做过对矩形的分段填充,这个操作就类似于进度条。这次对三角形区域进行分段填充。

我们可以将这个操作想象为从左到右拿着一根线一点一点的进行扫描,要记录每一个瞬间的图形,然后通过CreatePolygonRgn函数将扫描过程中的图形创建出来,然后用FillRgn上色填充。具体代码如下:


#include <windows.h>


//GDI分段绘制区域


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


int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
	static TCHAR szAppName[] = TEXT("ProgressBar");
	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_INFORMATION);
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szAppName;

	RegisterClass(&wndclass);

	hwnd = CreateWindow(szAppName, L"自绘一个进度条",
		WS_OVERLAPPEDWINDOW,
		100, 200, 800, 600, NULL, NULL, hInstance, NULL
	);


	ShowWindow(hwnd, nShowCmd);
	UpdateWindow(hwnd);

	RECT rect;
	GetClientRect(hwnd, &rect);
	
	while (1)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			if (msg.message == WM_QUIT)
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			
		}
	}


	return msg.wParam;
}




LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	HRGN hRgn,hRgn2;
	HBRUSH hBrush, hBrush2;
	POINT point[4] = { 100,300,100,400,200,350,100,300 }; //三角形区域,第一个点100,300和第二个点100,400构成一条直线
	static int line = 100;  //从x=100开始扫描              //第二个点100,400和第三个点200,350构成一条直线
	static int x1 = 0, y1 = 0,x2=0,y2=0;//变化的两个点     //第三个点200,350和100,300构成最后一条直线
	RECT rect;
	POINT p[4] = { 100,300,100,400,0,0,0,0 };//前两个点是一样的,就变化两个点
	//因为在扫描三角形的过程中,图形会变成一个梯形,但变化的只有两个点
	

	//分段填充三角形
	//第一个点和第二个点是在x轴上,所以我们从x=100开始分段填充三角形区域
    //就相当于拿根横穿三角形的直线,计算与两个斜边的交点,加上前两个点构成一个区域
	//创建这个区域,然后用FillRgn进行填充,以此来达到分段填充的目的
	//第一个点和第三个点的直线方程为:y=1/2x+250,第二个点与第三个点的直线方程为:y=-1/2x+450,可以用两点式方程算下

	switch (message)
	{
	case WM_TIMER:   //定时器消息 
		GetClientRect(hwnd, &rect);
		InvalidateRect(hwnd, &rect, TRUE);//因为所重绘的图形不多,所以就无效整个客户区的矩形
		return 0;
	case WM_CREATE:
		SetTimer(hwnd, 1, 100, NULL);
		return 0;
	case WM_SIZE:

		return 0;
	case WM_PAINT:

		hdc = BeginPaint(hwnd, &ps);
		
		hBrush = CreateSolidBrush(BLACK_BRUSH);
		
		hRgn = CreatePolygonRgn(point, 4, ALTERNATE); //创建了一个三角形区域,这个区域用的是跟窗口背景
		                                              //一样的白色,所以看不出来
		SelectObject(hdc, hRgn);
		PaintRgn(hdc, hRgn);   //使用当前的画刷,也就是窗口的的背景色
		
		if (line < 200)
		{
			//计算与两条直线的交点
		    //第一条;y=1/2x+250
			x1 = line;
			y1 = 1.0 / 2.0 * line + 250;
			//第二条:y=-1/2x+450
			x2 = line;
			y2 = -1.0 / 2.0 * line + 450;
			p[2].x = x2;
			p[2].y = y2;
			p[3].x = x1;
			p[3].y = y1;
			hRgn2 = CreatePolygonRgn(p, 4, ALTERNATE);
			SelectObject(hdc, hRgn2);
			FillRgn(hdc, hRgn2, hBrush);
			DeleteObject(hRgn2);
			
			line++;
		}
		
		
		if (line == 200)
		{
			hRgn2 = CreatePolygonRgn(point, 4, ALTERNATE);
			SelectObject(hdc, hRgn2);
			FillRgn(hdc, hRgn2, hBrush);
			DeleteObject(hRgn2);
		}

		

		DeleteObject(hRgn);
		DeleteObject(hBrush);
		EndPaint(hwnd, &ps);
		return 0;
	case WM_DESTROY:

		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}


瞬间的结果如下:

 三角形区域如下:

 通过这次学习,我感觉搞图形研究数学很关键,我这次还是简单的三角形,在复杂点就要写好多方程了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamXY12

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值