C# 为什么Microsoft Word为已打开的文档触发DocumentOpen事件

C# 为什么Microsoft Word为已打开的文档触发DocumentOpen事件,c#,vsto,add-in,office-interop,C#,Vsto,Add In,Office Interop,我有一个使用VSTO和interop的Microsoft Word加载项。如果为已打开的文档触发了DocumentOpen事件,则我的代码出现问题。通过打开一个文档doc1,打开另一个文档doc2,然后再次尝试打开doc1,我能够始终如一地复制这一点 Doc1显然已打开,但Doc1再次触发DocumentOpen事件。这是一种预期的设计吗?如果是,是否有一种简单的方法可以告诉我是否正在为已打开的文档触发事件 private void ThisAddIn_Startup(object sender

我有一个使用VSTO和interop的Microsoft Word加载项。如果为已打开的文档触发了
DocumentOpen
事件,则我的代码出现问题。通过打开一个文档doc1,打开另一个文档doc2,然后再次尝试打开doc1,我能够始终如一地复制这一点

Doc1显然已打开,但Doc1再次触发DocumentOpen事件。这是一种预期的设计吗?如果是,是否有一种简单的方法可以告诉我是否正在为已打开的文档触发事件

private void ThisAddIn_Startup(object sender, System.EventArgs a)
{
  try
  {
    this.Application.DocumentOpen += 
      new MSWord.ApplicationEvents4_DocumentOpenEventHandler(Application_DocumentOpen);

  }
}

private void Application_DocumentOpen(MSWord.Document document)
{
  HandleOpenedDocument(document);
}

就我所知,通过阅读并进行一些实证研究,如果出现以下情况,
DocumentOpen
事件将被触发:

  • 打开doc1,然后打开doc2,然后再打开doc1
但是,如果您:

  • 打开doc1,然后再次打开doc1,事件仅在第一次打开doc1时触发
因此,规则可能是这样的:“如果反复打开同一文档,事件只会触发一次,但是,当您打开与最近打开的文档不同的文档时,无论该文档是否已在Word的运行实例中打开,都会为新打开的文档触发事件。”

我一直在文档中寻找关于这方面的更多细节,但没有任何运气。然而,如果你真的想知道发生了什么,我建议你在MSDN论坛上提问,一些MVP可能会在那里提供帮助

然后你问:

是否有一种简单的方法可以判断是否正在为已打开的文档触发事件

private void ThisAddIn_Startup(object sender, System.EventArgs a)
{
  try
  {
    this.Application.DocumentOpen += 
      new MSWord.ApplicationEvents4_DocumentOpenEventHandler(Application_DocumentOpen);

  }
}

private void Application_DocumentOpen(MSWord.Document document)
{
  HandleOpenedDocument(document);
}
是的,我想:)

基本上,您可以在应用程序中保留一组打开的文档,并使用
DocumentOpen
DocumentBeforeClose
事件来维护该文档集。知道哪些文档当前处于打开状态,在触发事件时确定文档是否已打开就变得简单了—只需在集合中进行查找,就可以开始了

为了说明这一点,我构建了一个示例实现,说明了如何使用Word Interop实现这一点——据我所知,这应该将1:1映射到VSTO。我在代码中提供了一些注释,因此应该很容易理解正在发生的事情

using Microsoft.Office.Interop.Word;
using Application = Microsoft.Office.Interop.Word.Application;

namespace WordDocStats
{
    internal class Program
    {
        private static readonly HashSet<Document> OpenDocuments = new HashSet<Document>();

        private static void Main()
        {
            var wordApplication = new Application() { Visible = true };

            // Listen for documents open
            wordApplication.DocumentOpen += WordApplicationDocumentOpen;

            // Listen for documents close
            wordApplication.DocumentBeforeClose += WordApplicationDocumentBeforeClose;

            Console.ReadLine();
            wordApplication.Quit();
        }

        static void WordApplicationDocumentBeforeClose(Document doc, ref bool cancel)
        {
            OpenDocuments.Remove(doc);
            Console.WriteLine(doc.Name + " closed!");
        }

        static void WordApplicationDocumentOpen(Document doc)
        {
            // If this returns true, the doc is not in the set of open documents, hence the doc is not already open
            if(OpenDocuments.Add(doc))
            {
                OpenDocuments.Add(doc);
                Console.WriteLine(doc.Name + " opened...");
            }
            // Otherwise, the doc is already in the set of open documents, hence we know the document is already open
            else
            {
                Console.WriteLine(doc.Name + " is already open!");
            }
        }
    }
}
使用Microsoft.Office.Interop.Word;
使用Application=Microsoft.Office.Interop.Word.Application;
名称空间WordDocStats
{
内部课程计划
{
私有静态只读HashSet OpenDocuments=new HashSet();
私有静态void Main()
{
var wordApplication=new Application(){Visible=true};
//侦听打开的文档
wordApplication.DocumentOpen+=WordApplicationDocumentOpen;
//近距离监听文档
wordApplication.DocumentBeforeClose+=WordApplicationDocumentBeforeClose;
Console.ReadLine();
wordApplication.Quit();
}
关闭前静态作废Word应用程序文档(文档文档,参考bool取消)
{
OpenDocuments.Remove(doc);
Console.WriteLine(doc.Name+“closed!”);
}
静态作废Word应用程序文档打开(文档文档)
{
//如果返回true,则该文档不在打开的文档集中,因此该文档尚未打开
if(OpenDocuments.Add(doc))
{
OpenDocuments.Add(doc);
Console.WriteLine(doc.Name+“已打开…”);
}
//否则,文档已经在打开的文档集中,因此我们知道文档已经打开
其他的
{
Console.WriteLine(doc.Name+“已打开!”);
}
}
}
}

希望这有帮助!:)

如果你打开Doc1,然后直接打开Doc1,它会开火吗?当你编辑一点Doc1,不保存它,然后再打开一个Doc1怎么样?奇怪。。我想这是你打开它的线程/进程的原因吧?抱歉,我帮不上忙我已经在跟踪打开的文档了,所以这很有效。我仍然很想知道为什么OpenDocument事件会被多次触发。我很高兴提议的解决方案能起作用:)我同意你的观点,我很高兴知道
OpenDocument
实际上应该如何工作。很抱歉反应太晚,但请在关闭前注意并警告
DocumentBeforeClose
。未保存文档时(因此
saved
属性设置为
False
),它会提示用户是否保存文件。可能是用户选择了取消选项,然后文档保持打开状态,但
DocumentBeforeClose
被触发!所以要小心!