现在的位置: 首页 > 综合 > 正文

windows程序设计(7):绘制贝塞尔曲线

2013年08月20日 ⁄ 综合 ⁄ 共 2773字 ⁄ 字号 评论关闭
#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);
}

在windows中,使用PolyBezier函数绘制贝塞尔曲线。

程序中要注意的是:WM_MOUSEMOVE下的消息处理方式:先用白色的画笔画曲线,再用黑色的画笔画曲线,这样就做出了皮筋一样的效果:第一条曲线实际上是随着鼠标运动而产生的轨迹,不是我们想要的结果,我们想要的是最后移动到位置时的曲线,所以最后才用我们自定义的笔(这里定义为红色,虚线)画图。

抱歉!评论已关闭.