CustomTaskPane and ExcelRibbon

Feb 26, 2013 at 11:26 PM
Hello,

I am trying to add custom task pane (CTP) to my Excel DNA (edna) module. The module already contains an Excel Ribbon (ER) and UDF's which loaded fine previously.

Is there a subtlety one should be aware of between CTP and ER?
Or is there a particular approach to register a CTP when a ribbon already exists for the edna module?

The code snippet below is failing. If I remove it from a STA thread launched during module init, then the module loads fine. I noticed there were some security exceptions and it appears there is an issue with COM class registration, but previously I did not have to run as administrator when loading my edna module. In my .dna file, I have marked the module with ComServer="true". Is that sufficient? See attached screenshot below as well.

My Code
        private void AddCustomTaskPane()
        {
            if (CustomTaskPane == null)
            {
                CustomTaskPane = CustomTaskPaneFactory.CreateCustomTaskPane(typeof(TaskPaneView), "MyModule");
                CustomTaskPane.Visible = true;
            }
        }
My Exception Screenshot
Image

Much Obliged,
Bishr
Feb 26, 2013 at 11:34 PM
For clarity, I am using Excel v0.30 and .NET v4.0.
Coordinator
Feb 27, 2013 at 9:23 PM
Hi Bishr,

I can't think of any interaction between the ribbon and CTP support.

The Excel-DNA code is likely to assume you are loading the CTP from the main thread. Your note
"If I remove it from a STA thread launched during module init..."
makes me nervous. I would not expect it to work from a separate thread that you create yourself.

You should not need administrator access to load the CTP, but you do need write access to the HKEY_CURRENT_USER\Software\Classes key. Excel-DNA will first attempt to register under the machine hive, and if that fails then under the user hive. The security error you see might be due to the first attempt, but should not indicate a problem since the user hive will be tried next.

ComServer=true does not interact with the CTP loading. It is only used to mark assemblies for direct access from VBA.

-Govert
Mar 6, 2013 at 4:02 PM
Hi Govert,

Thanks for the feedback. I have refactored the CTP show() so that it occurs on the main Excel thread as the result of a user click on a ribbon button (much like the CustomTaskPane.dna example in the samples which works just fine).

I now observe the "Unable to create specified ActiveX control." exception thrown from ExcelDna.Integration.CustomUI.ICTPFactory.CreateCTP(String CTPAxID, String CTPTitle, Object CTPParentWindow). I noticed this happened for others due to UAC restrictions, and that there were 2 separate security exceptions (see below), but I am running as a non-admin on my machine and have successfully run other Excel DNA components (ribbon without CTP before). Btw, the control I am loading is a simple user control with a hello world label.

Access to the registry key 'HKEY_CLASSES_ROOT\CtpSrv.3edd231e8d9a45ce8cd54ced72ae731a\CLSID' is denied.
Access to the registry key 'HKEY_CLASSES_ROOT\CLSID{3EDD231E-8D9A-45CE-8CD5-4CED72AE731A}\InProcServer32' is denied.

Thoughts?

Thanks,
Bishr
Coordinator
Mar 6, 2013 at 8:27 PM
Edited Mar 6, 2013 at 8:29 PM
Hi Bishr,

If you want to use the just-in-time registration, you should not call the CreateCTP overload that takes a ProgId, but rather the CustomTaskPaneFactory.CreateCuatomTaskPane(Type type,....) method (like in the examples). This should take care of non-admin registration correctly.

(I might be misunderstanding your question - does the CTP sample work on your machine?)

Regards,
Govert
Mar 14, 2013 at 8:50 PM
Hi Bishr,

Where you able to resolve this issue. I am unable to make the distribution example work. I always get the error: "Unable to create specified ActiveX control" when i call CustomTaskPaneFactory.CreateCuatomTaskPane(Type type,....) using my custom user control. what is even more interesting is if i use a normal Microsoft control such as a label or a text box the the CustomTaskPaneFactory.CreateCuatomTaskPane(Type type,....) works great no issues.
Coordinator
Mar 14, 2013 at 8:59 PM
Hi,

The way I read Bishr's messages, the CustomTaskPane sample did work for him, but there were problems with his own library.

If the CustomTaskPane.dna sample does not work for you, please use RegEdit to confirm that you can create new keys under HKEY_CURRENT_USER\Software\Classes.
If you can, then it would also help if you can post the exception details you get.

-Govert
Mar 14, 2013 at 9:01 PM
Edited Mar 14, 2013 at 9:04 PM
Hi Bishr,

So here is my Work around:
Imports ExcelDna.Integration.CustomUI
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports WindowsControlLibrary1

' Define the backing class for the Ribbon 
' Would need to be marked with [ComVisible(true)] if in a project that is marked as [assembly:ComVisible(false)] which is the default for VS projects.
<ComVisible(True)> _
Public Class MyRibbon
    Inherits ExcelDna.Integration.CustomUI.ExcelRibbon

    Private WithEvents ctp As CustomTaskPane

    Public Shared Sub ctp_VisibleStateChange(ctp As CustomTaskPane)
        MsgBox("Visibility changed to " & ctp.Visible)
    End Sub

    Public Shared Sub ctp_DockPositionStateChange(ctp As CustomTaskPane)
        Dim ctrl As MyUserControl
        ctrl = CType(ctp.ContentControl, MyUserControl)
        ctrl.TheLabel.Text = "Moved to " & ctp.DockPosition.ToString()
    End Sub

    Public Sub OnShowCTP(ByVal control As IRibbonControl)
        If ctp Is Nothing Then
            ctp = CustomTaskPaneFactory.CreateCustomTaskPane(GetType(__GroupBox__), "My Super Custom Task Pane!")
            ctp.Visible = True
            ctp.DockPosition = MsoCTPDockPosition.msoCTPDockPositionLeft
            AddHandler ctp.DockPositionStateChange, AddressOf ctp_DockPositionStateChange
            AddHandler ctp.VisibleStateChange, AddressOf ctp_VisibleStateChange
        Else
            ctp.Visible = True
        End If
    End Sub

    Public Sub OnDeleteCTP(ByVal control As IRibbonControl)
        If Not ctp Is Nothing Then
            ctp.Delete()
            ctp = Nothing
        End If
    End Sub

    __Private Sub ctp_VisibleStateChange1(CustomTaskPaneInst As ExcelDna.Integration.CustomUI.CustomTaskPane) Handles ctp.VisibleStateChange
        Dim taskpane As GroupBox
        taskpane = CustomTaskPaneInst.ContentControl
        taskpane.Controls.Add(New usercontrol1)
    End Sub
__End Class
So The code above is direcetly out of the Distro Example with the exception of what we passed to the CustomTaskPaneFactory.CreateCustomTaskPane

and the ctp_VisibleStateChange1

Basicly we passed a control that we knew would work "GroupBox" which is a standard MS control. The control has to allow you to add addtional controls to it after it is created so a group box works great. then on the show event of the CTP we get a handle on the "groupbox", thanks to the "ContentControl" property of the CTP. we recast it to its original type "GroupBox" and we add our custom user control to the GroupBox and It works
Mar 18, 2013 at 5:29 PM
Problem solved by using a vanilla content control (e.g. GroupBox) embedded in the CTP, setting its dock style to Fill, and then adding my custom control as a child.

Thanks to you both for your feedback and help. Much obliged.
Mar 23, 2013 at 5:17 AM
I am so Glad that we could help

Thnx,

Daniel Terry
Cool up and coming HVAC - Spartan Mechanical - David Terry
Mar 23, 2013 at 5:18 AM
I am so Glad that we could help

Thnx,

Daniel Terry
Cool up and coming HVAC - Spartan Mechanical - David Terry