Windows图形设备接口和绘图

1.画刷和画笔的应用:

新建一个空的Win32项目,手动添加一个源文件Source.cpp,键入以下代码:

#include<Windows.h>
#include<stdlib.h>
#include<string.h>

long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
BOOL InitWindowsClass(HINSTANCE hInstance);
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow);

//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
	MSG Message;
	if (!InitWindowsClass(hInstance))return FALSE;  //窗口类初始化或者叫注册
	if (!InitWindows(hInstance, nCmdShow))return FALSE;  //初始化窗口
	while (GetMessage(&Message, 0, 0, 0))  //消息循环
	{
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}
	return Message.wParam;
}

long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam)
{
	HDC hDC;  //定义设备环境句柄
	HBRUSH hBrush;  //定义画刷句柄
	HPEN hPen;  //定义画笔句柄
	PAINTSTRUCT PtStr;  //定义指向包含绘图信息的结构体变量
	//定义一个POINT数组,包括6个点
	POINT points[6] = { { 100, 212 }, { 70, 227 }, { 70, 250 }, { 130, 250 }, { 130, 227 }, { 100, 212 } };
	switch (iMessage)  //消息处理
	{
	case WM_PAINT:  //处理绘图消息
		hDC = BeginPaint(hWnd, &PtStr);
		hPen = (HPEN)GetStockObject(NULL_BRUSH);  //获取系统定义的空画笔
		SelectObject(hDC, hPen);  //选择画笔
		hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH); //获取系统定义的画刷
		SelectObject(hDC, hBrush);  	//选择画刷
		LineTo(hDC, 50, 50);  		//画线
		DeleteObject(hPen); 		//删除画笔
		hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); //创建画笔
		SelectObject(hDC, hPen);  	//选择画笔
		//画一个三角形
		LineTo(hDC, 150, 50);
		LineTo(hDC, 100, 137);
		LineTo(hDC, 50, 50);
		Polyline(hDC, points, 6); //画一个五边形
		Arc(hDC, 63, 137, 138, 212, 100, 137, 100, 137); //画一个圆
		Pie(hDC, 213, 137, 288, 212, 240, 137, 260, 137); 	//画一个圆饼
		Rectangle(hDC, 213, 212, 287, 250);  //画一个长方形
		RoundRect(hDC, 213, 100, 287, 137, 20, 20);  //画一个圆角长方形
		DeleteObject(hPen);    //删除画笔
		DeleteObject(hBrush);  //删除画刷
		EndPaint(hWnd, &PtStr);  //结束绘图
		return 0;
	case WM_DESTROY:  //结束应用程序
		PostQuitMessage(0);
		return 0;
	default://其他消息处理程序
		return(DefWindowProc(hWnd, iMessage, wParam, lParam));
	}
}
//初始化窗口
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;
	hWnd = CreateWindow(L"WinFill", L"填充示例", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
	if(!hWnd)
		return FALSE;
	ShowWindow(hWnd, nCmdShow);  //显示窗口
	UpdateWindow(hWnd);
	return TRUE;
}
BOOL InitWindowsClass(HINSTANCE hInstance)
{
	WNDCLASS WndClass;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH)); //窗口背景:白色
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, L"END");
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = WndProc;  //消息处理函数
	WndClass.lpszClassName = L"WinFill";
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	return RegisterClass(&WndClass);
}

执行结果如图:


2.设置映像模式

映像模式定义了将逻辑单位转化为设备的度量单位以及设备的x方向和y方向。缺省的模式为TEXT绘图模式。

#include<Windows.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
BOOL InitWindowsClass(HINSTANCE hInstance);
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow);
int nMode;  //记录映射模式
//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
	MSG Message;
	if (!InitWindowsClass(hInstance))return FALSE;  //窗口类初始化或者叫注册
	if (!InitWindows(hInstance, nCmdShow))return FALSE;  //初始化窗口
	while (GetMessage(&Message, 0, 0, 0))  //消息循环
	{
		TranslateMessage(&Message);
		DispatchMessage(&Message);
	}
	return Message.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam)
{
	HDC hDC;  //定义设备环境句柄
	HBRUSH hB1,hB2;  //定义画刷句柄
	PAINTSTRUCT ps;  //定义指向包含绘图信息的结构体变量
	
	switch (iMessage)  //消息处理
	{
	case WM_LBUTTONDOWN:  //鼠标左键单击消息
		nMode = MM_ISOTROPIC;				//更改映射模式为MM_ISOTROPIC
		InvalidateRect(hWnd, NULL, 1);		//刷新用户区
		break;
	case WM_RBUTTONDOWN:					//单击鼠标右键消息
		nMode = MM_ANISOTROPIC;			//更改显示模式为MM_ANISOTROPIC
		InvalidateRect(hWnd, NULL, 1);		//刷新用户区
		break;
	case WM_DESTROY:  //结束应用程序
		PostQuitMessage(0);
		return 0;
	case WM_PAINT:
		hDC = BeginPaint(hWnd, &ps);			//取得设备环境句柄
		SetMapMode(hDC, nMode);				//设置映射模式
		SetWindowExtEx(hDC, 150, 150, NULL); 	//设置窗口区域
		SetViewportExtEx(hDC, 150, 100, NULL); 	//设置视口区域
		SetViewportOrgEx(hDC, 150, 60, NULL); 	//设置视口原点
		hB1 = (HBRUSH)GetStockObject(WHITE_BRUSH);		//定义白色画刷
		hB2 = (HBRUSH)GetStockObject(BLACK_BRUSH);		//定义黑色画刷
		SelectObject(hDC, hB1);				//将黑白刷选入设备环境
		RoundRect(hDC, 0, 0, 150, 150, 30, 30);	//绘制圆角矩形并填充
		SelectObject(hDC, hB2);				//更改当前画刷为黑色画刷 
		Ellipse(hDC, 0, 10, 150, 140);			//绘制椭圆并填充
		EndPaint(hWnd, &ps);					//释放设备环境句柄
		DeleteObject(hB1);					//删除画刷句柄
		DeleteObject(hB2);
		break;
	default://其他消息处理程序
		return(DefWindowProc(hWnd, iMessage, wParam, lParam));
	}
}
//初始化窗口
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow)
{
	HWND hWnd;
	hWnd = CreateWindow(L"映射模式", L"My_Map_Mode", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
	if(!hWnd)
		return FALSE;
	ShowWindow(hWnd, nCmdShow);  //显示窗口
	UpdateWindow(hWnd);
	return TRUE;
}
BOOL InitWindowsClass(HINSTANCE hInstance)
{
	WNDCLASS WndClass;
	WndClass.cbClsExtra = 0;
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH)); //窗口背景:白色
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(NULL, L"END");
	WndClass.hInstance = hInstance;
	WndClass.lpfnWndProc = WndProc;  //消息处理函数
	WndClass.lpszClassName = L"映射模式";
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_HREDRAW | CS_VREDRAW;
	return RegisterClass(&WndClass);
}

执行结果:

按下左键:按下鼠标右键:


3.实现一个圆沿着正玄曲线移动的试验,并且每四分之一周期颜色发生变化。

#include<Windows.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<cmath>
#define Pi 3.1415926
long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);	//消息处理函数声明.
double dfTheta = 0, dfRange = 100.0;						//正弦曲线的角度变量.
long i = 0, j = 0;
long lCentreX = 0, lCentreY = 0, lRadious = (long)(0.2*dfRange);//定义圆心坐标和圆坐标.
POINT lpSin[100];	//定义正弦曲线的点坐标.

//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
	MSG Message;			//定义消息变量.
	HWND hWnd;				//定义窗口句柄.

	WNDCLASS WndClass;		//定义窗口类.
	WndClass.cbClsExtra = 0;		//无窗口类扩展.
	WndClass.cbWndExtra = 0;		//无窗口实例扩展.
	WndClass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH));//背景为白色.
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);	//窗口采用箭头光标.
	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);	//采用缺省图标.
	WndClass.hInstance = hInstance;					//当前应用程序句柄.
	WndClass.lpfnWndProc = WndProc;					//窗口处理函数.
	WndClass.lpszClassName = L"SIN";					//窗口类名称.
	WndClass.lpszMenuName = NULL;						//无窗口菜单.
	WndClass.style = 0;								//窗口类型为缺省类型.

	if (!RegisterClass(&WndClass))			//注册窗口.
	{
		MessageBeep(0);
		return FALSE;
	}

	hWnd = CreateWindow(L"SIN",				//窗口类名.
		L"4_6",					//标题名.
		WS_OVERLAPPEDWINDOW,	//带标题栏,最大和最小按钮的窗口.
		CW_USEDEFAULT,			//窗口左上角坐标.
		0,
		CW_USEDEFAULT,			//采用缺省的宽度和高度.
		0,
		NULL,					//无父窗口.
		NULL,					//无主菜单.
		hInstance,				//当前实例句柄.
		NULL);					//不要此参数.
	ShowWindow(hWnd, nCmdShow);			//显示窗口.
	UpdateWindow(hWnd);					//更新并绘制用户区.

	for (int j = 0; j<100; j++)		//生成正弦曲线的点坐标.
	{
		lpSin[j].x = (long)(j * 2 * Pi / 100 * 60);
		lpSin[j].y = (long)(dfRange*sin(j * 2 * Pi / 100));
	}

	while (GetMessage(&Message, 0, 0, 0))
	{
		TranslateMessage(&Message);			//消息循环.
		DispatchMessage(&Message);
	}
	return Message.wParam;
}
long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam)	//消息处理函数.
{
	HDC hDC;				//定义设备环境句柄.
	HBRUSH hBrush;			//定义画刷句柄
	HPEN hPen;				//定义画笔句柄
	PAINTSTRUCT PtStr;		//定义包含绘图信息的结构体变量

	switch (iMessage)
	{
	case WM_PAINT:  //处理绘图消息.
		hDC = BeginPaint(hWnd, &PtStr);		//获得设备环境指针.
		SetWindowOrgEx(hDC, -100, -100, NULL);	//设置原点坐标为(-100,-100).

		hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));	//创新画笔.
		SelectObject(hDC, hPen);					//选入画笔.
		Polyline(hDC, lpSin, 100);				//绘制正弦曲线.

		if (i <= 25) //第一个1/4周期.
		{
			hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));//创新红笔.
			hBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(255, 0, 0));//创新红画刷.
			lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
		}
		else if (i <= 50)//第二个1/4周期.
		{
			hPen = CreatePen(PS_DASH, 1, RGB(0, 255, 0));//创新绿笔.
			hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 255, 0));//创新绿刷.
			lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
		}
		else if (i <= 75)//第三个周期.
		{
			hPen = CreatePen(PS_DASH, 1, RGB(0, 0, 255));//创新蓝笔
			hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 0, 255));//创新蓝刷.
			lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
		}
		else//第四个周期.
		{
			hPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));//创新黄笔
			hBrush = CreateHatchBrush(HS_VERTICAL, RGB(255, 255, 0));//创新黄刷.
			lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
		}
		SelectObject(hDC, hBrush);	//选入画刷.
		SelectObject(hDC, hPen);		//选入画笔.
		lCentreX = lpSin[i].x;		//圆心x坐标.
		lCentreY = lpSin[i].y;		//圆心y坐标.
		Ellipse(hDC, lCentreX - lRadious, lCentreY - lRadious,lCentreX + lRadious, lCentreY + lRadious);	//画圆,当椭圆的长短轴相等时为圆

		i++;
		DeleteObject(hPen);		//删除画笔.
		DeleteObject(hBrush);	//删除画刷.
		EndPaint(hWnd, &PtStr);	//删除设备环境指针.
		Sleep(100);				//停0.1秒.
		if (i<100) InvalidateRect(hWnd, NULL, 1);	//刷新用户区.
		return 0;
	case WM_DESTROY:  //关闭窗口.
		PostQuitMessage(0);
		return 0;

	default:
		return(DefWindowProc(hWnd, iMessage, wParam, lParam));
	}
}


运行结果:


4.字符消息的响应,以及不同的映射模式下的图形显示

#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int nMode = MM_TEXT;  //初始绘图模式
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,
	LPSTR lpszCmdLine, int nCmdShow)
{
	HWND hwnd;
	MSG Msg;
	WNDCLASS wndclass;
	//char lpszClassName[] ="映射模式";
	//char lpszTitle[] = "My_Map_Mode";
	wndclass.style = 0;
	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 = L"映射模式";

	if (!RegisterClass(&wndclass))
	{
		MessageBeep(0);
		return FALSE;
	}

	hwnd = CreateWindow(L"映射模式" ,//lpszClassName
		L"My_Map_Mode",//lpszTitle,
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL);

	ShowWindow(hwnd, nCmdShow);	//显示窗口
	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;
	switch (message){
	case WM_CHAR:  //字符消息
		if (wParam == 'a' || wParam == 'A')
			nMode = MM_ISOTROPIC;
		else if (wParam == 'b' || wParam == 'B')
			nMode = MM_ANISOTROPIC;
		else if (wParam == 'c' || wParam == 'C')
			nMode = MM_LOMETRIC;
		else
			;
		InvalidateRect(hwnd, NULL, 1);		//刷新用户区
		break;
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);			//取得设备环境句柄
		SetMapMode(hdc, nMode);              //设置映射模式
		SetWindowExtEx(hdc, 15, 15, NULL); 	//设置窗口区域
		SetViewportExtEx(hdc, 15, 10, NULL); 	//设置视口区域
		SetViewportOrgEx(hdc, 120, 120, NULL); //设置视口原点
		hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); //创建红色画笔
		SelectObject(hdc, hPen);  //将画笔选入设备环境
		//画坐标系,原点在视口原点
		LineTo(hdc, 200, 0);
		LineTo(hdc, 195, -5);
		MoveToEx(hdc, 200, 0, NULL);
		LineTo(hdc, 195, 5);
		MoveToEx(hdc, 0, 0, NULL);
		LineTo(hdc, 0, 200);
		LineTo(hdc, -5, 195);
		MoveToEx(hdc, 0, 200, NULL);
		LineTo(hdc, 5, 195);
		DeleteObject(hPen); //删除画笔
		EndPaint(hwnd, &ps);	//释放设备环境句柄

		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;

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

下图为原始状态、按下A/a键、按下B/b键、按下C/c键后的效果


清华大学MOOC课件

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值