第五节 CView和GDI以及类与继承.docx
《第五节 CView和GDI以及类与继承.docx》由会员分享,可在线阅读,更多相关《第五节 CView和GDI以及类与继承.docx(14页珍藏版)》请在冰豆网上搜索。
![第五节 CView和GDI以及类与继承.docx](https://file1.bdocx.com/fileroot1/2022-12/13/e8b14f05-c724-4b5a-9ade-2bb8419141c7/e8b14f05-c724-4b5a-9ade-2bb8419141c71.gif)
第五节CView和GDI以及类与继承
第4节CView和GDI以及类与继承
一.建立MFC单文档
首先打开VS2008,在“文件”中新建项目,选择visualC++中的“MFC应用程序”
命名为“Five”确认,弹出“MFC应用程序向导”;
点击下一步,在应用程序类型中选择“单文档”,在“用户功能界面”中勾选“最大化”;点击下一步,在生成的类中的基类选择“CView”,点击完成单文档CView的建立。
然后像以前一样将工程属性中的常规中使用的字符集改为“使用多字节字符集”。
2.熟悉CView的结构
CView不像前面所说的CFromView,在CView中没有对话框,没有可以从工具箱拖动的控件等,只能在自己利用代码创建一个控件并为其添加事件。
下面我们以建立一个CTreeCtrl,即树状控件。
首先在FiveView.h中实例化一个控件对象,代码如下:
CTreeCtrlm_tree;
然后再FiveView.cpp中创建一个CTreeCtrl,创建前需要先为FiveView.cpp添加一个OnCreat()事件,创建方法在前面几节中有介绍,下面创建CTreeCtrl,代码如下:
intCFiveView:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
if(CView:
:
OnCreate(lpCreateStruct)==-1)
return-1;
m_tree.Create(WS_VISIBLE|WS_CHILD|WS_BORDER|TVS_HASLINES|TVS_HASBUTTONS|TVS_EDITLABELS|TVS_LINESATROOT|TVS_CHECKBOXES,CRect(0,0,0,0),this,IDC_TREECTRL);
m_tree.ModifyStyle(TVS_CHECKBOXES,0);
return0;
}
如果直接写上面的程序会报出错误,因为没有IDC_TREECTRL,其中IDC代表资源文件。
因此我们需要现在resources.h中声明此ID,代码如下:
#defineIDC_TREECTRL130
不能与resources.h中的其他重复。
另外我需要介绍下m_tree.Creat方法中的相关内容,代表了创建的CTreeCtrl拥有的样式,
而后面的m_tree.ModifyStyle()的作用是对CTreeCtrl的样式进行增加或删除,其定义为:
BOOLModifyStyle(DWORDdwRemove,DWORDdwAdd,UINTnFlags=0);
dwRemove是进行删除的项,若没有,设为0;dwAdd是进行添加的项,同样,没有则设为0。
上面的功能就是移除已经定义了的TVS_CHECKBOXES。
其中的CRect(0,0,0,0)代表建立一个确定坐标的矩形。
当改变窗体大小时,树状控件也随其变化,并充满窗体。
首先为FiveView.cpp添加一个OnSize()事件,写下如下代码:
if(m_tree.m_hWnd)
m_tree.SetWindowPos(NULL,0,0,cx,cy,SWP_NOZORDER);
在属性为FiveView.cpp添加一个OnInitialUpdate()方法,通过此方法为树状控件添加节点,代码如下:
voidCFiveView:
:
OnInitialUpdate()
{
CView:
:
OnInitialUpdate();
HTREEITEMm_node=m_tree.InsertItem("根节点",TVI_ROOT);
m_tree.InsertItem("第一层节点",m_node);
m_tree.InsertItem("根节点2",TVI_ROOT);
}
运行效果如图:
3.基于CView的GDI绘图
新建一个工程,命名为“Five_GDI”,方法与上面一样。
找到Five_GDIView.cpp中的OnDraw()方法,其中的CDC就是进行绘图的类,
1)下面在指定坐标上输出文字,代码如下:
voidCFive_GDIView:
:
OnDraw(CDC*pDC)
{
CFive_GDIDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(!
pDoc)
return;
pDC->TextOut(100,100,"Hello,World!
");
}效果如图
2)
在窗口中画线,代码如下:
pDC->MoveTo(100,200);
pDC->LineTo(500,600);
效果如图
3)在窗口画矩形和椭圆
pDC->Rectangle(100,100,200,200);
pDC->Ellipse(400,200,500,400);
效果如图
4)画红色边框的矩形
CPenpPen,*oldPen;
pPen.CreatePen(1,2,RGB(255,0,0));
oldPen=pDC->SelectObject(&pPen);
pDC->Rectangle(100,100,200,300);
pDC->SelectObject(oldPen);
pPen.DeleteObject();
5)画内部填充颜色的矩形框
CPenpPen,*oldPen;
pPen.CreatePen(1,2,RGB(255,0,0));
oldPen=pDC->SelectObject(&pPen);
CBrushpBrush,*oldBrush;
pBrush.CreateSolidBrush(RGB(0,225,0));
oldBrush=pDC->SelectObject(&pBrush);
pDC->Rectangle(100,100,200,300);
pDC->SelectObject(oldPen);
pPen.DeleteObject();
pDC->SelectObject(oldBrush);
pBrush.DeleteObject();
其中外框属于CPen类,而内部为CBrush类
注:
在将新画笔使用完成后,需要还原为默认颜色,否则画笔颜色会被更改。
另外使用完成后要删除对象,否则可能会引起内存泄露。
6)
创建没有边框的内有填充的矩形
CPenpPen,*oldPen;
oldPen=(CPen*)pDC->SelectStockObject(NULL_PEN);
CBrushpBrush,*oldBrush;
pBrush.CreateSolidBrush(RGB(255,0,0));
oldBrush=pDC->SelectObject(&pBrush);
pDC->Rectangle(100,200,200,400);
pDC->SelectObject(oldBrush);
pDC->SelectObject(oldPen);
pBrush.DeleteObject();
其中外框选择NULL_PEN,因此不需要为其设定颜色。
7)创建只有边框没有内部填充的矩形
CPenpPen,*oldPen;
pPen.CreatePen(1,2,RGB(255,0,0));
oldPen=pDC->SelectObject(&pPen);
CBrushpBrush,*oldBrush;
oldBrush=(CBrush*)pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(100,100,200,300);
pDC->SelectObject(oldPen);
pPen.DeleteObject();
pDC->SelectObject(oldBrush);
pBrush.DeleteObject();
此情况与6)情况相同。
8)关于用户坐标与窗口坐标的转换
CRectwinrt;
GetWindowRect(winrt);
ScreenToClient(winrt);
CRectrt;
GetClientRect(rt);
在应用中要注意我们所使用的坐标系统,并成功进行转换。
4.利用类与继承画矩形和椭圆
首先在工程的包含.h文件目录下建立一个文件夹,命名为“include”;然后在VS05中“解决方案资源管理器”中的工程中添加一个类,选择“C++类”,类名为:
RectPainter,.h文件中输入include\Rectpainter.h,确定。
然后再添加两个筛选器,分别命名为:
include.cpp和include.h。
然后将生成的Rectpainter.cpp和Rectpainter.h分别拖入其中。
如图:
1)类:
在Rectpainter.h中声明类的方法和属性,代码如下:
classRectPainter
{
public:
RectPainter(void);
virtual~RectPainter(void);
voidSetRect(doubleleft,doubletop,doubleright,doublebottom);
inlinevoidSetBackColor(COLORREFcr,COLORREFcb)
{
backColor=cr;
backColor2=cb;
}
voidDraw(CDC*pDC);
protected:
DOUBLEl,t,r,b;
COLORREFbackColor;
COLORREFbackColor2;
};
然后在Rectpainter.cpp中实现上面的方法:
RectPainter:
:
RectPainter(void)
{
}
RectPainter:
:
~RectPainter(void)
{
}
voidRectPainter:
:
SetRect(doubleleft,doubletop,doubleright,doublebottom)
{
l=left;
t=top;
r=right;
b=bottom;
}
voidRectPainter:
:
Draw(CDC*pDC)
{
CPenpPen,*oldPen;
pPen.CreatePen(0,2,backColor);
oldPen=pDC->SelectObject(&pPen);
CBrushpBrush,*oldBrush;
pBrush.CreateSolidBrush(backColor2);
oldBrush=pDC->SelectObject(&pBrush);
pDC->Rectangle(l,t,r,b);
pDC->SelectObject(oldPen);
pPen.DeleteObject();
}
上面我们完成了Rectpainter类的建立,下面我们来实例化该类并应用
在Five_GDI2View.h实例化,并添加头文件,代码如下:
#include"include\RectPainter.h"
.........
RectpainterpPainter;
然后在OnCreat事件中写下如下代码
intCFive_GDI2View:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
............
pPainter.SetRect(100,100,200,200);
pPainter.SetBackColor(RGB(255,0,0),RGB(0,255,0));
.............
}
最后绘制图像,即在OnDraw事件中添加代码:
voidCFive_GDI2View:
:
OnDraw(CDC*pDC)//注意把原有的/**/去掉
{
pPainter.Draw(pDC);
}
运行效果如图:
2)继承:
新建一个工程命名为Five_GDI1,建立方法与上面一致。
在Rectpainter.h中声明类的方法和属性,
classCGeometryPainter
{
public:
CGeometryPainter()
{
};
virtual~CGeometryPainter()
{
};
voidSetRect(doubleleft,doubletop,doubleright,doublebuttom);
voidSetBackColor(COLORREFcr)
{
backColor=cr;
};
virtualvoidDraw(CDC*pDC)=0;
protected:
DOUBLEl,t,r,b;
COLORREFbackColor;
};
classCRectPainter:
publicCGeometryPainter
{
public:
CRectPainter();
virtual~CRectPainter();
voidDraw(CDC*pDC);
};
classCEllipsesPainter:
publicCGeometryPainter
{
public:
CEllipsesPainter();
virtual~CEllipsesPainter();
voidDraw(CDC*pDC);
};
其中CGeometryPainter为基类,而CRectPainter和CEllipsesPainter都继承与它,由于其中的Draw方法具有不同,所以需要在CGeometryPainter将其设为虚方法;
virtualvoidDraw(CDC*pDC)=0;
而CGeometryPainter则为抽象类,不能进行实例化,如果要实例需要用到指针,后面将要使用。
然后在Rectpainter.cpp中实现上面的方法:
voidCGeometryPainter:
:
SetRect(doubleleft,doubletop,doubleright,doublebuttom)
{
l=left;
t=top;
r=right;
b=buttom;
}
CRectPainter:
:
CRectPainter(void)
{
}
CRectPainter:
:
~CRectPainter(void)
{
}
voidCRectPainter:
:
Draw(CDC*pDC)
{
CBrushpBrush,*oldBrush;
pBrush.CreateSolidBrush(backColor);
oldBrush=pDC->SelectObject(&pBrush);
pDC->Rectangle(l,t,r,b);
pDC->SelectObject(oldBrush);
pBrush.DeleteObject();
}
CEllipsesPainter:
:
CEllipsesPainter(void)
{
}
CEllipsesPainter:
:
~CEllipsesPainter(void)
{
}
voidCEllipsesPainter:
:
Draw(CDC*pDC)
{
CBrushpBrush,*oldBrush;
pBrush.CreateSolidBrush(backColor);
oldBrush=pDC->SelectObject(&pBrush);
pDC->Ellipse(l,t,r,b);
pDC->SelectObject(oldBrush);
pBrush.DeleteObject();
}
上面我们完成了Rectpainter类的建立,下面我们来实例化该类并应用
在Five_GDI2View.h实例化,并添加头文件,代码如下:
#include"include\RectPainter.h"
protected:
CArraypGeoPainters;
这儿我们使用数组用来存放各个图形。
然后在OnCreat事件中写下如下代码
CGeometryPainter*pGeoPainter;//这就是上面所说的抽象类的实例
for(inti=0;i<6;i++)
{
if(i%2==0)
{
pGeoPainter=newCRectPainter();
pGeoPainter->SetRect(100+i*100,100+i*100,200+i*100,200+i*100);
pGeoPainter->SetBackColor(RGB(255,0,0));
}
else
{
pGeoPainter=newCEllipsesPainter();
pGeoPainter->SetRect(100+i*100,100+i*100,200+i*100,250+i*100);
pGeoPainter->SetBackColor(RGB(0,255,0));
}
pGeoPainters.Add(pGeoPainter);
}
在此创建图形,最后在OnDraw事件中绘制完成,代码如下:
voidCFive_GDI1View:
:
OnDraw(CDC*pDC)
{
CFive_GDI1Doc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
if(!
pDoc)
return;
intSize=pGeoPainters.GetSize();
for(intk=0;k{
pGeoPainters[k]->Draw(pDC);
}
}
运行效果如图: