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

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.

Related

How to add Outlook toolbar under the subject line?

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

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

In C# winforms using telerik assembly references how to export radGridView to pdf ( Im not using MCV or WPF, implementing in normal winforms)

using Telerik.WinControls.Data;
using Telerik.WinControls.UI.Export;
namespace Directory
{
public partial class radForm : Form
{
public radForm()
{
InitializeComponent();
}
private void radForm_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'directoryDataSet.DirDetails' table. You can move, or remove it, as needed.
this.dirDetailsTableAdapter.Fill(this.directoryDataSet.DirDetails);
}
// Button click
private void button1_Click(object sender, EventArgs e)
{
ExportToPDF exporter = new ExportToPDF(this.radGridView1);
//The FileExtension property allows you to change the default (*.pdf) file extension of the exported file
exporter.FileExtension = "pdf";
exporter.HiddenColumnOption = Telerik.WinControls.UI.Export.HiddenOption.DoNotExport;
// This to make the grid fits to the PDF page width
exporter.FitToPageWidth = true;
// Exporting data to PDF is done through the RunExport method of ExportToPDF object
string fileName = "c:\\Directory-information.pdf";
exporter.RunExport(fileName);
}
}
}
Some how Im missing something here and my gridview isn't exporting into pdf and no file creation takes place.
private void button1_Click(object sender, EventArgs e)
{
ExportToPDF exporter = new ExportToPDF(this.radGridView1);
exporter.FileExtension = "pdf";
exporter.HiddenColumnOption = Telerik.WinControls.UI.Export.HiddenOption.DoNotExport;
exporter.ExportVisualSettings = true;
exporter.PageTitle = "Directory Details";
exporter.FitToPageWidth = true;
string fileName = "c:\\Directory-information.pdf";
exporter.RunExport(fileName);
MessageBox.Show("Pdf file created , you can find the file c:\\Directory-informations.pdf");
}

I want to merge two .png images

I want to merge two .png images. but when I ga to save them there occurred an error called a generic error occurred in gdi+. I want to continue my project as soon as possible. please help me. Thanks
private void MergeImages(string ImageBack,string ImageFore)
{
try
{
System.Drawing.Graphics myGraphic = null;
Image imgB;// =new Image.FromFile(ImageBack);
imgB = Image.FromFile(ImageBack);
//FileInfo fileInfoBack = new FileInfo(ImageBack);
Image imgF;// =new Image.FromFile(ImageBack);
imgF = Image.FromFile(ImageFore);
//Bitmap tempBitmap = new Bitmap(imgB.Width, imgB.Height,imgB.PixelFormat );
// tempBitmap.Save("a"+fileInfoBack.Extension);
Image m;
m = Image.FromFile(ImageBack);
// m = Image.FromFile("a" + fileInfoBack.Extension);
myGraphic = System.Drawing.Graphics.FromImage(m);
myGraphic.DrawImageUnscaled(imgB,0,0);
myGraphic.DrawImageUnscaled(imgF,posX,posY);
myGraphic.Save();
m.Save(ImageBack.Replace(".jpg",".jpeg"),System.Drawing.Imaging.ImageFormat.Jpeg);
//m.Save(ImageBack, System.Drawing.Imaging.ImageFormat.Png);
// m.Save("d.png", System.Drawing.Imaging.ImageFormat.Png);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnFileProtector_Click(object sender, System.EventArgs e)
{
if (openFileDialog1.ShowDialog()==DialogResult.OK)
{
txtFileProtector.Text=openFileDialog1.FileName;
}
}
private void btnFilesToProtect_Click(object sender, System.EventArgs e)
{
listFilesToProtect.Items.Clear();
if (openFileDialog2.ShowDialog()==DialogResult.OK)
{
if (openFileDialog2.FileNames.Length>0)
{
for(int i=0;i<openFileDialog2.FileNames.Length;i++)
{
listFilesToProtect.Items.Add(openFileDialog2.FileNames[i]);
}
}
}
}
private void btnLoad2_Click(object sender, System.EventArgs e)
{
posX = int.Parse(textBox1.Text);
posY = int.Parse(textBox2.Text);
// heightBackImage = int.Parse(textBox3.Text);
// widthBackImage = int.Parse(textBox4.Text);
if (listFilesToProtect.Items.Count>0)
{
foreach(object it in listFilesToProtect.Items)
{
MergeImages(it.ToString(), txtFileProtector.Text);
}
}
}
You didn't show us at which line this exception is thrown, So I am going to guess here. This error usually occurs when the path of the image that you are trying to load/save is not correct, so check the path for both ImageBack and ImageFore.
Also make sure that the file you are trying to load/save to is not open by another process including your application.
It is worth to mentioned here that you should dispose the images/graphics when you finish from using them, for instance by use using. like
using(Image imgB = Image.FromFile(ImageBack))
{
//the code that is using the imgB here
}

Categories