Proper signature for VSTO's Button.GetImage - c#

I have created a working add-in for Outlook and now I try to add an image to a button. I've seen in many questions that you need to set the getImage="GetImage" property and provide a callback function for it, so I did:
public Bitmap GetImage(IRibbonControl ribbon)
However, with this method the add-in doesn't even load. I tried a couple of other signatures like
public stdole.IPictureDisp GetImage(Microsoft.Office.Core.IRibbonControl ribbon)
public Bitmap GetImage(Microsoft.Office.Core.IRibbonControl control)
public stdole.IPictureDisp GetImage(string idMso, int Width, int Height)
but none of them worked. What is the correct signature of this function?

The getImage callback's signature is listed below:
C#: IPictureDisp GetImage(IRibbonControl control)
-
VBA: Sub GetImage(control As IRibbonControl, ByRef image)
-
C++: HRESULT GetImage([in] IRibbonControl *pControl, [out, retval] IPictureDisp ** ppdispImage)
-
Visual Basic: Function GetImage(control as IRibbonControl) as IPictureDisp
Read more about the Fluent UI (aka Ribbon 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)

I got it and I post a self-answer, maybe it helps someone someday...
In order to use the getImage callback you must not set the image property. It's either or.

Related

DLLImportAttribute C# - Outlook

I'm trying to develop a snippet in C # code that enables the "voting option" function of Outlook.
This code will be used by a platform called Blue Prism.
The "vote" function of Outlook is in the Microsoft.Office.Interop.Outlook namespace, so I need to import it using C#, but I dont have enough knowledge to develop this.
I tried to do something like this but it is giving an error.
Here is the code:
public class program {
[DllImport(#"C:\Program Files\Blue Prism Limited\Blue Prism Automate\Microsoft.Office.Interop.Outlook.dll", EntryPoint = "VotingOptions")]
public static extern string Outlook(uint type);
static void Main()
{
// Create the Outlook application.
Outlook.Application oApp = new Outlook.Application();
oApp.VotingOption = "Yes; No";
}
}
So, can someone help me?
The VotingOptions property belongs to the MailItem class , not Outlook Application. Voting options on messages are used to give message recipients a list of choices and to track their responses. To create voting options programmatically, set a string that is a semicolon-delimited list of values for the VotingOptions property of a MailItem object. The values for the VotingOptions property will appear under the Vote command in the Respond group in the ribbon of the received message.
private void OrderPizza()
{
Outlook.MailItem mail = (Outlook.MailItem)Application.CreateItem(
Outlook.OlItemType.olMailItem);
mail.VotingOptions = “Cheese; Mushroom; Sausage; Combo; Veg Combo;”
mail.Subject = “Pizza Order”;
mail.Display(false);
}
Also you may find the C# app automates Outlook (CSAutomateOutlook) sample project helpful, it shows how to automate Outlook in C#.
Com objects aren't accessed through DLLImport. They're accessed using references. From the sample Eugene linked:
Create a Console application and reference the Outlook Primary Interop Assembly (PIA). To reference the Outlook PIA, right-click the project file and click the "Add Reference..." button. In the Add Reference dialog, navigate to the .NET tab, find Microsoft.Office.Interop.Outlook 12.0.0.0 and click OK.
Now you'll have access to the Microsoft.Office.Interop.Outlook object.
If you are using Blue Prism then rather than having to specify DLL references you may also chose to go the GetObject or CreateObject way, you will be able to interact with Outlook just like Blue Prism does with Excel. The drawback of this approach is that you have to use VB.NET (unless I am mistaken) and that you will not be able to use text representation of enum values (so for OlItemType you will not be able to use olMailItem but only its numeric value, which is 0).
Please note that Blue Prism has released a new version recently (6.3) and with it a new VBO for interaction with Outlook. It's nothing revolutionary, but it may provide some insight.

Outlook Ribbon Implementation for IRibbonUI

I am confused about the implementation of the IRibbonUI interface that is exposed in the Outlook Object Model.
When the XML file for the either the Explorer or Inspector ribbon are written, we have to define which method will be responsible for loading the XML into Outlook.
Note: that this code was not originally written by me but I've been tasked to fix the solution..or at the least find a reason why this thing doesn't work as expected.
Anyways, the methods to set the ribbons are defined in the following methods: Ribbon_OnLoad and ERibbon_OnLoad
Public Sub Ribbon_OnLoad(ByVal Ribbon As Office.IRibbonUI)
m_Ribbon = Ribbon
End Sub
Public Sub ERibbon_OnLoad(ByVal Ribbon As Office.IRibbonUI)
m_ERibbon = Ribbon
End Sub
Now what I am confused is why the method for the Inspector never fires? When I step through the code and even when I open an inspector object, my global variable m_Ribbon is sometimes Nothing and vice versa for the m_ERibbon variable.
There have been times where m_ERibbon has been nothing and there has been times m_Ribbon has been nothing..I'm starting to think I may have deeply misunderstood how the Ribbon for Office works.
Now it becomes more intricate when I have to invoke the callbacks via the Invalidate method. I have an explorer wrapper and a inspector wrapper which invoke either m_ERibbon.Invalidate() or m_Ribbon.Invalidate() depending if the user is using the Explorer or Inspector.
What I do not understand is this:
Why doesn't Ribbon_OnLoad fire ALL the time, and why doesn't ERibbon_OnLoad fire all the time, despite the fact I've explictly set the onLoad method to fire these methods?
Why are there instances where m_ERibbon or m_Ribbon are Nothing?
From what I can tell is despite the Invalidate() method being invoked from the Explorer or the Inspector...the call to Invalidate() invokes ALL of the callbacks despite some callbacks being placed in the inspector and vice versa.
Have I understood this incorrectly?
EDIT I'm adding code for the GetCustomUI because this is where the markup is defined. Despite the respective XML markups being available for both the Explorer and the Inspector; the method Ribbon_OnLoad (for the Inspector) doesn't fire.
Function GetCustomUI(ByVal RibbonID As String) As String Implements Microsoft.Office.Core.IRibbonExtensibility.GetCustomUI
Select Case RibbonID
Case "Microsoft.Outlook.Mail.Read"
Return basRibbon.QFGetRibbonMailRead()
Case "Microsoft.Outlook.Explorer"
Return basRibbon.GetRibbonExplorerFolder()
Case Else
Return String.Empty
End Select
End Function
And a snippet of the XML markup is the following (note that this is for the Inspector):
sRibbonXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2006/01/customui"" onLoad=""Ribbon_OnLoad"" >" & _
Snippet of the XML markup for the Explorer:
sRibbonXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2009/07/customui"" onLoad=""ERibbon_OnLoad"" " & _
Microsoft Office applications call the GetCustomUI method to obtain an XML string that defines the user interface of your custom Ribbon.
public class Connect : Object, Extensibility.IDTExtensibility2, IRibbonExtensibility
...
public string GetCustomUI(string RibbonID)
{
StreamReader customUIReader = new System.IO.StreamReader("C:\\RibbonXSampleCS\\customUI.xml");
string customUIData = customUIReader.ReadToEnd();
return customUIData;
}
Note, sometimes you need to return the XML markup for different ribbonID values passed as an argument. In that case you will get the onLoad callback invoked (for inspectors too).
public string GetCustomUI(string ribbonID)
{
string ribbonXML = String.Empty;
if (ribbonID == "Microsoft.Outlook.Mail.Compose")
{
ribbonXML = GetResourceText("Trin_RibbonOutlookBasic.Ribbon1.xml");
}
return ribbonXML;
}
See Customizing a Ribbon for Outlook for more information.
You can read more about the Fluent UI (aka Ribbon 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)
Please remember that by default, if an VSTO add-in attempts to manipulate the Microsoft Office user interface (UI) and fails, no error message is displayed. However, you can configure Microsoft Office applications to display messages for errors that relate to the UI. You can use these messages to help determine why a custom Ribbon does not appear, or why a Ribbon appears but no controls appear. See How to: Show Add-in User Interface Errors for more information.

Call C# Add-in from Visio double click event

I am tring to call with =CALLTHIS("pp",) and with =CALLTHIS("ThisDocument.pp",) from shape event dblClick. I´m using C# Visio 2010 Add-in in Visual Studio 2015 without success.
The method is:
public static void pp(Visio.Shape shpObj) {
MessageBox.Show("My id is: " + shpObj.ID);
}
To call a managed C# (VSTO/COM) add-in from shape sheet formula cell, such as "dblClick" event, use QUEUEMARKEREVENT function. CALLTHIS only works for VBA functions. RUNADDON/RUNADDONWARGS only works for unmanaged (VSL) addons.
Here you can find a step-by-step guide how to make it happen:
https://blogs.msdn.microsoft.com/chcast/2004/11/03/calling-com-add-ins-from-the-shapesheet/

Opening a downloaded Word document with VSTO in edit mode by default

I have a word document, downloaded from the internet, that I would like to perform some operations on in an Application-level Add-In. These operations (document search, unprotecting the document, etc) require that the document be in edit mode when it is opened. Here is some sample code that illustrates my needs:
private void ThisAddIn_Startup(object sender, EventArgs e)
{
Application.DocumentOpen += application_DocumentOpen;
}
private void application_DocumentOpen(Document doc)
{
if (doc.ProtectionType != WdProtectionType.wdNoProtection)
{
// this throws a COMException if the document is opened in read-only mode
doc.Unprotect("password");
}
// ...
}
Since this add-in will be distributed to multiple users, I can't assume that the user will set any application properties, such as opening downloaded documents in edit mode by default, so doing it in code would be ideal. Is there some means with VSTO or the interop library to accomplish this, given my constraints? Thanks for any help.
EDIT: My application-level add-in was tested as installed on Word 2013, and was created with VS 2013, VSTO 4.0.
A sample document that displays the requisite characteristics can be found here. The document is protected with WdProtectionType.wdAllowOnlyFormFields, and the password is "password".
What version of Word/VSTO are you using.
I tried this using Word 2013 ( 64-bit ) and VSTO 4.0/Visual Studio 2013 and do not get any Exception in the even handler function "application_DocumentOpen". For both read-only and protected docs.
EDIT:
Try to change the view to Print View before unprotecting the document.
if (doc.ProtectionType != Word.WdProtectionType.wdNoProtection)
{
doc.ActiveWindow.View.Type = Word.WdViewType.wdPrintView;
doc.Unprotect("password");
}
Reference : http://answers.microsoft.com/en-us/office/forum/office_2013_release-word/not-available-for-reading-error-on-unprotecting-a/a888701b-d70a-4dbc-a1ec-68b8bad80848

How-to: Run existing Word VBA Macros from C# Ribbon Addin

Background: I have an extensive set of specialized VBA macros used in Word for document formatting purposes. In Word 2003, these macros were activated from a customized toolbar. I have recently transitioned to Word 2007 and would like to be able to run these existing VBA macros from a new Word Ribbon created with VS 2010. I have created a Ribbon; however, I cannot figure out how to call the existing macros from the new Ribbon buttons.
Question: How do I call the existing VBA macros, which are stored in a .dotm template, from the C# Word Add-in?
Any help would be greatly appreciated.
The technique described in MS KB article 306683 -- in particular, function RunMacro defined there -- should allow you to call a VBA macro from within C# code: You define a function RunMacro
private void RunMacro(object oApp, object[] oRunArgs)
{
oApp.GetType().InvokeMember("Run",
System.Reflection.BindingFlags.Default |
System.Reflection.BindingFlags.InvokeMethod,
null, oApp, oRunArgs);
}
and then call your macro like this:
RunMacro(oApp, new object[] {"NameOfMyMacro"})
or
RunMacro(oApp, new object[] {"NameOfMyMacro", "some", 3, "parameters"})
oApp is the Word.Application object, which I'm sure is available somewhere in a Word add-in.

Categories

Resources