MFC代码--圆上点的计算

MFC的作业

  • 设计基于单文档/视图结构的程序。绘制2条圆形轨道,然后设计2个卫星(圆形代替),使其分别沿内外轨迹匀速行走。轨道路宽度、半径、颜色由轨道设定菜单加对话框指定;有开始、结束菜单;有高速、中速、低速三个菜单控制卫星速度;卫星颜色、标号由按下鼠标左键加对话框指定。
  • 简单分析:两个圆形轨道和卫星应该是用Ellipse()函数实现,匀速行走则是通过定时器来实现,至于菜单对话框什么的都不是很复杂。说白了这个题目并没有什么难度,只是说考察的点很多,比较繁琐。 ### 设计菜单 菜单包括:Status(Start/Stop)、Speed(High/Medium/Low)、Preferences(Width/Radii/Color)。
    还有添加一个鼠标左键消息处理函数。
    1
    void CSatelliteView::OnStart() { // TODO: Add your command handler code here CSatelliteDoc *pDoc=GetDocument(); ASSERT_VALID(pDoc); SetTimer(1,100,NULL); } void CSatelliteView::OnStop() { // TODO: Add your command handler code here CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); KillTimer(1); } void CSatelliteView::OnHigh() { // TODO: Add your command handler code here CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->m_speed = 1.0; } void CSatelliteView::OnMedium() { // TODO: Add your command handler code here CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->m_speed = 0.5; } void CSatelliteView::OnLow() { // TODO: Add your command handler code here CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->m_speed = 0.1; } void CSatelliteView::OnWidth() { // TODO: Add your command handler code here CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); Width dlgInput; int nRet = dlgInput.DoModal(); if(nRet == IDOK) { pDoc->m_widthDoc=dlgInput.m_width; pDoc->m_widthDocx=dlgInput.m_widthx; Invalidate(); } } void CSatelliteView::OnRadii() { // TODO: Add your command handler code here CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); Radii dlgInput; int nRet = dlgInput.DoModal(); if(nRet == IDOK) { pDoc->m_radiiDoc=dlgInput.m_radii; pDoc->m_radiiDocx=dlgInput.m_radiix; Invalidate(); } } void CSatelliteView::OnColor() { // TODO: Add your command handler code here CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); CColorDialog dlg; if(dlg.DoModal() == IDOK) { pDoc->m_orbitColor=dlg.GetColor(); Invalidate(); } } void CSatelliteView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); CColorDialog dlg; if(dlg.DoModal() == IDOK) { pDoc->m_satelliteColor=dlg.GetColor(); Invalidate(); } CView::OnLButtonDown(nFlags, point); } void CSatelliteView::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default CSatelliteDoc *pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->m_angle += pDoc->m_speed; Invalidate(); CView::OnTimer(nIDEvent); }

代码并不是特别的复杂,只是比较繁琐,至于创建类,声明变量之类的就不一一赘述了。

绘图

我做了一个响应式的布局,思路大概是先获得用户区的大小,然后算出中点。以该中点为圆心画出两个半径为用户指定的同心圆。注意画笔的选择,画刷选择为空,否则大圆会覆盖小圆。
通过公式计算出两个圆上的点来确定卫星的圆心,然后以卫星的圆心画半径为定值的圆,通过定时器不断重绘从而让它运动起来。
详细的代码如下:

void CSatelliteView::OnDraw(CDC* pDC)
{
    CSatelliteDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    CRect rectClient;
    GetClientRect(&rectClient);
    double x,y;
    x=(rectClient.right-rectClient.left)/2;
    y=(rectClient.bottom-rectClient.top)/2;
    pDC->SelectStockObject(NULL_BRUSH);
    CPen newPen;
    CPen newPenx;
    CPen newPen_satellite;
    newPen.CreatePen(PS_SOLID,pDoc->m_widthDoc,pDoc->m_orbitColor);
    newPen_satellite.CreatePen(PS_SOLID,2,pDoc->m_satelliteColor);
    newPenx.CreatePen(PS_SOLID,pDoc->m_widthDocx,pDoc->m_orbitColor);
    CPen *poldPen;
    poldPen=pDC->SelectObject(&newPen);
    pDC->Ellipse(x-pDoc->m_radiiDoc,y-pDoc->m_radiiDoc,x+pDoc->m_radiiDoc,y+pDoc->m_radiiDoc);
    poldPen=pDC->SelectObject(&newPenx);
    pDC->Ellipse(x-pDoc->m_radiiDocx,y-pDoc->m_radiiDocx,x+pDoc->m_radiiDocx,y+pDoc->m_radiiDocx);
    poldPen=pDC->SelectObject(&newPen_satellite);
    pDC->Ellipse(x+pDoc->m_radiiDoc*cos(pDoc->m_angle)-15,y+pDoc->m_radiiDoc*sin(pDoc->m_angle)-15,x+pDoc->m_radiiDoc*cos(pDoc->m_angle)+15,y+pDoc->m_radiiDoc*sin(pDoc->m_angle)+15);
    pDC->Ellipse(x+pDoc->m_radiiDocx*cos(pDoc->m_angle)-15,y+pDoc->m_radiiDocx*sin(pDoc->m_angle)-15,x+pDoc->m_radiiDocx*cos(pDoc->m_angle)+15,y+pDoc->m_radiiDocx*sin(pDoc->m_angle)+15);
    // TODO: add draw code for native data here
}

我觉得我写的简直乱到一定程度了--#
### 小结 这个程序几乎是一气呵成的,编译一遍通过简直感人。但是这个程序还是有很多细节有待完善,比如说设置初始值的问题。个人认为用户在打开这个程序的时候应该是两个卫星在跑而不是一片空白,用户根据自己的个性化需求更改一些参数,这样看起来会更友好一些。单论MFC的文档/视图结构的话貌似并没什么太复杂的内容,整个就是一个大模版,只要你循规蹈矩,解出这些水题也就是时间问题吧=
=