QQ登录

只需一步,快速开始

上位机MFC组合逻辑仿真器源代码下载

[ 复制链接 ]

上位机MFC组合逻辑仿真器源代码下载

上位机MFC组合逻辑仿真器源代码下载
转出结果如下:
2.png
源代码下载地址:
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:上位机MFC组合逻辑仿真器源代码下载.rar 
文件大小:36.86 KB  售价:1金币
下载权限: 不限 以上或 VIP会员   [购买捐助会员]   [充值积分]   有问题联系我

  

halcon从自学到接项目视频教程,另外再赠送全网最全资源  

  

欢迎围观我录制的一套halcon自学视频教程(进入)

  

上位机VC MFC程序开发精典实例大全源码与视频讲解配套下载408例

  

经历1年的编程与录制点击进入查看

  

如果您认可,可联系功能定制!

  

如果您着急,充值会员可直接联系发您资料!

  

QQ联系我

微信扫扫联系我

  

工程的介绍可以参考下面。
程序由几个大模块组成:元件数据结构模块,
电路图编辑模块,元件库模块,计算结果(仿真)模块。
l  元件数据结构模块
统一的元件数据结构可以提高程序运行速度,方便程序编制。不足是由于元件的不同存储空间上可能会有少许浪费。
所有的元件种类共有8种,如图
3.png
定义数据结构如下:
              typedefstruct tagMyNode
{
                     Mytypetype;                //元件类型
              MySubtype Subtype;      //元件子类型
                     tagMyNode*input1;      //输入端1
tagMyNode* input2;      //输入端1
              tagMyNode* output1;   //输出端1
                     UINTinput1value;     //输入端input1的值
                     UINTinput2value;     //输入端input2的值
              UINT output1value;    //输出端output1的值
                     intinputs;            //当前已经有几个输入端有值
              int number;            //对于输入结点的序号
                     CPointOrgpoint;       //记录元件左上角位置
              int width;          //记录元件宽度
       int height;          //记录元件高度
}MyNode;
      
u 元件类型:元件类型Mytype type中Mytype是一个枚举类型定义如下:
enum Mytype
       {
              Node,     //结点
              Gate,      //门
       };
       分为两种类型:Node结点和Gate门。
      
u 元件子类型元件子类型MySubtype Subtype中MySubtype也是一个枚举类
型,定义如下:
       enum MySubtype
       {
              Input,       //输入端
              Output,       //输出端
              ANDGate,     //与门
              ORGate,        //或门
              NOTGate,      //非门
              NORGate,      //或非门
              NANDGate,   //与非门
              XORGate,      //异或门
       };   
      
u 指针连接: tagMyNode* input1;
tagMyNode*input2;      
                                 tagMyNode*output1
是指向此结点的指针。由于元件之间是要相互连接的,于是设置这几个指针用于元件之间的连接。其中特殊情况有:
       非门:由于非门只有一个输入端,所以非门不用tagMyNode* input2;
       输入结点:输入结点只有一个链接端(这里称之为触点),采用tagMyNode* output1
       输出结点:同输入结点,只有一个触点,采用tagMyNode* input1;
u 保存触点值由于要进行仿真计算,所以还需保存各个触点的值:
UINT input1value;     
                     UINTinput2value;     
              UINT output1value;
       同指针连接,有3种特殊情况:
              非门:不用UINT input2value;     
       输入结点:采用UINT output1value;
输出结点:采用UINT input1value;     
u 进位标志:int inputs;
       在进行仿真计算时,要用进位标志辅助计算。如与门只有在两个输入端都有值时,即inputs==2时,才能进位。
u 输入结点序号:int number;
       每个输入结点都有不同的序号,从1开始递增。
u 元件位置和大小:
       CPoint Orgpoint;
       int width;
       int height;
       Orgpoint用于记录元件在视图中左上角的坐标
width用于记录元件宽度
       height用于记录元件高度
      
      
l  电路图编辑模块
电路图编辑模块又分为两个子模块:鼠标放置元件模块,鼠标连接元件模块
首先在工具栏中可以选择这两种状态,如图
4.png
在按钮上单击可以切换状态。
定义一个枚举类型MyStatus来记录当前状态:
enum MyStatus
{
       NONE,          //鼠标连接元件状态
       ANDGATE,   
       ORGATE,
       NOTGATE,
       NORGATE,
       NANDGATE,
       XORGATE,
       NODEINPUT,
       NODEOUTPUT
};
MyStatus Status;
其中:NONE为鼠标连接状态,其他为鼠标放置状态。
u 鼠标放置元件模块
其算法如图
5.png
n  DrawObject函数:
首先根据Status的状态,即六个门,两个端结点。共8种来调用DrawObject函数
2 引入准备好的八张位图(六个门,两个端)
CBitmap MyBitMap;
MyBitMap.LoadBitmap (nID);
                                   
2 将引入的位图拷贝入窗体窗户区
BITMAP bmpInfo;
                                   MyBitMap.GetBitmap (&bmpInfo);
                     pOldBitmap=dc.SelectObject (&MyBitMap);
ClientDC.BitBlt(point.x ,point.y,bmpInfo.bmWidth ,bmpInfo.bmHeight,&dc,0,0,SRCAND);
dc.SelectObject (pOldBitmap);
2 用全局变量bmWidth和bmHeight来保存元件的宽度和高度
bmWidth=bmpInfo.bmWidth ;
                     bmHeight=bmpInfo.bmHeight ;
n  CreateMyObject函数
函数声明为:CreateMyObject(Mytype type, MySubtype Subtype, CPoint point)
2 初始化元件
MyNode* pNode=new MyNode;
              pNode->type =type;
       pNode->Subtype=Subtype;
       pNode->input1 =0;
              pNode->input2 =0;
       pNode->output1 =0;
       pNode->output2 =0;
              pNode->Orgpoint =point;
       pNode->width=bmWidth;
       pNode->height=bmHeight;
              pNode->input1value =0;
       pNode->input2value=0;
       pNode->output1value=0;
       pNode->inputs =0;
2 如果创建的元件为输入结点,则要创建并画输入结点前的序号,这里
采用一个全局数组CArray<CPoint,CPoint> numpoint来记录结点前序号。
       if(Subtype==Input)
       {
              //当创建Input时加入点到numpoint数组中
              numpoint.Add(CPoint(point.x-15,point.y));
              pNode->number =numpoint.GetSize();
              //创建时重绘序号
              redrawnum();
       }
而redrawnum()函数就是将所有输入结点前的序号重绘。
2 最后将元件加入到全局链表CList<MyNode*,MyNode*> MyList中。
       MyList.AddTail (pNode);
u 鼠标连接元件模块
鼠标连接元件模块分为三个过程模块:鼠标移动模块,鼠标按下模块,鼠标抬起模块。
              
n  鼠标移动模块
其算法如图
6.png
代码如下:
void CMyView::OnMouseMove(UINT nFlags, CPoint point)
{
       // TODO: Add your messagehandler code here and/or call default
      
      
       //此时必然是非画图状态,所以status==NONE;
       if(Status==NONE)
       {
              //当前点在某个物件上吗? 并且 //当前点在该物件触点上吗?
              if(IsPointInObject(point)&& IsPointInPut(point))
              {
              //全局变量pNodeNow是在IsPointInObject()这个函数里面记录的
                     //circlepoint和put是在IsInInput1() IsInInput2() IsInOutput1()
                     //这三个函数中记录的
                     //判断此时触点时否己连接非常重要
                     
                     if(IsPutLinked())
                     {
                            //如果此时触点己连接,则退出
                            return;
                     }
                     
                     //此时鼠标移进触点
                     //当前是连接态吗?
                     if(IsLink)
                     {
                            //连接态画图
                            LinkStatusDraw(point);
                     }
                     //开启画圆圈态
                     IsDrawCircle=TRUE;
                     //画圆圈
                     DrawMyCircle();
              }
              else//此时鼠标移出触点
              {
                     //如果此时已画圆圈,则要擦除圆圈
                     if(IsDrawCircle==TRUE)
                     {
                            EraserMyCircle();
                            //关闭画圆圈状态
                            IsDrawCircle=FALSE;
                            //重绘连接线
                            moveoutredrawline();
                           
//重绘圆圈所在的那个物件,因为擦除圆圈的时候可能擦除了部分物件
                            //-------------------
                            redrawMyObject(pNodeNow);
                     
                            //如果此时是连接状态,连接态画图
                     }
                     if(IsLink)
                     {
                                   //连接态画图
                            LinkStatusDraw(point);
                     }
      
              }
       }
       CView::OnMouseMove(nFlags,point);
}
2 两个关键状态:可连接态IsDrawCircle和正在连接态IsLink
&#216; 可连接态IsDrawCircle 当且仅当鼠标移动到某个元件上的某个尚未连接的触点上,才开启可连接态IsDrawCircle。之所以取名IsDrawCircle是因为此时会在鼠标停留的尚未连接的触点上画一个黑色小圆圈。
当鼠标移动离开触点,可连接态IsDrawCircle关闭。
&#216;  正在连接态IsLink 当鼠标按下(见图5)并且此时可连接态IsDrawCircle开启(为TRUE)时正在连接态IsLink开启。
2  判断当前点是否在某个元件函数:IsPointInObject()
其算法如图
7.png
2  判断当前点是否在该元件触点上函数:IsPointInPut()
其算法如图
8.png
与门与其它5个门有所不同,与门只有一个输入端,所以要分开来判断
对于输入结点,则判断当前点是否在第一个输出端触点。
对于输出结点,则判断当前点是否在第一个输入端触点。
输入结点和输出结点的这样判断,一眼看上去似乎反了,但实际上有利于整个程序的编写。可以简单地这样分类:总共只有两种端,一种输入,一种输出。
                   这样,我们就可以将判断触点分为三个函数:
                   IsInInput1()
                   IsInInput2()
                   IsInOutput1()
                   拿IsInInput1()来分析:
                                       centerpoint=GetCirclePoint(Input_1);
                                          if(IsInArea(point))
                                          {
                                                 //说明此时就在触点Input_1,用全局变量put记录下来
                                                 put=Input_1;
                                                 //如果当前点在,则要保存触点中心点
                                                 circlepoint=centerpoint;
                                                 returnTRUE;
                                          }
                                          else
                                          {
                                                 //如果移出触点,肯定不要再保存中心点
                                                 returnFALSE;
                                          }
首先,调用函数GetCirclePoint()来取得当前触点的中心点。然后调用IsInArea(point)函数来判断当前点point是否在以当前触点中心点为中心的矩形区域内。如果是,则用一个全局枚举变量put来记录来前触点是两个输入端和一个输出端中哪一个。
我们看这个枚举类型:
enumMyput
{
    Input_1,
    Input_2,
    Output_1
};
接下来用一个全局变量circlepoint来记录当前触点中心点。再返回真。
如果当前点不在以当前触点中心点为中心的矩形区域内,则返回假。这时千万不能记录当前触点中心点。这点不注意会出大错。
2  判断当前触点是否已连接函数:IsPutLinked()
BOOLCMyView::IsPutLinked()
{
       switch(put)
       {
       case Input_1:
              if(pNodeNow->input1 !=0)
                     return TRUE;
              break;
       case Input_2:
              if(pNodeNow->input2 !=0)
                     return TRUE;
              break;
       case Output_1:
              if(pNodeNow->output1 !=0)
                     return TRUE;
       }
       return FALSE;
}
这里根据全局变量put的类型和全局变量pNodeNow所指向的元件,
就可以判断当前元件的当前触点是否已连接。如果连接相应指针不为0。返回真,否则返回假。
2  连接态画图函数:LinkStatusDraw()
voidCMyView:inkStatusDraw(CPoint point)
{
              CClientDC clientDC(this);
              CPenwhitepen(PS_SOLID,1,RGB(255,255,255));
              CPen* pOldPen;
              pOldPen=clientDC.SelectObject(&whitepen);
              clientDC.MoveTo (startpoint);
              clientDC.LineTo (lastpoint);
              clientDC.SelectObject (pOldPen);
              CPen redpen(PS_DOT,1,RGB(255,0,0));
              pOldPen=clientDC.SelectObject(&redpen);
              clientDC.MoveTo (startpoint);
              clientDC.LineTo (point);
              clientDC.SelectObject (pOldPen);
              lastpoint=point;
              //重绘所有输入结点前的序号
              redrawnum();
              //重绘连接线
              LinkLineRedraw(startpoint,point);
              //重绘物件
              lineRedraw(startpoint,point);
}
这里,startpoint是鼠标按下开始连接时起始元件触点中心点坐
标,lastpoint是上一次鼠标移动所停留的点。为了实在连接时鼠标移动
的动画效果,我们要先擦除上一次移动画的线(用白笔),然后再从startpoint到当前点point画线。移动时由于不信的擦除重画,可能将先前已画的元件,输入结点前的序号,和已经连接好的线擦除。于是我们需要重绘。
重绘所有输入结点前的序号
redrawnum();
voidCMyView::redrawnum()
{
       CClientDC dc(this);
       char buffer[20];
       CPoint point;
       //重绘所有Input前的序号
       for(int i=0;i<numpoint.GetSize ();i++)
       {
              //将数字转换成字符,存于buffer中
              _itoa(i+1,buffer,10);
              point=numpoint.GetAt (i);
              dc.TextOut (point.x ,point.y,buffer);
       }
}
    由于每创建一个输入结点,就要相应地记录一个序号。这个序号的位置点记录在numpoint这个数组中。数组声明如下:
    CArray<CPoint,CPoint> numpoint;
    而数组的下标加1就为序号。
    所以每次重绘为了方便,将所有序号都重绘。
    重绘连接线
voidCMyView:inkLineRedraw(CPoint startpoint, CPoint point)
{
       //将起点startpoint到终点point扩充成一个矩形drawrect
       CRect drawrect(startpoint,point);
       //rect用于产生连接线最大矩形
       CRect rect;
       //rectInter用于计算两个矩形的相交区域
       CRect rectInter;
       //point1和point2用于产生连接线最大矩形
       CPoint point1;
       CPoint point2;
       drawrect.NormalizeRect ();
       drawrect.InflateRect (1,1);
       //遍历MyPointList链表
       POSITION pos=MyPointList.GetHeadPosition();
       while(pos!=0)
       {
              //pPointArray用于指向点数组对象首址
              CArray<CPoint,CPoint>*pPointArray=MyPointList.GetNext (pos);
              point1=pPointArray->GetAt (0);
              switch(pPointArray->GetSize ())
              {
                     //分两种情况 :2个点和4,5个点的情况
              case 2:
                     //2个点时
                     point2=pPointArray->GetAt(1);
                     break;
              default:
                     //4,5个点时
                     point2=pPointArray->GetAt(3);
              }
              //用point1和point2设置矩形rect
              rect.left =point1.x ;
              rect.top =point1.y;
              rect.right =point2.x;
              rect.bottom =point2.y;
              rect.NormalizeRect ();
              rect.InflateRect (1,1);
              //如果两个矩形相交,则要重绘
              if(rectInter.IntersectRect(&drawrect,&rect))
              {
                     DrawLinkLine(pPointArray);
              }
       }
}
    主要的算法思想是:将起点startpoint到当前点point扩充成一个矩形drawrect,然后遍历连接线链表,将每根连接线扩充成一个矩形rect,再判断这两个矩形是否相交,若相交,则需要重绘这根连接线。
    连接线链表声明如下:
CList<CArray<CPoint,CPoint>*,CArray<CPoint,CPoint>*>
MyPointList;
链表中每个结点是一个数组对象的地址,而这个数组中每个元素是一个点。这样一个数组就表示了一根连接线,而一个链表可以遍历所以连接线。
   
2  画提示连接的小圆圈函数:DrawMyCircle()
voidCMyView:rawMyCircle()
{
       //此时全局变量circlepoint记录了要画圆圈的
       //而pNodeNow指向了当前的物件
       //将物件坐标中的circlepoint转换成VIEW中的坐标
       int x,y;
       x=pNodeNow->Orgpoint .x+circlepoint.x;
       y=pNodeNow->Orgpoint .y+circlepoint.y;
      
       CClientDC dc(this);
       //创建一个黑色的画刷
       CBrush brush(RGB(0,0,0));
       //创建指针pOldBrush用于保存原来的画刷
       CBrush* pOldBrush;
       //将黑色的画刷选进设备装置DC,并用pOldBrush保存原来的画刷
       pOldBrush=dc.SelectObject (&brush);
       //画一个圆圈,圆心是(x,y)
       //半径是4
       dc.Ellipse (x-4,y-4,x+4,y+4);
       //将原来的画刷选回
       dc.SelectObject (pOldBrush);
}
由于全局变量circlepoint保存的是元件内部的相对坐标,需要将它
                转换成视图中的坐标
    x=pNodeNow->Orgpoint .x +circlepoint.x;
       y=pNodeNow->Orgpoint .y+circlepoint.y;
                   以上两句完成坐标的转换。
                   然后以(x,y)为圆心,4为半径,画一个黑色小圆圈
dc.Ellipse (x-4,y-4,x+4,y+4)
2  擦除小圆圈函数:EraserMyCircle()
voidCMyView::EraserMyCircle()
{
       int x,y;
       x=pNodeNow->Orgpoint .x +circlepoint.x;
       y=pNodeNow->Orgpoint .y+circlepoint.y;
      
       CClientDC dc(this);
       CPenwhitepen(PS_SOLID,1,RGB(255,255,255));
       CPen* pOldPen;
       pOldPen=dc.SelectObject (&whitepen);
       dc.Ellipse (x-4,y-4,x+4,y+4);
       dc.SelectObject (pOldPen);
      
}
与画小圆圈不同的是,擦除时要选择白色的笔和白色的画刷(默认)
CPen whitepen(PS_SOLID,1,RGB(255,255,255));
       CPen* pOldPen;
       pOldPen=dc.SelectObject (&whitepen);
以上3句选择白色的笔。
2  鼠标移开触点重绘连接线函数:moveoutredrawline()
为什么需要这个函数,原因是在鼠标称出触点后,此时要擦除刚才画
的小圆圈,而如果此时已经生成了连接线,则会擦除掉连接线的一小部分。于是需要这个函数。
voidCMyView::moveoutredrawline()
{
       int x,y;
       x=pNodeNow->Orgpoint .x+circlepoint.x;
       y=pNodeNow->Orgpoint .y+circlepoint.y;
      
       CPoint point1;
       CPoint point2;
       point1.x=x-4;
       point1.y=y-4;
       point2.x=x+4;
       point2.y=y+4;
       LinkLineRedraw(point1,point2);
}
此时pNodeNow指向刚擦除小圆圈的元件,而circlepoint则记录着
触点中心。于是只要将以ciclepoint为中心的半径为4的矩形的左上角点和右下角点为参数调用LinkLineRedraw即可。
2  重绘元件函数redrawMyObject()
voidCMyView::redrawMyObject(MyNode* pNode)
{
       switch(pNode->Subtype )
       {
       case ANDGate:
              DrawObject(pNode->Orgpoint,IDB_ANDGATE);
              
              break;
       case ORGate:
              DrawObject(pNode->Orgpoint,IDB_ORGATE);
              
              break;
       case NOTGate:
              DrawObject(pNode->Orgpoint,IDB_NOTGATE);
              
              break;
       case NORGate:
              DrawObject(pNode->Orgpoint,IDB_NORGATE);
              
              break;
       case NANDGate:
              DrawObject(pNode->Orgpoint,IDB_NANDGATE);
              
              break;
       case XORGate:
              DrawObject(pNode->Orgpoint,IDB_XORGATE);
              
              break;
       case Input:
              DrawObject(pNode->Orgpoint,IDB_NODEINPUT);
              break;
       case Output:
              DrawObject(pNode->Orgpoint,IDB_NODEOUTPUT);
              
              break;
       }
}
该函数参数为指向元件的指针,用于重绘所指向的元件。
n  鼠标按下模块
如图
9.png
前面已经分析了放置元件状态,现在看连接元件状态中的判断:
“当前点是否在某个元件未连接的触点上”其实就是判断“可连接态”IsDrawCircle是否为真。代码如下:
              if(IsDrawCircle)//当前点在某个元件未连接的触点上
              {
                     //全局变量IsLink表示开始连接状态
                     IsLink=TRUE;
                     //全局变量pNodeStart记录当前物件
                     pNodeStart=pNodeNow;
//全局变量startpoint记录当前触点中心坐标(注,此时要进行坐标转换
                     startpoint.x=pNodeNow->Orgpoint.x +circlepoint.x;
                     startpoint.y=pNodeNow->Orgpoint.y +circlepoint.y;
                     //全局变量startput记录当前触点类别:Input_1,Input_2,Output_1;
                     startput=put;
                     //lastpoint用于鼠标移动时擦除线效果
                     lastpoint=startpoint;
              }
       进行连接初始化:首先开启开始连接状态
                                   IsLink=TRUE;
                                   然后用全局变量pNodeStart指向当前元件
                                   pNodeStart=pNodeNow
全局变量startpoint记录当前触点中心坐标(这时要进行坐标的转换)
                                   startpoint.x=pNodeNow->Orgpoint.x +circlepoint.x;
                                   startpoint.y=pNodeNow->Orgpoint.y +circlepoint.y;
                                   全局变量startput记录当前触点类别
                                   startput=put;
                                   最后lastpoint用于鼠标移动时擦除线效果
                                   lastpoint=startpoint;
n  鼠标抬起模块
其算法如图
10.png
代码如下:
voidCMyView::OnLButtonUp(UINT nFlags, CPoint point)
{
       // TODO: Add your message handler codehere and/or call default
      
       if(IsLink)
       {
              //首先擦除从startpoint到point
                     CClientDC clientDC(this);
                     CClientDC*pDC=&clientDC;
                           
                     CPenwhitepen(PS_SOLID,1,RGB(255,255,255));
                     CPen* pOldPen;
                     pOldPen=clientDC.SelectObject(&whitepen);
                     clientDC.MoveTo(startpoint);
                     clientDC.LineTo (point);
                     clientDC.SelectObject(pOldPen);
                     //重绘所有输入结点前的序号
                     redrawnum();
                     //重绘连接线
                     LinkLineRedraw(startpoint,point);
                     //重绘物件
                     lineRedraw(startpoint,point);
              if(IsDrawCircle)
              {
                     
                     //用全局变量pNodeCurrent记录终点连接的物体
                     pNodeCurrent=pNodeNow;
                     //用全局变量currentput记录终点连接的触点
                     currentput=put;
                     //用全局变量currentpoint记录终点触点的中心坐标
                     currentpoint.x=pNodeNow->Orgpoint.x +circlepoint.x;
                     currentpoint.y=pNodeNow->Orgpoint.y +circlepoint.y;
                     //IsTwoObjectsCanLink()函数判断两个物件是否能连接
                     if(IsTwoObjectsCanLink())
                     {
                            //先擦除圆圈
//EraserMyCircle();没有必要,只要鼠标移开时重绘连接线就可
                            //开始两个物件的画图连接
                            LineLink();
                            //开始真正连接:指针连接
                            RealLink();
                           
                     }
      
              }
                     //关闭连接状态:
                     IsLink=FALSE;
       }
       CView::OnLButtonUp(nFlags, point);
}
n  判断两个元件是否可以连接
BOOL CMyView::IsTwoObjectsCanLink()
{
       //判断两个物件是否能连接
       //这两个物件分别由pNodeStart和pNodeCurrent指向
       //两个触点分别由startput和currentput标识
      
       //若所指同一物件
       if(pNodeStart==pNodeCurrent)
       {
              MessageBox("连接错误!自身物件不能相互连接");
              return FALSE;
       }
       //输出直接结输出
       if(startput==Output_1 &&currentput==Output_1)
       {
              MessageBox("连接错误!输出端不能相互连接");
              return FALSE;
       }
       //输入直接连接输入
       if( (startput==Input_1 ||startput==Input_2)
              &&(currentput==Input_1||currentput==Input_2) )
       {
              MessageBox("连接错误!输入端不能相互连接");
              return FALSE;
       }
       //循环连接
       if( (startput==Output_1)
              &&(currentput==Input_1||currentput==Input_2))
       {
              if(pNodeCurrent->output1==pNodeStart)
              {
                     MessageBox("连接错误!不能循环连接");
                     return FALSE;
              }
       }
       if((startput==Input_1||startput==Input_2)
              &&(currentput==Output_1) )
       {
              if(pNodeStart->output1==pNodeCurrent)
              {
                     MessageBox("连接错误!不能循环连接");
                     return FALSE;
              }
       }
       //如果以上情况都不发生,表示可以连接
       return TRUE;
}
用图来表示上述几种错误:

同一元件不能连接
11.png
输出端不能连接输出端
12.png
输入端不能连接输入端
13.png
两个元件不能循环连接

上位机MFC组合逻辑仿真器源代码下载

上位机MFC组合逻辑仿真器源代码下载
n  两个元件的画图连接:LineLink()
该函数调用了recordLine()
代码如下:
void CMyView::recordLine()
{
//记录两个物件之间的连接线经过的关键点
//先动态生成一个数组CArray<CPoint,CPoint>之对象
//记录下连接线的关键点,然后将这个数组对象之地址加入到
//CList<CArray<CPoint,CPoint>*,CArray<CPoint,CPoint>*>MyPointList中
       int x0,y0,x1,y1,delta_x,delta_y;
       //(x0,y0)用于记录输出端起始点坐标
       //(x1,y1)用于记录输入端终点坐标
       //delta_x,delta_y用于记录x和y的偏移量
       //一定是从输出端向输入端画线
       if(startput==Output_1)
       {
              x0=startpoint.x;
              y0=startpoint.y;
              x1=currentpoint.x;
              y1=currentpoint.y;
       }
       else
       {
              x1=startpoint.x;
              y1=startpoint.y;
              x0=currentpoint.x;
              y0=currentpoint.y;
       }
       delta_x=5;
      
       //动态生成数组对象
       CArray<CPoint,CPoint>*pPointArray=new CArray<CPoint,CPoint>;
       //根据点的位置分为三种情况:2个点,4个点,5个点
       if(x0<x1)
       {
              if(y0==y1)
              {
                     //两个点情况
                     
                     pPointArray->Add(CPoint(x0,y0));
                     pPointArray->Add(CPoint(x1,y1));
              }
              else
              {
                     //4个点情况
                     pPointArray->Add(CPoint(x0,y0));
                     pPointArray->Add(CPoint(x0+delta_x,y0));
                     pPointArray->Add(CPoint(x0+delta_x,y1));
                     pPointArray->Add(CPoint(x1,y1));
              }
       }
       else if(x0==x1)
       {
              //两个点情况
                     pPointArray->Add(CPoint(x0,y0));
                     pPointArray->Add (CPoint(x1,y1));
       }
       else //x0>x1
       {
              //5个点情况
              if(y0<y1)
              {
                     delta_y=20;
              }
              else
              {
                     delta_y=-20;
              }
              pPointArray->Add(CPoint(x0,y0));
              pPointArray->Add(CPoint(x0,y0+delta_y));
              pPointArray->Add(CPoint(x1-delta_x,y0+delta_y));
              pPointArray->Add(CPoint(x1-delta_x,y1));
              pPointArray->Add(CPoint(x1,y1));
       }
       //加入当前数组对象地址到MyPointList
       MyPointList.AddTail (pPointArray);
       //用数组中的点画线
       DrawLinkLine(pPointArray);
}
首先保证从输出端向输入端画线,这样可以统一画线操作。
然后动态生成数组:
       CArray<CPoint,CPoint>*pPointArray=new CArray<CPoint,CPoint>;
用指针pPointArray指向该数组,用于存储连接线的关键点。
连接线根据位置总共有三种线型,如下图所示:

(1)两个关键点的连接线:
16.png
(2)4个关键点的连接线
16.png
(3)5个关键点的连接线
17.png
n  两个元件的指针连接:RealLink();
其代码如下:
voidCMyView::RealLink()
{
       //一定是输入连接输出或 输出连接输入
       if(startput==Input_1||startput==Input_2)
       {
              //输入连接输出
              if(startput==Input_1)
              {
                     pNodeStart->input1=pNodeCurrent;
              }
              else
              {
                     pNodeStart->input2=pNodeCurrent;
              }
              pNodeCurrent->output1=pNodeStart;
       }
       else//startput==Output_1
       {
              //输出连接输入
              pNodeStart->output1=pNodeCurrent;
              if(currentput==Input_1)
              {
                     pNodeCurrent->input1=pNodeStart;
              }
              else
              {
                     pNodeCurrent->input2=pNodeStart;
              }
       }
}
指针连接只有两种情况:输入连接输出和输出连接输入。可以用下图来表示

输入端连接输出端
19.png
输出端连接输入端

上位机MFC组合逻辑仿真器源代码下载

上位机MFC组合逻辑仿真器源代码下载


回复

使用道具 举报

快速回复 返回列表 客服中心 搜索