Outlook VSTO add context menu item

拥有回忆 提交于 2020-05-13 20:54:19

问题


I am trying to add a menu item to the attachment context menu. The problem is that the item does not show up. I've seen some examples where they say that this code should work:

this.Application.AttachmentContextMenuDisplay += new ApplicationEvents_11_AttachmentContextMenuDisplayEventHandler(ThisAddIn_AttachmentContextMenuDisplay);

private void ThisAddIn_AttachmentContextMenuDisplay(CommandBar commandBar, AttachmentSelection attachments)
{
    if (attachments.Count > 0)
    {
        var cbc = commandBar.Controls.Add(
                  MsoControlType.msoControlButton,
                  missing, missing, missing, true);

        cbc.Caption = "My custom item";
    }
}

The event ThisAddIn_AttachmentContextMenuDisplay is fired and the attachment count is larger than zero, but the menu item is not displayed.

Strange thing is that if I call commandBar.ShowPopup(); then the menu item will show (note the missing icons), but when it is clicked the context menu will show a second time:

Without calling commandBar.ShowPopup(); the context menu looks as usual, but it is missing my custom item:

EDIT: I am using Visual Studio 2013 and Outlook 2010


回答1:


This information is linked in a deleted answer from 2016.

The following example adds a context menu item to Outlook 2013 via a VSTO using Fluent UI. I haven't tested it in Outlook 2016.

First, create an Outlook Add-In project in Visual Studio. You may first need to install the Office development features for Visual Studio via Add/Remove Programs (or whatever it's called this year). In the Add New Project dialog, you'll find the project type "Outlook 2013 and 2016 VSTO Add-in" under Visual C#/Office/SharePoint/VSTO Add-ins.

Create the project. Mine's called OutlookAddIn. In project/Outlook/OutlookAddIn.cs, we find this class. It's mostly generated, but I added the CreateRibbonExtensibilityObject() method. The OutlookAddInExtensibility class is my own and is defined below. Yes, the Fluent UI XML interprets <button .../> to mean "context menu item" when used in the appropriate context.

To test the project, close Outlook and press F5 in Visual Studio. It will start up Outlook with your VSTO loaded.

using Microsoft.Office.Core;

public partial class OutlookAddIn
{
    protected override IRibbonExtensibility CreateRibbonExtensibilityObject()
    {
        return new OutlookAddInExtensibility();
    }

    private void ThisAddIn_Startup(object sender, EventArgs e)
    {
    }

    private void ThisAddIn_Shutdown(object sender, EventArgs e)
    {
        // Note: Outlook no longer raises this event. If you have code that 
        //    must run when Outlook shuts down, see https://go.microsoft.com/fwlink/?LinkId=506785
    }

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

OutlookAddInExtensibility.cs

The ComVisible attribute is required.

[ComVisible(true)]
public class OutlookAddInExtensibility : IRibbonExtensibility
{
    public string GetCustomUI(string RibbonID)
    {
        return
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<customUI xmlns=""http://schemas.microsoft.com/office/2009/07/customui"">
    <contextMenus>    
        <contextMenu idMso=""ContextMenuMailItem"">
            <button 
                id=""MyContextMenuMailItem""
                label=""ContextMenuMailItem""
                onAction=""RibbonMenuClick""
                />
        </contextMenu>  
    </contextMenus>
</customUI>
";
    }

    public void RibbonMenuClick(IRibbonControl control)
    {
        var selection = control.Context as Microsoft.Office.Interop.Outlook.Selection;

        var mailItems = selection.OfType<Microsoft.Office.Interop.Outlook.MailItem>().ToList();

        System.Diagnostics.Trace.WriteLine($"RibbonMenuClick control: {control} type {control?.GetType().Name ?? "(null)"}");
    }
}

This is a very minimal example. The approved way of doing this is not to return the XML in a literal string, but to add a Ribbon item to the project. By default, that will create code that creates a new ribbon. But this approach is much easier to paste into a StackOverflow answer as a reproducible example.

MSDN provides lavish documentation of the Fluent UI XML.




回答2:


Command bars were deprecated and shouldn't be used any longer except running controls programmatically (see ExecuteMso). You need to use the Ribbon UI (aka Fluent UI) instead. See Extending the User Interface in Outlook 2010 for more information.

Read more about the Fluent UI in the following series of articles:

  • Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)
  • Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3)
  • Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)

If you need to hide or show some controls depending on the context you can handle ribbon callbacks where you can decide whether a control should be shown to a user or not.



来源:https://stackoverflow.com/questions/37432326/outlook-vsto-add-context-menu-item

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