How to add Outlook toolbar under the subject line? - c#

I need to write an Outlook 2003-2010 plugin using C# that adds two buttons to the Message Ribbon Bar (#1 on the picture) and a several buttons toolbar or a Form Region under the "Subject" line (#2 on the picture).
See image here
Currently I managed to add a button to the Ribbon toolbar, but it appears in the "Add-ins" Ribbon Bar. How do I add buttons to the "Message" Ribbon Bar?
And how do I add the Toolbar #2 ? I currently have no clue about how to add it.
Please help me!
I now have the follwing code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;
namespace SendLaterToolbar
{
public partial class ThisAddIn
{
Office.CommandBar newToolBar;
Office.CommandBarButton firstButton;
Office.CommandBarButton secondButton;
Outlook.Explorers selectExplorers;
Outlook.Inspectors inspectors;
Office.CommandBarButton _objEmailToolBarButton;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
selectExplorers = this.Application.Explorers;
inspectors = this.Application.Inspectors;
selectExplorers.NewExplorer += new Outlook.ExplorersEvents_NewExplorerEventHandler(newExplorer_Event);
inspectors.NewInspector += new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(AddToEmail);
AddToolbar();
}
private void newExplorer_Event(Outlook.Explorer new_Explorer)
{
((Outlook._Explorer)new_Explorer).Activate();
newToolBar = null;
AddToolbar();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
private void AddToolbar()
{
if (newToolBar == null)
{
Office.CommandBars cmdBars =
this.Application.ActiveExplorer().CommandBars;
newToolBar = cmdBars.Add("NewToolBar",
Office.MsoBarPosition.msoBarTop, false, true);
}
try
{
Office.CommandBarButton button_1 =
(Office.CommandBarButton)newToolBar.Controls
.Add(1, missing, missing, missing, missing);
button_1.Style = Office
.MsoButtonStyle.msoButtonCaption;
button_1.Caption = "Button 1";
button_1.Tag = "Button1";
if (this.firstButton == null)
{
this.firstButton = button_1;
firstButton.Click += new Office.
_CommandBarButtonEvents_ClickEventHandler
(ButtonClick);
}
Office.CommandBarButton button_2 = (Office
.CommandBarButton)newToolBar.Controls.Add
(1, missing, missing, missing, missing);
button_2.Style = Office
.MsoButtonStyle.msoButtonCaption;
button_2.Caption = "Button 2";
button_2.Tag = "Button2";
newToolBar.Visible = true;
if (this.secondButton == null)
{
this.secondButton = button_2;
secondButton.Click += new Office.
_CommandBarButtonEvents_ClickEventHandler
(ButtonClick);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void AddToEmail(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
Outlook.MailItem _ObjMailItem = (Outlook.MailItem)Inspector.CurrentItem;
if (Inspector.CurrentItem is Outlook.MailItem)
{
_ObjMailItem = (Outlook.MailItem)Inspector.CurrentItem;
bool IsExists = false;
foreach (Office.CommandBar _ObjCmd in Inspector.CommandBars)
{
if (_ObjCmd.Name == "MyEmailToolBar")
{
IsExists = true;
_ObjCmd.Delete();
}
}
Office.CommandBar _ObjCommandBar = Inspector.CommandBars.Add("MyEmailToolBar", Office.MsoBarPosition.msoBarBottom, false, true);
_objEmailToolBarButton = (Office.CommandBarButton)_ObjCommandBar.Controls.Add(Office.MsoControlType.msoControlButton, 1, missing, missing, true);
if (!IsExists)
{
_objEmailToolBarButton.Caption = "My Email ToolBar Button";
_objEmailToolBarButton.Style = Office.MsoButtonStyle.msoButtonIconAndCaptionBelow;
_objEmailToolBarButton.FaceId = 500;
_objEmailToolBarButton.Click += new Office._CommandBarButtonEvents_ClickEventHandler(_objEmailToolBarButton_Click);
_ObjCommandBar.Visible = true;
}
}
}
private void ButtonClick(Office.CommandBarButton ctrl, ref bool cancel)
{
MessageBox.Show("You clicked: " + ctrl.Caption);
}
private void _objEmailToolBarButton_Click(Office.CommandBarButton ctrl, ref bool cancel)
{
MessageBox.Show("My Email ToolBar ...");
}
#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
}
}

The custom buttons you are creating are meant to be hosted on a CommandBar control for Outlook 2000-2003. You can use the Ribbon designer in your VSTO project to add a custom Ribbon Group to the Message tab (the ID for which is TabNewMailMessage).
Unfortunately, there's no way to inject a custom UI between the message body and the address header. You can use Task Panes and Form Regions but they must go above the header or to the left, right and bottom of the message body.

You might be able to display your own toolbar control under the Subject text box using Add-in Express. Have a look at Add-In Express Regions for Microsoft Outlook and VSTO

Related

Outlook 2010 Addin - change phrase to link without altering email body

I've created simple addin for Outlook 2010 that replace specific phrase with link, for example I want to replace ABC12345 with http://www.example.com?id=123456
I'm using this code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
inspectors = this.Application.Inspectors;
inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
}
void Inspectors_NewInspector(Outlook.Inspector Inspector)
{
var mailItem = Inspector.CurrentItem as Outlook.MailItem;
if (mailItem != null)
{
if (mailItem.EntryID != null)
{
string pattern = #"ABC(?<number>\d{1,6})";
var match = Regex.Match(mailItem.HTMLBody, pattern);
if (match.Success)
{
var replaced = Regex.Replace(mailItem.HTMLBody, pattern, m => "ABC"+ m.Groups["number"].Value+"");
mailItem.HTMLBody = replaced;
}
}
}
}
However I have two issues:
I must double click email in mailbox to have my event fired. I want to display that link when previewing emails (moving up and down in mailbox)
My code is replacing content, so Outlook "thinks" I've made some changes and when I want to close window it asks if I want to save those changes.
I don't want to alter body of email, I want to change phrase ABC123456 into link.
EDIT1:
I've tried using ActiveExplorer, this allows me to access email in preview window, but when I change email body those changes are saved. My intention is to change how specific text is displayed (change it to link), but not to alter email body on serwer.
I want those changes to be visible in my instance of Outlook, not saved on server (mailItem.HTMLBody.Replace does that).
Can I access view that displays email and alter that view?
This is the code:
Outlook.Explorer currentExplorer;
private void ThisAddIn_Startup(object sender, EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
var selectedFolder = this.Application.ActiveExplorer().CurrentFolder;
try
{
if (this.Application.ActiveExplorer().Selection.Count > 0)
{
var selObject = this.Application.ActiveExplorer().Selection[1];
if (selObject is Outlook.MailItem)
{
Outlook.MailItem mailItem = (selObject as Outlook.MailItem);
mailItem.HTMLBody = mailItem.HTMLBody.Replace("ABC", "DEF");
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
EDIT2
I'm able to get WordEditor inside Outlook, but I can't add hyperlink.
Last think I want now is to find specific phrases in email and add hyperlink to them. Here is my current code:
Outlook.Explorer currentExplorer;
private void ThisAddIn_Startup(object sender, EventArgs e)
{
currentExplorer = this.Application.ActiveExplorer();
currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(CurrentExplorer_Event);
}
private void CurrentExplorer_Event()
{
var selectedFolder = this.Application.ActiveExplorer().CurrentFolder;
try
{
if (this.Application.ActiveExplorer().Selection.Count > 0)
{
var selectedObject = this.Application.ActiveExplorer().Selection[1];
if (selectedObject is Outlook.MailItem)
{
var mail = (selectedObject as Outlook.MailItem);
var inspector = mail.GetInspector;
if (inspector.IsWordMail())
{
var document = (Document)inspector.WordEditor;
if (document != null)
{
var app = document.Application;
var find = document.Range().Find;
find.Text = "ABC";
while (find.Execute())
{
var rng = find.Parent as Range;
rng.Hyperlinks.Add(rng, "http://example.com/?query=" + rng.Text );
rng.Collapse(WdCollapseDirection.wdCollapseEnd);
}
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}

Outlook 2010 addins for automatic email-attachment extraction

Outlook 2010 add in for auto extraction of attachment from the configured email ids on outlook 2010.For each configured email ids there will be a separate folder in which it's attachments will be saved automatically.I don't want to click any button or reload it all the times.If a mail arrives in the inbox folder,if it's unread, it's attachments will be extracted and saved in its respective folder.
My problem is that i haven't been able to extract the attachments of non-default email ids on outlook 2010 and also my process is not automatically extracting the attachment.
How can i make the unread mail's attachment extraction and saving automatic for multiple configured email ids on outlook 2010? Here i'm attaching the code which i have tried....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using System.Windows.Forms;
using System.IO;
namespace ITAPOutlookAddIn
{
public partial class ThisAddIn
{
public void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.NewMail += new Microsoft.Office.Interop.Outlook
.ApplicationEvents_11_NewMailEventHandler(ThisApplication_NewMail);
this.Application.NewMail += new Microsoft.Office.Interop.Outlook
.ApplicationEvents_11_NewMailEventHandler(ThisApplication_NewMailStatus);
}
public void ThisApplication_NewMail()
{
const string destinationDirectory = #"C:\TestFileSave";
const string destinationDirectory2 = #"C:\TestFileForm";
if (!Directory.Exists(destinationDirectory))
{
Directory.CreateDirectory(destinationDirectory);
}
if (!Directory.Exists(destinationDirectory2))
{
Directory.CreateDirectory(destinationDirectory2);
}
Outlook.MAPIFolder inBox = this.Application.ActiveExplorer()
.Session.GetDefaultFolder(Outlook
.OlDefaultFolders.olFolderInbox);
Outlook.Items inBoxItems = inBox.Items;
Outlook.MailItem newEmail = null;
inBoxItems = inBoxItems.Restrict("[Unread] = true");
try
{
foreach (object collectionItem in inBoxItems)
{
newEmail = collectionItem as Outlook.MailItem;
if (newEmail == null)
continue;
if (newEmail != null)
{
if (newEmail.ReceivedByName == "Sumit Ray")
{
if (newEmail.Attachments.Count > 0)
{
for (int i = 1; i <= newEmail
.Attachments.Count; i++)
{
string filepath = Path.Combine(destinationDirectory, newEmail.Attachments[i].FileName);
string Sname = newEmail.SentOnBehalfOfName;
string timestamp = newEmail.ReceivedTime.ToString("MMddyyyy.HHmmss");
string result = filepath + Sname + timestamp + ".docx";
newEmail.Attachments[i].SaveAsFile(result);
// newEmail.Attachments[i].SaveAsFile
// (#"C:\TestFileSave\" +
// newEmail.Attachments[i].FileName);
}
}
} //end of inner-if
} //end of outer-if
} //end of for-each
}//end of try
catch (Exception ex)
{
Console.WriteLine(ex);
string errorInfo = (string)ex.Message
.Substring(0, 11);
if (errorInfo == "Cannot save" && newEmail.SenderName == "Sumit Ray")
{
MessageBox.Show(#"Create Folder C:\TestFileSave");
}
} //end of catch void ThisApplication_NewMailStatus()
{
Outlook.NameSpace outlookNameSpace = this.Application.GetNamespace("MAPI");
Outlook.MAPIFolder inbox = outlookNameSpace.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderInbox);
// Mark each unread message from Jeff Hay with a yellow flag icon.
Outlook.Items unreadMailItems =
inbox.Items.Restrict("[Unread]= true");
// if (Convert.ToBoolean(unreadMailItems)
if(unreadMailItems.Equals(true))
{
ThisApplication_NewMail();
}
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
Do you mean you need to read unread messages from a non-default store? Instead of using outlookNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox), loop through the Namespace.Stores collection and call Store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox).

Word 2007 Add-in Task Pane doesn't work in one specific case

I am just starting out with a Word VSTO Add-in. I want to add a group to the ribbon, which has a button to toggle a custom task pane. I want each document to have it's own independent task pane. I have this mostly working, but there is one situation that doesn't work:
Start Word - new document opened, all works fine
Open existing document (closes empty document)
Click on toggle button, pane doesn't appear
Create new document or open ANOTHER existing document, pane appears on that document
Pane now works as expected on all documents, including the problem one from 2/3.
Note that if you type something into the new document (1), everything works as expected, so this seems to be something to do with the existing document loading over the top of the initial empty one, but I can't work out what's going on.
Here's my code from ThisAddIn class:
Note that the PaneControl is a totally empty User Control, behaviour doesn't change when I add stuff to it.
public partial class ThisAddIn
{
private CustomTaskPane CurrentTaskPane(Object window)
{
foreach (CustomTaskPane ctp in CustomTaskPanes)
{
if (ctp.Window.Equals(window))
{
return ctp;
}
}
return null;
}
public bool ToggleTaskPane(Object window)
{
CustomTaskPane ctp = CurrentTaskPane(window);
if (ctp != null)
{
ctp.Visible = !ctp.Visible;
return ctp.Visible;
}
else
{
return false;
}
}
private void RemoveOrphanedTaskPanes()
{
for (int i = CustomTaskPanes.Count; i > 0; i--)
{
var ctp = CustomTaskPanes[i - 1];
if (ctp.Window == null)
{
CustomTaskPanes.Remove(ctp);
}
}
}
private void CreateTaskPane(Object window)
{
try
{
RemoveOrphanedTaskPanes();
// Add the new one
PaneControl ucPaneControl = new PaneControl();
CustomTaskPane ctp = CustomTaskPanes.Add(ucPaneControl, "Test Pane", window);
ctp.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight;
ctp.Width = 300;
}
catch
{
MessageBox.Show("Unable to create pane");
}
}
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
try
{
Word.ApplicationEvents4_Event app = (Word.ApplicationEvents4_Event)Application; // Disambiguate
app.DocumentOpen += new Word.ApplicationEvents4_DocumentOpenEventHandler(Application_DocumentOpen);
app.NewDocument += new Word.ApplicationEvents4_NewDocumentEventHandler(Application_NewDocument);
app.DocumentChange += new Word.ApplicationEvents4_DocumentChangeEventHandler(Application_DocumentChange);
CreateTaskPane(Application.ActiveWindow);
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
RemoveOrphanedTaskPanes();
}
void Application_DocumentChange()
{
RemoveOrphanedTaskPanes();
}
void Application_DocumentOpen(Word.Document Doc)
{
// Creeate pane for existing document
CreateTaskPane(Doc.ActiveWindow);
}
void Application_NewDocument(Word.Document Doc)
{
// Creeate pane for new blank document
CreateTaskPane(Doc.ActiveWindow);
}
#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
The code attached to the ribbon button is:
Globals.ThisAddIn.ToggleTaskPane(Globals.ThisAddIn.Application.ActiveWindow);
Any ideas why this might be happening?
Thanks
ROSCO

Word Add-In Ribbon

I created an Office Add-In project and I added ribbon menu for application. When I build my project word document have my ribbon there is no problem.
How can I save the active document as a file using StreamReader when clicking on a button from the ribbon menu using the button click event below?
private void btnsavefile_Click(object sender, RibbonControlEventArgs e)
{
//Getting FileStream here.
}
I found the following solution in Stack Overflow. Hopefully it is relevant to you.
Serialize current ActiveDocument from office 2007 add-in
Personally, I have done the same when I was dealing with this scenario. I have saved a copy of the file to the temporary location and pushed the copy to the server. In this case, the active document stays as is.
Excel.Workbook xlb = Globals.ThisAddIn.Application.ActiveWorkbook;
xlb.SaveCopyAs(filePath);
Hope this helps!
void Application_DocumentBeforeClose(Word.Document document, ref bool Cancel)
{
try
{
string filePath = this.Application.ActiveDocument.FullName.ToString();
string fileName = this.Application.ActiveDocument.Name;
//dialogFilePath = filePath;
dialogFileName = fileName;
string tempFile;
string tempPath;
if (true)
{
var confirmResult = System.Windows.Forms.MessageBox.Show("Are you sure to save this document ??",
"Confirm Save!!",
System.Windows.Forms.MessageBoxButtons.YesNo);
if (confirmResult == System.Windows.Forms.DialogResult.Yes)
{
//document.Save();
var iPersistFile = (IPersistFile)document;
iPersistFile.Save(tempPath, false);
//Do some action here
}
Word._Document wDocument = Application.Documents[fileName] as Word._Document;
//wDocument.Close(Word.WdSaveOptions.wdDoNotSaveChanges);
ThisAddIn.doc.Close(Word.WdSaveOptions.wdDoNotSaveChanges);
}
}
catch (Exception exception)
{
}
}
Create Word Addin project-> Add Ribbon visual designer from add new item.
Add menu to Ribbon designer and write below code in ribbonsample.cs
public partial class RibbonSample
{
private void RibbonSample_Load(object sender, RibbonUIEventArgs e)
{
// Initialise log4net
}
//Adding items in menu from DB
public RibbonSample()
: base(Globals.Factory.GetRibbonFactory())
{
InitializeComponent();
try
{
System.Data.DataTable dt = new DataAcces().GetData();
if (dt.Rows.Count > 0)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
RibbonButton Field = this.Factory.CreateRibbonButton();
Field.Label = dt.Rows[i][1].ToString();
Field.Tag = i;
Field.ControlSize =
Microsoft.Office.Core.RibbonControlSize.RibbonControlSizeLarge;
Field.Click += Field_Click;
menu1.Items.Add(Field);
}
}
else
{
System.Windows.Forms.MessageBox.Show("No Fields are available in database");
}
}
catch (Exception exception)
{
//thrw exception
}
}
//Select menu item text in word
void Field_Click(object sender, RibbonControlEventArgs e)
{
try
{
Microsoft.Office.Interop.Word.Range currentRange = Globals.ThisAddIn.Application.Selection.Range;
currentRange.Text = (sender as RibbonButton).Label;
}
catch (Exception exception)
{
log.Error(friendlyErrorMessage + " Field_Click Details:" + exception.Message, exception);
}
}
}

Outlook 2007 Add-in: How to add an icon to an msoControlButton

Background: I'm developing an Outlook 2007 Add-in in VS2010 in C#. The specific thing that I'm doing is adding a menu-item to the context menu associated with an email. I do this with the following code:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Application.ItemContextMenuDisplay += Application_ItemContextMenuDisplay;
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
private void Application_ItemContextMenuDisplay(Office.CommandBar commandBar, Outlook.Selection selection)
{
var cmdButtonCallContact = (Office.CommandBarButton)commandBar.Controls.Add(Office.MsoControlType.msoControlButton, 1, System.Reflection.Missing.Value, 6, System.Reflection.Missing.Value);
cmdButtonCallContact.Caption = "&Foo";
//cmdButtonCallContact.Picture = ?
cmdButtonCallContact.Click += cmdButtonCopy_Click;
}
private void cmdButtonCopy_Click(Office.CommandBarButton ctrl, ref bool canceldefault)
{
System.Windows.Forms.MessageBox.Show("Bar");
}
Problem: Can't seem to set the picture. Msdn examples rely on AxHost conversion functions that I don't have. Is there a straightforward way to just set an Image or BitMap to Picture?
Thanks.
If you want a custom image you have to rely on AxHost approach (see MSDN reference) or PictureDispConverter which is another approach created by Microsoft based on OleCreatePictureIndirect.
If you want to use the built-in icons you can just set the FaceId. Download Office Icons Gallery to view Office 2007 FaceId values.
The following code uses a System.Drawing.Bitmap (stored as a Resource) and converts it to an image, that is assignable to Office.CommandBarButton.Picture
private Office.CommandBarButton buttonOne;
void createbutton()
{
Office.CommandBar newMenuBar = Inspector.CommandBars.Add("EAD", Office.MsoBarPosition.msoBarTop, false, true);
buttonOne = (Office.CommandBarButton)newMenuBar.Controls.Add(Office.MsoControlType.msoControlButton, 1, missing, missing, true);buttonOne.Caption = "Ansari";
buttonOne.Style = Office.MsoButtonStyle.msoButtonIconAndWrapCaptionBelow;
buttonOne.Picture = getImage();
//Register send event handler
buttonOne.Click += buttonOne_Click;
newMenuBar.Visible = true;
}
void buttonOne_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault)
{
MessageBox.Show("Hi");
}
private stdole.IPictureDisp getImage()
{
stdole.IPictureDisp tempImage = null;
try
{
System.Drawing.Bitmap newIcon = Properties.Resources.Icon1;
System.Windows.Forms.ImageList newImageList = new System.Windows.Forms.ImageList();
newImageList.Images.Add(newIcon);
tempImage = ConvertImage.Convert(newImageList.Images[0]);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
return tempImage;
}
sealed public class ConvertImage : System.Windows.Forms.AxHost
{
private ConvertImage() : base(null)
{
}
public static stdole.IPictureDisp Convert(System.Drawing.Image image)
{
return (stdole.IPictureDisp)System.Windows.Forms.AxHost.GetIPictureDispFromPicture(image);
}
}
Note: Add image with name Icon1 in resource.
Just FYI, if you want to apply any office built-in images to your button (view the image gallery in here), you can simply call GetImageMso() method.
CommandBarButton.Picture = Application.CommandBars.GetImageMso("ImageMSO", 16, 16);
This is an alternative approach to using FaceID property.

Categories