分享
 
 
 

采用MFC编制MVC模式之球体演示程序

王朝vc·作者佚名  2006-05-23
窄屏简体版  字體: |||超大  

采用 MFC 编制 MVC 模式之球体演示程序

作者:haykey

下载源代码

在传统面向过程的程序设计中,往往采用 Input-Processing-Output 模式,这“归功”于 DOS 操作系统的单任务。当 Windows 图形界面

OS 出现后,MVC(Model-View-Controller)模型更适合 Windows 图形界面程序的设计,它将数据处理和数据显示分离开,使维护,扩展系统更加灵活

。其中,View:负责

显示数据,它从Model处获得数据然后显示。当然,一个Model会有用户可从不同角度来观察的多个View。Model:存储数据以及对数据进行各种运算和处理

。Controller:负责接受用户输入,并且把用户输入转换成对 Model 的操作。因此Controller 可能会修改 Model 的数据,当数据修改后,更新 View。其结构示意图如下:

一直采用MFC编程的朋友可能不太熟悉它,这是因为MFC的文档视图结构就是基于MVC的高层结构,这蒙蔽了我们的双眼。虽然MS替我们做了,我们还是有必要接触它,以在SDK

or 其他地方有的放矢。我做了一个球体演示的例子,其界面如下:

左侧两个表面积和体积Edit让使用者从文本的角度精确地观察,我们称其为TextView。右侧为从CStatic派生的CGraphicView,使得人们可直观地观察Sphere.对话窗口CMVCSphereDlg是控制器,来获取用户的键盘输入(输入半径后回车)和在Static上的鼠标点击与拖动(可动态调整球体半径并实时反馈球体变化)而CSphere类是模型,存储了球体半径和计算表面积,计算体积等处理半径数据的操作.

现在让我们详细看看代码,来感受下Model,View,Controller之间如何关联,如何协同工作的。

class CSphere

{

public:

... ....

//更新Graphic-VIEW

BOOL UpdateGraphicView(HWND hWnd,const CRect &rect,BOOL bErase);

//更新Text-VIEW

void UpdateTextView();

//外界Controller的接口:设置球体半径

void SetRadius(float r);

private:

//球体半径

float m_fRadius;

//计算球体表面积

float CalculateArea(float radius);

//计算球体体积

float CSphere::CalculateVolumn(float radius);

};

这里面 UpdateTextView,UpdateTextView 就是当用户输入新半径或拖动鼠标 Controller 捕获后通知 Model,Model 通知两个View更新显示

。具体代码如下:

BOOL CSphere::UpdateGraphicView(HWND hWnd,const CRect &rect,BOOL bErase)

{

//data format examination

if(!::IsWindow(hWnd)||::IsRectEmpty(&rect))

{

AfxMessageBox("View is not created by now or rect is empty");

return false;

}

//get the window pointer from window handle

CWnd *pView = CWnd::FromHandle(hWnd);

if(pView == NULL)

return false;

//set graphic view''s radius in order to painting

((CGraphicView*)pView)-SetRadius(m_fRadius);

bPaintSphere = true;//set paint tag true

//repaint

if(!::InvalidateRect(hWnd,&rect,bErase)&&

!::UpdateWindow(hWnd))

{

AfxMessageBox("UpdateView failed");

return true;

}

pView = NULL;

return false;

}

void CSphere::UpdateTextView()

{

CMVCSphereDlg *parent = (CMVCSphereDlg *)AfxGetMainWnd();

CWnd *wnd1 = parent-GetDlgItem(IDC_SURFACE);

CWnd *wnd2 = parent-GetDlgItem(IDC_VOLUMN);

CString str;

str.Format("%.2f平方米",CalculateArea(m_fRadius));

wnd1-SetWindowText(str);

str.Empty();

str.Format("%.2f立方米",CalculateVolumn(m_fRadius));

wnd2-SetWindowText(str);

}

CGraphicView中绘图关键代码如下:

void CGraphicView::OnPaint()

{

... .....

if(!bPaintSphere)

dc.DrawText("球体演示",rect,DT_VCENTER|DT_CENTER|DT_SINGLELINE);

else

{

int r=(int)m_radius;//半径取整

CPoint MiddlePoint = rect.CenterPoint();//以矩形框的中心为球心

int x=MiddlePoint.x;

int y=MiddlePoint.y;

oldpen = (CPen*)dc.SelectObject(&solid_pen);

oldbru = (CBrush*)dc.SelectObject(&brush);

dc.Ellipse(x-r,y-r,x+r,y+r); //先画一个圆形

dc.SelectObject(&dash_pen);

dc.Arc(x-r/2,y-r,x+r/2,y+r,x,y-r,x,y+r); //再画4个半圆弧

dc.Arc(x-r/2,y-r,x+r/2,y+r,x,y+r,x,y-r);

dc.Arc(x-r,y-r/2,x+r,y+r/2,x-r,y,x+r,y);

dc.Arc(x-r,y-r/2,x+r,y+r/2,x+r,y,x-r,y);

... ...

}

}

关于控制器CMVCSphereDlg响应用户输入半径回车核心代码如下:

BOOL CMVCSphereDlg::PreTranslateMessage(MSG* pMsg)

{

UpdateData();

//violation examination

if(m_r100)

{

AfxMessageBox("半径输入范围(0---100)");

return false;

}

if(pMsg-message == WM_KEYDOWN)

if(pMsg-wParam == VK_RETURN)//回车

{

CRect rect;

m_GraphicView.GetClientRect(rect);

m_Sphere.SetRadius(m_r);//把用户输入转换成对Model的操作

m_Sphere.UpdateTextView();//更新View

m_Sphere.UpdateGraphicView(m_GraphicView.GetSafeHwnd(),rect,true);//更新View

return true;

}

... ...

}

响应鼠标拖动核心代码如下:

void CMVCSphereDlg::OnMouseMove(UINT nFlags, CPoint point)

{

CRect rect;

m_GraphicView.GetClientRect(rect);

CPoint middlepoint = rect.CenterPoint();

//if click on the graphic view

if(rect.PtInRect(point)&&bIsDragging)

{

double dbDistance2 = (point.x-middlepoint.x)*(point.x-middlepoint.x)+(point.y-middlepoint.y)*(point.y-middlepoint.y);

double dbDistance = sqrt(dbDistance2);

if(dbDistance100.)

dbDistance = 100.;

m_r = (float)dbDistance;

//update radius edit

UpdateData(false);

m_Sphere.SetRadius(m_r);

m_Sphere.UpdateTextView();

m_Sphere.UpdateGraphicView(m_GraphicView.GetSafeHwnd(),rect,true);

}

... ...

}

该程序功能简单,只是示例性说明采用 MFC 如何实现MVC模型,就当抛砖引玉了。具体实现参考源代码例子。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有