【问题标题】:Visio Interop Application events causing undesired behaviour导致不良行为的 Visio 互操作应用程序事件
【发布时间】:2016-03-08 12:35:14
【问题描述】:

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

我正在使用 VS/C# 2013、Windows 窗体、Visio 2013(在 Windows 7 上)。虽然我的主要代码项目是使用插件在各种办公应用程序之间实现巨大的交换,但以下简单代码重现了相同的问题。它是一个 Windows 窗体项目(添加了对 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 总是会发生,但这对我来说不太重要。

我一直在寻找这个问题一段时间,但找不到任何相关的东西,所以非常感谢任何帮助。

【问题讨论】:

    标签: c# .net office-interop visio


    【解决方案1】:

    我不太确定是什么原因导致 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)
        {
        }
    }
    

    【讨论】:

    • 感谢您的回复。不幸的是,这会在以下位置生成 COMException:app.EventList.AddAdvise(DocCloseEventCode, this, null, null);
    • 您是否按原样复制了帖子中的代码? (注意属性 [ComVisible(true)]。意思是,要测试,用 1 个按钮创建一个新的 winforms 应用程序,然后从帖子中复制粘贴代码。
    • 再次感谢 Nikolay,您是对的。添加 ComVisible 属性使这项工作有效。标记为答案。我无法投票,因为我还没有回答任何人的问题,并且在我的代表更高之前无法发表评论。
    • 这确实解决了问题 #1(最小化后 Visio 变得无响应)。我不确定这个解决方案是否适用于我的完整应用程序,但这是我现在要探索的内容。一个额外的查询,你知道是否有一个 Visio(应用程序)的 AddAdvise 事件完全关闭吗?
    • 有一个事件到代码的表(映射).. close = app.BeforeQuit = (visEvtApp+visEvtBeforeQuit)。这里:msdn.microsoft.com/en-us/library/office/ff768620.aspx
    【解决方案2】:

    为了使用 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");
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多