如何在Word VSTO中获取Paragraph.SpaceAfterAuto为True时的实际文本区域
VSTO Word插件自动段落间距下获取实际文本区域解决方案
方法1:临时关闭自动间距读取实际值
操作逻辑:在不改变用户原有文档格式的前提下,临时关闭自动间距属性触发Word计算实际间距值,读取后立即还原原有配置,用户无感知。
- 先备份目标段落的
SpaceAfterAuto、SpaceAfter、SpaceBeforeAuto、SpaceBefore四个属性的原始值 - 将
SpaceAfterAuto和SpaceBeforeAuto设置为false,此时Word会自动将自动间距对应的实际磅值赋值给SpaceAfter和SpaceBefore属性 - 读取此时的
SpaceAfter、SpaceBefore值,按原有逻辑减去对应间距得到文本区域 - 立即将四个属性恢复为备份的原始值
代码示例:
Paragraph para = targetParagraph; // 备份原始属性 bool oldSpaceAfterAuto = para.SpaceAfterAuto; bool oldSpaceBeforeAuto = para.SpaceBeforeAuto; float oldSpaceAfter = para.SpaceAfter; float oldSpaceBefore = para.SpaceBefore; try { // 关闭自动间距触发实际值计算 para.SpaceAfterAuto = false; para.SpaceBeforeAuto = false; // 此时拿到的SpaceAfter、SpaceBefore就是实际渲染的间距值 float realSpaceAfter = para.SpaceAfter; float realSpaceBefore = para.SpaceBefore; // 原有逻辑计算文本区域 } finally { // 还原原始属性,保证用户文档无变化 para.SpaceAfterAuto = oldSpaceAfterAuto; para.SpaceBeforeAuto = oldSpaceBeforeAuto; para.SpaceAfter = oldSpaceAfter; para.SpaceBefore = oldSpaceBefore; }
方法2:取段落首尾字符坐标直接获取文本边界(更稳定)
无需计算段落间距,直接获取段落内纯文本的实际渲染坐标,不受自动间距、段落标记等因素影响:
- 取段落第一个字符的Range:
para.Range(para.Range.Start, para.Range.Start + 1),调用Window.GetPoint获取该字符的上边界坐标 - 取段落最后一个非段落标记字符的Range:
para.Range(para.Range.End - 2, para.Range.End - 1)(Word段落末尾的段落标记占1个字符位,所以往前偏移2位取最后一个文本字符),调用Window.GetPoint获取该字符的下边界坐标 - 横向边界直接沿用原Range的GetPoint返回的left、right值即可,拼接后就是实际文本区域
代码示例:
Window activeWindow = Globals.ThisAddIn.Application.ActiveWindow; Paragraph para = targetParagraph; // 获取首字符坐标 int firstCharLeft, firstCharTop, firstCharWidth, firstCharHeight; Range firstCharRange = para.Range(para.Range.Start, para.Range.Start + 1); activeWindow.GetPoint(out firstCharLeft, out firstCharTop, out firstCharWidth, out firstCharHeight, firstCharRange); // 获取尾字符坐标 int lastCharLeft, lastCharTop, lastCharWidth, lastCharHeight; Range lastCharRange = para.Range(para.Range.End - 2, para.Range.End - 1); activeWindow.GetPoint(out lastCharLeft, out lastCharTop, out lastCharWidth, out lastCharHeight, lastCharRange); // 拼接实际文本区域 int textLeft = firstCharLeft; int textTop = firstCharTop; int textRight = firstCharLeft + firstCharWidth; // 如果要整行宽度可沿用原Range的right值 int textBottom = lastCharTop + lastCharHeight;
方法3:通过Range.Information属性直接读取位置
直接调用Range的Information属性获取渲染后的实际位置,无需调用GetPoint:
Range textRange = para.Range; // 相对于页面左上角的水平位置,单位磅 float left = (float)textRange.Information[WdInformation.wdHorizontalPositionRelativeToPage]; // 相对于页面左上角的垂直位置,单位磅 float top = (float)textRange.Information[WdInformation.wdVerticalPositionRelativeToPage]; float width = (float)textRange.Information[WdInformation.wdWidth]; float height = (float)textRange.Information[WdInformation.wdHeight]; // 减去自动间距的部分可以配合方法1的临时取值逻辑使用
内容的提问来源于stack exchange,提问作者riahruoy
相关产品推荐
相关产品推荐

