.NET 操作 PowerPoint COM 组件:从零到精通的幻灯片制作实战
形状组合与自定义绘图
问题
文字和图片之外,PPT 还需要流程图、标注框、箭头指示等图形元素。PowerPoint 提供的自选图形库有 150+ 种预设形状,加上连接线和自由曲线,几乎可以画出任何图形。
MudTools 在 IPowerPointShapes 上暴露了 AddShape、AddLine、AddConnector 等 20+ 个创建方法,返回的 IPowerPointShape 可以进一步控制填充、线条、大小和层级关系。
绘制基本形状
AddShape 是创建自选图形的主入口,通过 MsoAutoShapeType 枚举选择形状类型:
using var app = PowerPointFactory.BlankDocument();
var pres = app.ActivePresentation;
var slide = pres.AddSlide(PpSlideLayout.ppLayoutBlank);
// 矩形
var rect = slide.Shapes.AddShape(
MsoAutoShapeType.msoShapeRectangle,
50, 50, 200, 120);
// 圆形(椭圆)
var circle = slide.Shapes.AddShape(
MsoAutoShapeType.msoShapeOval,
300, 50, 120, 120);
// 圆角矩形
var rounded = slide.Shapes.AddShape(
MsoAutoShapeType.msoShapeRoundedRectangle,
470, 50, 200, 120);
// 箭头
var arrow = slide.Shapes.AddShape(
MsoAutoShapeType.msoShapeRightArrow,
50, 220, 150, 60);
// 菱形
var diamond = slide.Shapes.AddShape(
MsoAutoShapeType.msoShapeDiamond,
250, 220, 120, 120);
// 五角星
var star = slide.Shapes.AddShape(
MsoAutoShapeType.msoShape5pointStar,
420, 220, 120, 120);常用 MsoAutoShapeType 枚举:
| 枚举 | 形状 |
|---|---|
msoShapeRectangle | 矩形 |
msoShapeOval | 椭圆/圆 |
msoShapeRoundedRectangle | 圆角矩形 |
msoShapeRightArrow | 右箭头 |
msoShapeLeftArrow | 左箭头 |
msoShapeDiamond | 菱形 |
msoShapePentagon | 五边形 |
msoShapeChevron | V 形 |
msoShapeParallelogram | 平行四边形 |
msoShapeFlowchartProcess | 流程图-过程 |
msoShapeFlowchartDecision | 流程图-判断 |
msoShape5pointStar | 五角星 |
形状的填充、线条、阴影和 3D 效果通过各自的 Format 接口控制:
// 填充颜色
rect.Fill.ForeColor.RGB = 0x3498DB;
rect.Fill.Visible = true;
// 线条边框
rect.Line.ForeColor.RGB = 0x2C3E50;
rect.Line.Weight = 1.5f;
rect.Line.DashStyle = MsoLineDashStyle.msoLineSolid;
// 阴影
rect.Shadow.Type = MsoShadowType.msoShadow1;
rect.Shadow.OffsetX = 3;
rect.Shadow.OffsetY = 3;
// 3D 效果
rect.ThreeD.Depth = 10;
rect.ThreeD.ExtrusionColor.RGB = 0x1A5276;直线与连接符
// 画一条直线(从 (50, 400) 到 (250, 400))
var line = slide.Shapes.AddLine(50, 400, 250, 400);
line.Line.Weight = 2;
line.Line.ForeColor.RGB = 0xE74C3C;
// 添加连接符
var connector = slide.Shapes.AddConnector(
MsoConnectorType.msoConnectorStraight,
300, 400, 500, 400);
connector.Line.Weight = 1.5f;连接符与普通线条的区别:连接符的两端可以附着在形状上,移动形状时连接符会自动跟随并重新路由。
// 连接两个形状
var shapeA = slide.Shapes.AddShape(MsoAutoShapeType.msoShapeRectangle, 50, 450, 100, 50);
var shapeB = slide.Shapes.AddShape(MsoAutoShapeType.msoShapeRectangle, 300, 450, 100, 50);
var conn = slide.Shapes.AddConnector(
MsoConnectorType.msoConnectorElbow,
150, 475, 300, 475);
// 连接端点
conn.ConnectorFormat.BeginConnect(shapeA, 1); // 连接到 shapeA 的连接点 1
conn.ConnectorFormat.EndConnect(shapeB, 1); // 连接到 shapeB 的连接点 1
conn.RerouteConnections(); // 让 PPT 自动选择最佳路由形状分组与层级
当一个复杂图形由多个形状构成,把它们组合成一个 Group 可以方便整体移动和缩放:
// 创建分组
var groupShapes = slide.Shapes.Range(new object[] { rect.Name, circle.Name, arrow.Name });
var group = groupShapes.Group();
// 解组
var ungrouped = group.Ungroup();层级控制通过 ZOrder 方法管理:
// 把形状移到最顶层
rect.ZOrder(MsoZOrderCmd.msoBringToFront);
// 把形状移到最底层
circle.ZOrder(MsoZOrderCmd.msoSendToBack);
// 上移一层
arrow.ZOrder(MsoZOrderCmd.msoBringForward);
// 下移一层
diamond.ZOrder(MsoZOrderCmd.msoSendBackward);ZOrderPosition 属性可以查询当前层级序号(1 = 最底层)。
flowchart TD
A["AddShape(type, left, top, width, height)"] --> B["配置 Fill 填充"]
A --> C["配置 Line 边框"]
A --> D["配置 Shadow 阴影"]
A --> E["配置 ThreeD 3D 效果"]
B --> F{需要组合?}
C --> F
D --> F
E --> F
F -->|"是"| G["Range(names).Group()"]
F -->|"否"| H["ZOrder 调整层级"]
G --> HSmartArt
Shapes.AddSmartArt 可以从代码创建 SmartArt 图形:
// 创建 SmartArt(需要 IOfficeSmartArtLayout 参数)
// 目前通过底层 COM 对象获取布局
var nativeSlide = (MsPowerPoint.Slide)slide; // 注意:此处需要从 IPowerPointSlide 获取AddSmartArt 接受 IOfficeSmartArtLayout 参数,后者需要通过 Office 的 SmartArt 布局库获取。在 MudTools 的框架下,可以通过 SmartArtLayouts 集合遍历找到目标布局。
自由曲线与多边形
通过 BuildFreeform 方法可以绘制任意多边形:
// 构建自由形状
var freeform = slide.Shapes.BuildFreeform(
MsoEditingType.msoEditingCorner, // 折线节点
100, 500 // 起点 x, y
);
// 添加节点
freeform.AddNodes(
MsoSegmentType.msoSegmentLine, // 直线段
MsoEditingType.msoEditingAuto, // 自动编辑
200, 550, // 中间控制点(line 不需要,传相同坐标)
200, 550 // 终点
);
freeform.AddNodes(
MsoSegmentType.msoSegmentLine,
MsoEditingType.msoEditingAuto,
300, 500,
300, 500
);
// 闭合路径并创建形状
var poly = freeform.ConvertToShape();
poly.Fill.ForeColor.RGB = 0x9B59B6;
poly.Fill.Visible = true;添加文本到任意形状
所有形状都有 HasTextFrame 属性和 TextFrame,这意味着矩形、圆形、箭头都可以直接写字:
var box = slide.Shapes.AddShape(
MsoAutoShapeType.msoShapeRectangle,
50, 550, 200, 60);
box.TextFrame.TextRange.Text = "点击此处输入";
box.TextFrame.TextRange.Font.Size = 14;
box.TextFrame.TextRange.ParagraphFormat.Alignment =
PpParagraphAlignment.ppAlignCenter;
box.TextFrame.VerticalAnchor = MsoVerticalAnchor.msoAnchorMiddle;艺术字通过 AddTextEffect 创建:
var wordArt = slide.Shapes.AddTextEffect(
MsoPresetTextEffect.msoTextEffect1,
"欢迎", // 文字
"Arial Black", // 字体
36, // 字号
true, // 加粗
false, // 斜体
150, 200 // 位置
);完整示例:流程图
using MudTools.OfficeInterop;
using MudTools.OfficeInterop.PowerPoint;
using MsCore = Microsoft.Office.Core;
using var app = PowerPointFactory.BlankDocument();
var pres = app.ActivePresentation;
var slide = pres.AddSlide(PpSlideLayout.ppLayoutBlank);
// 流程节点
var start = slide.Shapes.AddShape(
MsCore.MsoAutoShapeType.msoShapeRoundedRectangle,
280, 30, 160, 50);
start.TextFrame.TextRange.Text = "开始";
start.TextFrame.VerticalAnchor = MsCore.MsoVerticalAnchor.msoAnchorMiddle;
start.TextFrame.TextRange.ParagraphFormat.Alignment =
PpParagraphAlignment.ppAlignCenter;
start.Fill.ForeColor.RGB = 0x2ECC71;
start.Fill.Visible = true;
var process1 = slide.Shapes.AddShape(
MsCore.MsoAutoShapeType.msoShapeRectangle,
280, 120, 160, 50);
process1.TextFrame.TextRange.Text = "处理数据";
process1.TextFrame.VerticalAnchor = MsCore.MsoVerticalAnchor.msoAnchorMiddle;
process1.TextFrame.TextRange.ParagraphFormat.Alignment =
PpParagraphAlignment.ppAlignCenter;
process1.Fill.ForeColor.RGB = 0x3498DB;
process1.Fill.Visible = true;
var decision = slide.Shapes.AddShape(
MsCore.MsoAutoShapeType.msoShapeDiamond,
280, 220, 160, 120);
decision.TextFrame.TextRange.Text = "验证通过?";
decision.TextFrame.VerticalAnchor = MsCore.MsoVerticalAnchor.msoAnchorMiddle;
decision.TextFrame.TextRange.ParagraphFormat.Alignment =
PpParagraphAlignment.ppAlignCenter;
decision.Fill.ForeColor.RGB = 0xF39C12;
decision.Fill.Visible = true;
var process2 = slide.Shapes.AddShape(
MsCore.MsoAutoShapeType.msoShapeRectangle,
280, 380, 160, 50);
process2.TextFrame.TextRange.Text = "输出结果";
process2.TextFrame.VerticalAnchor = MsCore.MsoVerticalAnchor.msoAnchorMiddle;
process2.TextFrame.TextRange.ParagraphFormat.Alignment =
PpParagraphAlignment.ppAlignCenter;
process2.Fill.ForeColor.RGB = 0x3498DB;
process2.Fill.Visible = true;
// 箭头连接
void AddArrow(float x1, float y1, float x2, float y2, int color)
{
var line = slide.Shapes.AddLine(x1, y1, x2, y2);
line.Line.ForeColor.RGB = color;
line.Line.Weight = 2;
}
AddArrow(360, 80, 360, 120, 0x333333); // start → process1
AddArrow(360, 170, 360, 220, 0x333333); // process1 → decision
AddArrow(360, 340, 360, 380, 0x333333); // decision → process2
// 决策的"No"分支
var noLine = slide.Shapes.AddLine(280, 280, 150, 280);
noLine.Line.ForeColor.RGB = 0xE74C3C;
noLine.Line.Weight = 1.5f;
var noLabel = slide.Shapes.AddTextbox(
MsCore.MsoTextOrientation.msoTextOrientationHorizontal,
110, 260, 40, 20);
noLabel.TextFrame.TextRange.Text = "否";
Console.WriteLine("流程图已生成,按回车退出...");
Console.ReadLine();小结
AddShape + MsoAutoShapeType 覆盖了 150+ 种预设形状。连接符的自动路由能力对流程图场景至关重要,ZOrder 管理了三层以上图形的视觉遮挡关系。Group 分组在需要整体移动一组形状时非常实用。
下一篇文章进入动画和切换效果——如何让幻灯片里的元素动起来,以及触发方式的控制。