导致意外行为的 Visio 互操作应用程序事件



我正在尝试使用 Visio 应用程序事件。实例化新的应用程序对象并设置任何事件(即 BeforeDocumentClose)时,这似乎会导致在最小化 Visio 窗口后无法还原它。

我正在使用VS/C # 2013,Windows Forms,Visio 2013(在Windows 7上)。虽然我的主要代码项目是使用加载项在各种办公应用程序之间实现交换,但以下简单代码重现了相同的问题。它是一个Windows Forms项目(添加了对Microsoft.Office.Interop.Visio的引用)。

using Visio = Microsoft.Office.Interop.Visio;
Visio.Application app;
bool initialised = false;
private void visioButton_Click(object sender, EventArgs e)
{
    init();
    app.Documents.Add("c:\test.vst"); // creates new document from template
}
void init()
{
    if (!initialised)
    {
        // only initialise once
        app = new Visio.Application();
        app.BeforeDocumentClose += app_BeforeDocumentClose;
        initialised = true;
    }
}
void app_BeforeDocumentClose(Visio.Document doc)
{
}
问题

#1:这是主要问题。创建一个或多个 Visio 文档时,Visio 窗口在最小化后不会最大化。据我所知,没有抛出异常。Windows只是听到错误"ping"。

问题

#2:这是次要问题。创建两个或多个 Visio 文档,将鼠标悬停在 Windows 任务栏上,预览窗口显示等待光标,而不是正常的文档预览。

条件:问题 #1 仅在使用应用程序上的事件时发生。文档、页面/形状事件不会导致任何问题。所有事件都捕获良好。问题#2总是发生,但这对我来说不太重要。

我一直在搜索这个问题一段时间,但找不到与之相关的任何内容,因此非常感谢任何帮助。

我不太确定是什么原因导致 Visio 无法响应还原,但您可以尝试使用"AddAdvise"代替此方法:

[ComVisible(true)]
public partial class Form1 : Form, Visio.IVisEventProc
{
    public Form1()
    {
        InitializeComponent();
    }
    Visio.Application app;
    bool initialised = false;
    private void button1_Click(object sender, EventArgs e)
    {
        init();
        app.Documents.Add("C:\test.vst"); // creates new document from template
    }
    void init()
    {
        if (!initialised)
        {
            // only initialise once
            app = new Visio.Application();
            // app.BeforeDocumentClose += app_BeforeDocumentClose;
            app.EventList.AddAdvise(DocCloseEventCode, this, null, null);
            initialised = true;
            Application.DoEvents();
        }
    }
    const short DocCloseEventCode = unchecked((short)Visio.VisEventCodes.visEvtDoc + (short)Visio.VisEventCodes.visEvtDel);
    object Visio.IVisEventProc.VisEventProc(short eventCode, object source, int eventID, int eventSeqNum, object subject,object moreInfo)
    {
        if (eventCode == DocCloseEventCode)
            app_BeforeDocumentClose(subject as Visio.Document);
        return null;
    }
    void app_BeforeDocumentClose(Visio.Document doc)
    {
    }
}

为了使用 Nikolay 的建议为多个事件提供完整的解决方案,以下是完整的代码,包括事件和 Visio 应用程序的(取消)初始化,并且不使用模板。(请注意,消息框可能会在 Visio 窗口后面的背景中显示。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Visio = Microsoft.Office.Interop.Visio;
namespace VisioInteropTest
{
    [ComVisible(true)]
    public partial class TestForm : Form, Visio.IVisEventProc
    {
        Visio.Application app;
        bool initialised = false;
        // all AddAdvise events:
        // https://msdn.microsoft.com/en-us/library/office/ff768620.aspx
        const short appCloseEventCode = (short)(Visio.VisEventCodes.visEvtApp | Visio.VisEventCodes.visEvtBeforeQuit);
        const short docCloseEventCode = (short)(Visio.VisEventCodes.visEvtDoc | Visio.VisEventCodes.visEvtDel);
        public TestForm()
        {
            InitializeComponent();
        }
        private void visioButton_Click(object sender, EventArgs e)
        {
            if (init())
            {
                app.Documents.Add("");
            }
        }
        bool init()
        {
            if (!initialised)
            {
                app = new Visio.Application();
                app.EventList.AddAdvise(appCloseEventCode, this, null, null);
                app.EventList.AddAdvise(docCloseEventCode, this, null, null);
                initialised = true;
            }
            return initialised;
        }
        object Visio.IVisEventProc.VisEventProc(short eventCode, object source, int eventID, int eventSeqNum, object subject, object moreInfo)
        {
            switch (eventCode)
            {
                case appCloseEventCode: app_BeforeAppClose((Visio.Application)subject); break;
                case docCloseEventCode: app_BeforeDocumentClose((Visio.Document)subject); break;
            }
            return null;
        }
        void app_BeforeAppClose(Visio.Application app)
        {
            initialised = false;
            MessageBox.Show("App closed");
        }
        void app_BeforeDocumentClose(Visio.Document doc)
        {
            MessageBox.Show("Doc closed");
        }
    }
}

最新更新