How can I reliably get the object of a contact context menu in an Outlook 2013 addin?

拥有回忆 提交于 2019-12-02 10:02:58

问题


I am adding an entry to the context menu for a Contact in Outlook 2013 following the example in this article. Here is the XML:

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
  <contextMenus>
    <contextMenu idMso="ContextMenuContactItem">
      <button id="MyContextMenuContactItem" label="Do something..." onAction="OnDoSomething"  insertAfterMso="DialMenu"/>
    </contextMenu>
  </contextMenus>
</customUI>

The entry shows up in the menu properly, and when I click it, my event handler is executed:

public void OnDoSomething(IRibbonControl control)
{
    object context = control.Context;
    System.Diagnostics.Debug.WriteLine(context.GetType());
    if ((context as IMsoContactCard) != null) System.Diagnostics.Debug.WriteLine("IMsoContactCard");
    if ((context as ContactItem) != null) System.Diagnostics.Debug.WriteLine("ContactItem");
    if ((context as ContactCard) != null) System.Diagnostics.Debug.WriteLine("ContactCard");
    if ((context as _ContactItem) != null) System.Diagnostics.Debug.WriteLine("_ContactItem");
}

The referenced article seems to indicate that the context should be an IMsoContactCard, but that's not what I'm getting. The line that prints out context.GetType() is displaying System.__ComObject.

This article here seems to indicate that I should be able to cast that object into something useful, but all of the attempts to cast it into something logical (IMsoContactCard, ContactItem, ContactCard, _ContactItem) have failed.

In an attempt to sidestep the problem, I tried keeping track of the currently selected item, as per the instructions in this article. This actually works fairly well, with the caveat that the currently selected item is not always the item that the context menu applies to.

To elaborate, I can left-click on a contact and it is highlighted and my selection event fires. If I then right-click on a different contact to bring up the context menu without left-clicking on it first, then that contact will be outlined but not highlighted, and my selection event is not fired. When this happens, I end up applying the context menu click to the wrong contact.

Any advice or direction would be appreciated. Thanks.


Update with a solution based on information provided by Eugene Astafiev

Based on the information provided below, I was able to figure out that the Context of this particular callback is of type Microsoft.Office.Interop.Outlook.Selection. I can then use this to get the ContactItem as follows:

private ContactItem GetContactItemFromControlContext(IRibbonControl control)
{
    var selection = control.Context as Selection;
    if (selection != null && selection.Count == 1) 
        return selection[1] as ContactItem;
    else
        return null;
}

回答1:


The type of the Context object depends on the place where you clicked and the context menu type. To get the underlying type you need to do the following:

  1. Cast the object to the IDispatch interface.
  2. Get the ITypeInfo interface using the GetTypeInfo method of the IDispatch interface.
  3. Get the type name using GetDocumentation method of the ITypeInfo interface.

    public static string GetTypeName(object comObj)
    {
    
        if (comObj == null)
            return String.Empty;
    
        if (!Marshal.IsComObject(comObj))
            //The specified object is not a COM object
            return String.Empty;
    
        IDispatch dispatch = comObj as IDispatch;
        if (dispatch == null)
            //The specified COM object doesn't support getting type information
            return String.Empty;
    
        ComTypes.ITypeInfo typeInfo = null;
        try
        {
            try
            {
                // obtain the ITypeInfo interface from the object
                dispatch.GetTypeInfo(0, 0, out typeInfo);
            }
            catch (Exception ex)
            {
                //Cannot get the ITypeInfo interface for the specified COM object
                return String.Empty;
            }
    
            string typeName = "";
            string documentation, helpFile;
            int helpContext = -1;
    
            try
            {
                //retrieves the documentation string for the specified type description 
                typeInfo.GetDocumentation(-1, out typeName, out documentation,
                    out helpContext, out helpFile);
            }
            catch (Exception ex)
            {
                // Cannot extract ITypeInfo information
                return String.Empty;
            }
            return typeName;
        }
        catch (Exception ex)
        {
            // Unexpected error
            return String.Empty;
        }
        finally
        {
            if (typeInfo != null) Marshal.ReleaseComObject(typeInfo);
        }
    }
    

    }

See HowTo: get the actual type name behind System.__ComObject with Visual C# or VB.NET for more information.



来源:https://stackoverflow.com/questions/29970060/how-can-i-reliably-get-the-object-of-a-contact-context-menu-in-an-outlook-2013-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!