How to access TadxOlForm from TAddInModule in Outlook 2016

Add-in Express™ Support Service
That's what is more important than anything else

How to access TadxOlForm from TAddInModule in Outlook 2016
access a correct TadxOlForm from TAddInModule 
Peter Horak




Posts: 8
Joined: 2015-12-29
Happy New Year everyone!
I have this situation: I have a TadxOlForm that takes some user input in a new message Outlook form. It is actually looking up recipient's information from a database and is showing this information to the user. Once the user clicks 'Send', I want to attach an identifier to the end of the email message. I am able to do some processing in TAddInModule.adxOutlookAppEvents1ItemSend. I don't know how the whole COM system works, but I assume that for each 'new Outlook message window' there is a dedicated instance of my TadxOlForm. My question is, how do I access in TAddInModule.adxOutlookAppEvents1ItemSend a correct instance of my TadxOlForm that triggered the 'Send mail' event? In other words, how do I access the data user provided in this one specific instance of TadxOlForm after they clicked 'Send'? So far I am using a workaround that adds the data into the email body as they work with the TadxOlForm. The problem with this workaround is, that if they chose to alter the inserted encrypted text, I wouldn't know and I couldn't catch it in TAddInModule.adxOutlookAppEvents1ItemSend. I hope my explanation makes sense.
What would be a good way of solving this?
Thank you!

Edit; I found this in the past blogs:
https://www.add-in-express.com/forum/read.php?FID=1&TID=11535

Where can I get the "Item: TadxOlFormsCollectionItem" from?

Edit; Never mind, adxOlFormsManager1.CurrentForm; does the trick. Time to sleep.
Posted 03 Jan, 2016 03:55:51 Top
Dmitry Kostochko


Add-in Express team


Posts: 2875
Joined: 2004-04-05
Hi Peter,

Thank you for keeping us informed.
Posted 04 Jan, 2016 04:40:27 Top
Peter Horak




Posts: 8
Joined: 2015-12-29
Dmitry, it seems that I spoke too soon. The CurrentForm works fine with messages opened directly from Outlook Explorer, but when I reply to such a message, the 'CurrentForm' doesn't give me the new form.
This is what happens:
1. double-click on a mail item in Outlook Explorer
2. window opens with my TadxOlForm in it. All good.
3. click 'reply' in the new window -> another Outlook message Window opens (a reply-to window) with another TadxOlForm in it.
4. type in the 'reply-to' text, hit send
5. in TAddInModule.adxOutlookAppEvents1ItemSend I use Self.adxOlFormsManager1.CurrentForm; which points to the previous window, not the one where we clicked 'send'

6. - I am sure I should be using a different way of finding the form that initiated the 'Send' operation. How would you do it? Thank you!


This is the code:

procedure TAddInModule.adxOutlookAppEvents1ItemSend(ASender: TObject;
const Item: IDispatch; var Cancel: WordBool);
var
Mail: MailItem;
activeForm:TadxOlForm;
matter,s,body:string;
begin
// let's tag the email in case user provided a matter number
if Assigned(Item) then
begin
Item.QueryInterface(IID__MailItem, Mail);
if Assigned(Mail) then
try
activeForm:=Self.adxOlFormsManager1.CurrentForm;
if activeForm is TadxOlFormNewMail then
if (activeForm as TadxOlFormNewMail).isEmailTagged then
begin
matter:=(activeForm as TadxOlFormNewMail).ActiveMatter.MatterNum;
body:=Mail.HTMLBody;
// the email might be already tagged - if we are replying to an already tagged email
s:=TClientsDB.FindHiddenMatterNumber(body);
if s=matter then // it is alreadyy tagged the right way, nothing to tag
else
if s='' then // it is not tagged at all, so let's tag it
TClientsDB.HideMatterNumber(matter,body)
else // it is tagged with another matter number
begin
TClientsDB.DeleteAllHiddenMatterNumbers(body);
TClientsDB.HideMatterNumber(matter,body);
end;
Mail.HTMLBody:=body;
end
else
begin
// if the email is a reply to a tagged email, which we don't want tagged anymore, then we are here
// let's strip any potential encoded matter numbers
body:=Mail.HTMLBody;
TClientsDB.DeleteAllHiddenMatterNumbers(body);
Mail.HTMLBody:=body;
end;
finally
Mail := nil;
end;
end;
end;
Posted 04 Jan, 2016 10:35:20 Top
Dmitry Kostochko


Add-in Express team


Posts: 2875
Joined: 2004-04-05
Hi Peter,

You can use the GetForm method to get an instance of your form from a particular Explorer or Inspector window. Please see the code sample below:


procedure TAddInModule.adxOutlookAppEvents1ItemSend(ASender: TObject;
  const Item: IDispatch; var Cancel: WordBool);
var
  CurrentForm: TadxOlForm1;
  IInsp: _Inspector;
begin
  OutputDebugString('+++ ItemSend');

  IInsp := OutlookApp.ActiveInspector();
  if Assigned(IInsp) then
    try
      CurrentForm := adxOlFormsManager1.Items[0].GetForm(IInsp) as TadxOlForm1;
      if Assigned(CurrentForm) then begin
        // TODO
        //OutputDebugString(PChar('+++ ' + CurrentForm.Edit1.Text));
      end;
    finally
      IInsp := nil;
    end;
end;
Posted 05 Jan, 2016 10:06:39 Top
Peter Horak




Posts: 8
Joined: 2015-12-29
I tried it and the "CurrentForm" always gets 'nil'. Is the line:
>>>>> CurrentForm := adxOlFormsManager1.Items[0].GetForm(IInsp) as TadxOlForm; <<<<< correct?
I am using Outlook 2016 and XE10.


procedure TAddInModule.adxOutlookAppEvents1ItemSend(ASender: TObject;
const Item: IDispatch; var Cancel: WordBool);
var
Mail: MailItem;
IInsp: _Inspector;
CurrentForm:TadxOlForm; // I replaced TadxOlForm1 from your example with a class TadxOlForm
matter,s,body:string;
begin
// find a form that initiated the 'Send' operation
IInsp := OutlookApp.ActiveInspector();
if Assigned(IInsp) then
try // >>>>>>>>>>>>>> I am getting here, the 'IInsp' is assigned
CurrentForm := adxOlFormsManager1.Items[0].GetForm(IInsp) as TadxOlForm;
if Assigned(CurrentForm) then // >>>>>>>>>>>>>>>>>>>>>>>>>> this is always 'false'



Thank you.
Posted 07 Jan, 2016 00:01:15 Top
Dmitry Kostochko


Add-in Express team


Posts: 2875
Joined: 2004-04-05
Hi Peter,

I tested my code in Outlook 2016, it worked fine. I have just one item in the FormsManager.Items collection, may it be that you have two or more items and the first one does not relate to Inspector?
Posted 08 Jan, 2016 04:11:56 Top
Peter Horak




Posts: 8
Joined: 2015-12-29
You're right, it was the second item. This code took care of it:

CurrentForm:=nil;
for i:=0 to adxOlFormsManager1.Items.Count-1 do
begin
ci:=adxOlFormsManager1.Items[i];
CurrentForm:=ci.GetForm(IInsp);
if (CurrentForm is TadxOlFormNewMail) then break;
CurrentForm:=nil;
end;

The problem is, that even though an email was sent from Explorer (in Outlook 2016), the OutlookApp.ActiveInspector(); is not 'nil', thus throwing away all my assumptions. You can try by doing 'reply' in an inspector window, but not sending it, then doing a reply in explorer and actually sending that one. My users typically work on like 20 emails at one time ...

I gave up on this approach, and instead discovered the existence of MailItem.UserProperties. Now I am storing any temporary data in an associated mail item's user property, and life is good. I am still learning the Microsoft Office object model. Thank you for ideas!

Btw, how do you post your code to be nicely formatted? My pasted code looks really bad after I publish it.
Posted 09 Jan, 2016 15:22:46 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Peter,

Peter Horak writes:
The problem is, that even though an email was sent from Explorer (in Outlook 2016), the OutlookApp.ActiveInspector(); is not 'nil', thus throwing away all my assumptions. You can try by doing 'reply' in an inspector window, but not sending it, then doing a reply in explorer and actually sending that one. My users typically work on like 20 emails at one time ...


"Reply in explorer" - do you mean responding using an inline response? if so, you can use the Explorer.ActiveInlineResponse property to identify this scenario.

Peter Horak writes:
Btw, how do you post your code to be nicely formatted? My pasted code looks really bad after I publish it.


See the CODE button at the top of the Reply form.


Andrei Smolin
Add-in Express Team Leader
Posted 13 Jan, 2016 04:00:16 Top