MFC实现曲柄滑块以及铰链四杆机构的运动仿真

文章描述了一个使用MFC创建单文档应用程序的过程,重点在于设置用户界面和实现图形绘制。通过菜单栏和工具栏提供交互,用户可选择绘制曲柄滑块或铰链四杆机构,并动态更新图形。代码详细展示了如何添加事件处理程序、绘制图形元素和文字,以及颜色选择功能。
摘要由CSDN通过智能技术生成
  1. 创建MFC应用,选择单文档,在应用程序类型中的应用程序类型选择单文档,在项目样式中选择MFC standard,在用户界面功能中的命令行中选择 使用菜单栏和工具栏。

这样选择界面更好看一点,下面给出截图:

  1. 在资源视图中选择Menu中的IDR_MAINFRAME,双击它就会出现一个菜单栏界面,在里面可以加一些按钮,加了按钮以后还需要为相应的按钮添加事件处理程序,即当运行这个以后,点击按钮,程序会自动的去调用相应的函数来实现你点击的按钮的功能。

  1. 注意添加事件处理程序的时候,类列表要选择文件名+View这个类,否则后面会出错;

  1. 在相应的事件处理程序(函数)中添加相应的代码:

  • OnStart(), OnStop(),  OnTimer函数代码:

void CLiMotionView::OnStart()
{
    // TODO: 在此添加命令处理程序代码
    SetTimer(1, 200, NULL);
}


void CLiMotionView::OnStop()
{
    // TODO: 在此添加命令处理程序代码

    KillTimer(1);
}


void CLiMotionView::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    fFai1 += 0.05;
    if (fFai1 > 2 * Pi)
        fFai1 -= 2 * Pi;
    Invalidate(TRUE);

    CView::OnTimer(nIDEvent);

}

  1. 主要代码:OnDraw函数,图形的以及文字就是在这个函数中实现的,我猜测相当于一般C++程序中的main函数;

整体思想,如果op == 1 ,那么画曲柄滑块,如果op == 2,那么画铰链四杆机构,如果flag等于1,则介绍曲柄滑块的信息。op,flag的值在对应的消息映射函数去改变,具体在代码中实现;

 

注:字符串要用括号括起来,再在前面加一个_T,例如:

pDC->DrawText(_T("曲柄滑块机构是指用曲柄和滑块来实现转动和移动相互转换的平面连杆机构。,通过转动副联接曲柄和滑块的构件为连杆。"), rc, DT_WORDBREAK | DT_VCENTER | DT_CENTER);

int DrawText(const CString& str, LPRECF lpRect, UINT nFormat);

ipRect 参数是用来指定绘制时的参考矩形。 nFromat表示文本的格式。

  CString str;
  str.Format(_T("A"));
  pDC->TextOut(A.x - 4 * fR, A.y - 2 * fR, str);

上面这几句代码实现的作用是:将字符串中的内容保存到str中,然后再将str中的内容输出来;

  CPen* pDPen = new CPen;
        CPen newPen;
        pDPen->CreatePen(PS_INSIDEFRAME, 3, RGB(50, 100, 150));
        newPen.CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(pDPen);

CPen是一个类,实现画笔的功能,其成员函数CreatePen()是实现画笔的特性;第一个参数是线条类别,第二个参数是线条大小,第三个参数是画笔颜色; pDC是一个CDC指针,其成员函数SelectObject() 用来选择画笔给当前设备环境中,其参数为一个CPen指针;

pDC->Ellipse(A.x - fR, A.y - fR, A.x + fR, A.y + fR);

BOOL Ellipse(int x1, int y1, int x2, int y2)

画一个椭圆,x1, y1, x2, y2 表示椭圆外接矩形的位置;

 CRect rect;
 GetClientRect(&rect); //这一句一定需要,否则绘画不出图形来

该函数获取窗口客户区的坐标。客户区坐标指定客户区的左上角和右下角。由于客户区坐标是相对窗口客户区的左上角而言的,因此左上角坐标为(0,0)。这里应该注意一下:坐标包含两种:屏幕坐标与客户区坐标

void CLiMotionView::OnDraw(CDC* pDC)
{
    CLiMotionDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: 在此处为本机数据添加绘制代码

    if (op == 1)
    {
        float fTemp = (fh - fL1 * sin(fFai1)) / fL2;
        fFai2 = asin(fTemp);
        if (fTemp < 0)
            fFai2 += Pi;
        if (fFai2 > Pi / 2)    fFai2 -= Pi / 2;


        fs = fL1 * cos(fFai1) + fL2 * cos(fFai2);

        CRect rect;
        GetClientRect(&rect);
        float fCenterX = (rect.right - rect.left) / 2.0;
        float fCenterY = (rect.bottom - rect.top) / 2.0;
        float fR = 5;

        A.x = fCenterX - 100;
        A.y = fCenterY + 100;

        B.x = A.x + fL1 * cos(fFai1);
        B.y = A.y - fL1 * sin(fFai1);

        C.x = A.x + fs;
        C.y = A.y - fh;

        D.x = A.x + fs;
        D.y = A.y;

        Move_A.x = C.x - UnitX, Move_A.y = C.y - UnitY;
        Move_B.x = C.x + UnitX, Move_B.y = C.y - UnitY;
        Move_C.x = C.x + UnitX, Move_C.y = C.y + UnitY;
        Move_D.x = C.x - UnitX, Move_D.y = C.y + UnitY;

        UL.x = A.x - 100, UL.y = Move_B.y;
        UR.x = rect.right - 50, UR.y = Move_B.y;

        DL.x = UL.x, DL.y = Move_C.y;
        DR.x = UR.x, DR.y = Move_C.y;

        CPen* pDPen = new CPen;
        CPen newPen;
        pDPen->CreatePen(PS_INSIDEFRAME, 3, RGB(50, 100, 150));
        newPen.CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(pDPen);

        //画出移动副的接触顶面
        pDC->MoveTo(UL);
        pDC->LineTo(UR);

        //画出移动副的接触底面
        pDC->MoveTo(DL);
        pDC->LineTo(DR);

        //pDPen->CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(&newPen);

        //画出三个转动副的中心点
        pDC->MoveTo(A);
        pDC->LineTo(B);
        pDC->LineTo(C);

        //画移动副
        pDC->MoveTo(Move_A);
        pDC->LineTo(Move_B);
        pDC->LineTo(Move_C);
        pDC->LineTo(Move_D);
        pDC->LineTo(Move_A);

        //画出三个转动副
        pDC->Ellipse(A.x - fR, A.y - fR, A.x + fR, A.y + fR);
        pDC->Ellipse(B.x - fR, B.y - fR, B.x + fR, B.y + fR);
        pDC->Ellipse(C.x - fR, C.y - fR, C.x + fR, C.y + fR);

        CString str;
        str.Format(_T("A"));
        pDC->TextOut(A.x - 4 * fR, A.y - 2 * fR, str);
        str.Format(_T("B"));
        pDC->TextOut(B.x + fR, B.y, str);
        str.Format(_T("C"));
        pDC->TextOutW(C.x + 2 * fR, C.y - fR, str);
        str.Format(_T("D"));
        pDC->TextOut(C.x + UnitX + fR, C.y, str);

        //画机架:
        pDC->SelectObject(pDPen);

        POINT M, N, O, P;
        M.x = A.x - fR / 2, M.y = A.y + fR;
        N.x = A.x - 3 * fR, N.y = A.y + 4 * fR;
        O.x = A.x + fR / 2, O.y = A.y + fR;
        P.x = A.x + 3 * fR, P.y = A.y + 4 * fR;
        UL.x = N.x - UnitX, UL.y = N.y;
        UR.x = N.x + 1.2 * UnitX, UR.y = N.y;
        DL.x = UL.x, DL.y = UL.y + UnitY;
        DR.x = UR.x, DR.y = UR.y + UnitY;

        pDC->MoveTo(M);
        pDC->LineTo(N);
        pDC->MoveTo(O);
        pDC->LineTo(P);

        pDC->MoveTo(UL);
        pDC->LineTo(UR);
        pDC->LineTo(DR);
        pDC->LineTo(DL);
        pDC->LineTo(UL);
    }
    else if (op == 2)
    {
        fL = sqrt(fL1 * fL1 + fL4 * fL4 - 2 * fL1 * fL4 * cos(fFai1 - fSita4));
        fFai = atan((fL4 * sin(fSita4) - fL1 * sin(fFai1)) / (fL4 * cos(fSita4) - fL1 * cos(fFai1)));
        fFai3 = acos((fL2 * fL2 - fL * fL - fL3 * fL3) / (2 * fL * fL3)) + fFai;
        //fFai2 = atan((fL * sin(fFai) + fL3 * sin(fFai3)) / (fL * cos(fFai) + fL3 * cos(fFai3)));

        float fTemp = ((fL * sin(fFai) + fL3 * sin(fFai3)) / (fL * cos(fFai) + fL3 * cos(fFai3)));
        fFai2 = atan(fTemp);
        if (fTemp < 0)
            fFai2 += Pi;

        CRect rect;
        GetClientRect(&rect);
        float fCenterX = (rect.right - rect.left) / 2.0;
        float fCenterY = (rect.bottom - rect.top) / 2.0;

        A.x = fCenterX - fL4 / 2.0;
        A.y = fCenterY + 100;

        B.x = A.x + fL1 * cos(fFai1);
        B.y = A.y + fL1 * sin(fFai1);

        C.x = B.x + fL2 * cos(fFai2);
        C.y = B.y - fL2 * sin(fFai2);

        D.x = fCenterX + fL4 / 2.0;
        D.y = fCenterY + 100;

        CPen* pRedPen = new CPen;
        pRedPen->CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(pRedPen);

        //先画杆长:
        pDC->MoveTo(A);
        pDC->LineTo(B);
        pDC->LineTo(C);
        pDC->LineTo(D);
        //pDC->LineTo(A); //AD杆可以不用画出来

        float fR = 5;
        //再画转动副
        pDC->Ellipse(A.x - fR, A.y - fR, A.x + fR, A.y + fR);
        pDC->Ellipse(B.x - fR, B.y - fR, B.x + fR, B.y + fR);
        pDC->Ellipse(C.x - fR, C.y - fR, C.x + fR, C.y + fR);
        pDC->Ellipse(D.x - fR, D.y - fR, D.x + fR, D.y + fR);
            
        CString str;
        str.Format(_T("A"));
        pDC->TextOut(A.x - 4 * fR, A.y - 2 * fR, str);
        str.Format(_T("B"));
        pDC->TextOut(B.x , B.y + 2*fR, str);
        str.Format(_T("C"));
        pDC->TextOutW(C.x + 2 * fR, C.y - fR, str);
        str.Format(_T("D"));
        pDC->TextOut(D.x + fR, D.y + 2*fR, str);

        //画支座A:
        CPen *pDPen = new CPen;
        pDPen->CreatePen(PS_SOLID, 3, RGB(150, 100, 0));
        pDC->SelectObject(pDPen);

        POINT M, N, O, P;
        M.x = A.x - fR / 2, M.y = A.y + fR;
        N.x = A.x - 3 * fR, N.y = A.y + 4 * fR;
        O.x = A.x + fR / 2, O.y = A.y + fR;
        P.x = A.x + 3 * fR, P.y = A.y + 4 * fR;
        UL.x = N.x - UnitX, UL.y = N.y;
        UR.x = N.x + 1.2 * UnitX, UR.y = N.y;
        DL.x = UL.x, DL.y = UL.y + UnitY;
        DR.x = UR.x, DR.y = UR.y + UnitY;

        pDC->MoveTo(M);
        pDC->LineTo(N);
        pDC->MoveTo(O);
        pDC->LineTo(P);

        pDC->MoveTo(UL);
        pDC->LineTo(UR);
        pDC->LineTo(DR);
        pDC->LineTo(DL);
        pDC->LineTo(UL);

        //画支座D
        M.x = D.x - fR / 2, M.y = D.y + fR;
        N.x = D.x - 3 * fR, N.y = A.y + 4 * fR;
        O.x = D.x + fR / 2, O.y = D.y + fR;
        P.x = D.x + 3 * fR, P.y = D.y + 4 * fR;
        UL.x = N.x - UnitX, UL.y = N.y;
        UR.x = N.x + 1.2 * UnitX, UR.y = N.y;
        DL.x = UL.x, DL.y = UL.y + UnitY;
        DR.x = UR.x, DR.y = UR.y + UnitY;

        pDC->MoveTo(M);
        pDC->LineTo(N);
        pDC->MoveTo(O);
        pDC->LineTo(P);

        pDC->MoveTo(UL);
        pDC->LineTo(UR);
        pDC->LineTo(DR);
        pDC->LineTo(DL);
        pDC->LineTo(UL);
    }
    else if (flag)
    {
        // TODO: 在此添加命令处理程序代码

        CRect rect;
        GetClientRect(&rect); //这句必须要

        CRect rc(rect.left + 200, rect.top + 200, rect.right - 200, rect.bottom - 200);
        pDC->DrawText(_T("曲柄滑块机构是指用曲柄和滑块来实现转动和移动相互转换的平面连杆机构。,通过转动副联接曲柄和滑块的构件为连杆。曲柄滑块机构广泛应用于往复活塞式发动机、压缩机、冲床等的主机构中,把往复移动转换为不整周或整周的回转运动;压缩机、冲床以曲柄为主动件,把整周转动转换为往复移动。偏置曲柄滑块机构的滑块具有急回特性,锯床就是利用这一特性来达到锯条的慢进和空程急回的目的。曲柄滑块的运动特性常用曲柄转角与滑块行程s的关系曲线来表示。如果是对心曲柄滑块机构(如图1所示),没有急回特性,极位夹角为零。"), rc, DT_WORDBREAK | DT_VCENTER | DT_CENTER);

        double start = clock();
        while (flag)
        {
            double stop = clock();
            if ((stop - start) / CLOCKS_PER_SEC > 5) break;
        }

        flag = 0;
    }
}

  • CcolorDialog 类为应用程序提供了“颜色”对话框,其成员函数DoModal若返回IDOK,则可以调用GetColor()函数,返回用户选择的颜色;

GetColor函数原型:COLORREF GetColor() const;

  • Invalidate(TRUE);

该函数会调用OnDraw()函数;


void CLiMotionView::OnColor()
{
    // TODO: 在此添加命令处理程序代码
    CColorDialog  dColor;
    if (dColor.DoModal() == IDOK)
        m_color = dColor.GetColor();
}


void CLiMotionView::OnPrint()
{
    flag = 1;
    op = 0;
    Invalidate(TRUE);
}


void CLiMotionView::On_CrankSilder()
{
    // TODO: 在此添加命令处理程序代码
    op = 1;

    //曲柄滑块的初始化数据
    fL1 = 150.0;
    fL2 = 400.0;
    fFai1 = Pi / 4;
    fFai2 = 0.0;
    fh = 200.0;

    Invalidate(TRUE);
}


void CLiMotionView::On_HingedFourBar()
{
    // TODO: 在此添加命令处理程序代码
    op = 2;

    //铰链四杆的初始化数据
    fL = 0.0;
    fL1 = 150.0;
    fL2 = 300.0;
    fL3 = 250.0;
    fL4 = 280.0;

    fFai = 0.0;
    fFai1 = Pi / 4;
    fFai2 = 0.0;
    fFai3 = 0.0;
    fSita4 = 0.0;

    Invalidate(TRUE);
}

  1. 全局变量定义:

float fL, fL1, fL2, fL3, fL4;
    float fFai, fFai1, fFai2, fFai3, fSita4;
    POINT A, B, C, D; //分别表4个转动副的中心点;

    float  fh, fs;

    POINT Move_A, Move_B, Move_C, Move_D; //移动副

    POINT UL, UR; //移动副的接触顶面
    POINT DL, DR; //移动副的接触底面

    int flag = 0; //不为零就介绍曲柄滑块
    int op = 0; //为1画铰链四杆,为2画曲柄滑块

    COLORREF m_color;

定义位置在.h文件中,对应的位置如下图所示

  1. 具体实现功能展示:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值