小球在正弦曲线上运动(VC6.0—MFC)

小球在正弦曲线上运动(VC6.0——MFC)

画一条正弦曲线,和一个小球,小球按照正弦曲线的轨迹在运动。
步骤
1、打开VC6.0,点击屏幕左上角“文件(F)”,选择“新建(N)… Ctrl_N”,如下图所示。
在这里插入图片描述
2、在弹出的对话框中,选择“工程 >> MFC AppWizard(exe)”,选择创建工程的位置并给工程命名,点击“确定”,如下图所示。
在这里插入图片描述
3、选择“单文档(S)”,点击“完成”,点击“确定”,如下图所示。
在这里插入图片描述
在这里插入图片描述
4、在类视图中,鼠标选中右击,选择“Add Member Function…”,如下图所示。
在这里插入图片描述
5、分别添加画坐标轴(DrawCordinate)、画圆(DrawCircle)、画正弦函数(DrawSin)的成员函数(添加顺序无先后之分),如下图所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
6、在上面添加的三个成员函数中添加相应的代码。
在这里插入图片描述
代码如下:

void CExercise2View::DrawCordinate(CDC *pDC, CPoint orgPos) //orgPos是坐标原点
{
	//画横坐标
	pDC->MoveTo(orgPos.x - 200,orgPos.y);
	pDC->LineTo(orgPos.x + 1000,orgPos.y);
	//画纵坐标
	pDC->MoveTo(orgPos.x,orgPos.y - 200);
	pDC->LineTo(orgPos.x,orgPos.y + 200);
}

void CExercise2View::DrawCircle(CDC *pDC, POINT center, int radius) //center是圆心,radius是圆的半径
{
	CBrush brush; //创建画刷
	brush.CreateSolidBrush(RGB(255,0,0)); //填充圆
	pDC->SelectObject(&brush);
	pDC->BeginPath();
	pDC->Ellipse(center.x - radius, center.y - radius, center.x + radius, center.y + radius); //画圆
	pDC->EndPath();
	pDC->FillPath();
}

void CExercise2View::DrawSin(CDC *pDC, CPoint orgPos, int a, int b, int c) //a,b,c是sin的三个参数
{
	//画y=a*sin(b*x)+c  0<= x <= 900 画为弧度:x*3.14159/180
	int x, y;
	pDC->MoveTo(orgPos); //将sin起点移到坐标原点
	for(x = 0; x <= 900; x++)
	{
		y = 50 *a *sin(b *x *3.14159/180) + c; //50是放大纵坐标的值
		y = - y; //竖直向下为y轴正方向
		pDC->LineTo(orgPos.x + x,orgPos.y + y);
	}
}

7、定义圆的结构体,添加成员变量m_circle,如下图所示。
在这里插入图片描述
代码如下:

typedef struct
{
	POINT center; //定义圆心
	int radius; //定义半径
}MyCircle; //定义圆对象

8、在OnDraw()里调用,如下图所示。
在这里插入图片描述
代码如下:

void CExercise2View::OnDraw(CDC* pDC)
{
	CExercise2Doc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
	CPoint orgPos;
	orgPos.x = orgPos.y = 300;
	DrawCordinate(pDC,orgPos);
	DrawCircle(pDC, m_circle.center, m_circle.radius);
	DrawSin(pDC,orgPos,4,4,0); //第二个4是周期,0是从坐标原点开始
}

9、在类视图中,鼠标选中右击,选择“Add Virtual Function…”,添加“OnInitialUpdate()”函数,如下图所示。
在这里插入图片描述
在这里插入图片描述
10、在OnInitialUpdate()里对圆做初始化,其他的初始化均可放在OnInitialUpdate()函数中,如下图所示。
在这里插入图片描述
代码如下:

void CExercise2View::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
	m_circle.center.x = m_circle.center.y = 300;
	m_circle.radius = 10;
}

11、点击左下角中间的资源视图“ResourceView”,选择“Menu”新建菜单。双击“帮助(H)”右侧虚线框,在“标明©:”里添加“动画”;再双击“动画”下面的虚线框,添加内容如下图所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
12、分别在添加的“开始”,“停止”上右击选择“建立类向导…”,如下图所示。
在这里插入图片描述
13、详细步骤如下图所示。
在这里插入图片描述
14、在OnMStart()和OnMStop()中启动定时器和停止时钟,如下图所示。
在这里插入图片描述
代码如下:

void CExercise2View::OnMStart() 
{
	// TODO: Add your command handler code here
	SetTimer(1,200,NULL);
	//启动定时器。第一个参数是时钟ID号;第二个是间断的时间,
	//决定时钟每秒钟被调用多少次;第三个是回调函数(默认空)。
	//1s中断10次的话,100单位是毫秒,也就是0.1秒,0.1s/次,即1s/10次
}

void CExercise2View::OnMStop() 
{
	// TODO: Add your command handler code here
	KillTimer(1);//停止时钟
}

15、添加消息句柄,调用系统时钟(WM_TIMER), 如下图所示。
在这里插入图片描述
在这里插入图片描述
16、如下图所示。
在这里插入图片描述
代码如下:

void CExercise2View::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	//m_circle.center.x += 10;//1s中断10次,在每次中断的时候让圆心移动10个像素的单位 
	int dcircle = 0;
	int dsin = 0;
	dcircle = m_circle.center.x  - 300 + 2;
	dsin = -50 *4 *sin(4 *dcircle *3.14159/180);
	m_circle.center.x += 2;
	m_circle.center.y = dsin + 300 ;
	Invalidate(true);
	CView::OnTimer(nIDEvent);
}

17、运行结果如下图所示。
在这里插入图片描述
在这里插入图片描述

主要是模拟初中的物理实验的有源代码,可供初学者使用! 采用 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(dbDistance>100.) 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模型,就当抛砖引玉了。具体实现参考源代码例子。
好的,以下是在Visual C++ 6.0中使用MFC编写小球自由落体的基本步骤: 1. 创建一个MFC应用程序项目。 2. 在资源视图中添加一个静态文本框和一个按钮控件。 3. 在头文件中定义一个结构体,用于存储小球的状态信息,如位置、速度等。 4. 在按钮控件的消息处理函数中,初始化小球状态信息,并启动一个定时器。 5. 在定时器的消息处理函数中,更新小球的状态信息,并将小球绘制到静态文本框上。 6. 在绘制函数中,使用GDI+绘制小球。 下面是一个简单的代码示例,仅供参考: 首先,在头文件中定义一个结构体,用于存储小球的状态信息: ``` struct BallState { double x; // 小球x坐标 double y; // 小球y坐标 double vx; // 小球x方向速度 double vy; // 小球y方向速度 }; ``` 然后,在按钮控件的消息处理函数中,初始化小球状态信息,并启动一个定时器: ``` void CMyDlg::OnBtnStart() { BallState ball = { 100, 0, 0, 0 }; // 初始化小球状态 SetTimer(1, 10, NULL); // 启动定时器 } ``` 接着,在定时器的消息处理函数中,更新小球的状态信息,并将小球绘制到静态文本框上: ``` void CMyDlg::OnTimer(UINT_PTR nIDEvent) { static BallState ball = { 100, 0, 0, 0 }; // 定义静态变量,保存小球状态信息 double dt = 0.01; // 更新时间间隔 double g = 9.8; // 重力加速度 // 更新小球状态 ball.x += ball.vx * dt; ball.y += ball.vy * dt; ball.vy += g * dt; // 绘制小球 CDC *pDC = GetDlgItem(IDC_STATIC)->GetDC(); Graphics graphics(pDC->m_hDC); graphics.Clear(Color(255, 255, 255)); // 清空文本框 SolidBrush brush(Color(255, 0, 0)); graphics.FillEllipse(&brush, ball.x, ball.y, 20, 20); // 绘制小球 CDialog::OnTimer(nIDEvent); } ``` 最后,在OnInitDialog函数中启用双缓冲,以避免闪烁: ``` BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); // 启用双缓冲 GetDlgItem(IDC_STATIC)->SendMessage(WM_SETREDRAW, FALSE); GetDlgItem(IDC_STATIC)->SetDoubleBuffer(true); GetDlgItem(IDC_STATIC)->SendMessage(WM_SETREDRAW, TRUE); GetDlgItem(IDC_STATIC)->Invalidate(); return TRUE; } ``` 这样,一个简单的小球自由落体程序就完成了。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值