none
Access to Window of Custom Task Panes in PowerPoint 2010 doesn't work as expected RRS feed

  • Question

  • Hi all,

    in my VS2010/VSTO add-in for PowerPoint 2010 (Win7) I want to open a custom task pane. It should be displayed in every window i.e. a new copy needs to be added to the CustomTaskPanes collection as PPT 2010's document interface requires that.

    Unfortunately it appears I cannot

    1. associate a task pane correctly with a window if that window is not ActiveWindow
    2. get the correct .Window object of the task pane - it always returns ActiveWindow rather than the correct one

    Regarding no 1, my code does this:

            private void showTaskPaneActiveWindow()
            {
                // This function generates a new Task Pane in the active window
    
                UserControl CTPControl = new UserControl1();
                Microsoft.Office.Tools.CustomTaskPane CTP = this.CustomTaskPanes.Add(CTPControl, "My tools", this.Application.ActiveWindow);
                CTP.Visible = true;
            }

    I have to activate each window before running the code as any reference to another window than this.Application.ActiveWindow results in the task pane being associated with/shown in ActiveWindow (resulting in multiple same task panes in that window if the function is repeatedly called).

    Regarding no. 2 see this snippet:

            void Application_AfterPresentationOpen(PowerPoint.Presentation Pres)
            {
                // Check if that window already has a Task Pane (occurs when opening a file to an empty PPT window)
                bool bTaskPaneVisibleInActiveWindow = false;
                foreach (Microsoft.Office.Tools.CustomTaskPane CurrentTaskPane in this.CustomTaskPanes)
                {
                    PowerPoint.DocumentWindow CurrentWindow = null;
                    CurrentWindow = (PowerPoint.DocumentWindow)CurrentTaskPane.Window;
                    Debug.WriteLine("The current task pane is associated with window titled: " + CurrentWindow.Caption);
                    if (CurrentTaskPane.Window.Equals(Pres.Windows[1]))
                        bTaskPaneVisibleInActiveWindow = true;
                }
                // Show task pane if not already visible
                if (!bTaskPaneVisibleInActiveWindow)
                    showTaskPaneActiveWindow();
            }

    The function should loop over all custom task panes and check for each one if the associated window matches the currently active window where a presentation has just been opened. However, as you can see from the debug output, even when multiple windows are open and each has exactly one copy of the task pane visible, you do not get an output line for each of the windows, but rather the very same line multiple times in a row, always refering to the window that is the ActiveWindow.

    Does anyone have an idea how I can do better and get this working?

    Thanks a lot in advance!

    h-ruddi


    Tuesday, May 8, 2012 9:55 AM

Answers

  • hi h-ruddi,

    I hope following snippet will help you out:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;
    using PowerPoint = Microsoft.Office.Interop.PowerPoint;
    using Office = Microsoft.Office.Core;
    using System.Windows.Forms;
    
    namespace PowerPointAddIn7
    {
        public partial class ThisAddIn
        {
            private Microsoft.Office.Tools.CustomTaskPane ctp;
            private bool flag = false;
    
            private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
                Application.PresentationOpen += new 
                    PowerPoint.EApplication_PresentationOpenEventHandler(
                    Application_PresentationOpen);
                Application.AfterNewPresentation += new 
                    PowerPoint.EApplication_AfterNewPresentationEventHandler(
                    Application_AfterNewPresentation);
            }
    
            void Application_AfterNewPresentation(PowerPoint.Presentation Pres)
            {
                flag = true;
                ctp = CustomTaskPanes.Add(new UserControl1(), "test", Pres.Windows[1]);
                ctp.Visible = true;
                if (Application.Presentations.Count > 1)
                    flag = false;
            }
    
            void Application_PresentationOpen(PowerPoint.Presentation Pres)
            {
                try
                {
                    if (!flag)
                    {
                        ctp = CustomTaskPanes.Add(new UserControl1(), "test", Pres.Windows[1]);
                        ctp.Visible = true;
                    }
                    else
                    {
                        flag = false;
                    }
                }
                catch
                {
                    MessageBox.Show("Cut");
                }
            }
    
            private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
            {
            }
    
            #region VSTO generated code
    
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InternalStartup()
            {
                this.Startup += new System.EventHandler(ThisAddIn_Startup);
                this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
            }
            
            #endregion
        }
    }

    Best Regards,

    T.X.

    • Marked as answer by h-ruddi Friday, May 11, 2012 8:02 AM
    Wednesday, May 9, 2012 2:55 AM

All replies

  • hi h-ruddi,

    I hope following snippet will help you out:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;
    using PowerPoint = Microsoft.Office.Interop.PowerPoint;
    using Office = Microsoft.Office.Core;
    using System.Windows.Forms;
    
    namespace PowerPointAddIn7
    {
        public partial class ThisAddIn
        {
            private Microsoft.Office.Tools.CustomTaskPane ctp;
            private bool flag = false;
    
            private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
                Application.PresentationOpen += new 
                    PowerPoint.EApplication_PresentationOpenEventHandler(
                    Application_PresentationOpen);
                Application.AfterNewPresentation += new 
                    PowerPoint.EApplication_AfterNewPresentationEventHandler(
                    Application_AfterNewPresentation);
            }
    
            void Application_AfterNewPresentation(PowerPoint.Presentation Pres)
            {
                flag = true;
                ctp = CustomTaskPanes.Add(new UserControl1(), "test", Pres.Windows[1]);
                ctp.Visible = true;
                if (Application.Presentations.Count > 1)
                    flag = false;
            }
    
            void Application_PresentationOpen(PowerPoint.Presentation Pres)
            {
                try
                {
                    if (!flag)
                    {
                        ctp = CustomTaskPanes.Add(new UserControl1(), "test", Pres.Windows[1]);
                        ctp.Visible = true;
                    }
                    else
                    {
                        flag = false;
                    }
                }
                catch
                {
                    MessageBox.Show("Cut");
                }
            }
    
            private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
            {
            }
    
            #region VSTO generated code
    
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InternalStartup()
            {
                this.Startup += new System.EventHandler(ThisAddIn_Startup);
                this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
            }
            
            #endregion
        }
    }

    Best Regards,

    T.X.

    • Marked as answer by h-ruddi Friday, May 11, 2012 8:02 AM
    Wednesday, May 9, 2012 2:55 AM
  • Dear T.X.,

    thanks a lot for your helpful suggestion! I tried your approach however wasn't able to reach full functionality as numerous different states occur (e.g. presentation closes and window stays open). But building on your ideas I came up with a solution that works for me and I'd like to outline for others to come:

    I now store the Presentation's FullName property in CTP.Control.Tag where CTP is the CustomTaskPane of ActiveWindow at both events: AfterNewPresentation and AfterPresentationOpen.

    By that property, a specific CTP can be identified and removed from CustomTaskPanes collection at PresentationBeforeClose event. This way, an empty window, i.e. the last window still open after all presentations have been closed, never has a TaskPane.

    You also need to monitor PresentationBeforeSave and PresentationSave events to ensure  the reference doesn't break if a new file name is assigned (save Pres.FullName in PresentationBeforeSave, then in PresentationSave set the CTP.Control.Tag to the new Pres.FullName for the CTP having the before-stored old file name as .Control.Tag).

    Thanks again for your attention and help!

    h-ruddi

    Friday, May 11, 2012 8:02 AM