【问题标题】:CommandBars.OnUpdate stops being firedCommandBars.OnUpdate 停止被触发
【发布时间】:2019-10-23 21:44:33
【问题描述】:

在我的 PowerPoint 2010 Addin 中,我订阅了 CommandBars.OnUpdate 事件以记录形状和类似事件的移动:

 ppt = Globals.ThisAddIn.Application;
 ppt.CommandBars.OnUpdate += CommandBars_OnUpdate;

这在一段时间内效果很好。但是,最终该事件停止被触发。好吧,至少注册的事件处理程序没有被调用。我无法弄清楚,是什么导致了这种行为。这似乎有点不确定。不会引发将出现在调试输出中的异常。这似乎是在一段时间后发生的,并不是由用户操作引起的。

我认为,这将是由于 CommandBars 对象的更改。所以我添加了一个计时器,用于检查这些更改。但是==.Equals() 与最后一个对象的比较都会导致每个刻度都发生可识别的变化,这不太可能。

我也尝试定期(每 1 分钟)刷新事件处理程序,但这也不起作用:

ppt.CommandBars.OnUpdate -= CommandBars_OnUpdate;
ppt.CommandBars.OnUpdate += CommandBars_OnUpdate;

事件真的会在一段时间后停止吗?有没有其他方法可以检测物体移动、调整大小、删除等?


更新

与此同时,我重组了插件。我现在能够重现该问题。方法如下:

在插件的功能区中,我有一个按钮,它调用 ViewModel 上的方法 CreateRightEyeCopy()。在这个方法中,ViewModel 的另一个方法GetNextPairId() 被调用。这个电话似乎有问题。我把GetNextPairId()改成立即返回0,保证方法是问题。

这是return 0 行中生成的堆栈跟踪:

ViewModel.GetNextPairId()
[External Code]
ViewModel.CreateRightEyeCopy()
Button's event handler

我想知道,为什么我的两个函数之间有外部代码。此代码能否导致OnUpdate 事件停止?

如果有人感兴趣,这里是两个函数的代码:

CreateRightEyeCopy():

try
{
    var sel = ppt.ActiveWindow.Selection;
    if (sel.Type == PpSelectionType.ppSelectionShapes)
    {
        foreach (Shape s in sel.ShapeRange)
        {
            var pair = FindStereoPair(s);
            //Only add a new pair, if shape is not in a pair already
            if (pair == null)
            {
                // ** return; **
                int id = GetNextPairId(s.Parent);
                return; //for debugging purposes
            }
        }
    }
}
catch (Exception x)
{
    Debug.WriteLine("Exception occured during creation of stereo pair: " + x.Message);
}

GetNextPairId():

return 0;

如果我在调用GetNextPairId() 之前插入一个return 语句,那么OnUpdate 会继续。

我也尝试异步调用CreateRightEyeCopy(),但这并没有改变任何东西。

对这个问题有什么进一步的想法吗?

【问题讨论】:

  • 我很想知道您是否在这方面取得了更多进展,您最终采用了什么方法/发现了什么?
  • @Cilvic 我用WindowSelectionChange 事件解决了这个问题,该事件被可靠地触发。此外,我使用了一个计时器来反映部分变化。

标签: .net events vsto powerpoint


【解决方案1】:

不是真正的答案,而是MSDN says:“强烈建议将此事件主要用于检查自定义命令栏是否已被 COM 插件添加或删除。”

您可能应该选择不同的方法来跟踪其他事件。

事后想一想,您确定要捕获所有异常(UnhandledException、ThreadException)吗?

【讨论】:

  • 我知道,MSDN 是怎么说的。但我看不到其他选择。 VSTO 中的事件似乎非常罕见。我的代码绝对不会捕获任何异常。
  • 您是否考虑过订阅OnWindowSelectionChange 并在处理程序方法中检查命令栏/功能区状态是否有帮助?
  • 是的,但是在移动形状时不会触发此事件。我对命令栏/功能区的状态并不感兴趣。
  • 实际上我很惊讶在移动形状时会引发 CommandBars.OnUpdate 事件。但无论如何,您可能想研究窗口子类化以获得可靠的解决方案。这是我目前最好的主意——抱歉,我帮不上忙。
  • @PaulB。你能告诉我你会尝试子类化哪个窗口/如何以这种方式捕获更改事件吗?
【解决方案2】:

我知道这是一个非常古老的问题,但我遇到了类似的问题。在 Outlook 中,我丢失了 CommandBars.OnUpdate 的事件。它永远不会在我第一次打开会议时运行,但总是在我打开约会时运行。总体上非常随机的行为。

以下帖子的片段中描述了该修复: https://social.msdn.microsoft.com/Forums/en-US/c6472472-2ae4-496a-b553-a931aeb7a8f6/excel-commandbars-onupdate-event-handler-stops-responding?forum=vsto

我改变了两件事:

  • 引用不应直接指向 CommandBarsObject,而应存储在局部变量中(我假设引用正在以某种方式被垃圾收集)
  • 实际的事件订阅明确地使用_CommandBarsEvents_OnUpdateEventHandler(我认为这不是绝对必要的,但现在它可以工作了)

CommandBars 对象的全局引用

private Microsoft.Office.Core.CommandBars bars = Globals.ThisAddIn.Application.CommandBars

在赋值函数中

 bars.OnUpdate += new Microsoft.Office.Core._CommandBarsEvents_OnUpdateEventHandler(CommandBars_OnUpdate);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 2021-06-24
    • 2015-02-11
    • 2014-10-27
    相关资源
    最近更新 更多