工控编程吧
标题:
上位机MFC组合逻辑仿真器源代码下载
[打印本页]
作者:
qq263946146
时间:
2019-10-17 10:50
标题:
上位机MFC组合逻辑仿真器源代码下载
(, 下载次数: 0)
上传
点击文件名下载附件
转出结果如下:
(, 下载次数: 1)
上传
点击文件名下载附件
源代码下载地址:
(, 下载次数: 0)
上传
点击文件名下载附件
[halcon]1[/halcon]
[MFC408]1[/MFC408]
[weixinlianxi]1[/weixinlianxi]
工程的介绍可以参考下面。
程序由几个大模块组成:元件数据结构模块,
电路图编辑模块,元件库模块,计算结果
(
仿真
)
模块。
l
元件数据结构模块
统一的元件数据结构可以提高程序运行速度,方便程序编制。不足是由于元件的不同存储空间上可能会有少许浪费。
所有的元件种类共有8种,如图
(, 下载次数: 1)
上传
点击文件名下载附件
定义数据结构如下:
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
电路图编辑模块
电路图编辑模块又分为两个子模块:鼠标放置元件模块,鼠标连接元件模块
首先在工具栏中可以选择这两种状态,如图
(, 下载次数: 0)
上传
点击文件名下载附件
在按钮上单击可以切换状态。
定义一个枚举类型MyStatus来记录当前状态:
enum MyStatus
{
NONE, //鼠标连接元件状态
ANDGATE,
ORGATE,
NOTGATE,
NORGATE,
NANDGATE,
XORGATE,
NODEINPUT,
NODEOUTPUT
};
MyStatus Status;
其中:NONE为鼠标连接状态,其他为鼠标放置状态。
u
鼠标放置元件模块
其算法如图
(, 下载次数: 2)
上传
点击文件名下载附件
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
鼠标移动模块
其算法如图
(, 下载次数: 1)
上传
点击文件名下载附件
代码如下:
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
Ø
可连接态IsDrawCircle
当且仅当鼠标移动到某个元件上的某个尚未连接的触点上,才开启可连接态IsDrawCircle。之所以取名IsDrawCircle是因为此时会在鼠标停留的尚未连接的触点上画一个黑色小圆圈。
当鼠标移动离开触点,可连接态IsDrawCircle关闭。
Ø
正在连接态IsLink
当鼠标按下(见图5)并且此时可连接态IsDrawCircle开启(为TRUE)时正在连接态IsLink开启。
2
判断当前点是否在某个元件函数:IsPointInObject()
其算法如图
(, 下载次数: 0)
上传
点击文件名下载附件
2
判断当前点是否在该元件触点上函数:IsPointInPut()
其算法如图
(, 下载次数: 3)
上传
点击文件名下载附件
与门与其它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
鼠标按下模块
如图
(, 下载次数: 1)
上传
点击文件名下载附件
前面已经分析了放置元件状态,现在看连接元件状态中的判断:
“当前点是否在某个元件未连接的触点上”其实就是判断“可连接态”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
鼠标抬起模块
其算法如图
(, 下载次数: 1)
上传
点击文件名下载附件
代码如下:
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 &¤tput==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;
}
用图来表示上述几种错误:
同一元件不能连接
(, 下载次数: 0)
上传
点击文件名下载附件
输出端不能连接输出端
(, 下载次数: 0)
上传
点击文件名下载附件
输入端不能连接输入端
(, 下载次数: 1)
上传
点击文件名下载附件
两个元件不能循环连接
(, 下载次数: 3)
上传
点击文件名下载附件
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)两个关键点的连接线:
(, 下载次数: 2)
上传
点击文件名下载附件
(2)4个关键点的连接线
(, 下载次数: 1)
上传
点击文件名下载附件
(3)5个关键点的连接线
(, 下载次数: 0)
上传
点击文件名下载附件
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;
}
}
}
指针连接只有两种情况:输入连接输出和输出连接输入。可以用下图来表示
输入端连接输出端
(, 下载次数: 1)
上传
点击文件名下载附件
输出端连接输入端
(, 下载次数: 0)
上传
点击文件名下载附件
欢迎光临 工控编程吧 (https://www.gkbc8.com/)
Powered by Discuz! X3.4