C#进行Visio二次开发之动态仿真实现

简介:

Visio二次开发可以实现的项目情景很多,如电气线路分析、配电网络分析、流程图等,现因为项目需要,又认识多了一个应用场合,液压传动的仿真。项目效果图如下所示:

 

动态仿真,其实也就是模拟实际线路的走向,实现动画的展现。以前我的Visio的项目,基本上都是基于静态的图形展现,并没有设置太多的动态展现。原来配电网络的通电线路的分析,严格来说也是静态的,因为基本上是一次性把通电和不通电的线路给绘制出来。而动态仿真则要求慢慢的动画展现线路的走向和颜色变化。

如活塞运动的仿真,要求不停止动画的情况下,可以一直循环的变化。 如下图所示的效果:

 

 本文介绍如何实现线路走向、颜色变化,以及特定图形(如活塞)的动态仿真效果。

首先实现动态仿真效果,必须先分析出整个图纸的拓扑网络顺序及层次,这样我们才能知道正确的线路走向以及动画的变化顺序,如配电网络线路图中,必定是电源开始,通过导线或者设备传递电源,以实现电路的贯通。在液压线路中,由油箱开始,经过一系列设备,最后又回到油箱。

要在Visio图纸上实现如上图的动画效果,其中最重要的奥秘是使用下面代码:

 System.Windows.Forms.Application.DoEvents();
 Thread.Sleep(
50 );

很多情况下,我们可能对这个DoEvents函数的功能不是很熟悉,其实我们可以理解为主动触发事件,让消息流提前进入处理流程,这样我们就能够看到在Visio图纸上的图形更新效果了。

整个图形分析的过程,分为3个步骤:

1)进行简单的拓扑分析,把设备周边的关系保持到数据库进行分析。

2)根据数据库结构,对设备关系进行分析,获得拓扑网络的设备层次结构列表

3)根据不同的设备类型和图纸当前状态,对设备进行适当的绘制和动画仿真展示。

大致的代码如下所示:

        private   void  PowerCutAnalyze(Visio.Application app)
        {
            
#region  获取操作设备和判断是否图纸有设备
            Visio.Shape shapeSelected 
=   null ;
            
try
            {
                Visio.Window wndVisio 
=  app.ActiveWindow;
                
if  (wndVisio.Selection.Count  ==   1 )
                {
                    shapeSelected 
=  wndVisio.Selection.get_Item16( 1 );
                }
            }
            
catch  { ; }

            
if  ( ! VisioUtility.HasShapeInWindow(VisWindow))
            {
                MessageUtil.ShowWarning(
" 图纸上没有设备, 不能执行该操作 " );
                
return ;
            } 
            
#endregion

            app.UndoEnabled 
=   false ;
            List
< string >  list  =   new  List < string > ();
            
string  message  =   "" ;
            list 
=  powerCutBLL.RunPowerCutAnalyzing(app, shapeSelected,  ref  message);
            app.UndoEnabled 
=   true ;

            
if  (message  !=   "" )
            {
                MessageUtil.ShowError(message);
                
return ;
            }

            
if  (list.Count  >   0 )
            {
                AnalyzeShapeIdList.Clear();
                
foreach  ( string  shapeStrID  in  list)
                {
                    AnalyzeShapeIdList.Add(Convert.ToInt32(shapeStrID));
                }
                RunColorChanging(app);
            }
            
else
            {
                MessageUtil.ShowWarning(
" 请检查线路是否连接正确。 " );
            } 
        }

线路颜色变化以及动画展示部分的代码如下所示 :

         ///   <summary>
        
///  根据分析后的设备ID,把设备变色动画展示
        
///   </summary>
        
///   <param name="visApp"></param>
         private   void  RunColorChanging(Visio.Application visApp)
        {
            Visio.Cell cell 
=  visApp.ActiveDocument.Pages[ 1 ].PageSheet.get_Cells( " Scratch.A1 " );
            
int  intValue  =  Convert.ToInt32(VisioUtility.FormulaStringToString(cell.Formula));
            
if  (intValue  ==   1 )
            {
                cell.Formula 
=   " 0 " ;
            }
            
else
            {
                cell.Formula 
=   " 1 " ;
                isMovie 
=   ! isMovie;
            }
...................

            
int  sequence  =   1 ;
            
foreach  ( int  shapeId  in  AnalyzeShapeIdList)
            {
                Visio.Shape shape 
=  VisDocument.Pages[ 1 ].Shapes.get_ItemFromID(shapeId);
                
if  (shape  !=   null )
                {
                    
if  (intValue  ==   0 )
                    {
                        shape.Text 
=  sequence ++ .ToString( " D2 " ); // string.Format("{0}({1})", sequence++, shape.ID); //

                        VisioUtility.SetShapeLineColor(shape, VisDefaultColors.visDarkGreen);
// 有电(绿色)
                        System.Windows.Forms.Application.DoEvents();
                        Thread.Sleep(
500   *  minFlowValue);
                    }
                    
else
                    {
                        shape.Text 
=   "" ;
                        VisioUtility.SetShapeLineColor(shape, VisDefaultColors.visBlack);
// 无电(黑色)
                        System.Windows.Forms.Application.DoEvents();
                    }
                    
                    
string  equipType  =  VisioUtility.GetShapeCellValue(shape,  " 设备类型 " );
                    
if  ( ! string .IsNullOrEmpty(equipType))
                    {
                        
#region  单作用、双作用
                        
if  (equipType  ==   " 单作用 "   ||  equipType  ==   " 双作用 " )
                        {
                            
string  minValue  =   " Width*0.25 " ;
                            
string  maxValue  =   " Width*0.75 " ;
                            
string  cellName  =   " Controls.Row_1.X " ;
                            
try
                            {
                                
if  (shape.get_CellExistsU(cellName, ( short )VisExistsFlags.visExistsAnywhere)  !=   0 )
                                {
                                    
short  i  =  shape.get_CellsRowIndex(cellName);
                                    Visio.Cell typeCell 
=  shape.get_CellsSRC(( short )VisSectionIndices.visSectionControls, i, ( short )VisCellIndices.visCtlX);
                                    
if  (intValue  ==   0 )
                                    {
                                        ThreadParameterInfo param 
=   new  ThreadParameterInfo();
                                        param.Cell 
=  typeCell;
                                        param.ScratchCell 
=  cell;

                                        Thread thread 
=   new  Thread( new  ParameterizedThreadStart(HuoSaiMoving));
                                        thread.Start(param);
                                    }
                                    
else
                                    {
                                        typeCell.Formula 
=  VisioUtility.StringToFormulaForString(minValue);
                                        System.Windows.Forms.Application.DoEvents();
                                        
// Thread.Sleep(500 * minFlowValue);
                                    }
                                }
                            }
                            
catch  (Exception ex)
                            {
                                LogHelper.Error(ex);
                            }
                        } 
                        
#endregion
                    }
                }
                
            }
        }

其中我们注意到了,活塞运动时一个独立的线程进行处理的,如下所示

Thread thread  =   new  Thread( new  ParameterizedThreadStart(HuoSaiMoving));
thread.Start(param);

活塞运动是在线路联通后,继续循环进行动画的展示的,因为它是独立一个线程进行处理操作,通过判断标识来实现动画的停止控制的,具体处理活塞动画的效果实现代码如下所示:

         private   void  HuoSaiMoving( object  obj)
        {
            ThreadParameterInfo objParam 
=  obj  as  ThreadParameterInfo;
            Visio.Cell scratchCell 
=  objParam.ScratchCell;
            Visio.Cell typeCell 
=  objParam.Cell;
            
int  intValue  =  Convert.ToInt32(VisioUtility.FormulaStringToString(scratchCell.Formula));
            
while  (intValue  ==   1   &&  isMovie)
            {
                
string  minValue  =   " Width*0.25 " ;
                
string  maxValue  =   " Width*0.75 " ;
                
// Visio.Cell typeCell = objCell as Visio.Cell;
                 if  (typeCell  !=   null )
                {
                    
string  currentValue  =   "" ;
                    
// 增加
                     for  ( int  k  =   1 ; k  <=   10 ; k ++ )
                    {
                        currentValue 
=   string .Format( " Width*0.25 + Width*{0} " 0.05   *  k);
                        typeCell.Formula 
=  VisioUtility.StringToFormulaForString(currentValue);
                        System.Windows.Forms.Application.DoEvents();
                        Thread.Sleep(
50 );
                    }
                    
// 减少
                     for  ( int  k  =   1 ; k  <=   10 ; k ++ )
                    {
                        currentValue 
=   string .Format( " Width*0.75 - Width*{0} " 0.05   *  k);
                        typeCell.Formula 
=  VisioUtility.StringToFormulaForString(currentValue);
                        System.Windows.Forms.Application.DoEvents();
                        Thread.Sleep(
50 );
                    }
                }
                intValue 
=  Convert.ToInt32(VisioUtility.FormulaStringToString(scratchCell.Formula));
            }
        }

 Visio应用曲高和寡,代码贴图众口难调;不求一鸣惊人,但求潜移默化。

本文转自博客园伍华聪的博客,原文链接:C#进行Visio二次开发之动态仿真实现,如需转载请自行联系原博主。



目录
相关文章
基于C#的ArcEngine二次开发56:双击属性表跳转目标要素并闪烁
基于C#的ArcEngine二次开发56:双击属性表跳转目标要素并闪烁
基于C#的ArcEngine二次开发56:双击属性表跳转目标要素并闪烁
基于C#的ArcEngine二次开发54:IStatusBar状态栏接口的使用
基于C#的ArcEngine二次开发54:IStatusBar状态栏接口的使用
基于C#的ArcEngine二次开发54:IStatusBar状态栏接口的使用
|
NoSQL 数据处理 C#
基于C#的ArcEngine二次开发52:GDB数据处理过程中与Name相关的操作
基于C#的ArcEngine二次开发52:GDB数据处理过程中与Name相关的操作
基于C#的ArcEngine二次开发52:GDB数据处理过程中与Name相关的操作
基于C#的ArcEngine二次开发51:获取图层字段唯一值列表(Get Unique Values)
基于C#的ArcEngine二次开发51:获取图层字段唯一值列表(Get Unique Values)
基于C#的ArcEngine二次开发51:获取图层字段唯一值列表(Get Unique Values)
|
算法 C#
基于C#的ArcEngine二次开发50:生成面空洞连接线
基于C#的ArcEngine二次开发50:生成面空洞连接线
基于C#的ArcEngine二次开发50:生成面空洞连接线
|
存储 NoSQL Unix
基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理
基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理
基于C#的ArcEngine二次开发50:MDB创建新要素类及“无当前记录”异常处理
|
C# 开发工具
基于C#的ArcEngine二次开发47:Addins常见问题解决方案集锦
基于C#的ArcEngine二次开发47:Addins常见问题解决方案集锦
基于C#的ArcEngine二次开发47:Addins常见问题解决方案集锦
|
存储 C# Python
基于C#的ArcEngine二次开发46:编辑内容回撤与炸开multipart feature
基于C#的ArcEngine二次开发46:编辑内容回撤与炸开multipart feature
基于C#的ArcEngine二次开发46:编辑内容回撤与炸开multipart feature
|
C# 数据库
基于C#的ArcEngine二次开发45:属性值设置中的DBNull、null和default
基于C#的ArcEngine二次开发45:属性值设置中的DBNull、null和default
基于C#的ArcEngine二次开发45:属性值设置中的DBNull、null和default