DrawText函数
int DrawText(
HDC hDC, // 设备描述表句柄
LPCTSTR lpString, // 将要绘制的字符串
int nCount, // 字符串的长度
LPRECT lpRect, // 指向矩形结构RECT的指针
UINT uFormat // 正文的绘制选项
);
uFormat:
[输入]指定格式化文本的方法。它可以下列值的任意组合,各值描述如下:
DT_CALCRECT:这个参数比较重要,可以使DrawText函数计算出输出文本的尺寸。如果输出文本有多行,DrawText函数使用lpRect定义的矩形的宽度,并扩展矩形的底部以容纳输出文本的最后一行。如果输出文本只有一行,则DrawText函数改变矩形的右边界,以容纳下正文行的最后一个字符。出现上述任何一种情况,DrawText函数将返回格式化文本的高度,而不是绘制文本。
DT_CENTER:指定文本水平居中显示。
DT_VCENTER:指定文本垂直居中显示。该标记只在单行文本输出时有效,所以它必须与DT_SINGLELINE结合使用。
DT_SINGLELINE:单行显示文本,回车和换行符都不断行。
声明一个PAINTSTRUCT结构体的变量,然后传给BeginPaint函数,之后就可以画东西了。
DrawText(ps.hdc, L"希望你失去的是初吻而不是初夜.", -1, &rect, DT_CENTER);
设置颜色
SetTextColor(ps.hdc, RGB(0,150,255));
case WM_PAINT:
{
BeginPaint(hWnd, &ps);
TEXTMETRIC tm;
// 取得与文本相关的数据
GetTextMetrics(ps.hdc, &tm);
RECT rect;
rect.top = 0L;
rect.left = ps.rcPaint.left;
rect.right = ps.rcPaint.right;
rect.bottom = rect.top + tm.tmHeight;
// 第一行文本
SetTextColor(ps.hdc, RGB(0, 150, 255));
DrawText(ps.hdc, L"希望你失去的是初吻而不是初夜.", -1, &rect, DT_CENTER);
// 第二行文本
rect.top += tm.tmHeight;
rect.bottom += tm.tmHeight;
SetTextColor(ps.hdc, RGB(220, 12, 50));
DrawText(ps.hdc, L"回忆是过期的黑白电影", -1, &rect, DT_LEFT);
// 第三行文本
rect.top += tm.tmHeight;
rect.bottom += tm.tmHeight;
SetTextColor(ps.hdc, RGB(30, 255, 7));
DrawText(ps.hdc, L"只要我没有麻木只要我身体还有温度我就还是你的退路", -1, &rect, DT_RIGHT);
// 第四行文本
rect.top += tm.tmHeight;
rect.bottom += tm.tmHeight;
SetTextColor(ps.hdc, RGB(0, 40, 210));
DrawText(ps.hdc, L"那条旧路依然没有改变", -1, &rect, DT_RIGHT);
EndPaint(hWnd, &ps);
return 0;
}
画线
绘制弧线使用Arc函数,第一个参数是目标HDC,随后的4个参数用于确定弧线所在的位置的矩形,最后4个参数是确定弧线的开始点和结束点的坐标。
BOOL WINAPI Arc(
HDC hdc, //DC的句柄
int x1, // 矩形的左坐标
int y1, //矩形上坐标
int x2,//矩形的右坐标
int y2, //矩形的下坐标
int x3, //起点x坐标
int y3, //起点y坐标
int x4, //终点x坐标
int y4 //终点y坐标
);
逆时针
// 绘制弧线
HPEN pen = CreatePen(PS_SOLID, 2, RGB(200, 100, 20));//创建笔
// 将笔选到DC中
auto oldObj = SelectObject(ps.hdc, pen);
// 画弧线
Arc(ps.hdc, 20, 100, 300, 300, 39, 110, 280, 285);
Arc(ps.hdc, 200, 160, 390, 400, 300,350, 380,165);
// 画完之后,把原先的笔选回去
SelectObject(ps.hdc, oldObj);
// 清理
DeleteObject(pen);
默认是逆时针方向,现在我想画顺时针方向的弧线。看下面例子,通过SetArcDirection函数改变弧线的方向。
/*
AD_COUNTERCLOCKWISE表示逆时针方向
AD_CLOCKWISE表示顺时针方向
*/
SetArcDirection(ps.hdc, AD_CLOCKWISE);
Arc(ps.hdc, 20,150, 460,450, 90,162, 85,300);
一条线三种不同颜色的效果
首先要声明回调函数函数,在调用之后定义,就必须先声明,不然编译的时候找不到。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
思路:
[1]定义一个回调函数;
[2]提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
[3]当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
VOID CALLBACK LineDDAProc(int x, int y, LPARAM lpData);
定义
VOID CALLBACK LineDDAProc(int x, int y, LPARAM lpData)
{
// 从参数中取得HDC
HDC hdc = *((HDC*)lpData);
// 不同位置的线段设置不同的颜色
int type=0;
if(x <= 510 || y <= 200)
{
type = 0;
}
else if((x > 510 && x <= 700) ||
(y > 720 && y <= 360))
{
type = 1;
}
else
{
type = 2;
}
// 根据不同情况着色
switch(type)
{
case 0:
SetPixel(hdc,x,y,RGB(0,255,0));
break;
case 1:
SetPixel(hdc,x,y,RGB(0,0,255));
break;
case 2:
SetPixel(hdc,x,y,RGB(255,0,0));
break;
default:
SetPixel(hdc,x,y,RGB(255,0,0));
}
}
在相应WM_PAINT消息的时候调用LineDDA函数。
LineDDA(420,130,800,470,LineDDAProc, (LPARAM)&ps.hdc);
LinaDDa文档介绍
BOOL LineDDA(
int nXStart, // x-coordinate of starting point
int nYStart, // y-coordinate of starting point
int nXEnd, // x-coordinate of ending point
int nYEnd, // y-coordinate of ending point
LINEDDAPROC lpLineFunc, // callback function
LPARAM lpData // application-defined data
);
完整
CreatePen函数
HPEN CreatePen(
int iStyle, //钢笔的样式,如虚线、实线
int cWidth, //线条宽度
COLORREF color //线条颜色
);
第一个参数指定线条的样式,如
#define PS_SOLID 0
#define PS_DASH 1 /* ------- */
#define PS_DOT 2 /* ....... */
#define PS_DASHDOT 3 /* _._._._ */
#define PS_DASHDOTDOT 4 /* _.._.._ */
#define PS_NULL 5
#define PS_INSIDEFRAME 6
#define PS_USERSTYLE 7
#define PS_ALTERNATE 8
函数成功创建钢笔后就会返回HPEN,H开头的你就要知道它表示句柄。Pen也是系统资源,所以创建笔后系统要为它一个标识。
SelectObject函数
调用SelectObject函数,把刚才创建的钢笔与绘图纸关联,就等于把我们创建的绘图资源放进DC工具箱中,
HGDIOBJ WINAPI SelectObject(
HDC hdc, //设备描述表的句柄
HGDIOBJ h //要放到DC中的资源的句柄
);
调用成功后,返回原先的资源句柄。
MoveToEx是设置绘制的起点,下次绘图将从这个点开始。它的最后一个参数将被设置为当前点,即Move后的坐标。LineTo从当前坐标开始,到指定坐标之间绘制一条线段。
BeginPaint(hWnd, &ps);
// 创建钢笔
HPEN pen = CreatePen(PS_DASH, 1, RGB(0, 255, 50));
// 把笔选到DC中
SelectObject(ps.hdc, pen);
// 设定线段的起点
MoveToEx(ps.hdc, 150, 250, NULL);
// 绘制线条
LineTo(ps.hdc, 65, 49);
LineTo(ps.hdc, 12, 120);
LineTo(ps.hdc, 250, 78);
LineTo(ps.hdc, 312, 185);
DeleteObject(pen);
EndPaint(hWnd, &ps);
用完后调用DeleteObject函数将其销毁。
如图
PolyBezier函数和PolyBezierTo函数
两个函数都是用来绘制贝塞尔曲线的,不同的是,PolyBezier函数包含指定的起点和终点,PolyBezierTo是从当前点开始绘制贝塞尔曲线。
● 原型
BOOL PolyBezier(HDC hdc, CONST POINT *lppt, DWORD cPoints);
● 参数
hdc:指定的设备环境句柄。
lppt:POINT结构数组的指针,包括了样条端点和控制点的坐标,其顺序是起点的坐标、起点的控制点的坐标、终点的控制点的坐标和终点的坐标。
cPoints:指明数组中的点的个数。
前者和后者其实很相像,参数都是两个,第一个参数都是POINT结构体的数组指针,第二个参数都是一个指示POINT结构体个数的整数,只不过,前者要求是四或者四的倍数,后者要求是三或者是三的倍数。
都是用来画曲线的。
PolyPolyline绘制复合线条
PolyPolyline函数可以绘制多段复合线条。它的声明如下:
BOOL PolyPolyline(
HDC hdc,
const POINT *lppt,
const DWORD *lpdwPolyPoints,
DWORD cCount
);
lppt参数指向一个POINT的数组,它包含绘制复合线条所需的所有点;lpdwPolyPoints指向一个数组,这个数字数组指明如何分配点数组。
例如,lppt有7个点,我计划,前2个点绘制第一条线,接着3个点绘制第二条线,最后2个点绘制第三条线,这样一来,lpdwPolyPolyPoints得值应为:
{ 2, 3, 2 }
nCount里包含lpdwPolyPolyPoints中的数量,我们上面的例子是3.
由于两点决定一条线段,因此,lpdwPolyPolyPoints里面的值记得要>=2。
PolyBezierTo(ps.hdc, pts2, 3);
delete[] pts2;
pen = CreatePen(PS_DASHDOTDOT, 1, RGB(80, 20, 160));
SelectObject(ps.hdc, pen);
POINT plpts[10] =
{
{ 647, 3 }, { 511, 46 }, { 828, 199 }, { 403, 305 }, { 694, 22 },
{ 902, 377 }, { 521, 45 }, { 437, 7 }, { 500, 398 }, { 775, 25 }
};
DWORD arr[4] = { 2, 3, 3, 2 };
PolyPolyline(ps.hdc, &plpts[0], &arr[0], 4);
最后截图