|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Hi All,
I have followed a couple of the blog articles to hook up the OutlookItemEvents class to the Inspector and Explorers and to make use of the events of mailitems.
I have used the following guides:
https://www.add-in-express.com/creating-addins-blog/2011/11/28/handle-outlook-item-events/
https://www.add-in-express.com/creating-addins-blog/2011/09/06/outlook-item-events/
The first guide has got my Inspector successfully hooked up and I am seeing the PropertyChange event fired and it works great.
I have followed the second guide to try and hook up the explorer (usually when it is an inline response), I can see it executing the ConnectToSelectedItem function but the events never fire when I change a property such as To or Subject.
Below is the code I am using to hook up my explorer:
Private Sub ConnectToSelectedItem(ByVal explorer As Object)
Dim sel As Outlook.Selection = Nothing
Try
Dim expl As Outlook._Explorer = CType(explorer, Outlook._Explorer)
sel = expl.Selection
If sel.Count = 1 Then
Dim item As Object = sel(1)
If TypeOf item Is Outlook._MailItem Then
OutlookItemEvents.ConnectTo(item, True)
Else
Marshal.ReleaseComObject(item)
End If
End If
Finally
End Try
End Sub
Private Sub AdxOutlookAppEvents_ExplorerActivate(sender As Object, explorer As Object) Handles AdxOutlookAppEvents.ExplorerActivate
ConnectToSelectedItem(explorer)
End Sub
Private Sub AdxOutlookAppEvents_ExplorerClose(sender As Object, explorer As Object) Handles AdxOutlookAppEvents.ExplorerClose
Dim count As Integer = 0
Dim expls As Outlook._Explorers = Nothing
Try
expls = OutlookApp.Explorers
count = expls.Count
Catch
Finally
If expls IsNot Nothing Then
Marshal.ReleaseComObject(expls)
End If
End Try
If count = 0 Then
CanConnect = False
End If
End Sub
Can anyone assist with getting the events for my inline responses to fire correctly?
On a side not is it possible to get the MailItem from inside my ADXForm? I need to get the mailItem the ADXForm is currently embedded in and send it to another function, currently I have this bit of code in my ADXForm:
Private Sub chkDoNotFile_Click(sender As Object, e As RoutedEventArgs) Handles chkDoNotFile.Click
am.DoBackgroundPaint()
End Sub
Would the sender be the active inspector/explorer? Could I just make use of this?
Thanks in advance! |
|
Posted 19 Feb, 2020 09:47:33
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18844
Joined: 2006-05-11
|
Hello Alex,
The item selected and the item shown in an inline response are different items! See Explorer.ActiveInlineResponse. Also, you may need to use InlineResponse-related events of the Outlook Events component.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 19 Feb, 2020 10:05:20
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Ah OK I should know this by now! So I can just use the InlineResponseEx and CloseEx events to grab the inline response and connect that to the OutlookItemEvents Class then? |
|
Posted 19 Feb, 2020 10:50:43
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18844
Joined: 2006-05-11
|
Hello Alex,
I think yes, you can. Note that that item is being composed, not viewed. In other words, you can't expect it fires the Reply event, for instance. It is okay to wait for the Write event though.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 20 Feb, 2020 02:27:41
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
OK so I'm already using he ExplorerInlineResponseEx event as follows:
Private Sub AdxOutlookAppEvents_ExplorerInlineResponseEx(sender As Object, itemObject As Object, sourceObject As Object) Handles AdxOutlookAppEvents.ExplorerInlineResponseEx
Dim form As EmailAutoFilingHost = CType(Me.AdxOlFormsCollectionItem1.GetForm(sourceObject), EmailAutoFilingHost)
If TypeOf itemObject Is Outlook.MailItem Then
Dim item As Outlook._MailItem = CType(itemObject, Outlook._MailItem)
OutlookItemEvents.ConnectTo(item, True)
End If
If form IsNot Nothing Then
form.ShowFields()
End If
End Sub
And here is my ProcessPropertyChange event in the OutlookItemEvents class:
Public Overrides Sub ProcessPropertyChange(ByVal Name As String)
Dim props() As String = {"TO", "CC", "BCC", "SUBJECT"}
If Not String.IsNullOrEmpty(Name) Then
Dim found As String = Array.Find(props, Function(x) (x.Equals(Name.ToUpper)))
If found IsNot Nothing Then
If TypeOf Me.ItemObj Is Outlook._MailItem Then
Dim mailItem As Outlook._MailItem = CType(Me.ItemObj, Outlook._MailItem)
If Not mailItem.Sent Then
am.DoBackgroundPaint()
End If
End If
End If
End If
End Sub
It hooks in correctly and fires the ProcessPropertyChange event however on line
If TypeOf Me.ItemObj Is Outlook._MailItem Then
of the event I receive the following error:
System.Runtime.InteropServices.InvalidComObjectException: 'COM object that has been separated from its underlying RCW cannot be used.'
Any ideas on this? |
|
Posted 20 Feb, 2020 07:39:58
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18844
Joined: 2006-05-11
|
Hello Alex,
The issue originates from the other method:
Private Sub AdxOutlookAppEvents_ExplorerInlineResponseEx(sender As Object, itemObject As Object, sourceObject As Object) Handles AdxOutlookAppEvents.ExplorerInlineResponseEx
Dim form As EmailAutoFilingHost = CType(Me.AdxOlFormsCollectionItem1.GetForm(sourceObject), EmailAutoFilingHost)
If TypeOf itemObject Is Outlook.MailItem Then
Dim item As Outlook._MailItem = CType(itemObject, Outlook._MailItem)
OutlookItemEvents.ConnectTo(item, True)
End If
In this event handler, you connect to the COM object that the item and itemObject variables point to. The problem is: Add-in Express releases that COM object right after the method above completes.
To bypass this, create a different COM object representing the same email and ConnectTo that COM object:
Private Sub AdxOutlookAppEvents_ExplorerInlineResponseEx(sender As Object, itemObject As Object, sourceObject As Object) Handles AdxOutlookAppEvents.ExplorerInlineResponseEx
Dim form As EmailAutoFilingHost = CType(Me.AdxOlFormsCollectionItem1.GetForm(sourceObject), EmailAutoFilingHost)
If TypeOf itemObject Is Outlook.MailItem Then
Dim item As Outlook._MailItem = CType(itemObject, Outlook._MailItem)
Dim newItemReference As Object = Marshal.GetUniqueObjectForIUnknown(Marshal.GetIUnknownForObject(itemObject))
OutlookItemEvents.ConnectTo(newItemReference, True)
End If
Please let me know whether this compiles and works.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 20 Feb, 2020 08:48:37
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Thanks Andre,
This works great, I have taken a similar approach in my OutlookItemEvents class to maintain a new object in the DoBackgroundPaint function. Code snippets below:
Private Sub AdxOutlookAppEvents_ExplorerInlineResponseEx(sender As Object, itemObject As Object, sourceObject As Object) Handles AdxOutlookAppEvents.ExplorerInlineResponseEx
Dim form As EmailAutoFilingHost = CType(Me.AdxOlFormsCollectionItem1.GetForm(sourceObject), EmailAutoFilingHost)
If TypeOf itemObject Is Outlook.MailItem Then
Dim item As Object = Marshal.GetUniqueObjectForIUnknown(Marshal.GetIUnknownForObject(itemObject))
OutlookItemEvents.ConnectTo(item, True)
DoBackgroundPaint(item)
End If
If form IsNot Nothing Then
form.ShowFields()
End If
End Sub
Private Sub AdxOutlookAppEvents_ExplorerInlineResponseCloseEx(sender As Object, sourceObject As Object) Handles AdxOutlookAppEvents.ExplorerInlineResponseCloseEx
Dim form As EmailAutoFilingHost = CType(Me.AdxOlFormsCollectionItem1.GetForm(sourceObject), EmailAutoFilingHost)
If form IsNot Nothing Then
form.HideFields()
form.Clear()
End If
If OutlookItemEvents.IsConnected Then
OutlookItemEvents.RemoveConnection()
End If
End Sub
Public Overrides Sub ProcessPropertyChange(ByVal Name As String)
Dim props() As String = {"TO", "CC", "BCC", "SUBJECT"}
If Not String.IsNullOrEmpty(Name) Then
Dim found As String = Array.Find(props, Function(x) (x.Equals(Name.ToUpper)))
If found IsNot Nothing Then
If TypeOf Me.ItemObj Is Outlook._MailItem Then
Dim mailItem As Object = Marshal.GetUniqueObjectForIUnknown(Marshal.GetIUnknownForObject(Me.ItemObj))
If Not mailItem.Sent Then
am.DoBackgroundPaint(mailItem)
End If
End If
End If
End If
End Sub
Public Sub DoBackgroundPaint(Optional ByVal mail As Outlook.MailItem = Nothing)
Dim form As EmailAutoFilingHost = CType(Me.AdxOlFormsCollectionItem1.GetCurrentForm(), EmailAutoFilingHost)
Dim mailItem As Object = Marshal.GetUniqueObjectForIUnknown(Marshal.GetIUnknownForObject(mail))
If mail IsNot Nothing And form IsNot Nothing Then
If HasExternalRecipients(mail.Recipients) And StringHasCaseCodes(mail.Subject) And Not form.ShouldNotFile Then
form.DoBackgroundPaint(True, OfficeColorScheme)
Else
form.DoBackgroundPaint(False, OfficeColorScheme)
End If
End If
End Sub
One final question, when I tick a box on my ADXForm at the top of the mailitem, is it possible to get the mailitem that the ADX form is associated with from the ADX form. Or does this need to be done by looking at the active window/inspector/explorer? I ask as I need to fire off the DoBackgroundPaint function when this box is ticked & pass the mailitem to it. |
|
Posted 20 Feb, 2020 10:34:04
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18844
Joined: 2006-05-11
|
Hello Alex,
Alex Carter writes:
HasExternalRecipients(mail.Recipients)
This call either leaves the Recipients collection unreleased or the HasExternalRecipients() function has a side effect: in addition to returning a Boolean it releases that COM object. I would do that call in this way:
Dim recipients as Outlook.Recipients = mail.Recipients
Dim hasRecipients as Boolean = HasExternalRecipients(recipients)
Marshal.ReleaseComObject(recipients): recipients = Nothing
If hasRecipients And StringHasCaseCodes(mail.Subject) And Not form.ShouldNotFile Then
...
Alex Carter writes:
is it possible to get the mailitem that the ADX form is associated with from the ADX form.
See ADXOlForm.InspectorObj. If it is not Nothing - and it is Nothing (null in C#) if the ADXOlForm is shown in an Explorer window - you cast it to Outlook.Inspector and retrieve Inspector.CurrentItem.
You shouldn't release what ADXOlForm.InspectorObj returns - Add-in Express relies on it. You should release the result of the Inspector.CurrentItem call.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 21 Feb, 2020 01:49:33
|
|
Top
|
|
Alex Carter
Posts: 59
Joined: 2019-02-21
|
Morning Andre,
Apologies for the late reply I've been on with several things! I've implemented your suggestions and also made use of InspectorObj & ExplorerObj, it works great.
As usual, thanks for all the help! |
|
Posted 26 Feb, 2020 05:27:26
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 18844
Joined: 2006-05-11
|
Hello Alex,
No problem at all! It's great to have this issue solved.
Andrei Smolin
Add-in Express Team Leader |
|
Posted 26 Feb, 2020 05:38:32
|
|
Top
|
|