GDI总结:http://dingchaoqun12.blog.163.com/blog/static/11606250420112213396361/
对话框
控件
视图类
应用程序框架都会调用该CWnd的消息响应成员函数(的覆盖)来绘制窗口客户区。
在Windows中,绘图一般在视图窗口的客户区进行,使用的是MFC的设备上下文DC类CDC中各种绘图函数。
在绘图前,必须先得到客户区大小和DC、设置绘图颜色,然后再根据文档数据或用户操作来绘制图形。
一.客户区大小和DC
在绘图前,必须先得到客户区大小和设备上下文DC。
1.获得客户区
绘图一般都是在视图窗口的客户区进行,而客户区的大小在运行时可由用户改变,为了使绘制的图形能随窗口大小自动改变,必须先得到当前客户区大小的数据(宽w和高h)。
获取客户区大小的方法有如下两种:
1)在消息响应函数OnSize中获得
利用属性窗口的信息页,在视图类中添加WM_SIZE消息的响应函数OnSize。该函数在窗口第一次显示或窗口大小被改变时会被Windows系统调用。其输入参数中的cx和cy就是客户区大小的宽和高,可将它们赋值给类变量(如m_iW和m_iH)供绘图时使用。例如
void CDrawView::OnSize(UINT nType, int cx, int cy) {
CView::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
m_iW = cx; m_iH = cy;
}
其中,nType的值为:
SIZE_MAXIMIZED(窗口已被最大化)
SIZE_MINIMIZED(窗口已被最小化)
SIZE_RESTORED(窗口已被改变大小)
SIZE_MAXHIDE(其他窗口被最大化)
SIZE_MAXSHOW(其他窗口从最大化还原)
2)调用成员函数GetClientRect得到
可在绘图前,定义一个矩形变量rect,然后再调用CWnd类的成员函数GetClientRect:
void GetClientRect( LPRECT lpRect ) const;
得到当前客户区矩形的数据,其中的右(right)与底(bottom)就是客户区的宽与高(其左left与顶top都为0)。例如:
RECT rect;
GetClientRect(&rect);
int w = rect.right, h = rect.bottom;
2.DC
在Windows中,绘图使用的是MFC的DC(Device-Context, 设备上下文)类CDC中各种绘图函数。
0)CDC类
CDC是CObject的直接派生类,CDC类自己也有若干派生类,其中包括窗口客户区DC所对应的CClientDC类、OnPaint和OnDraw消息响应函数的输入参数中使用的CPaintDC类、图元文件对应的CMetaFileDC类和整个窗口所对应的CWindowDC类。
CDC类中有许多成员函数,可以用来设置各种绘图环境、属性和参数,以及绘制各种图形和图像等,将在后面陆续加以介绍。
1)获得DC
可以从OnDraw函数的输入参数pDC或调用CWnd的成员函数GetDC:
CDC* GetDC( );
来获得DC的指针。
2)释放DC
因为Windows限制可用DC的数量,所以DC属于稀缺的公用资源。因此,对每次获得的DC,在使用完成后必须立即释放。
从OnDraw函数的输入参数pDC获得的DC,在该函数运行结束后,系统会自动释放。但由GetDC所获得的DC,必须自己来释放,这可以通过调用CWnd的成员函数ReleaseDC来完成:
int ReleaseDC( CDC* pDC ); // 成功返回非0
例如:
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
ReleaseCapture();
if (m_bLButtonDown) {
CDC* pDC = GetDC();
pDC->SelectObject(new CPen(PS_SOLID, 0, RGB(255, 0, 0)));
pDC->SelectStockObject(NULL_BRUSH);
pDC-> Ellipse (rect);
ReleaseDC(pDC);
m_bLButtonDown = FALSE;
}
CView::OnLButtonUp(nFlags, point);
}
二.绘图工具
1)GDI对象
Windows的图形设备接口(GDI = graphics device interface)对象指各种绘图工具,如笔、刷、位图、字体、调色板、区域等,对应的MFC类为CPen、CBrush、CBitmap、CFont等。这些图形绘制对象类都是CGDIObject的派生类,而CGDIObject则是直接从CObject类派生的抽象基类。其中,Windws CE不支持调色板类CPalette;CRgn为区域类,对应于窗口中的一个矩形、多边形或(椭)圆区域(region),可用于移动、拷贝、合并、判断和裁剪。
2)选入
可用设备上下文类CDC的多态成员函数SelectObject,来将绘图工具对象选入设备上下文,以供绘图时使用:
CPen* SelectObject( CPen* pPen );
CBrush* SelectObject( CBrush* pBrush );
virtual CFont* SelectObject( CFont* pFont );
CBitmap* SelectObject( CBitmap* pBitmap );
int SelectObject( CRgn* pRgn );
CGdiObject* SelectObject( CGdiObject* pObject );
3)获取
可用API函数GetCurrentObject来获得当前在DC中的指定类型的绘图对象:
HGDIOBJ GetCurrentObject(
HDC hdc, // handle to device context
UINT uObjectType // specifies the object-type
);
其中,参数uObjectType可取值:
OBJ_PEN // Returns the current selected pen.
OBJ_BRUSH // Returns the current selected brush.
OBJ_PAL // Returns the current selected palette.
OBJ_FONT // Returns the current selected font.
OBJ_BITMAP // Returns the current selected bitmap.
也可分别调用CDC类的下列成员函数来做同样的事:
CPen* GetCurrentPen( ) const;
CBrush* GetCurrentBrush( ) const;
CFont* GetCurrentFont( ) const;
CBitmap* GetCurrentBitmap( ) const;
CPalette* GetCurrentPalette( ) const;
5.清屏
Windows没有提供专门的清屏函数,可以调用CWnd的下面两个函数调用来完成该功能:
void Invalidate(BOOL bErase = TRUE);
void UpdateWindow( );
或调用CWnd的函数
BOOL RedrawWindow(
LPCRECT lpRectUpdate = NULL,
CRgn* prgnUpdate = NULL,
UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE
);
来完成。
例如(菜单项ID_CLEAR的事件处理函数):
CDrawView::OnClear() { // 调用OnDraw来清屏
//Invalidate();
//UpdateWindow( );
RedrawWindow( );
}
也可以用画填充背景色矩形的方法来清屏,如:
RECT rect;
GetClientRect(&rect);
pDC->FillSolidRect(&rect, RGB(255, 255, 255));
6.在控件上绘图
可以在对话框资源中放置图片控件,并对其类型属性选Frame。可在对话框的绘图消息响应函数OnPaint或其他函数中,用CWnd类的函数GetDlgItem:
CWnd* GetDlgItem( int nID ) const;
来获得图片控件的窗口对象,再用函数GetDC:
CDC* GetDC( );
由窗口对象得到DC,然后就可以用该DC在控件中画图。如(在ID为IDC_HUESAT的图片控件上画调色板)
void CColorDlg::OnPaint()
{
if (IsIconic()) {
... ...
}
else {
CDialog::OnPaint();
int i, j;
BYTE r, g, b;
// get control window and DC of Hue&Saturation
CWnd *pWin = GetDlgItem(IDC_HUESAT);
CDC *pDC = pWin->GetDC();
}
... ...
}
}
在非Frame类静态控件上绘图,必须先按顺序依次调用CWnd类的Invalidate和UpdateWindow函数后,再开始用DC画图。如在一个ID为IDC_COLOR的按钮上绘图:
void CComDlgDlg::DrawColor()
{
CWnd* pWnd = GetDlgItem(IDC_COLOR);
CDC* pDC = pWnd->GetDC();
CRect rect;
pWnd->GetClientRect(&rect);
pWnd->Invalidate();
pWnd->UpdateWindow();
pDC->FillRect(&rect, new CBrush(m_crCol));
}
附录:
CDC
└CDC |
CDC类定义的是设备上下文对象的类。
CDC对象提供处理显示器或打印机等设备上下文的成员函数,以及处理与窗口客户区对应的显示上下文的成员。
通过CDC对象的成员函数进行所有的绘图。
类对设备上下文操作提供了成员函数,处理绘图工具。安全型图形设备接口(GDI)对象收集,以及处理颜色和调色板。
它还为获取和设置绘图属性、映射,处理视点、窗口扩展、转换坐标,处理区域、剪贴、绘制直线及绘制简单椭圆和多边形等形状提供了成员函数。
另外还为绘制文本、处理字体,使用打印机跳转,滚动和播放元文件提供成员函数。
使用CDC对象时要构造它,然后调用与它平等的、使用设备上下文的Windows函数的成员函数。
注意:
Windows 95下所有屏幕坐标限制在16位以内。因此向CDC成员函数传递的int必须在-32768至32767之间。
为了特定用途,Microsoft基本类库提供了几个CDC派生类。
包括BeginPaint和EndPaint调用。 | |
管理窗口用户区对应的显示上下文。 | |
管理与整个窗口对应的显示上下文,包括它的结构和控件。 | |
与带元文件的设备上下文对应。 |
CDC包含m_hDC和m_hAttribDC两个设备上下文,它们在CDC对象创建时参考同一个设备。
CDC指导所有对m_hDC的输出GDI调用以及对m_hAttribDC的大部分属性GDI调用(GetTextColor是属性调用的例子,而SetTextColor是一个输出调用)。
例如框架使用这两个设备上下文实现CMetaFileDC对象,在从物理设备读取属性期间向元文件发送输出。
打印预览以相同风格在框架中实现。还可以以相似方法在特殊应用代码中使用这两个设备上下文。
可能多次需要来自m_hDC和m_hAttribDC设备上下文的文本度量信息。
以下几对函数提供了这项功能:
使用m_hAttribDC | 使用m_hDC |
有关CDC的更多信息,请参阅联机文档“Visual C++程序员指南”中的“设备上下文”。
#include <afxwin.h>
请参阅:CPaintDC,CClientDC, CWindowDC, CMetaFileDC
CDC类成员
数据成员
CDC对象使用的输出设备上下文 | |
CDC对象使用的输出属性上下文 |
构造函数
构造一个CDC对象 |
初始化
为指定设备创建设备上下文 | |
为指定设备创建信息上下文。这提供了一种不创建设备上下文即获取有关设备信息的快速方式 | |
创建内存设备上下文,与另一个设备上下文匹配。可以用它在内存中准备图像 | |
删除CDC对象对应的Windows设备上下文 | |
给定设备上下文句柄时,返回指向CDC对象的指针。如果CDC对象未附加到句柄,则创建并附加一个临时CDC对象 | |
由CWinApp空闲时间句柄调用,删除FromHandle创建的临时CDC对象。同时分离设备上下文 | |
把Windows设备上下文附加到这个CDC对象 | |
从CDC对象分离Windows设备上下文. | |
设置属性设备上下文m_hAttribDC | |
设置输出设备上下文m_hDC | |
释放属性设备上下文m_hAttribDC | |
释放输出设备上下文m_hDC | |
返回指向当前选择的CBitmap对象的指针 | |
返回指向当前选择的CBrush对象的指针 | |
返回指向当前选择的CFont对象的指针 | |
返回指向当前选择的CPalette对象的指针 | |
返回指向当前选择的CPen对象的指针 | |
返回显示设备上下文对应的窗口 |
设备上下文函数
返回输出设备上下文m_hDC | |
保存设备上下文当前状态 | |
恢复SaveDC保存的设备上下文以前状态 | |
更新m_hAttribDC设备上下文 | |
获取有关给定显示设备功能的指定类型指定设备信息 | |
确定正在使用的设备上下文是否用于打印 |
安全型选择帮助器
获取当前画刷的起点 | |
指定选入设备上下文的下一个画刷的起点 | |
枚举设备上下文中有效的笔和画刷 |
颜色和颜色调色板函数
选择笔等GDI绘图对象 | |
选择Windows提供的预定义的一个笔、画刷或字体 |
绘图工具函数
获取与给定设备能显示的指定逻辑颜色最接近的逻辑色 | |
选择逻辑调色板 | |
把当前逻辑调色板中的调色板入口映射到系统调色板 | |
通过客户区当前颜色在像素基础上与系统调色板的匹配,更新设备上下文的客户区 | |
获取半色调画刷 |
绘图属性函数
获取当前背景色 | |
设置当前背景色 | |
获取背景模式 | |
设置背景模式 | |
获取当前多边形填充模式 | |
设置多边形填充模式 | |
获取当前绘图模式 | |
设置当前绘图模式 | |
获取当前位图拉伸模式 | |
设置位图拉伸模式 | |
获取当前文本颜色 | |
设置文本颜色 | |
获取用于设备上下文的颜色调整值 | |
使用指定值设置设备上下文的颜色调整值 |
映射函数
获取当前映射模式 | |
设置当前映射模式 | |
获取视区起点的X和Y坐标 | |
设置视区起点 | |
相对于当前视区起点坐标修改视区起点 | |
获取视区X和Y范围 | |
设置视区X和Y范围 | |
相对于当前值修改视区范围 | |
获取参应窗口起点的X和Y坐标 | |
设置设备上下文的窗口起点 | |
相对于当前窗口起点的坐标修改窗口起点 | |
获取对应窗口的X和Y坐标 | |
设置对应窗口的X和Y坐标 | |
相对于当前值修改窗口范围 |
坐标函数
设备单位转换为HIMETRIC单位 | |
逻辑单位转换为HIMETRIC单位 | |
设备单位转换为逻辑单位 | |
逻辑单位转换为设备单位 | |
单位转换为设备单位 | |
单位转换为逻辑单位 |
区域函数
用指定画刷填充指定区域 | |
用画刷在指定区域周围绘制边线 | |
反转区域中的颜色 | |
用选取的画刷填充区域 |
剪切函数
控制指定设备上下文绑定的矩形信息的累计 | |
返回到设备上下文当前累计的绑定矩形 | |
获取当前剪切边界周围最紧绑定矩形的维数 | |
使用指定模式合并给定区域和当前剪切区域 | |
创建包含现有剪切区域减掉指定矩形的一个新剪切区域 | |
通过从剪切区域排除窗口中的更新区域,防止在窗口的无效区域中绘图 | |
通过构成当前区域和矩形的交集创建一个新的剪切区域 | |
移动给定设备的剪切区域 | |
确定给定点是否在剪切区域内 | |
确定给定矩形的任何部分是否在剪切区域内 |
线输出函数
获取笔的当前位置(以逻辑坐标表示) | |
移动当前位置 | |
从当前位置到一点画直线,但不包括那个点 | |
画一段椭圆弧 | |
画一段椭圆弧。除了更新当前位置以外,这个函数与Arc类似 | |
画一条线段和圆弧,把当前位置移到圆弧终点 | |
对设备上下文返回当前圆弧方向 | |
设备圆弧和矩形函数要用到的绘图方向 | |
画一组线段和Bezier样条。这个函数更新当前位置Polyline画一组与指定点连接的线段 | |
画多组相连线段。这个函数不使用也不更新当前位置 | |
画一条或多条直线,并把当前位置移到最后一条直线的终点 | |
画一条或多条Bezier样条。不使用也不更新当前位置 | |
画一条或多条Bezier样条,并把当前位置移到最后一条Bezier样条的终点 |
简单绘图函数
用指定画刷填充给定矩形 | |
在矩形周围绘制边界 | |
反转矩形内容 | |
绘制图标 | |
拖拽矩形时擦除并重绘它 | |
用实颜色填充矩形 | |
绘制三维矩形 | |
绘制矩形边 | |
绘制帧控件 | |
显示图像并应用可视化效果来表示一个状态 |
椭圆和多边形函数
绘制椭圆弧(椭圆和一条线段相交围成的闭合图形) | |
绘制用于表示焦点的风格的矩形 | |
绘制椭圆 | |
绘制饼形图 | |
绘制多边形,包含由线段连接的一个或多个点(顶点) | |
创建使用当前多边形填充模式的两个或多个多边形,多边形可以相互分开或叠加 | |
绘制多边形,包含连接指定点的一组线段 | |
使用当前笔绘制矩形,用当前画刷填充 | |
使用当前笔绘制圆角矩形,用当前画刷填充 |
位图函数
创建位特征 | |
从指定设备上下文拷贝位图 | |
把位图由源矩形和设备移动到目标矩形,必要时拉伸或压缩位图以适合目标矩形的维数 | |
获取指定点像素的RGB颜色值 | |
设置指定点像素为最接近指定色的近似值 | |
设置指定点坐标为最接近指定色的近似值。SetPixelV比SetPixel快,原因是它不用返回实际绘制点的颜色值 | |
用当前画刷填充区域 | |
用当前画刷填充区域。比FloodFill成员函数提供更多灵活性 | |
使用给定屏蔽和光栅操作对源和目标位图合并颜色数据 | |
从源设备上下文的指定矩形到给定设备上下文中指定平行多边形,执行颜色数据位的位块传递 |
文本函数
用当前选取字体在指定位置写字符串 | |
用当前选取字体在矩形区域写字符串 | |
在指定位置写字符串,制表符扩展为制表符停止位置数组中指定值 | |
在指定矩形内绘制格式化文本 | |
使用当前字体在属性设备上下文上计算文本行的宽度和高度,确定维数 | |
使用当前字体在输出设备上下文上计算文本行的宽度和高度,确定维数 | |
使用当前字体在属性设备上下文上计算字符串的宽度和高度 | |
使用当前字体在输出设备上下文上计算字符串的宽度和高度 | |
在给定位置绘制暗(灰色)文本 | |
获取文本对齐标记 | |
设置文本对齐标记 | |
以空终止字符串形式把当前字体字样名拷贝到缓冲区 | |
从属性设备上下文为当前字体获取度量 | |
从输出设备上下文为当前字体获取度量 | |
把空格添加到字符串的中断字符 | |
对字符间空格数量获取当前设置 | |
设置字符间空格数量 |
字体函数
从比例字体文件获取字体度量信息。获取的信息通过指定字体文件与返回信息长度的偏移量标识 | |
获取指定设备上下文中当前选取的字体字符实对 | |
获取用于TrueType字体的字体度量信息 | |
获取用于当前字体中外线字符串的外线曲线或位图 | |
从当前字体获取给定范围相继字符以逻辑单位计数的宽度 | |
从当前字体获取给定范围相继字符的分数宽度 | |
从使用输出设备上下文的当前字体获取相继字符组中各个字符的宽度 | |
改变字体映射表在从逻辑字体到物理字符映射时使用的算法 | |
获取当前长宽比过滤器的设置 |
打印机跳离函数
对打印应用调用AbortPro回滚函数,询问打印是否应终止 | |
允许应用访问不能通过GDI直接使用的特殊设备的功能。同时允许访问Windows跳离函数。应用调用的Escape调用经翻译传送到设备驱动程序 | |
访问通过图形设备接口(GDI)不能直接使用的视频显示器的绘图功能 | |
通告设备驱动程序开始一项新打印作业 | |
通告设备驱动程序开始新页 | |
通告设备驱动程序页结束 | |
如果打印作业必须终止,设置Windows调用的由程序员提供的回滚函数 | |
终止当前打印任务,擦除自上次调用StartDoc成员函数以来应用写入设备的任何内容 | |
结束由StartDoc成员函数启动的打印作业 |
滚动函数
水平和垂直滚动位矩形 |
元文件函数
在给定设备上播放指定元文件类型。增强版本的PlayMetaFile显示以增强格式元文件保存的图片。元文件可以播放任意次数 | |
从缓冲区把注释拷贝到指定增强格式元文件 |
路径函数
关闭并拒绝设备上下文中任何路径 | |
打开设备上下文中一个路径括号 | |
关闭路径中一个打开的图表 | |
关闭一个路径括号,并把括号定义的路径选择到设备上下文 | |
关闭当前路径中任何打开的图表,并用当前画刷和多边形填充模式填充路径内部 | |
变形选取到当前设备上下文路径中的任何曲线,把曲线变成一系列直线 | |
返回用于设备上下文的限制 | |
获取定义直线端点和从选择到设备上下文路径中找到的曲线控制点的坐标 | |
对设备上下文选择当前路径作为剪切区域,通过使用指定模式合并新区域和任何现有剪切区域 | |
设备用于设备上下文的连接长度限制 | |
关闭路径中任何打开的图表,使用当前笔点路径外线,使用当前画刷填充它内部 | |
使用当前笔描绘指定路径 | |
如果路径使用过了当前选取到设备上下文中的笔点,重新定义当前路径为要画的区域 |