Posts 1 - 10 of 11
First | Prev. | 1 2 | Next | Last
|
|
Steve Faleiro
Posts: 15
Joined: 2024-09-12
|
Using: Delphi 10.2 Tokyo, Add-in Express for Office and VCL 10.1.1705, Outlook 2024
I need the task pane to appear in Explorer mail item view, as well as in the mail Inspector window, independent of each other ie. separate instances of the same class.
Is it possible?
Background:
I created an addin for Outlook using the wizard and chose to add a task pane. As a result, the project got a unit and designer file (pas and dfm files) for the task pane. Also, in the property inspector of the addin module designer, there is a property TaskPanes, which is a list, and in that list there is one task pane (Type = TadxCustomTaskPane), for which I have set the Title property. It also has a set property: OutlookWindows with options to select the values olExplorers and olInspectors.
I developed and tested the addin in a mail item inspector, and so i set olInspectors to True, and left olExplorers as False.
I added controls and code as needed to the task pane, and its working correctly in mail inspector windows.
Now I have a requirement to also show the task pane in Explorer view. My addin reads the email contacts (sender, recipients) and does some processing with those (eg. sending them to an external API). So far it is working correctly when the task pane loads in mail Inspector windows.
But I am facing difficulties if I show the task pane in Explorer mail views (by setting olExplorers = True).
These are:
1. Access violation when starting Outlook.
Access violation at address 0000000000406D92 in module 'myaddin.dll'. Read of address FFFFFFFFFFFFFFFF.
2. When Outlook does start, the task pane works in the mail Inspector windows, but it is static and does not run the code from the task pane unit in the Explorer mail views. That code is launched from 'ActiveFormCreate' event of the task pane, and it relates to getting the email contact list of the selected email.
This is my current code:
1. In Addin module
In the class definition:
public
FInspectorMailItem: TMailItem;
FExplorerMailItem: TMailItem;
Event handlers:
procedure TAddInModule.adxCOMAddInModuleAddInBeginShutdown(Sender: TObject);
begin
if Assigned(FInspectorMailItem) then
begin
FInspectorMailItem.Disconnect();
FreeAndNil(FInspectorMailItem);
end;
if Assigned(FExplorerMailItem) then
begin
FExplorerMailItem.Disconnect();
FreeAndNil(FExplorerMailItem);
end;
end;
procedure TAddInModule.adxCOMAddInModuleOLExplorerSelectionChange(Sender: TObject);
var
Sel: Selection;
imail: _MailItem;
mailitem: TMailItem;
savedemail: Boolean;
begin
if Assigned(FExplorerMailItem) then
begin
FExplorerMailItem.Disconnect();
FreeAndNil(FExplorerMailItem);
end;
// Show task pane only when opening an existing email
try
Sel := OutlookApp.ActiveExplorer.Selection;
except
Sel := nil;
end;
if Assigned(Sel) then
begin
if Sel.Count >= 1 then
begin
Sel.Item(1).QueryInterface(IID__MailItem, imail);
if (Assigned(imail)) then
begin
FExplorerMailItem := TMailItem.Create(Self);
FExplorerMailItem.Tag := 1;
FExplorerMailItem.ConnectTo(imail);
savedemail := (FExplorerMailItem.EntryID <> EmptyStr);
imail := nil;
end;
end;
end;
adxclsMyAddin.TaskPanes[0].Visible := savedemail;
end;
procedure TAddInModule.adxCOMAddInModuleOLNewInspector(ASender: TObject; const Inspector: _Inspector);
var
imail: _MailItem;
mailitem: TMailItem;
savedemail: Boolean;
begin
if Assigned(FInspectorMailItem) then
begin
FInspectorMailItem.Disconnect();
FreeAndNil(FInspectorMailItem);
end;
// Show task pane only when opening an existing email
Inspector.CurrentItem.QueryInterface(IID__MailItem, imail);
if (Assigned(imail)) then
begin
FInspectorMailItem := TMailItem.Create(Self);
FInspectorMailItem.Tag := 2;
FInspectorMailItem.ConnectTo(imail);
savedemail := (FInspectorMailItem.EntryID <> EmptyStr);
imail := nil;
end;
adxclsMyAddin.TaskPanes[0].Visible := savedemail;
end;
2. In task pane module 'OnCreate' event (in the code it is named as 'ActiveFormCreate')
var
mailitm: TMailItem;
c: Integer;
begin
if (Assigned(adxclsMyAddin.FInspectorMailItem)) then
mailitm := adxclsMyAddin.FInspectorMailItem
else if (Assigned(adxclsMyAddin.FExplorerMailItem)) then
mailitm := adxclsMyAddin.FExplorerMailItem;
...
...
then I use mailitm to get the Sender and Recipients names and email addresses.
I guess that the code in 'OnCreate' is incorrect in the way that it gets the mailitm, because a mail Inspector can be open, and the user can also select mail items in the explorer view. I'm not sure how to handle that.
What I need is this:
The task pane should work as it is currently working in the mail Inspector windows, and it should also work in the Explorer view when the user selects different emails, it should refresh the task pane that is displayed on the right side, by running code in the task panes unit (it can be OnCreate or any other public method), which will read the contacts from the selected email and populate a list control in the task pane.
Please tell me what changes I need to make so that it works correctly.
Thanks in advance. |
|
Posted 10 Oct, 2024 21:07:29
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 19041
Joined: 2006-05-11
|
Hello Steve,
Steve Faleiro writes:
I need the task pane to appear in Explorer mail item view, as well as in the mail Inspector window, independent of each other ie. separate instances of the same class.
You can have different panes showing instances of the same (or different) UserControl; the UserControl instances can reflect the state of a class (a single instance or multiple instances).
Regards from Poland (GMT+2),
Andrei Smolin
Add-in Express Team Leader |
|
Posted 14 Oct, 2024 08:48:35
|
|
Top
|
|
Steve Faleiro
Posts: 15
Joined: 2024-09-12
|
Hi Andrei,
You can have different panes showing instances of the same (or different) UserControl; the UserControl instances can reflect the state of a class (a single instance or multiple instances).
Thanks for this. I've started over by creating a new add-in, and added 2 task panes - one for Explorer window, and one for Inspector windows. Then I created a frame control with my required user interface controls and added it to both of the task panes. Next, I have code in the add-in module, that selectively shows or hides the task pane depending on whether the active mail item is an existing email or not (it new email in compose or reply mode). Its the next bit that I'm not able to figure out - I'm unable to access the selected mail item from the task pane. It gives an access violation.
Here is my current code:
public
FInspectorMailItem: TMailItem;
FExplorerMailItem: TMailItem;
FInspectorMailItemFlag: Boolean;
FExplorerMailItemFlag: Boolean;
..
uses
coTaskPane_Inspector, coTaskPane_Explorer;
..
procedure TAddInModule.adxCOMAddInModuleAddInBeginShutdown(Sender: TObject);
begin
if Assigned(FInspectorMailItem) then
begin
FInspectorMailItem.Disconnect();
FreeAndNil(FInspectorMailItem);
end;
if Assigned(FExplorerMailItem) then
begin
FExplorerMailItem.Disconnect();
FreeAndNil(FExplorerMailItem);
end;
end;
procedure TAddInModule.adxCOMAddInModuleOLExplorerSelectionChange(Sender: TObject);
var
Sel: Selection;
imail: _MailItem;
mailitem: TMailItem;
savedemail: Boolean;
begin
if Assigned(FExplorerMailItem) then
begin
FExplorerMailItem.Disconnect();
FreeAndNil(FExplorerMailItem);
end;
// Show task pane only when opening an existing email
try
Sel := OutlookApp.ActiveExplorer.Selection;
except
Sel := nil;
end;
if Assigned(Sel) then
begin
if Sel.Count >= 1 then
begin
Sel.Item(1).QueryInterface(IID__MailItem, imail);
if (Assigned(imail)) then
begin
FExplorerMailItem := TMailItem.Create(Self);
FExplorerMailItem.Tag := 1;
FExplorerMailItem.ConnectTo(imail);
savedemail := (FExplorerMailItem.EntryID <> EmptyStr);
imail := nil;
if (savedemail) then
begin
adxcoOutlookMailChimpAddin.TaskPanes[1].Visible := True;
TcoTaskPane_Explorer(adxcoOutlookMailChimpAddin.TaskPanes[1]).LoadContacts(FExplorerMailItem);
end;
end;
end;
end;
end;
..
TAPIContact = record
ContactName: String;
ContactEmailAddr: String;
end;
TAPIContactArray = array of TAPIContact;
..
procedure TcoTaskPane_Explorer.LoadContacts(AMailItem: TMailItem);
var
FContactArray: TAPIContactArray;
c: Integer;
begin
if (AMailItem = nil) then
Exit;
SetLength(AAPIContactArray, 0);
SetLength(AAPIContactArray, AMailItem.Recipients.Count + 1);
// Sender
// AAPIContactArray[0].ContactEmailAddr := (OleVariant(adxclsOutlookMailChimpAddin.FInspectorMailItem.DefaultInterface)).SenderEmailAddress;
AAPIContactArray[0].ContactEmailAddr := (OleVariant(AMailItem.DefaultInterface)).SenderEmailAddress;
AAPIContactArray[0].ContactName := AMailItem.SenderName;
// Recipient
for c := 1 to AMailItem.Recipients.Count do
begin
AAPIContactArray[c].ContactEmailAddr := AMailItem.Recipients.Item(c).Address;
AAPIContactArray[c].ContactName := AMailItem.Recipients.Item(c).Name;
end;
LoadContacts(FExplorerMailItem); causes an access violation when trying to access AMailItem.
How can I access AMailItem in the task pane unit? Or is there some other way to do this?
Thanks in advance. |
|
Posted 18 Oct, 2024 01:14:23
|
|
Top
|
|
Steve Faleiro
Posts: 15
Joined: 2024-09-12
|
**Please ignore duplicate message** |
|
Posted 18 Oct, 2024 01:16:11
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 19041
Joined: 2006-05-11
|
|
Posted 18 Oct, 2024 12:58:05
|
|
Top
|
|
Steve Faleiro
Posts: 15
Joined: 2024-09-12
|
Hi Andrei,
I updated my code as per your example, but I get an access violation. Please see the code below:
procedure TAddInModule.adxCOMAddInModuleOLExplorerSelectionChange(Sender: TObject);
var
Sel: Selection;
imail: _MailItem;
mailitem: TMailItem;
savedemail: Boolean;
CTP: TadxCustomTaskPane;
Instance: TadxCustomTaskPaneInstance;
Form: IcoTaskPane_Explorer;
begin
if Assigned(FExplorerMailItem) then
begin
FExplorerMailItem.Disconnect();
FreeAndNil(FExplorerMailItem);
end;
// Show task pane only when opening an existing email
try
Sel := OutlookApp.ActiveExplorer.Selection;
except
Sel := nil;
end;
if Assigned(Sel) then
begin
if Sel.Count >= 1 then
begin
Sel.Item(1).QueryInterface(IID__MailItem, imail);
if (Assigned(imail)) then
begin
FExplorerMailItem := TMailItem.Create(Self);
FExplorerMailItem.Tag := 1;
FExplorerMailItem.ConnectTo(imail);
savedemail := (FExplorerMailItem.EntryID <> EmptyStr);
imail := nil;
if (savedemail) then
begin
adxcoOutlookMailChimpAddin.TaskPanes[1].Visible := True;
// TcoTaskPane_Explorer(adxcoOutlookMailChimpAddin.TaskPanes[1]).LoadContacts(FExplorerMailItem);
CTP := Self.TaskPanes[1];
Instance := CTP.Instances.Items[OutlookApp.ActiveWindow()];
Form := Instance.Control as IcoTaskPane_Explorer; // <---------- AV on this line
TcoTaskPane_Explorer(Form).LoadContacts(FExplorerMailItem);
end;
end;
end;
end;
end;
|
|
Posted 18 Oct, 2024 14:00:54
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 19041
Joined: 2006-05-11
|
Hello Steve,
Steve Faleiro writes:
Instance := CTP.Instances.Items[OutlookApp.ActiveWindow()];
Is Instance nil?
Regards from Poland (GMT+2),
Andrei Smolin
Add-in Express Team Leader |
|
Posted 18 Oct, 2024 15:35:11
|
|
Top
|
|
Steve Faleiro
Posts: 15
Joined: 2024-09-12
|
Yes, Instance is nil.
if (savedemail) then
begin
adxcoOutlookMailChimpAddin.TaskPanes[1].Visible := True;
// TcoTaskPane_Explorer(adxcoOutlookMailChimpAddin.TaskPanes[1]).LoadContacts(FExplorerMailItem);
CTP := Self.TaskPanes[1];
Instance := CTP.Instances.Items[OutlookApp.ActiveWindow()];
if(Instance = nil) then
Showmessage('Instance is nil');
Form := Instance.Control as IcoTaskPane_Explorer; // <---------- AV on this line
TcoTaskPane_Explorer(Form).LoadContacts(FExplorerMailItem);
end;
|
|
Posted 18 Oct, 2024 16:01:28
|
|
Top
|
|
Andrei Smolin
Add-in Express team
Posts: 19041
Joined: 2006-05-11
|
Does this occur at startup? Or, maybe, after you switch to a folder?
If so, create a test button to check if the task pane instance exists and to invoke LoadContacts(). Start Outlook and click the button. If this works, introduce a small delay - e.g. 100-300 ms (but do not suspend the main thread!) - before invoking LoadContacts().
Regards from Poland (GMT+2),
Andrei Smolin
Add-in Express Team Leader |
|
Posted 18 Oct, 2024 16:17:01
|
|
Top
|
|
Steve Faleiro
Posts: 15
Joined: 2024-09-12
|
Hi Andrei,
Yes, this occurs at startup. Adding a TTimer to introduce a delay (500ms) solves the problem.
Thank you. |
|
Posted 18 Oct, 2024 17:20:00
|
|
Top
|
|
Posts 1 - 10 of 11
First | Prev. | 1 2 | Next | Last
|