0

I am wanting to bring Outlook's main window to the front, from within a VSTO add-in. I tried the approaches described in the various answers to this question, and it just doesn't seem to work, at least for Outlook 2021.

I get the Outlook main window's handle (which I verified using spy++ and appears to be correct), using either

Process.GetProcessesByName("outlook").FirstOrDefault().MainWindowHandle

or

(Globals.ThisAddIn.Application.ActiveExplorer() as IOleWindow).GetWindow()

(both yield the same result).

Then I try to bring the window to the front (probably some redundant calls in there, I was just trying everything I could to get this to work):

ShowWindow(proc.MainWindowHandle, SW_SHOWNORMAL);
ShowWindow(proc.MainWindowHandle, SW_RESTORE);
SetForegroundWindow(proc.MainWindowHandle);
SwitchToThisWindow(proc.MainWindowHandle, true);

What am I doing wrong?

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
Jimmy
  • 5,131
  • 9
  • 55
  • 81

3 Answers3

1

Only the foreground process can set the active window using SetForegroundWindow. To trick Windows into thinking your process is in the foreground, use AttachThreadInput. Here is what I use:

        public static bool ForceForegroundWindow(IntPtr hWnd)
        {
            bool Result = false;
            uint ForegroundThreadID = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
            uint ThisThreadID = GetWindowThreadProcessId(hWnd, IntPtr.Zero);
            if (AttachThreadInput(ThisThreadID, ForegroundThreadID, true))
            { 
                BringWindowToTop(hWnd); 
                SetForegroundWindow(hWnd);
                AttachThreadInput(ThisThreadID, ForegroundThreadID, false);
                Result = (GetForegroundWindow() == hWnd);
            }
            if (!Result)
            {
                int timeout = 0;
                SystemParametersInfo(SPI.SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref timeout, 0);
                int newTimeout = 0;
                SystemParametersInfo(SPI.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref newTimeout, SPIF.SPIF_SENDCHANGE);
                BringWindowToTop(hWnd); 
                SetForegroundWindow(hWnd);
                SystemParametersInfo(SPI.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref timeout, SPIF.SPIF_SENDCHANGE);
                Result = (GetForegroundWindow() == hWnd);
            }
            return Result;
        }
Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
0

All Outlook windows implement the IOleWindow interface which provides methods that allow an application to obtain the handle to the various windows that participate in in-place activation. So, you can use the retrieved window handle for calling Windows API functions such as SetForegroundWindow method which brings the thread that created the specified window into the foreground and activates the window. Also keyboard input is directed to the window, and various visual cues are changed for the user.

Also you may consider calling the Explorer.Activate or Inspector.Activate methods that activate an explorer or inspector window by bringing it to the foreground and setting keyboard focus.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
  • Thanks for the answer. As per the code sample above, I did use IOleWindow to get the window handle; that part works fine. Also, I didn't show it above, but I did try Explorer.Activate(); it doesn't seem to do anything. The code I have above does bring the outlook window to the front if the outlook window is minimized or maximized (SetForegroundWindow() returns 1). But if it is "normal", but behind some other window, then nothing happens (SetForegroundWindow() returns 0). It turns out that simulating ALT click works: https://stackoverflow.com/a/13881647/68936 – Jimmy Sep 22 '22 at 18:40
0

It turns out that the missing piece was simulating an ALT click (just the up part part is sufficient) before calling SetForegroundWindow(). No need to call SwitchToThisWindow().

As a bonus, setting ActiveExplorer().CurrentFolder() = ... reliably scrolls up & down to the selected folder (which it wasn't doing when outlook was not in the foreground).

Jimmy
  • 5,131
  • 9
  • 55
  • 81