第五章 图形基础(一)

保存设备描述表

   在释放设备描述表之后,仍然保存程序中设备描述表的改变,以便在下一次调用时起作用

   在登陆窗口类时,将CS_OWNDC标志包含位窗口类的一部分

   wndclass.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;

   这样,基于这个窗口类的所创建的每个窗口将都拥有自己的设备描述表,他一直存在,直到窗口被删除,如果使用了CS_OWNDC,就只需要初始化设备描述表一次,处理WM_CREATE消息期间完成这一操作:

   case WM_CREATE

   hdc=GetDC(hwnd);

   RelaeseDC(hwnd,hdc);

   这些属性在改变之前一直有效。

5.3.1写像素

5.3.2直线

MoveToEx 设置设备描述表的当前属性,然后LineTo函数从当前位置到它的点画一条直线。

获取当前位置

GetCurrentPositionEx(hdc,&pt);

绘制网格

GetClientRect(hWnd, &rect);

void paintGrid(HDC hDc, RECT &rect)
{
    int x, y;
    for (x = 0; x < rect.right; x += 120)
    {
        MoveToEx(hDc, x, 0, NULL);
        LineTo(hDc, x, rect.bottom);
    }
    for (y = 0; y < rect.bottom; y += 210)
    {
        MoveToEx(hDc, 0, y, NULL);
        LineTo(hDc, rect.right, y);
    }
}

绘制正弦曲线

case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return (0);

case WM_PAINT:
        hDC = ::BeginPaint(hWnd, &ps);

MoveToEx(hDC, 0, cyClient / 2, NULL);
        LineTo(hDC, cxClient, cyClient/2);

        for (i=0;i<NUM;i++)
        {
            pt[i].x = i * cxClient / NUM;
            pt[i].y = int(cyClient/2 *(1- sin (2*3.1415926*i/NUM)));
        }
        Polyline(hDC, pt, NUM);

       ::EndPaint(hWnd, &ps);
        return (0);

PolyLine 和 PolyLineTo

5.3.3边界框函数

矩形

Rectangle(hDC, 100, 100, 400, 500);

椭圆形

Ellipse(hDC, 700, 100, 1000, 200);

RoundRect

条弧,弓形扇形

   

  

5.3.4贝塞尔曲线

转自:https://blog.csdn.net/thefutureisour/article/details/7578107

#include <windows.h>
#include <math.h>
#define NUM 1000
#define TWOPI (2*3.14159)

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

int WINAPI WinMain(HINSTANCE hInstance,		//当前实例句柄
	HINSTANCE hPrevInstance, //先前实例句柄
	LPSTR lpCmdLine,			//命令行
	int iCmdShow)			//显示状态
{
	static TCHAR szAppName[] = TEXT("Bezier");
	//窗口句柄
	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))
	{
		return -1;
	}

	//创建窗口
	hwnd = CreateWindow(szAppName,				//窗口类的名称,必须是已经注册的
		TEXT("贝塞尔函数"),		//窗口标题
		WS_OVERLAPPEDWINDOW,	//窗口风格
		CW_USEDEFAULT,			//X坐标
		CW_USEDEFAULT,			//Y坐标
		CW_USEDEFAULT,			//宽度
		CW_USEDEFAULT,			//高度
		NULL,					//父窗口句柄
		NULL,					//菜单窗口句柄
		hInstance,				//高级版本的windos忽略
		NULL);

	//显示窗口
	//ShowWindow(hwnd,SW_SHOWNA);
	ShowWindow(hwnd, iCmdShow);

	//更新窗口
	UpdateWindow(hwnd);

	//消息循环
	while (GetMessage(&msg, NULL, 0, 0))
	{

		TranslateMessage(&msg);
		//将消息给窗口
		DispatchMessage(&msg);

	}

	return msg.wParam;

}


void DrawBezier(HDC hdc, POINT apt[])
{
	//调用系统的绘制贝塞尔函数
	PolyBezier(hdc, apt, 4);

	MoveToEx(hdc, apt[0].x, apt[0].y, NULL);
	LineTo(hdc, apt[1].x, apt[1].y);

	MoveToEx(hdc, apt[2].x, apt[2].y, NULL);
	LineTo(hdc, apt[3].x, apt[3].y);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;
	int i, j;
	static int cxClient, cyClient;
	static POINT apt[4];
	switch (message)
	{

	case WM_SIZE:
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);

		//4个点分别是起点,第一控制点,第二控制点。终点
		apt[0].x = cxClient / 4;
		apt[0].y = cyClient / 2;

		apt[1].x = cxClient / 2;
		apt[1].y = cyClient / 4;

		apt[2].x = cxClient / 2;
		apt[2].y = 3 * cyClient / 4;

		apt[3].x = 3 * cxClient / 4;
		apt[3].y = cyClient / 2;

		return 0;
	case WM_LBUTTONDOWN:
	case WM_RBUTTONUP:
	case WM_MOUSEMOVE:
		//左键或者右键均可画图
		if (wParam & MK_LBUTTON || wParam & MK_RBUTTON)
		{
			hdc = GetDC(hwnd);
			//用白笔
			SelectObject(hdc, GetStockObject(WHITE_PEN));
			//自定义的画贝叶斯曲线的函数
			DrawBezier(hdc, apt);
			//左键控制第一控制点
			if (wParam & MK_LBUTTON)
			{
				apt[1].x = LOWORD(lParam);
				apt[1].y = HIWORD(lParam);
			}
			//右键控制第二控制点
			if (wParam & MK_RBUTTON)
			{
				apt[2].x = LOWORD(lParam);
				apt[2].y = HIWORD(lParam);
			}
			//换成自定义的画笔

			SelectObject(hdc, CreatePen(PS_DASH, 0, RGB(255, 0, 0)));
			//画曲线
			DrawBezier(hdc, apt);

			ReleaseDC(hwnd, hdc);
		}
		return 0;
	case WM_PAINT:
		InvalidateRect(hwnd, NULL, TRUE);
		hdc = BeginPaint(hwnd, &ps);
		//这一句的目的是为了一开始的时候就有曲线
		DrawBezier(hdc, apt);

		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
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值