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應用曲高和寡,代碼貼圖眾口難調;不求一鳴驚人,但求潛移默化。
主要研究技術:代碼生成工具、Visio二次開發、送水管理軟件等共享軟件開發
出處:http://www.iqidi.com