Use WPF to make a PowerPoint series based on OpenXML parsing to realize PPT text stroke effect

Use WPF to make a PowerPoint series based on OpenXML parsing to realize PPT text stroke effect

This article is a PowerPoint series blog using WPF. This article tells you how to analyze the text stroke effect in PPT and draw it in WPF applications to achieve the same pixel level.

最后更新 12/18/2021 6:24 PM
lindexi
预计阅读 7 分钟
分类
WPF
标签
.NET WPF OpenXML

This article is a PowerPoint series blog using WPF. This article tells you how to analyze the text stroke effect in PPT and draw it in WPF applications to achieve the same pixel level.

background knowledge

在开始之前,期望你了解了 PPT 解析的入门知识。如对 PPT 解析了解很少,请参阅 C# dotnet 使用 OpenXml 解析 PPT 文件

In PPT, you can set stroke effects on some text. The stroke effect is not a special effect from the OpenXML layer, but only a border attribute. In PPT, you can add the Outline border attribute to text to make the text stroke

effect

Before we start, let's let's show the effect first

parsing

Before starting, read the document first, the code is as follows. The following code and test files can be obtained at the end of this article

var file = new FileInfo("Test.pptx");

using var presentationDocument = PresentationDocument.Open(file.FullName, false);
var slide = presentationDocument.PresentationPart!.SlideParts.First().Slide;

In order to tell you the core logic easily, the following code in this article will make the judgment of ignoring many parameters based on the Test.pptx document. In actual projects, please also make your own parameter judgment logic.

This test document has only one element on the first page, which is the element with text strokes in this article. The obtained code is as follows

var shape = slide.CommonSlideData!.ShapeTree!.GetFirstChild<Shape>()!;

The OpenXML content of this Shape is roughly as follows

<p:sp>
<p:spPr>
    <a:prstGeom prst="rect">
    </a:prstGeom>
    <a:noFill />
</p:spPr>
<p:txBody>
    <a:bodyPr wrap="square" rtlCol="0">
    <a:spAutoFit />
    </a:bodyPr>
    <a:lstStyle />
    <a:p>
    <a:r>
        <a:rPr lang="zh-CN" altLang="en-US" sz="10000">
        <a:ln w="9525">
            <a:solidFill>
            <a:srgbClr val="00FF00" />
            </a:solidFill>
        </a:ln>
        </a:rPr>
        <a:t>一行文本</a:t>
    </a:r>
    <a:endParaRPr lang="en-US" sz="10000" dirty="0" />
    </a:p>
</p:txBody>
</p:sp>

The text box inside PPT is also a shape, which is the default rectangle.

var shapeProperties = shape.ShapeProperties!;
var presetGeometry = shapeProperties.GetFirstChild<PresetGeometry>()!;
// 这是一个文本框
Debug.Assert(presetGeometry.Preset?.Value == ShapeTypeValues.Rectangle);
Debug.Assert(shapeProperties.GetFirstChild<NoFill>() is not null);

The above only tells you how to get the shape, you need to judge it in your own business code.

Get the text of the text box, you can use the following code

var textBody = shape.TextBody!;
Debug.Assert(textBody != null);

There are many paragraphs in a text. In paragraphs, the text has different styles. For example, a paragraph can have different bold text. The same style of text is placed in a TextRun. Different styles of text are placed in different TextRuns

Therefore, parsing requires first traversing the paragraph and then traversing the TextRun element

foreach (var paragraph in textBody.Elements<DocumentFormat.OpenXml.Drawing.Paragraph>())
{
    // 这个文本段落是没有属性的,为了方便样式,就不写代码
    //if (paragraph.ParagraphProperties != null)

    foreach (var run in paragraph.Elements<DocumentFormat.OpenXml.Drawing.Run>())
    {
    }
}

Get the following properties for TextRun

var runProperties = run.RunProperties!;

You can get information such as the font size of the current text on this property, and the code is as follows

var fontSize = new PoundHundredfold(runProperties.FontSize!.Value).ToPound();

Next is the core of this article. Get the Outline attribute, the code is as follows

var outline = runProperties.Outline!;

The corresponding OpenXML code is as follows

<a:ln w="9525">   <a:solidFill>
     <a:srgbClr val="00FF00" />
   </a:solidFill>
 </a:ln>

We only focus on thickness and color, and the acquisition methods are as follows

var outlineWidth = new Emu(outline.Width!.Value);

The code to get the color is as follows

var solidFill = outline.GetFirstChild<SolidFill>()!;
var rgbColorModelHex = solidFill.GetFirstChild<RgbColorModelHex>()!;
var colorText = rgbColorModelHex.Val!;

通过 win10 uwp 颜色转换 的方法可以将 colorText 转换为 SolidColorBrush 对象

Then get the text content, and you will probably be done

// 默认字体前景色是黑色

var text = run.Text!.Text;

The next step is to draw in the interface

drawn

WPF 文字描边 博客,先通过 FormattedText 构建出 Geometry 对象,再通过 Geometry 对象进行绘制

code is as follows

var formattedText = new FormattedText(text, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface
(
    // 默认是宋体
    new FontFamily("宋体"),
    FontStyles.Normal,
    FontWeights.Normal,
    FontStretches.Normal
),
// 在 WPF 里面,采用的是 EM 单位,约等于像素单位
    fontSize.ToPixel().Value,
Brushes.Black, 96);

The code to build the Geometry object through FormatedText is as follows

var geometry = formattedText.BuildGeometry(new ());

Then draw the Geometry onto the interface through System.Windows.Shapes.Path

var path = new System.Windows.Shapes.Path
{
    Data = geometry,
    Fill = Brushes.Black,
    Stroke = BrushCreator.CreateSolidColorBrush(colorText),
    StrokeThickness = outlineWidth.ToPixel().Value,

    HorizontalAlignment = HorizontalAlignment.Center,
    VerticalAlignment = VerticalAlignment.Center,
};

Root.Children.Add(path);

With the above code, you can draw the same interface as PPT on the interface

code

本文所有代码和测试文件放在githubgitee 欢迎访问

You can obtain the source code of this article by creating an empty folder first, then using the command line cd command to enter the empty folder, and entering the following code on the command line to obtain the code of this article

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 71af5b0e47493ff7f5f43be33583265805da9d84

The above is the source of gitee. If gitee cannot be accessed, please replace it with the source of github

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git

After getting the code, go to the Pptx folder

reference

  1. WPF 文字描边
  2. 更多请看 Office 使用 OpenXML SDK 解析文档博客目录

Blog in the Blog Park is only backed up and will not be updated when published. If you want to see the latest blogs, please visit https://blog.lindexi.com/

Creative Commons license

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 9/13/2025

Migration from WPF to Avalonia series: Why I have to migrate WPF programs to Avalonia

In the past few years, our host computer software has been mainly developed using WPF and WinForm. These technologies are really easy to use on the Windows platform, and they have also accompanied us through the stage of small-scale trial production to today's large-scale delivery. However, with the development of business and changes in customer needs, the single Windows technology stack has gradually become a hurdle that we must overcome.

继续阅读
同分类 / 同标签 1/26/2025

WPF internationalizes with custom XML files

This article describes in detail the methods of using custom XML files to achieve internationalization in WPF programs, including installing the necessary NuGet package, dynamically obtaining language lists, dynamically switching languages, using translation strings in code and xaml interfaces, etc. It also provides source code links to help developers easily internationalize WPF applications.

继续阅读