Create a new message in Outlook and display as a modal

I need to create and send a message with Outlook from an application. The email form should appear modal, mainly because I am creating an attachment, and should be removed when the user sends (or drops) an email.

My problem is that I am making Outlook a modal modal ("MailIt.Display (True)"), the Outlook message box displayed in the background. The "Outlook.ActiveWindow.Activate" command brings it to the front, but it can be called when the windows are already visible, and so I cannot name it if the window is modal. I tried this code:

MailIt.Display(False);
OleVariant(Outlook.ActiveWindow).Activate;
MailIt.Display(True);

      

But the id doesn't work, if the form already displays it normally, it can't be switched to modal. Any ideas? My environment: Windows 8 (UAC disabled), XE3, Outlook 2010.

Just tried to send my form to the 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 front-end (as I need it), but mine from may become invisible (if there are other applications running with forms open), so it doesn't solve the problem either. It should be Outlook in modal state on top and my app is next to Outlook.

SetWindowPos(AWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE) 

      

Better then HWND_BOTTOM, but Outlook is not guaranteed to be prioritized.

EDITED2. Final (hopefully) event based solution (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;

      

Therefore, it is solved (try # 3). Thank!

+2


source to share


1 answer


If you can't bring Outlook to the front, maybe you can push your own app back by sending a message from the helper thread?



+1


source







All Articles