Note:
1.图形输出设备分为光棚设备和矢量设备。大部分pc输出设备都是光棚设备,即以点模式表示图像。矢量设备使用线来绘制图像,如绘图仪。使用矢量的程序是在硬件之上的一层抽象。
2.GDI函数的分类。
获取(创建)、释放(清除)设备描述表的函数,如GetDc,ReleaseDC;获取设备描述表信息的函数,如GetTextMetrics;绘图函数,如TextOut;设着和获取设备描述表参数的函数,如SetTextColor控制TextOut输出字颜色;使用GDI对象的函数,如CreatePen等。
3.图元。直线和曲线,由Pen画;填充区域;位图;文本;
4.设备描述表的获取方式:
1)hdc = BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
2)hdc = GetDC(hwnd); // Note:GetDC(NULL)获取整个屏幕的DC
ReleaseDC(hwnd,hdc);
3)hwd = GetWindowDC(hwnd);
ReleaseDC(hwnd,hdc);
4)hdc = CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData); // Note:CreateDC(_T("DISPLAY"),NULL,NULL,NULL)获取整个屏幕DC
DeleteDC(hdc);
5)hdcMem = CreateCompatibleDC(hdc); //使用位图时,可用内存设备描述表
DeleteDC(hdcMem);
6)hdcMeta = CreateMetaFile(pszFileName); //获取元文件设备描述表
hmf = CloseMetaFile(hdcMeta);
5.一个设备描述表通常就是一个物理显示设备。
iValue = GetDeviceCaps(hdc, iIndex); //根据iIndex获取dc的相关属性。
6.保存设备描述表。
wndclass.style = CS_OWNDC; //可以为窗口建立自己的DC,在修改DC之后DC一直有效直到EndPaint或者ReleaseDC。
idSaved = SaveDC(hdc);
//修改DC属性
RestoreDC(hdc,idSaved); //恢复保存的DC
上述语句等价于 SaveDC(hdc);
RestoreDC(hdc,-1);
7.画线。
影响画线的dc属性:当前画笔位置;画笔;背景方式;背景色;绘图模式。
画直线:
MoveToEx(hdc,xBeg,yBeg,NULL);
LineTo(hdc,xEnd,yEnd);
GetCurrentPositionEx(hdc,&pt);//获取当前位置
8.画笔。
HPEN hPen,hPenOld;
hPen = GetStockObject(WHITE_PEN); //获取现有画笔的句柄
hPenOld = SelectObject(hdc,hPen);//将画笔选进设备描述表,hPenOld记录老的画笔
//CreateOwnPen
HPEN hPen = CreatePen(iPenStyle,iPenWidth,crColor); // 一种方法
LOGPEN logpen;
HPEN hPen = CreatePenIndirect(&logpen);//另一种方法
DelectObject(SelectObject(hdc,hPen));//及时删除画笔,节省资源
//获取画笔信息
GetObject(hPen,sizeof(LOGPEN),(LPVOID)&logpen);//获取hPen属性
hPen = GetCurrenObject(hdc,OBJ_PEN);//获取当前dc中HPEN
//点画线和虚线的空隙填充,受dc的背景模式和背景色影响
SetBkColor(hdc,crColor);//设置背景颜色
SetBkMode(hdc,TRASPARENT);//TRANSPARENT组织填充背景,OPAQUE模式将用背景色填充空隙
//绘图方式
//画笔像素与目标位置处原来像素之间按位运算,叫做“光栅运算”ROP,画线只有二维,称为ROP2,有意思的东西。
SetROP2(hdc,iDrawMode);
iDrawMode=GetROP2(hdc);//默认为R2_COPYPEN,画笔色彩替代背景
9.填充区域。
Rectangle、Ellipse、RoundRect、Chord、Pie、Polygon、PolyPolygon
边界框画法跟画线一样、封闭区域使用HBRUSH填充。
HBRUSH hBrush = GetStockObject(WHITE_BURSH);
SelectObject(hdc,hBrush);
SelectObject(hdc,GetStockObject(NULL_PEN));//画无边界框
SelectObject(hdc,GetStockObject(NULL_BRUSH));//不填充区域
//多边形的填充方式有ALTERNATE和WINDING两种,区别很神奇。
10.画刷。
HBRUSH hBrush = CreateSolidBrush(crColor);//创建画刷
hBrush = CreateHatchBrush(iHatchStyle,crColor);//创建斜影画刷
hBrush = CreatePatternBrush/*CreateDIBPatternBrushPt*/; //创建基于位图的画刷
LOGBRUSH logBrush;
hBrush = CreateBrushIndirect(&logBrush);
//其余操作类似HPEN
11.GDI映射方式。
SetMapMode(hdc,iMapMode);
iMapMode = GetMapMode(hdc);
//至于其他相关映射方式,个人认为使用的可能性很小。
12.矩形、区域、剪裁。
FillRect(hdc,&rect,hBrush);//无需将hBrush选进hdc
FrameRect(hdc,&rect,hBrush); //用brush画矩形框,但不填充
InvertRect(hdc,&rect); //将矩形框中所有像素翻转
SetRect(&rect,xLeft,yTop,xRight,yBottom);
OffsetRect(&rect,x,y);//将矩形移动几个单元
InflateRect(&rect,x,y);//增减矩形的尺寸
SetRectEmpty(&rect);//矩形为0
CopyRect(&rcDest,&rcSrc);//拷贝
IntersectRect(&rcDest,&rcSrc1,&rcSrc2);//取两矩形交集
UnionRect(&rcDest,&rcSrc1,&rcSrc2);//取两矩形并集
bEmpty = IsRectEmpty(&rect);//确定是否为空
bInRect = PtInRect(&rect,Point);//点是否在矩形内
13.PeekMessage(&msg,NULL,0,0,PM_REMOVE);//大家伙,值得注意
The PeekMessage function normally does not remove WM_PAINT messages from the queue. WM_PAINT messages remain in the queue until they are processed. However, if a WM_PAINT message has a NULL update region, PeekMessage does remove it from the queue. —— 摘自MSDN 貌似跟书上说的有出入,需要注意
14.区域
HRGN hRgn = CreateRectRgn(xLeft,yTop,xRight,yBottom);
hRgn = CreateRectRgnIndirect(&rect);
hRgn = CreateEllipticRgn(xLeft,yTop,xRight,yBottom);
hRgn = CreateEllipticRgnIndirect(&rect);
iRgnType = CombineRgn(hDestRgn,hSrcRgn1,hSrcRgn2,iCombine);
//区域填充参数类似Rect
小结:
最近公司项目用到了大量画图操作,主要设计界面自画,重复的将bitmap贴到特定rect,设置透明色。作为windows程序设计,不可避免的都会涉及到自画控件的开发,而自画控件很大一部分工作就是改变控件的UI,画图基础可以让自己更好的理解代码,