【问题标题】:How can I reliably get the object of a contact context menu in an Outlook 2013 addin?如何在 Outlook 2013 插件中可靠地获取联系人上下文菜单的对象?
【发布时间】:2015-07-10 07:01:54
【问题描述】:

我在the example in this article 之后在 Outlook 2013 中为 联系人 的上下文菜单添加一个条目。这是 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>

该条目正确显示在菜单中,当我单击它时,我的事件处理程序被执行:

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");
}

referenced article 似乎表明上下文应该是IMsoContactCard,但这不是我得到的。打印出context.GetType() 的行显示System.__ComObject

This article here 似乎表明我应该能够将该对象转换为有用的东西,但是所有将其转换为逻辑的尝试(IMsoContactCardContactItemContactCard_ContactItem)失败了。

为了回避这个问题,我尝试按照the instructions in this article 跟踪当前选定的项目。这实际上效果很好,但需要注意的是当前选定的项目并不总是上下文菜单适用的项目。

更详细地说,我可以左键单击一个联系人,它会突出显示并触发我的选择事件。如果我然后右键单击其他联系人以调出上下文菜单先不左键单击,则该联系人将被概述但不会突出显示,并且我的选择事件不会被触发。发生这种情况时,我最终会将上下文菜单单击应用到错误的联系人。

任何建议或指导将不胜感激。谢谢。


根据 Eugene Astafiev 提供的信息更新解决方案

根据下面提供的信息,我能够确定此特定回调的ContextMicrosoft.Office.Interop.Outlook.Selection 类型。然后我可以使用它来获取ContactItem,如下所示:

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;
}

【问题讨论】:

    标签: c# vsto outlook-addin outlook-2013


    【解决方案1】:

    上下文对象的类型取决于您单击的位置和上下文菜单类型。要获取底层类型,您需要执行以下操作:

    1. 将对象强制转换为 IDispatch 接口。
    2. 使用 IDispatch 接口的 GetTypeInfo 方法获取 ITypeInfo 接口。
    3. 使用 ITypeInfo 接口的 GetDocumentation 方法获取类型名称。

      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);
          }
      }
      

      }

    更多信息请参见HowTo: get the actual type name behind System.__ComObject with Visual C# or VB.NET

    【讨论】:

    • 谢谢!这正是我想要的。对于未来的读者,我只想提一下,您必须阅读所引用的文章,因为此处提供的示例函数如果没有围绕它添加一些额外的代码将无法工作。我已接受您的回答,并在此基础上为我的问题添加了更多信息。
    • 我跳过了 PInvoke 声明,因为您可以在网络上找到所需的代码(没有示例项目)。
    猜你喜欢
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多