Windows绘图基础

Author:秋时残叶
Date:2017.12.30
《windows程序设计》笔记

1.GDI函数

GDI包含几百个函数,可以分类为:

  • 获取(建立)和释放(销毁)设备环境的函数
  • 获取设备环境信息的函数
  • 绘图函数
  • 设置和获取设备环境属性的函数
  • 使用GDI"对象"的函数

2. GDI基本图形

  • 线条和曲线
  • 可被填充的封闭区域
  • 位图
  • 文本

3. 其它

  • 映射模式和转换
  • 图元文件
  • 区域
  • 路径
  • 剪裁
  • 调色板
  • 打印

4. GetDC和BeginPaint区别:

从GetDC函数返回的句柄可以在整个窗口客户区的客户区内绘制,并且, GetDC和RealseDC并不使任何客户区的无效区域变为有效。

还有一个更通用的获取设备环境句柄的函数:

hdc = CreateDC(pszDriver, pszDevice, pszOutput, pData,;
......
DeleteDC(hdc);

可以通过这样获取整个屏幕的设备环境句柄:

CreateDC(L"DISPLAY", NULL, NULL, NULL);

可以通过在调用GetDC时使用一个NULL参数来获取整个屏幕的设备环境。

5. 信息上下文

仅需要环境信息,而不需要在上面绘制东西,可以用:

CreateIC(L"DISPALY", NULL, NULL, NULL);

6. 处理位图时,用到"内存设备环境"

hdcMem = CreateCompatibleDC(hdc);
....
DeleteDC(hdcMem);

可以把位图选入内存设备环境,并调用GDI函数绘制一个位图

7. 图元设备环境

hdcMeta = CreateMetaFile(pszFilename);
......
hmf = CloseMetaFile(hdcMeta);

8. 获取设备环境的信息

iValue = GetDeviceCaps(hdc, iIndex);

参数说明:

iIndex:

  • HORZRES:以像素为单位返回设备的宽度
  • VERTRES:以像素为单位返回设备的高度

hdc:

  • 如果为屏幕设备环境句柄,获取到时的信息和GetSystemMetrics一样。
  • 如果为打印机设备环境,将以像素为单位返回打印机显示区域的高度和宽度。

9. 在释放设备环境时保存对属性做的改变

wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

只需初始一次,在下次改变前一直有效。

只对GetDC和BeginPaint有效,对GetWindowDC无效

10. 保存设备环境的状态:

idSaved = SaveDC(hdc);

11. 返回调用SavaDC函数之前存在的设备环境

RestoreDC(hdc, idSaved);

可以这样使用:

SaveDC(hdc);          //不必保存返回值
...                   //改变一些属性
SaveDC(hdc);          //再次调用
RestoreDC(hdc, -1);   //将设备环境恢复到已保存的状态

//类似push pop
//使环境恢复到最近一次由SaveDC函数保存的状态

12. 点(并不常用的)

SetPixel(hdc, x, y, crColor); //将坐标为x, y的像素设为color色
GetPixel(hdc, x, y);          //返回指定坐标位置像素的颜色

13. 直线

LineTo                   //画直线
Polyline PolylineTo      //画一条由多条首尾相连的直线构成的拆线
PolyPolyline             //画多条直线
Arc                      //画椭圆弧线
PolyBezier PolyBezierTo  //画贝赛尔样条曲线
ArcTo AngleArc           //画椭圆弧线
PolyDraw                 //画多条贝赛尔样条曲线或者一条由多条首尾相连直线构成的拆线

既完成画线还填充的封闭图形:

Rectangle  //矩形
Ellipse    //椭圆
RoundRect  //圆角矩形
Pie        //椭圆的一部分,看起来像扇形
Chord      //由弦分割出的部分椭圆,呈弓形

画一条直线:

MoveToEx(hdc, xBeg, yBeg, NULL);  //最后一个参数为指向POINT的指针
LineTo(hdc, xEnd, yEnd);

14. 获取当前位置

GetCurrentPosition(hdc, &pt);

15. 获取客户区大小

GetClientRect(hwnd, &rect);

16. 将点连成线

Polyline(hdc, apt, 5);   //5:点的个数

17. 画矩形

Rectangle(hdc, xLeft, yTop, xRight, yBottom);

18. 画椭圆

Ellipse(hdc, xLeft, yTop, xRight, yBottom);

19. 圆角矩形

RoundRect(hdc, xLeft, yTop, xRight, yBottom, xCornerEllipse, yCornerEllipse);
//xCornerEllipse:小椭圆宽度
//yCornerEllipse:小椭圆高度

20. 椭圆弧线

Arc(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);

21. 弓形

Chord(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);

22. 扇形

Pie(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);

23. 贝塞尔曲线

PolyBezier(hdc, apt, iCount);   //iCount = 曲线条数的三倍加上1
PolyBezierTo(hdc, apt, iCount);   //把当前位置当作第一个起点
DrawBezier(hdc, apt);

24. 创建钢笔

hPen = CreatePen(iPenStyle, iWidth, crColor);
//iPenStyle:
PS_SOLID         ------
PS_DASH          - - - -
PS_DOT           . . . . ..
PS_DASHDOT       -.-.-.-.
PS_DASHDOTDOT    -..-..-..
PS_NULL
PS_INSIDEFRAME   ---------   唯一可以使用抖动色的画笔样式

25. 建立不同画笔

LOGPEN logpen;
hPen = CreatePenIndirect(&logPen);   //建立一个画笔,需要创建很多不同的画笔时,很有效

26. 创建,选择,删除

static HPEN hPen1, hPen2, hPen3;
hPen1 = CreatePen(PS_SOLID, 1, 0);
hPen2 = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
hPen3 = CreatePen(PS_DOT, 0, 0);
SelectObject(hdc, hPen1);
...
DeleteObject(hPen1);
....

27.

LOGPEN logpen;
GetObject(hPen, sizeof(LOGPEN), (LPVOID)&logpen);  //获取logpen信息

hPen = GetCurrentObject(hdc, OBJ_PEN);  //获取当前被选入设备环境的画笔句柄

28. 调置填充空隙的背景颜色

SetBkColor(hdc, crColor);

29. 背景模式为透明来阻止windows填充空隙

SetBkMode(hdc, TRANSPARENT);

ROP2——绘图模式

SetROP2(hdc, iDrawMode);   //设置绘图模式
GetDOP2(hdc);   //获取当前绘图模式

默认为:

R2_COPYPEN       //只是用画笔颜色替代目标颜色
R2_NOTCOPYPEN    //画笔为黑,画则为白;白则为黑
R2_BLACK         //总是黑色
R2_WHITE         //总是白色
R2_NOP           //"不操作", 让目标颜色保持不变

30、多边形

Polygon(hdc, apt, iCount);  //若最后一点与第一个点不同,会再加一条线连接(Polyline)不会这么做

31、多个多边形

PolyPolygon(hdc, apt, aiCounts, iPolyCount);  //多个多边形

32、不含边框的图形

SelectObject(hdc, GetStockObject(NULL_PEN);  //绘制不含边框线的图形

33、只绘制边框线

SelectObject(hdc, GetStockObject(NULL_BRUSH);  //只想绘制边框线,不想填充

34、 默认使用环境中画刷来填充区域

可以调用设置填充模式:

SetPolyFillMode(hdc, iMode); 
//ALTERNAME(交替)   默认
//WINDING(螺旋)

35. 邻近色

crPureColor = GetNearestColor(hdc, crColor);  //确定与某种颜色值最接近的非合成颜色

36. 画刷

36_1. 建立逻辑画笔:

hBrush = CreateSolidBrush(crColor);

36_2. 建立阴影线画刷:

hBrush = CreateHatchBrush(iHatchStyle, crColor);
iHatchStyle:
HS_HORIZONTAL   ____     HS_BDIAGONAL    //////
                ____                     //////
                ____                     //////

HS_VERTICAL    |||||     HS_CROSS       ++++++
               |||||                    ++++++

HS+FDIAGONAL   \\\\\\    HS_DIAGCROSS   XXXXXX
               \\\\\\                   XXXXXX

36_3. 建立位图画刷

HBRUSH CreatePatternBrush(HBITMAP hbmp);
HBRUSH CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec);

36_4. 建立逻辑画刷,包含其它4个函数的所有功能

hBrush = CreateBrushIndirect(&logbrush);

typedef struct tagLOGBRUSH { // lb 
   UINT     lbStyle; 
   COLORREF lbColor; 
   LONG     lbHatch; 
} LOGBRUSH; 
//param:
lbStyle             lbColor           lbHatch
        
BS_SOLID            画刷的颜色        忽略
BS_HOLLOW           忽略             忽略
BS_HATCHED          阴影线的颜色      阴影线画刷样式
BS_PATTERN          忽略             位图的句柄
BS_DIBPATTERNPT     忽略             指向DIB的指针

选入:

SelectObject(hdc, hBrush);

删除:

DeleteObject(hBrush);

37. 获取画刷信息

GetObject(hBrush, sizeof(LOGBRUSH), (LPVOID)&logbrush);

38. GDI映射模式

MM_TEXT         右(x)   下(y)    像素
MM_LOMETRIC     右(x)   上(y)    0.1mm(LO HI:精度的高低)
MM_HIMETRIC     右(x)   上(y)    0.01mm
MM_LOENGLISG    右(x)   上(y)    0.01in
MM_HIENGLISG    右(x)   上(y)    0.001in
MM_TWIPS        右(x)   上(y)    1/1440in  英寸
MM_ISOTROPIC    可选     可选     任意(x = y)
MM_ANISOTROPIC  可选     可选     任意(x != y)

38_1. 设置映射模式

SetMapMode(hdc, iMapMode);

38_2. 获取当前映射模式

GetMapMode(hdc);

39. 客户区坐标转换为屏幕坐标

ClientToScreen();

40. 屏幕坐标转换为客户区坐标

ScreenToClient();

41. 以屏幕坐标的形式获取整个窗口的位置和大小

GetWindowRect();

42. 设备点转换为逻辑点

DPtoLP(hdc, pPoints, iNumber);    //将设备点转换为逻辑点

//把从GetClientRect()获取的客户区大小转换为逻辑坐标很有用
GetClientRect(hwnd, &rect);
DPtoLP(hdc, (PPOINT)&rect, 2);

43. 逻辑点转换为设备点

LPtoDP(hdc, pPoints, iNumber);

44. 设置逻辑点位置

//参数总是以设备单位的形式给出
SetViewportOrgEx(hdc, cxClient /2, cyClient / 2, NULL);  //设置逻辑点为客户区中心

//参数总是以逻辑单位的形式给出
SetWindowOrgEx(hdc, -cxClient / 2, -cyClient / 2, NULL);  //结果相同

45. 获取当前视口和窗口的原点

GetViewportOrgEx(hdc, &pt);   //设备坐标形式
GetWindowOrgEx(hdc, &pt);     //逻辑坐标形式

46. 设置/获取窗口和视口的范围

SetViewPortExtEx(hdc, cxClient, -cyClient, NULL);
GetViewportExtEx();

SetWindowExtEx(hdc, 32767, 32767, NULL);
GetWindowExtEx();

47. 处理矩形

FillRect(hdc, &rect, hBrush);   //使用指定画刷填充矩形   不需事先把画刷选入设备环境

FrameRect(hdc, &rect, hBrush);  //使用画刷绘制一个矩形框,但并不填充矩形

InvertRect(hdc, &rect);   //翻转矩形内所有的像素,1 > 0, 0 > 1。

48.设置rect

SetRect(hdc, xLeft, yTop, xRight, yBottom);
//简化了:
rect.left = xLeft;
rect.top = yTop;
......

49.

OffsetRect(&rect, x, y);          //将矩形沿x轴和y轴移动几个单位
InflateRect(&rect, x, y);         //增大或减小矩形的尺寸
SetRectEmpty(&rect);              //把矩形结构的各字段设置为0
CopyRect(&DestRect, &SrcRect);    //将一个矩形结构复制到另一个矩形结构
IntersectRect(&DestRect, &SrcRect1, &SrcRect2);  //获取两个矩形的交集
UnionRect(&DestRect, &SrcRect1, &SrcRect2);      //获取两个矩形的并集
bEmpty = IsRectEmpty(&rect);      //判断矩形是否为空
bInRect = PtInRect(&rect, point); //判断点是否在矩形内部

50. 建立一个矩形区域

hRgn = CreateRectRgn(xLeft, yTop, xRight, yBottom);
hRgn = CreateRectRgnIndirect(&rect);

51. 建立椭圆区域

hRgn = CreateEllipticRgn(xLeft, yTop, xRight, yBottom);
hRgn = CreateEllipticRgnIndirect(&rect);

52. 创建圆角矩形区域

CreateRoundRectRgn();

53. 创建多边形区域

hRgn = CreatePolygonRgn(&point, iCount, iPolyFillMode);

54. 结合两个源区域组成新区域

iRgnType = CombineRgn(hDestRgn, hSrcRgn1, hSrcRgn2, iCombine);
//iCombine:
RGN_AND     //公共部分
RGN_OR      //全部
RGN_XOR     //全部,除去公共部分
RGN_DIFF    //hSrcRgn1不在hSrcRgn2中的部分
RGN_COPY    //hSrcRgn1的全部(忽略hSrcRgn2)

return value:

NULLREGION:空的区域 
SIMPLEREGION:指的是一个简单的矩形,椭圆或多边形
COMPLEXREGION:批的是矩形,椭圆或多边形的组合
ERROR:有错误发生

填充区域:

FillRgn(hdc, hRgn, hBrush);
FrameRgn(hdc, hRgn, hBrush, xFrame, yFrame);
InvertRgn(hdc, hRgn);
PaintRgn(hdc, hRgn);

用于区域:

InvalidateRgn(hwnd, hRgn, bErase);
ValidateRgn(hwnd, hRgn);

将区域选入设备环境句柄:

SeleteObject(hdc, hRgn);
或
SeleteClipRgn(hdc, hRgn);

55. 从剪裁区域去除一个矩形

ExcludeClipRect();

56.

IntersectClipRect();   //建立一个新的剪裁区域, 新剪裁区域是先前的剪裁区域和某个矩形的交集

57.

OffsetClipRgn();   //把一个剪裁区域移动到客户区的另一部分

猜你喜欢

转载自www.cnblogs.com/coolcpp/p/windows-drawing.html