1. CDC类的画线函数:
1) CDC的画线函数大致可以分为三类,一类是画直线和曲线,一类是画矩形等多边形,另一类是画圆、椭圆以及弧线等;
2) 使用CDC画线时有个非常重要的概念,就是当前绘图点,是一个客户区中的像素点,很多画线函数默认的起始画线点都是当前绘图点,用户可以通过相关函数设定当前绘图点的位置;
3) 画线函数命名时的后缀“To”,凡是带后缀“To”的函数都会自动将当前绘图点的位置设定成画线的末尾,比如LineTo、PolylineTo等,这些函数在画线结束后都会默认将当前绘图点的位置更新至画线的最后一个像素点位置,而没有后缀“To”的函数画线结束后不改变当前绘图点的位置,还有更直接的MoveTo函数,它可以直接显示设定当前绘图点的位置;
2. 画直线:
1) 使用MoveTo和LineTo函数的组合;
-
- CPoint MoveTo(int x, int y);
- CPoint MoveTo(CPoint point);
-
-
-
- BOOL LineTo(int x, int y);
- BOOL LineTo(CPoint point);
2) 当然也可以连续使用LineTo接着上一条的末尾话而无需再重设当前位置:
- dc.MoveTo(0, 0);
- dc.LineTo(0, 100);
- dc.LineTo(100, 100);
3. 画折线:
1) 使用Polyline函数:
-
-
-
-
- BOOL Polyline(LPPOINT lpPoints, int nCount);
-
- BOOL PolylineTo(LPPOINT lpPoints, int nCount);
!!!CPoint数组也可以用,POINT是从Win32继承下来的,为了兼容以前的程序以及以前的变成风格,建议使用新的CPoint。
2) 以下两者效果相同:
- POINT aPoint[5] = { 0, 0, 0, 100, 100, 100, 100, 0, 0, 0 };
- dc.Polyline(aPoint, 5);
-
- POINT aPoint[4] = { 0, 100, 100, 100, 100, 0, 0, 0 };
- dc.Polyline(aPoint, 4);
!!!前缀a表示数组,aPoint就是Point数组的意思,即array point。
3) 一个示例——用折线来拟合正弦曲线:
- #include <math.h>
-
- #define SEGMENTS 500
- #define PI 3.1415926
-
- void CMyWnd::OnPaint()
- {
- CPaintDC dc(this);
- CRect rect;
- CPoint aPoint[SEGMENTS];
-
- GetClientRect(&rect);
- int nWidth = rect.Width();
- int nHeight = rect.Height();
-
- for (int i = 0; i < SEGMENTS; i++) {
- aPoint[i].x = i * nWidth / SEGMENTS;
- aPoint[i].y = (int)(nHeight * (1 - sin(2 * PI * i / SEGMENTS)) / 2);
- }
-
- dc.Polyline(aPoint, SEGMENTS);
- }
4. 画弧:
1) 弧线即圆或椭圆周边上截取的一段曲线,使用Arc绘制:
-
-
-
-
-
- BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
- BOOL Arc(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
2) 奇葩的ArcTo:参数返回值和Arc一模一样,只不过画之前会先从当前位置连一条直线到ptStart,然后再画弧,弧画完后将当前位置改为ptEnd,一般很少用。
5. Bezier曲线:
1) Bezier曲线是一种光滑的曲线,有两个端点和两个控点组成,可以使用PolyBezier和PolyBezierTo函数绘制:
-
-
-
-
- BOOL PolyBezier(const POINT* lpPoints, int nCount);
-
- BOOL PolyBezierTo(const POINT* lpPoints, int nCount);
2) 画一个Nike的Swoosh:
- POINT aPoint1[4] = {120, 100, 120, 200, 250, 150, 500, 40};
- POINT aPoint2[4] = {120, 100, 50, 350, 250, 200, 500, 40 };
-
- dc.PolyBezier(aPoint1, 4);
- dc.PolyBezier(aPoint2, 4);
!!!所有画线函数都不会画最后一个点,要画的画必须自己使用SetPixel来上色!
6. 画椭圆:
-
-
- BOOL Ellipse(int x1, int y1, int x2, int y2);
- BOOL Ellipse(LPCRECT lpRect);
7. 画矩形:
1) 普通矩形直接使用Rectangle:
-
-
- BOOL Rectangle(int x1, int y1, int x2, int y2);
- BOOL Rectangle(LPCRECT lpRect);
2) 圆角矩形使用RoundRect:
-
-
-
-
- BOOL RoundRect(int x1, int y1, int x2, int y2, int x3, int y3);
- BOOL RoundRect(LPCRECT lpRect, POINT point);
3) 关于矩形边框上的像素问题:边框范围是x1 ~ x2,y1 ~ y2,其中x1可以大于x2,y1也可以大于y2,而x2这条线上的边和y2这条线上的边的像素点不上色!!这就是线的终点不上色延伸到了二维平面上来了!
8. 楔形(弦形)、饼:
1) 楔形就是将弧的两个端点直接用直线连接形成一个封闭图形,饼就是将椭圆中点和弧的两个端点直线连接形成的封闭图形;
2) 分别使用函数Chord和Pie完成绘制,其用法和函数原型和Arc一模一样,都是矩形框定椭圆,两个点定弧,接下里的活都是自动完成的:
- BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
- BOOL Chord(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
-
- BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
- BOOL Pie(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
3) 示例——制作一个饼图报表(四个季度的业绩):
- void CMyWnd::OnPaint()
- {
- int nPerformences[4] = { 125, 376, 252, 184 };
- CPaintDC dc(this);
- CRect rect;
-
- GetClientRect(&rect);
-
- dc.SetViewportOrg(rect.Width() >> 1, rect.Height() >> 1);
-
- int nTotal = 0;
- for (int i = 0; i < 4; i++) {
- nTotal += nPerformences[i];
- }
-
- int x1 = 0;
- int y1 = -1000;
- int nSum = 0;
-
- for (i = 0; i < 4; i++) {
- nSum += nPerformences[i];
- double rad = (nSum * 2 * PI / nTotal) + PI;
- int x2 = (int)(sin(rad) * 1000);
- int y2 = (int)(cos(rad) * 1000 * 3 / 4);
- dc.Pie(-200, -150, 200, 150, x1, y1, x2, y2);
- x1 = x2;
- y1 = y2;
- }
- }