Ms word 检查段落属性将丢失选择

Ms word 检查段落属性将丢失选择,ms-word,vsto,selection,Ms Word,Vsto,Selection,在我的vsto插件中,我有一些关于计时器的简单代码 private void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (!dialogopen & Application.Documents.Count > 0) { var doc = Application.ActiveDocument;

在我的vsto插件中,我有一些关于计时器的简单代码

private void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (!dialogopen & Application.Documents.Count > 0)
        {
            var doc = Application.ActiveDocument;
            Word.InlineShapes shps;
            Word.Paragraphs pars;
            try
            {
                pars = doc.Paragraphs;
            }
            catch (Exception)
            {
                return;
            }
            var pars2 = pars.Cast<Word.Paragraph>().ToList();
            foreach (var obj in pars2)
            {
                if (obj.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText )//PROBLEM HERE
                {

                };
            }

        }
    }
如您所见,我必须删除实际的检查,因为它导致光标闪烁并失去选择


请告知

我们试图消除查询
ActiveDocument
,认为这可能会产生副作用,导致问题,但事实并非如此

然后,我们确认选择没有“丢失”,屏幕更新是唯一的问题,因此我们尝试使用
应用程序恢复UI。ScreenRefresh
,虽然它确实起作用,但它会导致屏幕在每次计时器启动时闪烁,这还不够好

最后,知道这只是一个UI问题,我试着简单地关闭
应用程序

this中addin

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
    Timer timer = new Timer(2000);
    timer.Elapsed += (s, t) =>
    {
        var scrnUpdating = Application.ScreenUpdating;
        Application.ScreenUpdating = false;

        MainTimer.onElapsed(Application, t);

        if (scrnUpdating)
            Application.ScreenUpdating = true;
    };
    timer.Start();
}
在另一个类库中(注意它是静态的,我仍然认为这是最好的方法)

公共静态类MainTimer
{
公共静态无效失效(Word.Application state、System.Timers.ElapsedEventArgs e)
{
如果(state.Documents.Count>0)
{
var doc=state.ActiveDocument;
Word.InlineShapes;
字。段落部分;
尝试
{
PAR=文件段落;
}
捕获(例外)
{
返回;
}
var pars2=pars.Cast()
.Where(p=>p.OutlineLevel==Word.WdOutlineLevel.wdOutlineLevelBodyText)
.Select(p=>p)//使用所选的Parragraph进行填充。。。
.ToList();
}
}
}
这对我很有用。 选择将保留并显示在UI中,不会闪烁


我还从代码中消除了一些过早的枚举:在
foreach
之前不需要
.ToList()

我们使用
Application.screenUpdate=true
这将保留对
段落
中所有属性的选择,但
范围
属性除外

然后,我们尝试通过反射来访问范围,这就是解决方案

Range rng = (Range)typeof(Paragraph).GetProperty("Range").GetValue(comObj);

显示更多代码。如何初始化和加载
PAR
?您好。我只是在我的NDA下尽可能多地压缩代码……您是否尝试过将其设置为静态类,并通过发送方和/或事件参数传递所需的上下文?避免访问
应用程序.ActiveDocument
可能是个好主意。您可以对System.Timers.ElapsedEventArgs进行子类
。您甚至可以传入UI分派对象并将其放在不同的线程上。您可以检查的另一件事是选择是否确实丢失。这可能是一个屏幕更新问题,可以(某种程度上)通过缩小/缩小或
应用程序解决。ScreenRefresh
。将PAR传递给静态函数没有帮助,如何避免使用
ActiveDocument
?我(最初)如何访问这些段落?谢谢谢谢你的代码可以工作。我不太明白静态代码是如何做到这一点的,但它是有效的。此外,我认为UI仍然有点古怪,但对于MVP来说,它也可以。格雷西亚斯!静态代码只是我对最佳实践的(一次性)看法,但与解决方案无关。*修复*是关闭“应用程序.屏幕更新”。这似乎是关键。而且。。。你为什么认为用户界面还是有点古怪?它还在为你闪烁吗?我不确定。似乎鼠标的反应不是很灵敏,有时需要点击几下才能选中某个对象。现在还处于测试阶段,但我相信我的用户很快就会抱怨…。@YisroelM.Olewski好吧,像这样同步轮询文档并不是一种推荐的方法,如果你有一个重要的段落名称,即使你将它们传递给后台线程,你仍然会有一个奇怪的UI。如果你必须这样做,那么我想你必须在花时间处理之前,以某种方式索引这些鹦鹉图并检查是否有变化。噢,哇!那是个很酷的主意。很好!谢谢我自己也不会想到的。。。
public static class MainTimer
{
    public static void onElapsed (Word.Application state, System.Timers.ElapsedEventArgs e)
    {
        if (state.Documents.Count > 0)
        {
            var doc = state.ActiveDocument;
            Word.InlineShapes shps;
            Word.Paragraphs pars;
            try
            {
                pars = doc.Paragraphs;
            }
            catch (Exception)
            {
                return;
            }
            var pars2 = pars.Cast<Word.Paragraph>()
                .Where(p => p.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText)
                .Select(p => p) // do stuff with the selected parragraphs...
                .ToList();
        }
    }
}
Range rng = (Range)typeof(Paragraph).GetProperty("Range").GetValue(comObj);