從靜態拓撲分析進化到動態仿真,Visio 可透過 Application.DoEvents() + Thread.Sleep() 實現幀級動畫。本文展示液壓傳動系統仿真:線路依拓撲順序逐段變色、活塞以獨立執行緒循環往覆運動,完整呈現流體動力過程。
System.Windows.Forms.Application.DoEvents(); // 強制處理 UI 訊息,立即重繪
Thread.Sleep(50); // 控制幀率約 20 FPS
DoEvents 讓訊息迴圈處理 Paint 事件,配合 Thread.Sleep 形成動畫時間軸。
AnalyzeShapeIdList。DoEvents/Sleep。
private void RunColorChanging(Application visApp) {
// 切換動畫狀態標記 (儲存在 PageSheet.Scratch.A1)
Cell scratch = visApp.ActiveDocument.Pages[1].PageSheet.Cells["Scratch.A1"];
int state = int.Parse(FormulaStringToString(scratch.Formula));
scratch.Formula = (state == 0) ? "1" : "0";
isMovie = (state == 0);
int seq = 1;
foreach (int shapeId in AnalyzeShapeIdList) {
Shape shape = visDoc.Pages[1].Shapes.ItemFromID[shapeId];
if (shape == null) continue;
if (state == 0) { // 通電/通油 動畫
shape.Text = seq++.ToString("D2");
SetShapeLineColor(shape, VisDefaultColors.visDarkGreen); // 綠
DoEventsSleep(500);
} else { // 斷電/斷油 復原
shape.Text = "";
SetShapeLineColor(shape, VisDefaultColors.visBlack);
DoEventsSleep(0);
}
// 活塞/閥門特殊動畫
string equipType = GetShapeCellValue(shape, "設備類型");
if (equipType == "單作用" || equipType == "雙作用") {
AnimatePiston(shape, scratch);
} else if (equipType == "4/2閥") {
AnimateDirectionalValve(shape);
}
}
}
private void DoEventsSleep(int ms) {
Application.DoEvents();
if (ms > 0) Thread.Sleep(ms);
}
private void AnimatePiston(Shape shape, Cell scratchCell) {
// 找出控制點 Cell: Controls.Row_1.X
string cellName = "Controls.Row_1.X";
if (shape.CellExistsU[cellName] == 0) return;
short row = shape.CellsRowIndex[cellName];
Cell ctrlCell = shape.CellsSRC[(short)VisSectionIndices.visSectionControls, row, (short)VisCellIndices.visCtlX];
Thread thread = new Thread(o => {
var param = (ThreadParam)o;
Cell pistonCell = param.Cell;
Cell flagCell = param.ScratchCell;
int flag = int.Parse(FormulaStringToString(flagCell.Formula));
while (flag == 1 && isMovie) {
// 前進:Width*0.25 → Width*0.75 (10 幀)
for (int k = 1; k <= 10; k++) {
pistonCell.Formula = StringToFormulaForString($"Width*0.25 + Width*{0.05*k}");
DoEventsSleep(50);
}
// 後退:Width*0.75 → Width*0.25 (10 幀)
for (int k = 1; k <= 10; k++) {
pistonCell.Formula = StringToFormulaForString($"Width*0.75 - Width*{0.05*k}");
DoEventsSleep(50);
}
flag = int.Parse(FormulaStringToString(flagCell.Formula));
}
});
thread.Start(new ThreadParam { Cell = ctrlCell, ScratchCell = scratchCell });
}
見「組合形狀操作」一文:透過 GroupSelectMode = 2 選取子形狀,Selection.Move 位移實現左右切換,動畫完成後還原 GroupSelectMode = 0。
此技術已應用於液壓訓練模擬系統,支援百元件級即時仿真,展現 Visio 超越靜態繪圖的動態視覺化潛力。