Windows GDI 教程(三) 绘制函数图像以及多边形

SetPixel

画一个点。函数原型:

COLORREF SetPixel(
  _In_  HDC hdc,	// DC句柄
  _In_  int X,		// x 坐标
  _In_  int Y,		// y 坐标
  _In_  COLORREF crColor // 颜色
);

绘制函数图像

上一节有说过在画渐变的时候其实用画点的函数会更好用,这里就使用 SetPixel 函数来绘制一个点。

#include <windows.h>
#include <math.h>

// 用于注册的窗口类名
const char g_szClassName[] = "myWindowClass";

#define POS_X 150		// 坐标系原点 x 
#define POS_Y 130		// 坐标系原点 y 
#define POS_WIDTH 100	// 坐标系宽度
#define BLACK_COLOR RGB(0, 0, 0) // 黑色

/*
 * 要绘制的函数:
 * f(x) = sin(x/10) * 20
 */
double f(double x)
{
	return sin(x/10) * 20;
}

void Paint(HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc;   // DC(可画图的内存对象) 的句柄
    HPEN hpen; // 画笔
    int x, y;
	double i;

    hdc = BeginPaint(hwnd, &ps);
    hpen = CreatePen(PS_SOLID, 1, BLACK_COLOR);
    SelectObject(hdc, hpen);

	// 绘制 x 轴
    MoveToEx(hdc, POS_X - POS_WIDTH, POS_Y, NULL);
    LineTo(hdc, POS_X + POS_WIDTH, POS_Y);

	// 绘制 y 轴
	MoveToEx(hdc, POS_X, POS_Y + POS_WIDTH, NULL);
	LineTo(hdc, POS_X, POS_Y - POS_WIDTH);

	// 绘制 f(x) = sin(x/10) * 20 的函数图像
	for (i = -POS_WIDTH; i < POS_WIDTH; i += 0.05) // x每增长0.05绘制1个点
	{
		x = POS_X + i;
		y = POS_Y + f(i);
		// 在 (x,y) 处绘制一个点
		SetPixel(hdc, x, y, BLACK_COLOR);
	}

    DeleteObject(hpen);
    EndPaint(hwnd, &ps);
}

效果图:
绘制函数图像

PS: 这个画点的 SetPixel 函数很简单,各位可以试着用它来修改一下上一节中颜色渐变的例子。

Polyline

Polyline 与 lineto 类似,区别在于 lineto 每画一条线当时就写入显存,而 Polyline则是把指定的坐标数组中所有线都画完之后才写入显存。

BOOL Polyline(
  _In_  HDC hdc,			// DC句柄
  _In_  const POINT *lppt,	// 要绘制的点的数组
  _In_  int cPoints			// 要绘制的点的个数
);

一次绘制多条连通的线示例

void Paint(HWND hwnd)
{
	PAINTSTRUCT ps;
	HDC hdc;
	HPEN hPen;
	POINT poly[4];

	hdc = BeginPaint(hwnd, &ps);

	// 设置画笔
	hPen = CreatePen(PS_SOLID, 3, RGB(0,0,255));
	SelectObject(hdc, hPen);

	poly[0].x = 100;
	poly[0].y = 150;

	poly[1].x = 200;
	poly[1].y = 150;

	poly[2].x = 150;
	poly[2].y = 50;

	poly[3].x = 250;
	poly[3].y = 50;

	Polyline(hdc, poly, 4);

	EndPaint(hwnd, &ps);
}

效果图:
绘制不规则图形

RECT 结构体

RECT 即 Rectangle 矩形结构体,实际上就存储了两个坐标,一个是左上、一个是右下。

typedef struct 
{
    LONG    left;	// 左
    LONG    top;	// 上
    LONG    right;	// 右
    LONG    bottom; // 下
} RECT;

SetRect

用于设置 RECT 结构体的值。

BOOL SetRect(
    __out LPRECT lprc,	// RECT 结构体指针
    __in int xLeft,		// 左
    __in int yTop,		// 上
    __in int xRight,	// 右
    __in int yBottom	// 下
);

RectVisible

检查目标DC中的指定矩形区域是否可见

WINGDIAPI BOOL WINAPI RectVisible(
	__in HDC hdc, 				// 目标DC
	__in CONST RECT * lprect 	// 指定矩形区域
);

SetViewportOrgEx

修改指定DC中的坐标系原点

BOOL SetViewportOrgEx(
  _In_   HDC hdc,
  _In_   int X,
  _In_   int Y,
  _Out_  LPPOINT lpPoint
);

多边形绘制实例

包括三角形、正方形、五边形、六边形。

POINT aptTriangle[4] = { {50,2}, {98,86},  {2,86}, {50,2}}, 
	aptRectangle[5]  = { { 2,2}, {98,2},  {98,98},  {2,98}, {2,2}}, 
	aptPentagon[6]   = { {50,2}, {98,35}, {79,90}, {21,90}, {2,35}, {50,2}}, 
	aptHexagon[7]    = { {50,2}, {93,25}, {93,75}, {50,98}, {7,75}, {7,25}, {50,2}}; 

void Paint(HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc;   // DC(可画图的内存对象) 的句柄
    HPEN hpen; // 画笔
	RECT rc;

	hdc = BeginPaint(hwnd, &ps); 
	// 初始化矩形 rc 用于表明绘图范围
	SetRect(&rc, 0, 0, 100, 100); 

	// 如果 rc 所包括的范围可见
	if (RectVisible(hdc, &rc)) 
		// 绘制三角形
		Polyline(hdc, aptTriangle, 4); 

	// 修改当前DC坐标系原点为 (100,0)
	SetViewportOrgEx(hdc, 100, 0, NULL); 
	if (RectVisible(hdc, &rc)) 
		// 绘制正方体
		Polyline(hdc, aptRectangle, 5); 

	// 修改当前DC坐标系原点为 (0,100)
	SetViewportOrgEx(hdc, 0, 100, NULL); 
	if (RectVisible(hdc, &rc)) 
		// 绘制五边形
		Polyline(hdc, aptPentagon, 6); 

	// 修改当前DC坐标系原点为 (100,100)
	SetViewportOrgEx(hdc, 100, 100, NULL); 
	if (RectVisible(hdc, &rc)) 
		// 绘制六边形
		Polyline(hdc, aptHexagon, 7); 

	EndPaint(hwnd, &ps); 
}

效果图:
绘制多边形

教程索引

上一节:Windows GDI 教程(二) 画笔的颜色与样式
下一节:Windows GDI 教程(四) 文字与字体

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google+ photo

You are commenting using your Google+ account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s