实习指导书3基于MFC的单文档程序设计.docx
- 文档编号:5395595
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:50
- 大小:636.80KB
实习指导书3基于MFC的单文档程序设计.docx
《实习指导书3基于MFC的单文档程序设计.docx》由会员分享,可在线阅读,更多相关《实习指导书3基于MFC的单文档程序设计.docx(50页珍藏版)》请在冰豆网上搜索。
实习指导书3基于MFC的单文档程序设计
第三部分基于MFC的
单文档程序设计
1MFC中的GDI编程
GDI(GraphicsDeviceInterface,图形设备接口)是Windows操作系统的传统图形子系统,负责与设备无关的图形绘制,Win32API为应用程序提供了丰富的绘图函数和功能,MFC对它们进行了C++类封装,参见下图。
Windows应用程序
MFC
Win32API
执行程序
用户界面(User)
图形子系统(GDI)
设备驱动程序
内核(Kernel)
图形驱动程序
硬件抽象层(HAL)
计算机硬件
图1.GDI与Windows操作系统(其中彩色部分为操作系统)
传统GDI是随Windows1.0于1985年11月推出的,新式GDI+则是随WindowsXP于2001年10月推出的GDI的改进版,增加了α混色、渐变画刷、样条曲线、矩阵变换、图像处理、持久路径等新功能。
随WindowsVista及.NET框架3.0微软于2006年11月又推出了基于DirectX和.NET框架的全新图形子系统WPF(WindowsPresentationFoundation,视窗显示/展现基础),它统一了桌面和浏览器等客户端应用程序的图形界面,采用XAML声明式编程,将用户界面的设计和编程彻底分离开来,是Windows的下一代GUI显示系统。
在MFC应用程序中,绘图一般在视图类的(屏幕/打印机)绘图消息响应函数OnDraw中进行,例如:
voidCDrawView:
:
OnDraw(CDC*/*pDC*/){
CDrawDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(!
pDoc)
return;
//TODO:
在此处为本机数据添加绘制代码
}
每次需要重绘窗口时(如程序启动、窗口大小改变、全部或部分窗口重现、程序员调用函数RedrawWindow或Invalidate/UpdateWindow),应用程序框架都会调用此CWnd消息响应成员函数(的覆盖)来绘制窗口客户区。
在Windows中,绘图一般在框架窗口的客户区(对应于视图类C*View)进行,使用的是封装在MFC的设备上下文(Device-Context,DC)类CDC中的各种绘图函数。
在绘图前,一般需先得到客户区大小和CDC对象、设置绘图颜色,然后再根据文档数据或用户操作来绘制各种图形。
1.1几何对象的结构和类
图2.GDI几何对象的结构与类
为了使用绘图函数,应该先了解绘图所用到的几种表示几何对象的结构和类,包括点、大小和矩形,其中常用的是点和矩形。
这些结构和类被分别定义在头文件windef.h和afxwin.h中。
MFC中的几何对象类都是独立的类(不是CObject的派生类),是对API中对应结构的C++封装,参见图2。
1.2客户区大小和DC
在绘图前,一般需先获得客户区大小和设备上下文DC。
1.2.1获得客户区大小
绘图一般都是在框架窗口的客户区(对应于视图类)进行,而客户区的大小在运行时可由用户动态改变,为了使绘制的图形能随窗口大小自动改变,需先得到当前客户区大小的数据(宽w和高h)。
获取客户区大小的方法有如下两种:
1.在消息响应函数OnSize中获得
可利用属性窗口的消息页,为视图类添加WM_SIZE消息的响应函数OnSize。
该函数会在窗口第一次显示或窗口大小被改变时被系统调用。
其输入参数中的cx和cy就是当前客户区的宽和高,可将它们赋值给类变量(如m_iW和m_iH)供绘图时使用。
例如:
voidCDrawView:
:
OnSize(UINTnType,intcx,intcy){
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来得到当前客户区矩形的数据,该函数的原型为:
voidGetClientRect(LPRECTlpRect)const;
其中,矩形结构的右(right)与底(bottom)就是客户区的宽与高(其左left与顶top都为0)。
例如:
RECTrect;
GetClientRect(&rect);
intw=rect.right,h=rect.bottom;
1.2.2DC
图3DC类
在Windows中,绘图使用的是封装在MFC的DC(Device-Context,设备上下文/绘图环境)类CDC中各种绘图函数。
1.CDC类
CDC是CObject的直接派生类,CDC类自己也有若干派生类,其中包括:
窗口客户区DC所对应的CClientDC类、OnPaint和OnDraw消息响应函数的输入参数中使用的CPaintDC类、图元文件对应的CMetaFileDC类和整个窗口所对应的CWindowDC类,参见图8-3。
在MFC绘图中,一般直接使用CDC类即可。
CDC类中有许多成员函数,可以用来设置各种绘图环境、属性和参数,以及绘制各种图形和图像等,将在后面陆续加以介绍。
2.获得DC
在OnDraw函数中应该使用输入参数pDC,在其他函数中则可调用从CWnd类继承的成员函数GetDC来获得当前窗口(如客户区/视图类)DC的指针,该函数的原型为:
CDC*GetDC();
注意,每次从OnDraw函数的输入参数或调用GetDC所获得的DC,都是一个全新的临时默认DC,具有默认的绘图环境和设置。
它不能用类变量来长期保存,而且原来选入的各种GDI对象全都被作废、原来设置的各种状态也失效,一切都必须从头再来。
3.释放DC
因为Windows限制可用DC的数量,所以DC属于稀缺的公用资源。
因此,对每次获得的DC,在使用完成后必须立即释放。
从OnDraw函数的输入参数pDC获得的DC,在该函数运行结束后,系统会自动释放。
但由GetDC所获得的DC,则必须自己来手工释放,这可以通过调用从CWnd类继承的成员函数ReleaseDC来完成。
该函数的原型为:
intReleaseDC(CDC*pDC);//成功返回非0
例如:
voidCDrawView:
:
OnLButtonUp(UINTnFlags,CPointpoint)
{
CDC*pDC=GetDC();//获取DC
pDC->SelectObject(&pen);//选入笔
pDC->Rectangle(&rect);//绘制矩形
ReleaseDC(pDC);//释放DC
CView:
:
OnLButtonUp(nFlags,point);
}
4.安全DC句柄
可以用CDC类的成员函数GetSafeHdc来获取DC所对应窗口(如客户区)的安全DC句柄,该函数的原型为:
HDCGetSafeHdc();
与用GetDC函数所得到的临时DC不同,该安全DC句柄在窗口的存在期间内一直是有效的。
例如,可先定义类变量HDCm_hDC;,再在适当的地方给它赋值m_hDC=GetDC()->GetSafeHdc();,然后就可以放心地使用了。
还可以使用CDC类的成员函数Attach来将一空CDC对象与此安全DC句柄连接在一起,该函数的原型为:
BOOLAttach(HDChDC);//成功返回非0
5.屏幕DC
可以以NULL为输入参数,调用全局的API函数GetDC:
HDCGetDC(HWNDhWnd);
来可获取屏幕DC的句柄。
再利用CDC类的成员函数Attach,将屏幕DC的句柄选入自定义的CDC类中。
例如:
HDChdc=:
:
GetDC(NULL);//获取屏幕DC的句柄
CDCsDC;//定义空屏幕DC对象
sDC.Attach(hdc);//粘上屏幕DC句柄
sDC.Ellipse(0,0,150,100);//在屏幕左上角画一椭圆
1.3绘图颜色与工具
在WindowsAPI中用4个字节的双字来定义颜色类型COLORREF,有红(Red)绿(Green)蓝(Blue)三个字节分量,可用RGB宏来为颜色赋值。
在GDI中有画线状图的笔(pen)、画填充图的刷(brush)、画文字的字体(font)等绘图工具。
而GDI中使用的颜色种类则有4种之多,它们分别是像素所对应的点色、笔所对应的线色、刷所对应面色、文字所对应的文本色。
其中的像素和文本色,可以通过调用对应的专门函数来设置和获取。
而笔和刷的颜色,则必须先利用颜色参数创建笔和刷对象,然后调用通用的选择对象函数SelectObject将笔、刷等绘图工具选入DC,再利用DC来绘制各种颜色的图形。
1.颜色
Windows中的颜色一般用4个字节表示(0BGR(整数序)或RGB0(字节序),因为IntelCPU的低位字节在前),Win32API中定义了一个专门表示颜色索引值的变量类型COLORREF(windef.h):
typedefDWORDCOLORREF;//0x00bbggrr
和一个由红绿蓝三原色构造颜色值的宏RGB(wingdi.h):
#defineRGB(r,g,b)
((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
其中,r、g、b为字节变量,分部对应于红、绿、蓝三原色,取值范围为0~255。
RGB宏所对应的函数说明为:
COLORREFRGB(BYTEbRed,BYTEbGreen,BYTEbBlue);
例如:
COLORREFred,gray;
red=RGB(255,0,0);
gray=RGB(128,128,128);
在API中还定义了由COLORREF变量获取各个颜色分量的宏GetXValue(wingdi.h),它们对应的函数说明为(其中的DWORDrgb等价于COLORREFcol):
BYTEGetRValue(DWORDrgb);
BYTEGetGValue(DWORDrgb);
BYTEGetBValue(DWORDrgb);
2.像素
在Windows中,像素(pixel)的颜色是直接由CDC类的成员函数SetPixel来设置的,该函数的原型为:
COLORREFSetPixel(intx,inty,COLORREFcrColor);
COLORREFSetPixel(POINTpoint,COLORREFcrColor);
其中,x与y分别为像素点的横坐标与纵坐标,crColor为像素的颜色值。
例如:
pDC->SetPixel(10,10,RGB(0,255,0));
另外,还可以用CDC的成员函数
COLORREFGetPixel(intx,inty)const;
COLORREFGetPixel(POINTpoint)const;
来获得指定点(x,y)或point的颜色。
例如:
COLORREFcol;
col=pDC->GetPixel(10,10);
3.笔
在Windows中,线状图必须用笔(pen)来画,所以线的颜色就由笔色来确定。
在MFC中,笔的属性和功能由CPen类提供(CPen是CGDIObject的派生类)。
笔的创建与使用的步骤为:
1创建笔对象
创建CPen类笔对象的方法有如下两种:
●使用非默认构造函数创建初始笔:
CPen(intnPenStyle,intnWidth,COLORREFcrColor);
其中:
⏹nPenStyle为笔的风格,可取值见下表。
表1笔风格nPenStyle值
符号常量
数值
风格名称
线例
PS_SOLID
0
实心
PS_DASH
1
虚线
PS_DOT
2
点线
PS_DASHDOT
3
虚点线
PS_DASHDOTDOT
4
虚点点线
PS_NULL
5
空笔
PS_INSIDEFRAME
6
框内
注意:
1~4号笔风格只是在笔宽=0或1时有效,笔宽>1时总为实心的。
⏹nWidth为笔宽,与映射模式有关,使用默认映射时为像素数,若nWidth=0,则不论什么映射模式,笔宽都为一个像素。
⏹crColor为笔的颜色值。
例如:
CPen*pGrayPen=newCPen(PS_SOLID,0,RGB(128,128,128));
CPengrayPen(PS_SOLID,0,RGB(128,128,128));
●使用成员函数CreatePen(多次)创建笔:
BOOLCreatePen(intnPenStyle,intnWidth,COLORREFcrColor);
可先用CPen类的默认构造函数创建一个空笔对象,然后再调用CreatePen创建具有新内容的笔,例如:
CPengrayPen;
grayPen.CreatePen(PS_SOLID,0,RGB(128,128,128));
2选笔入DC
为了能使用我们自己所创建的笔对象,必须先将它选入DC,这可以调用设备上下文类CDC的成员函数SelectObject来完成:
CPen*SelectObject(CPen*pPen);
该函数的返回值为指向原来笔对象的指针(一般将其保存下来,供下次选出新笔时使用)。
例如:
pOldPen=pDC->SelectObject(&pen);
另外,Windows中有一些预定义的笔对象(参见表2),可用CDC的另一成员函数SelectStockObject将其选入DC,其函数原型为:
virtualCGdiObject*SelectStockObject(intnIndex);
表2预定义笔
符号常量
数值
笔
WHITE_PEN
6
白色笔
BLACK_PEN
7
黑色笔
NULL_PEN
8
空笔
例如:
pDC->SelectStockObject(BLACK_PEN);
3绘制线状图
在将笔对象选入DC后,就可以使用CDC类中的绘图函数,利用DC中的笔对象,来画线状图及面状图的边线。
如果不创建和选入笔对象,则使用的是DC中的默认笔,为单像素宽的实心黑色笔。
Windows中的线状图有直线、折线、矩形、(椭)圆(弧)等。
4删除笔
不能直接删除已使用过的笔对象,必须先将它从DC中释放出来后才能删除。
释放的方法是装入其他的笔对象(一般是重新装入原来的笔对象)。
例如:
pDC->SelectObject(pOldPen);
删除笔对象的方法有如下几种:
●删除笔内容:
调用笔类CDC的成员函数DeleteObject删除笔的当前内容(但是未删除笔对象,以后可再用成员函数CreatePen在笔对象中继续创建新的笔内容)。
例如:
pen.DeleteObject();
●删除笔对象:
使用删除运算符delete将笔对象彻底删除,例如deletepen;。
●自动删除:
若笔对象为局部变量,则在离开其作用域时,笔对象会被系统自动删除。
5例子
下面为一段较完整地创建与使用笔的例子代码:
CDC*pDC=GetDC();//获取DC
CPenpen,*pOldPen;//定义笔对象和指针
//创建单像素宽的红色虚线笔
pen.CreatePen(PS_DASH,0,RGB(255,0,0));
pOldPen=pDC->SelectObject(&pen);//选入红色笔
pDC->MoveTo(10,10);pDC->LineTo(100,100);//画直线
pDC->SelectObject(pOldPen);//选出红色笔
pen.DeleteObject();//删除红色笔
//创建10单位宽的绿色实心笔
pen.CreatePen(PS_SOLID,10,RGB(0,255,0));
pOldPen=pDC->SelectObject(&pen);//选入绿色笔
pDC->Rectangle(10,10,100,100);//画矩形
pDC->SelectObject(pOldPen);//选出绿色笔
deletepen;//删除笔对象
ReleaseDC(pDC);//释放DC
4.画刷
在Windows中,面状图必须用刷(brush)来填充,所以面色是由刷色来确定的。
MFC中的刷类为CBrush(它也是CGDIObject的派生类),刷的创建与使用的步骤与笔的相似。
6构造函数
CBrush类有4个构造函数,分别用于创建空刷、实心刷、条纹刷和图案刷:
●CBrush();//创建一个刷的空对象
●CBrush(COLORREFcrColor);//创建颜色为crColor的实心刷
●CBrush(intnIndex,COLORREFcrColor);//创建风格由nIndex指定且颜色为crColor的条纹(hatch,孵化/影线)刷,其中nIndex可取条纹风格(HatchStyles)值见表3和图4。
表3条纹风格nIndex值
符号常量
数值
风格
HS_HORIZONTAL
0
水平线
HS_VERTICAL
1
垂直线
HS_FDIAGONAL
2
正斜线
HS_BDIAGONAL
3
反斜线
HS_CROSS
4
十字线(正网格)
HS_DIAGCROSS
5
斜十字线(斜网格)
水平线垂直线正斜线反斜线十字线斜十字线
图4条纹刷的种类
●CBrush(CBitmap*pBitmap);//创建位图为pBitmap的图案(pattern)刷
7创建函数
与构造函数相对应,CBrush类有多个创建不同类型刷的成员函数,如:
●BOOLCreateSolidBrush(COLORREFcrColor);//创建实心刷
●BOOLCreateHatchBrush(intnIndex,COLORREFcrColor);//创建条纹刷
●BOOLCreatePatternBrush(CBitmap*pBitmap);//创建图案刷
8预定义刷
预定义的刷对象见表4有:
表4预定义刷
符号常量
数值
刷
WHITE_BRUSH
0
白刷
LTGRAY_BRUSH
1
亮灰刷
GRAY_BRUSH
2
灰刷
DKGRAY_BRUSH
3
暗灰刷
BLACK_BRUSH
4
黑刷
HOLLOW_BRUSH
5
空刷
NULL_BRUSH
5
空刷
9选入刷
与笔一样,可以用函数SelectObject或SelectStockObject将自定义刷或预定义刷选入DC中,供绘面状图时使用。
如果未选入任何刷,则系统会使用DC中的默认刷来绘图,默认刷为白色实心刷。
10例子
下面是一个创建、选入并使用自定义实心刷的简单例子代码段:
CRectrect(10,10,210,160);
CBrushbrush(RGB(0,255,0)),*pOldBrush;
CDC*pDC=GetDC();
pOldBrush=pDC->SelectObject(&brush);
pDC->Rectangle(&rect);
pDC->SelectObject(pOldBrush);
brush.DeleteObject();
ReleaseDC(pDC);
5.绘图工具
Windows的绘图工具为各种GDI(GraphicsDeviceInterface,图形设备接口)对象,备封装在对应的CGDIObject派生类中。
将GDI对象用SelectObject函数选入DC后,就可利用对应的绘图工具进行图形绘制。
11GDI对象
图5GDI对象的类层次结构
GDI对象(绘图工具)有笔、刷、位图、字体、调色板、区域等,对应的MFC类为CPen、CBrush、CBitmap、CFont等。
这些绘图工具对象类都是CGDIObject的派生类,而CGDIObject则是直接从CObject类派生的抽象基类,参见图6。
12选入函数
可用CDC类的多态成员函数SelectObject,将绘图工具对象选入DC,以供绘图时使用:
CPen*SelectObject(CPen*pPen);
CBrush*SelectObject(CBrush*pBrush);
virtualCFont*SelectObject(CFont*pFont);
CBitmap*SelectObject(CBitmap*pBitmap);
intSelectObject(CRgn*pRgn);
CGdiObject*SelectObject(CGdiObject*pObject);
1.4输出文本
一般使用CDC类的TextOut等函数,采用DC中的当前字体和文本颜色等来输出文本。
还可以用SetTextAlign函数来设置文本的对齐方式,用SetTextColor和SetBkColor函数来分别设置文本的前景和背景颜色。
1.4.1文本输出函数
在CDC类中,封装了多种文本输出函数,它们都是使用当前的字体、文本颜色和背景颜色,在屏幕或打印机上输出文本(绘制文字)。
常用的文本输出函数有基本的TextOut、矩形区域的DrawText和可裁减和调字间距的扩展的ExtTextOut。
1.TextOut
TextOut的函数原型为:
virtualBOOLTextOut(intx,inty,LPCTSTRlpszString,intnCount);
BOOLTextOut(intx,inty,constCString&str);
其中,x与y为显示串的左上角坐标,lpszString或str为要显示的文本串,nCount为串lpszString中的字符数。
例如:
pDC->TextOut(10,30,L"Testtext");
2.DrawText
DrawText的函数原型为:
virtualintDrawText(LPCTST
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实习 指导书 基于 MFC 文档 程序设计
![提示](https://static.bdocx.com/images/bang_tan.gif)