I am developing a Microsoft Outlook Add-in, where I have added one button in Add-In tab name OPENISMS. I could see the button, however on click the event is not getting fired. I have no clue why it is behaving in this manner. Please find below are code for adding button and attaching event to it. Any help will be highly appreciated.
private void AddButtonToNewDropdown()
{
Office.CommandBar commandBar = this.Application.ActiveExplorer().CommandBars["Standard"];
Office.CommandBarControl ctl = commandBar.Controls["&New"];
if (ctl is Office.CommandBarPopup)
{
Office.CommandBarButton commandBarButton;
Office.CommandBarPopup newpopup = (Office.CommandBarPopup)ctl;
commandBarButton = (Office.CommandBarButton)newpopup.Controls.Add(1, missing, missing, missing, true);
commandBarButton.Caption = "OpenISMS";
commandBarButton.Tag = "OpenISMS";
commandBarButton.FaceId = 6000;
//commandBarButton.Enabled = false;
commandBarButton.OnAction = "OpenISMSThruMail.ThisAddIn.ContextMenuItemClicked";
commandBarButton.Click += new Office._CommandBarButtonEvents_ClickEventHandler(ContextMenuItemClicked);
}
}
private void ContextMenuItemClicked(CommandBarButton Ctrl, ref bool CancelDefault)
{
if (currentExplorer.Selection.Count > 0)
{
object selObject = currentExplorer.Selection[1];
if (selObject is MailItem)
{
// do your stuff with the selected message here
MailItem mail = selObject as MailItem;
MessageBox.Show("Message Subject: " + mail.Subject);
}
}
}
I am calling AddButtonToNewDropdown() method from ThisAddIn_Startup event.
You need to make the CommandBarButton a class-member variable in scope - otherwise it will be garbage collected and the event will not fire as you've observed.
public class ThisAddIn
{
Office.CommandBarButton commandBarButton;
private void AddButtonToNewDropdown()
{
// ...
}
}
See related SO post regarding similar issue.
Related
I have found a similar post by another user.
https://stackoverflow.com/questions/61183940/is-there-any-way-to-call-send-method-on-composed-mail-opened-in-inline-reply-bas
which is answered, But the page which has answer is no longer active
https://stackoverflow.com/questions/61142613/using-activeinlineresponse-in-vsto-add-in-send-mailitem-after-modifying-header/61144021#comment108226887_61144021
Tried noting as such
Edit : I did call the Item.Send in the Inspector Activate event.. and new inspector event where i call the activate method.
But the window does not disappear unless I click on the window icon in the task bar [to bring it to focus.].
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
Base objBase = new Base();
dynamic mailItem = objBase.GetItemObject(Inspector.CurrentItem);
var inspector = Inspector as Outlook.InspectorEvents_10_Event;
if (inspector != null)
{
inspector.Close += Inspectors_CloseInspector;
}
if (mailItem != null)
{
//if (mailItem.EntryID == null)
//{
if (mailItem is Outlook.MailItem)
{
if (IsInlineItem)
{
_MailItem = mailItem;
((Outlook.InspectorEvents_Event)Inspector).Activate += new Outlook.InspectorEvents_ActivateEventHandler(InspectorActivate);
((Outlook.InspectorEvents_Event)Inspector).Deactivate += new Outlook.InspectorEvents_DeactivateEventHandler(InspectorDeactivate);
((Outlook.InspectorEvents_Event)Inspector).Close += new Outlook.InspectorEvents_CloseEventHandler(Inspectors_CloseInspector);
Inspector.Activate();
}
else if (mailItem.Sent == false)
{ _MailItem = mailItem; }
else
{
Marshal.ReleaseComObject(mailItem);
}
}
else
{
_MailItem = mailItem;
Marshal.ReleaseComObject(mailItem);
}
//}
}
objBase.WriteError("new Inspector");
}
private void InspectorActivate()
{
Base objBase = new Base();
Outlook.Inspector ActiveInspector = Application.ActiveInspector();
if (ActiveInspector is null)
{
}
else
{
//Base objBase = new Base();
dynamic selectedItem = objBase.GetItemObject(ActiveInspector.CurrentItem);
if (selectedItem != null && _MailItem.Subject == selectedItem.Subject && selectedItem.Sent == false)
{
try
{
selectedItem.Send();
}
catch (Exception e)
{
}
finally
{
Marshal.ReleaseComObject(selectedItem);
Marshal.ReleaseComObject(ActiveInspector);
}
}
}
That question got deleted. I will repost the answer:
Yes, OOM blocks some methods for the inline response. The best you can do is simulate a click on the Send button using the accessibility API.
If using Redemption is an option (I am its author), it exposes SafeExplorer.ActiveInlineResponseSend method:
SafeExplorer sExplorer = new Redemption.SafeExplorer();
sExplorer.Item = Application.ActiveExplorer;
sExplorer.ActiveInlineResponseSend();
The Explorer.ActiveInlineResponse property returns an item object representing the active inline response item in the explorer reading pane. You ca use the same properties and methods of the MailItem object on this item, except for the following:
MailItem.Actions property
MailItem.Close method
MailItem.Copy method
MailItem.Delete method
MailItem.Forward method
MailItem.Move method
MailItem.Reply method
MailItem.ReplyAll method
MailItem.Send method
As you can see the Send method is not supported on the inline response items in Outlook.
As a possible workaround you may call the Display method which can open the item in a new inspector window where you could get the instance and call the Send method. The NewInspector event is fired whenever a new inspector window is opened, either as a result of user action or through program code. But I'd suggest getting the Inspector.Activate event fired to get the MailItem instance and call the Send method.
So, as the subject says...what is the easiest way to hide FormRegion if email is in Reply mode whether its in a new window or with InlineResponse?
Just set the FormRegion.Visible property which returns a Boolean value that indicates whether the form region is visible or hidden.
Went back to test the approach in my answer after the question from #EugeneAstafiev and -- of course -- this was more complicated than I first thought... but I did get it working with some additional code.
The issue is that when the user clicks "Reply", it opens a new inspector window with a new instance of the FormRegion. So setting the Visible property to false in the event handler sets it only on the current "Read" mode inspector window -- rather than the new "Compose" mode inspector window that gets opened. So, instead the code samples below set up a bool flag property in ThisAddIn called LoadFormRegion that can be toggled to "false" when the Reply or ReplyAll event is fired.
Also, I noticed that setting Visible to false on the FormRegion still draws the area of the FormRegion on the inspector window, just with nothing in it. To completely prevent the FormRegion from loading, you can test for "Compose" mode and then the ThisAddin.LoadFormRegion flag in the FormRegionInitializing event handler located inside of the "Form Region Factory" at the top of the code page -- which is usually folded away from view. In that code block, setting "e.Cancel = true" will prevent the FormRegion from loading at all.
Here is the revised code for the FormRegion, which now subscribes to all three email button click events (Reply, ReplyAll, Forward), and sets the ThisAddIn.LoadFormRegion flag accordingly:
namespace TESTINGOutlookAddInVSTO
{
partial class FormRegion1
{
#region Form Region Factory
[Microsoft.Office.Tools.Outlook.FormRegionMessageClass(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Note)]
[Microsoft.Office.Tools.Outlook.FormRegionName("TESTINGOutlookAddInVSTO.FormRegion1")]
public partial class FormRegion1Factory
{
// Occurs before the form region is initialized.
// To prevent the form region from appearing, set e.Cancel to true.
// Use e.OutlookItem to get a reference to the current Outlook item.
private void FormRegion1Factory_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e)
{
if (e.FormRegionMode == Outlook.OlFormRegionMode.olFormRegionCompose)
{
var myAddIn = Globals.ThisAddIn;
if (myAddIn.LoadFormRegion == false)
{
e.Cancel = true;
}
}
}
}
#endregion
// Occurs before the form region is displayed.
// Use this.OutlookItem to get a reference to the current Outlook item.
// Use this.OutlookFormRegion to get a reference to the form region.
private void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
{
// Reset ThisAddIn.LoadFormRegion flag to true (in case user starts
// composing email from scratch without clicking Reply, ReplyAll or Forward)
var myAddin = Globals.ThisAddIn;
myAddin.LoadFormRegion = true;
var myMailItem = this.OutlookItem as Outlook.MailItem;
// Track these events to set the ThisAddIn.FormRegionShowing flag
((Outlook.ItemEvents_10_Event)myMailItem).Reply += myMailItem_Reply;
((Outlook.ItemEvents_10_Event)myMailItem).ReplyAll += myMailItem_ReplyAll;
((Outlook.ItemEvents_10_Event)myMailItem).Forward += myMailItem_Forward;
}
// Sets FormRegionShowing flag on ThisAddin
private void SetFormRegionShowing(bool show)
{
var myAddIn = Globals.ThisAddIn;
myAddIn.LoadFormRegion = show;
}
private void myMailItem_Forward(object Forward, ref bool Cancel)
{
SetFormRegionShowing(true);
}
private void myMailItem_ReplyAll(object Response, ref bool Cancel)
{
SetFormRegionShowing(false);
}
private void myMailItem_Reply(object Response, ref bool Cancel)
{
SetFormRegionShowing(false);
}
// Occurs when the form region is closed.
// Use this.OutlookItem to get a reference to the current Outlook item.
// Use this.OutlookFormRegion to get a reference to the form region.
private void FormRegion1_FormRegionClosed(object sender, System.EventArgs e)
{
}
}
}
And here's the new code for ThisAddIn to setup the LoadFormRegion property flag:
namespace TESTINGOutlookAddInVSTO
{
public partial class ThisAddIn
{
private bool loadFormRegion;
public bool LoadFormRegion { get => loadFormRegion; set => loadFormRegion = value; }
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
LoadFormRegion = true;
}
private void ThisAddIn_Shutdown(object sender, System.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
}
}
Tested the above and works nearly perfectly... I noticed that if there is a "Draft" reply in the user's Inbox created before the add-in was loaded, clicking on that email to continue editing in the Preview window or a new inspector window will cause some wonky display issues with the FormRegion. However, once I closed out that draft, then everything seemed to return to normal.
I am developing an Outlook plugin and faced with the problem when my callback NewMailEx is not called for a newly added storage.
My code looks like the next:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Application.ItemSend += Application_ItemSend;
Application.NewMailEx += Application_NewMailEx;
}
private void Application_NewMailEx(string EntryIDCollection)
{
logger.Debug("Received e-mail with ID: {0}", EntryIDCollection);
var outlook_namespace = Application.GetNamespace("MAPI");
dynamic item = outlook_namespace.GetItemFromID(EntryIDCollection);
if (!(item is Outlook.MailItem))
return;
// do some stuff with mail
}
I also tried to subscribe for a new storage:
{
Application.Session.Stores.StoreAdd += Stores_StoreAdd;
}
private void Stores_StoreAdd(Outlook.Store store)
{
logger.Info("New store is added: " + store.DisplayName);
Outlook.MAPIFolder rootFolder = store.GetRootFolder();
Outlook.MAPIFolder inbox = store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
inbox.Items.ItemAdd += items_ItemAdd;
}
private void items_ItemAdd(object item)
{
if (item is Outlook.MailItem)
{
Outlook.MailItem mail = item as Outlook.MailItem;
// do some stuff with mail
}
}
But ItemAdd is called only for items during the synchronization. For a new mails neither NewMailEx nor ItemAdd are called.
But after the restart everything works and NewMailEx works as usual.
Do you have any ideas how to fix it or some workaround?
Your items_ItemAdd event handler will never fire because you set up the event handler on an implicit variable created by the compiler on the line inbox.Items.ItemAdd += items_ItemAdd. You need to save Items object in a dedicated variabler (or event better a List<Items>) to make sure it stays alive and GC never releases it.
I'm developing a mobile application on Xamarin Forms for UWP, Android and IOS on Visual Studio.
I'm currently testing the app on my computer(Windows 10) and my phone (also Windows 10).
I'm using Zxing MobileBarcodeScanner to scan multiple barcodes.
When i press the back button i call the MobileBarcodeScanner.Cancel().
The only thing that it does is to close the camera. It doesn't depose the MobileBarcodeScanner's UI and i didn't found any solution for that.
Can anyone help me or suggest a solution?
Also the Cancel Button and the Flash Button aren't shown to the scanner UI.
Code:
private void showScanner()
{
var scanner = new MobileBarcodeScanner(App.coreDispatcher)
{
UseCustomOverlay = false,
TopText = "Hold camera up to barcode to scan",
BottomText = "Barcode will automatically scan",
CancelButtonText = "Done",
FlashButtonText = "Flash"
}
var opt = new MobileBarcodeScanningOptions { DelayBetweenContinuousScans = 3000 };
scanner.ScanContinuously(opt, HandleScanResult);
}
protected override bool OnBackButtonPressed()
{
scanner.Cancel();
}
private void HandleScanResult(ZXing.Result result)
{
string msg;
if (result != null && !string.IsNullOrEmpty(result.Text)) // Success
{
msg = result.Text;
}
else // Canceled
{
msg = "Scanning Canceled!";
}
}
The only thing that it does is to close the camera. It doesn't depose the MobileBarcodeScanner's UI and i didn't found any solution for that
There is an issue in your code snippets. In the showScanner() method, you have defined a scanner variable, but in OnBackButtonPressed() method, looks like you have used a global variable also called scanner.
Maybe the following way should be correct:
MobileBarcodeScanner scanner;
private void showScanner(){
scanner = new MobileBarcodeScanner(App.coreDispatcher) //Here, remove var
{
......
}
}
protected override bool OnBackButtonPressed()
{
scanner.Cancel();
}
And if you have check the Xamarin.Forms sample
It uses the ZXingScannerPage to host your layout and handle some logics, including Cancel and ToggleTorch etc, see here
Also the Cancel Button and the Flash Button aren't shown to the scanner UI.
Please use Custom Overlay, just set MobileBarcodeScanner.UseCustomOverlay property to true and check the sample code in here
And also ZXing.Net.Mobile Getting Started
I'm setting the Cancel check in the Item_Write event handler for a meeting request because if I set the Cancel to true in Item_Send, the meeting window closes. What I'm trying to do is prompt the user that they have recipients that would normally get processed using a custom button in the ribbon (button details not important for my question). Anyway, when I try to Cancel the Item_Write event a meeting notice is sent regardless. No matter what I try, I cannot stop the meeting notice from going out even though I'm setting the ref Cancel to true. If I cancel on Item_Send then the window closes, which is not what the users want. The only thing I can think of at this point is perhaps the requestDetailsRegion.SaveRequestDetailsToLocalOutlookItemProperties(), which saves custom form region field properties to defined custom properties on the AppointmentItem, is triggering the Application_Item_Load event and this somehow is prompting Outlook to send the meeting invite notice, as if it's pending. I'm running this in Outlook 2010. Thank you in advance.
Here's some example code:
void Item_Write(ref bool Cancel)
{
Cancel = CancelInvite(Cancel);
}
private bool CancelInvite(bool Cancel)
{
Inspector activeInspector = Globals.ThisAddIn.Application.ActiveInspector();
WindowFormRegionCollection formRegions = Globals.FormRegions[activeInspector];
RequestDetailsFormRegion requestDetailsRegion = formRegions.RequestDetailsForm;
// Add request form details to meeting item.
requestDetailsRegion.SaveRequestDetailsToLocalOutlookItemProperties();
// Checking if there's an incomplete form request pending submission
if (requestDetailsRegion.txtFileName_Hidden.TextLength == 0 &&
appointmentItem != null && appointmentItem.MeetingStatus != OlMeetingStatus.olMeetingCanceled)
{
Persons meetingRecipients = new Persons();
foreach (Outlook.Recipient recipient in appointmentItem.Recipients)
if (recipient.Address != activeInspector.Session.CurrentUser.Address)
meetingRecipients.Add(new MeetingRecipient(recipient));
if (meetingRecipients.ContainsSpecialRecipients)
{
CustomDialog customDialog = new CustomDialog();
customDialog.OkButtonText = messageBoxTextStatusOK;
customDialog.CancelButtonText = messageBoxTextStatusCancel;
DialogResult dialogResult = customDialog.ShowDialog();
if (dialogResult == DialogResult.Cancel)
{
Cancel = true;
}
else
{
Cancel = false;
}
customDialog.Close();
}
}
return Cancel;
}
public void SaveRequestDetailsToLocalOutlookItemProperties()
{
if (this.OutlookItem is Outlook.AppointmentItem)
{
Outlook.AppointmentItem appointmentItem = (Outlook.AppointmentItem)this.OutlookItem;
// Checking if organizer already cancelled meeting. If so, then no need to update apppointment item properties.
if (appointmentItem.MeetingStatus != Outlook.OlMeetingStatus.olMeetingCanceled)
{
appointmentItem.ItemProperties[RequestSubmitted].Value = chkSubmitted.Checked; // Hidden
appointmentItem.ItemProperties[Filename].Value = txtFileName_Hidden.Text; // Hidden
appointmentItem.ItemProperties[ReasonForVisit].Value = txtReason.Text;
// SPARING SIMILAR LINES OF CODE
...
chkSaved.Checked = true;
}
}
You never set the (ref) Cancel parameter to true
void Item_Write(ref bool Cancel)
{
this.cancelInviteResult = CancelInvite(Cancel);
Cancel = this.cancelInviteResult;
}