2

I have not yet been able to see a workable solution for this problem.

I have an external application that launches an outlook compose window, and I want to make sure it always pop up in front. It does not all the time. E.g. if I tab to Outlook and then back to the application and launch the task, it will just blink in the bottom.

I've tried several suggestions with getinspector.Active() etc. but nothing works.

Some sample code:

String address = "someone@example.com";

Outlook.Application oApp = new Outlook.Application();
Outlook._MailItem oMailItem = (Outlook._MailItem)oApp.CreateItem(Outlook.OlItemType.olMailItem);
oMailItem.To = address

oMailItem.Body = "example";  

oMailItem.Display(true); //true = modal which I need for this task, have tried without also.

similar thread but with Delphi code that I do not know how to translate into c#

Community
  • 1
  • 1
Morten_564834
  • 1,479
  • 3
  • 15
  • 26
  • SetForegroundWindow() + [simulating an ALT up](https://stackoverflow.com/a/13881647/68936) worked for me in Outlook 2021 – Jimmy Sep 22 '22 at 18:42

8 Answers8

5

Here's the working code you need. The missing ingredient to bring the window to the foreground is in fact "inspector.Activate()", and you must call this after "mailItem.Display".

var outlookApp = new Microsoft.Office.Interop.Outlook.Application();
MailItem mailItem = outlookApp.CreateItem(OlItemType.olMailItem);
mailItem.Subject = "subject";
var inspector = mailItem.GetInspector; // Force the "HTMLBody" property to be populated with any email signature, so that we can append it to our content.
mailItem.HTMLBody = "My message" + mailItem.HTMLBody;
mailItem.Attachments.Add("attachment.dat", OlAttachmentType.olByValue);
mailItem.Display(false); // Display the email
inspector.Activate(); // Bring the editor to the foreground.
Boinst
  • 3,365
  • 2
  • 38
  • 60
1

This solution sets the Outlook process MainWindow in the foreground, right after calling oMailItem.Display(true).

 [DllImport("User32.dll", SetLastError = true)]
 static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

  oMailItem.Display(true);
  var outlookProcess = Process.GetProcessesByName("OUTLOOK");                  
  IntPtr handle = outlookProcess[0].MainWindowHandle;
  SwitchToThisWindow(handle, true);      

Not gracefull, but it works.

Javert
  • 248
  • 2
  • 7
0

I dont have outlook installed but you could bring the whole outlook window to front if it was minimized:

        [DllImport("user32.dll")]
        private static extern int SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        private const int SW_SHOWNORMAL = 1;
        private const int SW_RESTORE = 9;

        Process proc = Process.GetProcessesByName("spotify").FirstOrDefault();
        if (proc != null)
        {
             ShowWindow(proc.MainWindowHandle, SW_SHOWNORMAL);   // Make the window visible if it was hidden
             ShowWindow(proc.MainWindowHandle, SW_RESTORE);      // Next, restore it if it was minimized
             SetForegroundWindow(proc.MainWindowHandle);         // Finally, activate the window 
        }

SetForegroundWindow: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx

ShowWindow: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx

Lofbergio
  • 26
  • 2
0

Do you have a particular problem translating the sample function from how to make the Outlook Compose window top most??

If you cannot make IOleWindows / AttachThreadInput / SetForegroundWindow work, you can use Redemption (I am its author) and its SafeInspector / SafeInspector.Activate methods. The following VB script will bring the main Outlook window to the foreground:

set App = CreateObject("Outlook.Application")
set sExplorer = CreateObject("Redemption.SafeExplorer")
sExplorer.Item = App.ActiveExplorer
sExplorer.Activate
Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
0

Just to expound @Nonus answer. This works for me. Maximize the outlook window first before calling the Email display function.

    [DllImport("user32.dll")]
    private static extern int SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);   
    private const int SW_SHOWMAXIMIZE = 3; 

    public void Display()
    {
        message = RedemptionLoader.new_SafeMailItem();
        message.Item = mailApp.CreateItem(Outlook.OlItemType.olMailItem);
        Process proc = Process.GetProcessesByName("outlook").FirstOrDefault();
        if (proc != null)
        {
            ShowWindow(proc.MainWindowHandle, SW_SHOWMAXIMIZE);   
            SetForegroundWindow(proc.MainWindowHandle);         
        }

        ((Outlook.MailItem)message.Item).Display(false);    // Show email to user, false = Non-Modal

    }
Ric
  • 11
  • 5
0

I tried using the answer from Boinst, but it failed to bring the new email to the foreground in Outlook was minimized. This seems to work more consistently for me:

MailItem mailItem = applicationOutlook.CreateItem(OlItemType.olMailItem);
mailItem.To = strTo;
mailItem.CC = strCC;
mailItem.Subject = strSubject;
mailItem.HTMLBody = strHtmlBody;

Inspector inspector = mailItem.GetInspector;
inspector.Activate();
inspector.WindowState = OlWindowState.olMinimized;
mailItem.Display(false);
inspector.WindowState = OlWindowState.olNormalWindow;
-1

This cannot, in general, be done. Considered what would happen if two applications both wanted to be topmost at the same time?

See http://blogs.msdn.com/b/oldnewthing/archive/2005/06/07/426294.aspx for a more extensive discussion.

Richard
  • 106,783
  • 21
  • 203
  • 265
-1

try printing something to the debug window before displaying the message:

Set itm = ol.CreateItem(olMailItem)

Set ins = itm.GetInspector

Debug.Print "this makes the window display..."

ins.Activate
ins.WindowState = olNormalWindow
itm.Display