I need to generate and send message with Outlook from application. Mail form should be displayed as modal, mostly because i generate attachment and it should be deleted when user send email (or discard it).
My problem is when i make Outlook dialog modal ("MailIt.Display(True)"), Outlook message window shown in background. Command "Outlook.ActiveWindow.Activate" brings it to front, but it can be called when windows already visible and so i can't call it if window is modal. I tried this code:
MailIt.Display(False);
OleVariant(Outlook.ActiveWindow).Activate;
MailIt.Display(True);
But id doesn't work, if form already displayed it normal mode it can not be switched to modal. Any ideas? My environment: Windows 8 (UAC disabled), XE3, Outlook 2010.
Just tried to send my form into background as suggested by Arioch:
SetWindowPos(AWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
MailIt.Display(AModal);
SetForegroundWindow(AWnd);
In this case Outlook became foreground (as i need it), but my from can became invisible (if there are other running apps with opened forms), so it also doesn't solve the problem. It should be Outlook in modal state on the top and my application is next to Outlook.
SetWindowPos(AWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE)
Better then HWND_BOTTOM, but it is not guaranteed that Outlook became foreground.
EDITED2. Final (hopefully) solution based on events (suggestion from Kobik):
uses
Vcl.OleServer, Winapi.ActiveX;
Type
TOutlookMsgForm = class
private
protected
FOutlook: OutlookApplication;
FMessageSent: Boolean;
procedure OnOpen(ASender: TObject; var Cancel: WordBool);
procedure OnSend(ASender: TObject; var Cancel: WordBool);
function TryDisplayOutlookMail(const AMailTo, ASubject, ABody: string;
const AAttachmentFileNames: array of string; AWnd: HWND; AModal: Boolean): boolean;
property Outlook: OutlookApplication read FOutlook write FOutlook;
property MessageSent: Boolean read FMessageSent write FMessageSent;
public
class function DisplayOutlookMail(const AMailTo, ASubject, ABody: string;
const AAttachmentFileNames: array of string; AWnd: HWND; AModal: Boolean = True): boolean; static;
end;
{ TOutlookMsgForm }
procedure TOutlookMsgForm.OnOpen(ASender: TObject; var Cancel: WordBool);
begin
if (Outlook<>nil) and (Outlook.ActiveWindow<>nil) then
OleVariant(Outlook.ActiveWindow).Activate;
end;
procedure TOutlookMsgForm.OnSend(ASender: TObject; var Cancel: WordBool);
begin
Cancel := False;
MessageSent := True;
end;
function TOutlookMsgForm.TryDisplayOutlookMail(const AMailTo, ASubject, ABody: string;
const AAttachmentFileNames: array of string; AWnd: HWND; AModal: Boolean): boolean;
var
MailIt: MailItem;
Mail: TMailItem;
i: Integer;
begin
MessageSent := False;
try
OleInitialize(nil);
try
Outlook := CoOutlookApplication.Create;
Mail := nil;
try
MailIt := Outlook.CreateItem(olMailItem) as MailItem;
MailIt.To_ := AMailTo;
MailIt.Subject := ASubject;
MailIt.Body := ABody;
for i := Low(AAttachmentFileNames) to High(AAttachmentFileNames) do
MailIt.Attachments.Add(AAttachmentFileNames[i], EmptyParam, EmptyParam, EmptyParam);
Mail := TMailItem.Create(nil);
Mail.ConnectTo(MailIt);
Mail.OnOpen := OnOpen;
Mail.OnSend := OnSend;
MailIt.Display(AModal);
if AModal and (AWnd<>0) then
SetForegroundWindow(AWnd);
Result := true;
finally
FreeandNil(Mail);
MailIt := nil;
Outlook := nil;
end;
finally
OleUnInitialize;
end;
except
Result := False;
end;
end;
So it is solved (try#3). Thanks!