How to intercept clicking of a built-in Office Ribbon control - c#

I'm wondering if it's possible to detect when a user has clicked the Header/Footer button in Excel so I can show some custom header/footer related ribbon controls on my add-in's tab and hide them when the user is not in header/footer edit mode.
Is it possible to hijack this button click somehow? I've seen applications hijack the Excel Save before. I'm looking for similar behavior just with the header/footer button.
I'm using C#, Visual Studio 2012 and Excel 2010. I've created my custom ribbon using the Ribbon XML approach.

One way I've discovered that worked was to use the <commands> section in the Ribbon XML (which I didn't know existed.) Apparently this mechanism allows you to re-purpose actions intrinsic to Excel but beware that not all controls support re-purposing the onAction callback)
<?xml version="1.0" encoding="UTF-8"?>
<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<commands>
<command idMso="HeaderFooterInsert" onAction="testHeaderFooter"/>
</commands>
<ribbon>
<tabs>...
along with the associated event handler:
public void testHeaderFooter(Office.IRibbonControl control, bool cancelDefault)
{
MessageBox.Show("Testing.");
cancelDefault = false;
}
This link was very helpful:
http://social.msdn.microsoft.com/Forums/office/en-US/e1a60d16-053e-4697-b17c-b22d602f0400/intercept-the-onaction-event-of-a-gallery-element-of-excel-2007-ui-ribbon?forum=vsto

Related

Adding to Ribbon at run time works once

Hi I'm trying to add the current open contacts phone numbers to a ribbon.
I have created the ribbon and added a SplitButton which will contain the phone numbers.
In 'ThisAddin' when the current explorer changes it triggers an event which simply gets the item type. If its a contact it calls
//ThisAddin.cs on explorer change event - if is contact run:
Globals.Ribbons.CallContact.AddButton(contactItem.BusinessTelephoneNumber);
//Ribbon class
internal void AddButton(string name)
{
if (name != null && name.Count() > 2)
{
RibbonButton item = Globals.Factory.GetRibbonFactory().CreateRibbonButton();
item.Label = name;
item.ShowLabel = true;
this.newSplit.Items.Add(item);
}
}
This works once, first time opening a contact the phone number is displayed in the ribbon. Opening another contact window will cause the ribbon items to be added but are blank and null.
I'm simply trying to add the contacts phone numbers to the ribbon and leave them there while the user can open another contact and the same code runs adding the phone numbers to the ribbon.
I don't need to keep reference to the items once they are added. Thank you for the help. I feel there needs to be an invoke in here somewhere.
You must tell Outlook to refresh the ribbon. See https://learn.microsoft.com/en-us/visualstudio/vsto/walkthrough-updating-the-controls-on-a-ribbon-at-run-time?view=vs-2019 for the sample code.
You will need to specify a callback to retrieve the button's caption instead of hard-coding it in the ribbon's XML.
Note that since you can have multiple inspectors open, you must provide data specific to each item opened in its own inspector.
The Ribbon UI is a static thing because it is loaded once at startup (or before the window is shown). The best what you can do is to define callbacks and get them called wherever you need. For example, you can define 'getVisible' callback for your ribbon controls instead of adding new elements at runtime.
The IRibbonUI.Invalidate method invalidates the cached values for all of the controls of the Ribbon user interface.
You can customize the Ribbon UI by using callback procedures in COM add-ins. For each of the callbacks that the add-in implements, the responses are cached.
For example, if an add-in writer implements the getImage callback procedure for a button, the function is called once, the image loads, and then if the image needs to be updated, the cached image is used instead of recalling the procedure. This process remains in place until the add-in signals that the cached values are invalid by using the Invalidate method, at which time, the callback procedure is again called and the return response is cached. The add-in can then force an immediate update of the UI by calling the Refresh method.
<customUI … OnLoad="MyAddinInitialize" …>
Dim MyRibbon As IRibbonUI
Sub MyAddInInitialize(Ribbon As IRibbonUI)
Set MyRibbon = Ribbon
End Sub
Sub myFunction()
MyRibbon.Invalidate() ' Invalidates the caches of all of this add-in's controls
End Sub
The Fluent UI is described in-depth in the following 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)
Also, you may find the Walkthrough: Create a custom tab by using Ribbon XML helpful. Note, you can export an existing custom ribbon UI to the XML and continue dealing with a raw markup.

Add notification badge icon to Ribbon control in Add-in

We are working on powerpoint add-in. As per requirement, we need to implement notification feature to the add-in application. We are already having some Ribbon button in our Ribbon control. We need to add a badge button in the Ribbon button along with the existing buttons.
Below is the sample badge button we are looking.
I have checked with “Ribbon Button”, Split Button etc. But I couldn’t reach the solution. Will it be a possible requirement?
Is there any way to get the Location of Ribbon button? I have checked the ribbon button properties, but not found any location properties. If we get the location of Ribbon Button we can display notification panel near to ribbon button.
The best way is most probably to provide a callback for the image, and render the notification when returning the image.
Note that you need to switch to XML definition of the ribbon for that (the visual ribbon designer in Visual Studio does not support image callbacks/events, as far as I remember, it supports only trivial "click" event). Use "Export to XML" menu item to export the ribbon to XML, then define a custom image callback.
Here is a somewhat related question: How can I add the images to button using the ribbon xml?
That should do. Note that you need to force repaint when you want to change the notification; for that, you may use "onload" event to capture the ribbon, and call "repaint" method on it.
Below is an almost complete example that shows an auto-incrementing number on a ribbon button.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
onLoad="Ribbon_Load">
<ribbon>
<tabs>
<tab idMso="TabAddIns">
<group id="MyGroup" label="My Group">
<button id="MyButton" size="large" label="Button With Flag"
getImage="Ribbon_GetHelloImage"
onAction="Ribbon_SayHello" />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
C#
[ComVisible(true)]
public class Ribbon1 : Office.IRibbonExtensibility
{
private Office.IRibbonUI ribbon;
private Timer timer = new Timer();
public void Ribbon_Load(Office.IRibbonUI ribbonUI)
{
this.ribbon = ribbonUI;
timer.Interval = 1000;
timer.Start();
timer.Tick += (sender, args) => ribbon.InvalidateControl("MyButton");
}
public Bitmap Ribbon_GetHelloImage(Office.IRibbonControl ctrl)
{
var bitmap = new Bitmap(32, 32);
var flagGraphics = Graphics.FromImage(bitmap);
flagGraphics.DrawString(DateTime.Now.Second.ToString(),
new Font(FontFamily.GenericSansSerif, 10),
Brushes.Red, 12, 0);
return bitmap;
}
public void Ribbon_SayHello(Office.IRibbonControl ctrl)
{
MessageBox.Show("Hello", "Hello");
}

VSTO customise outlook folder context menu

I am basically looking to do this:
C# (outlook add-in) context menu on folders
But the problem is the it never fires the FolderContextMenuDisplay event.
Looking at the documentation it seems to be deprecated, but does anyone know what I should use instead?
Thanks!
By using Ribbon XML you can set the visibility of context menu.
In this post, I will show you how to show and hide items in a context menu by using Ribbon XML.
The context menu appears when a user right-clicks an Outlook folder.
First, add a Ribbon XML item to your Outlook project.
Then add the following code to your ThisAddIn class. This example assumes that your Ribbon is called Ribbon1 and that you are using C#:
protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return new Ribbon1();
}
Next, replace the contents of the Ribbon1.xml file with the following:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<contextMenus>
<contextMenu idMso="ContextMenuFolder">
<button idMso="FolderPropertiesContext" getVisible="IsVisible" />
</contextMenu>
</contextMenus>
</customUI>
But wait. There’s more!
In Ribbon1.cs file create this method.
public bool IsVisible(Office.IRibbonControl control)
{
string name = ((Outlook.Folder)control.Context).Name;
if (foldername == "Inbox")
{
return false;
}
return true;
}
When user right-clicks the folder, then we tell Outlook to not show the command by returning false. Otherwise, we tell Outlook to go ahead and make the command visible by returning true.

VSTO Excel preserve Ribbon state

I have simple VSTO Excel 2013 Application level Add-in with custom Ribbon, which includes toggle button and checkbox. If I open two files (workbooks) I can see that the Ribbons do not preserve their state across multiple windows, meaning if I click on checkbox or toggle button on Second workbook the same checkbox state is shown on a first workbook and vise versa. I found an article which describes a similar situation for outlook : https://www.add-in-express.com/creating-addins-blog/2013/01/30/preserve-outlook-ribbon-controls-state/ but unfortunately the Inspector window event is not available in Excel. Any idea on how to deal with it?
You need to use callbacks instead of attributes in the Ribbon XML. Also when a user changes the active window you need to call the Invalidate/InvalidateControl method of the IRibbonUI interface to force Office applications (Excel in your case) call your callbacks for the current state of controls. It's pretty easy...
You can read more about the Ribbon UI (aka Fluent UI) in the following series of articles in MSDN:
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)
Also you may find the following ones helpful:
Chapter 11: Creating Dynamic Ribbon Customizations (1 of 2)
Chapter 11: Creating Dynamic Ribbon Customizations (2 of 2)
I tried a sample with a toggle button with toggle on and then switched to another workbook the toggle button doesnt persist. But then if you stored the pressed value in a variable and return that on getPressed callback of a toggle button it worked.
Ribbon.xml
<?xml version="1.0" encoding="UTF-8"?>
<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab idMso="TabAddIns">
<group id="group1" label="group1">
<toggleButton id="toggleButton1" label="toggleButton1" size="large" getPressed="buttonPressed" onAction="buttonAction"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
Ribbon.cs
private bool isButtonPressed = false;
public void buttonAction(Office.IRibbonControl control, bool isPressed)
{
isButtonPressed = isPressed;
}
public bool buttonPressed(Office.IRibbonControl control)
{
return isButtonPressed;
}

c# Excel - Display ribbon on exit

I'm using VSTO to design an application with an Excel interface. I want to hide the ribbon on startup (shouldn't be needed in the application) and re-display it on exit (if the user had it originally displayed), to avoid irritating people who use the application and want a ribbon the next time they open Excel.
I can hide the ribbon using essentially the following code in ThisWorkbook_Startup (from this question Excel 2007 Minimize the Ribbon programatically but Not the menu bar):
Office.CommandBars cbs = null;
cbs = Application.CommandBars;
foreach (Office.CommandBar commandBar in cbs)
{
if (commandBar.Name == "Ribbon")
{
this.Application.ActiveWindow.Activate();
Application.SendKeys("^{F1}", true);
}
}
However, the same code or similar variations from the previously referenced question do not seem to work when placed in either the ThisWorkbook_Shutdown or ThisWorkbook_BeforeClose methods. The code is hit but never seems to execute - the ribbon is never restored.
Is there another way to restore the ribbon on exit?
Thanks,
Andrew

Categories