0

I've got an app that runs in the system tray to capture keypresses by the user. I'm only concerned with the windows button and F12 combination. When this happens, I'd like to bring a specific app (that's open) to the front, on top of all other windows. I've read a bunch of SO articles and have been able to capture the key combination but am not having luck bringing the app to the front.

MainForm.cs code:

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

[DllImport("user32.dll")]
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

readonly KeyboardHook hook = new KeyboardHook();

public MainForm()
{
    InitializeComponent();
    hook.AutoRepeat = true;
    hook.SetKeys(new KeyCombination(KeysEx.WinLogo | KeysEx.F12));
    hook.Pressed += hook_Pressed;
    hook.Engage();
}

void hook_Pressed(object sender, EventArgs e)
{
    Action a = () =>
    {
        Process[] currentProcess = Process.GetProcessesByName("Whiteboard");

        if (currentProcess.Length > 0)
        {
            IntPtr hWnd = currentProcess[0].MainWindowHandle;

            if (hWnd != IntPtr.Zero)
            {
                SetForegroundWindow(hWnd);
                ShowWindow(hWnd, (int)ShowWindowCommands.SW_MAXIMIZE);
                return;
            }
        }
    };

    Task.Run(a);
}

The KeyboardHook class/project was taken from this Refactorsaurus Rex article and the full source on GitHub.

The ShowWindowCommands class looks like this:

    public static class Enums
{
    public enum ShowWindowCommands : uint
    {
        //Hides the window and activates another window.
        SW_HIDE = 0,

        //Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
        SW_SHOWNORMAL = 1,

        //Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
        SW_NORMAL = 1,

        //Activates the window and displays it as a minimized window.
        SW_SHOWMINIMIZED = 2,

        //Activates the window and displays it as a maximized window.
        SW_SHOWMAXIMIZED = 3,

        //Maximizes the specified window.
        SW_MAXIMIZE = 3,

        //Displays a window in its most recent size and position. This value is similar to <see cref="ShowWindowCommands.SW_SHOWNORMAL"/>, except the window is not activated.
        SW_SHOWNOACTIVATE = 4,

        //Activates the window and displays it in its current size and position.
        SW_SHOW = 5,

        //Minimizes the specified window and activates the next top-level window in the z-order.
        SW_MINIMIZE = 6,

        //Displays the window as a minimized window. This value is similar to <see cref="ShowWindowCommands.SW_SHOWMINIMIZED"/>, except the window is not activated.
        SW_SHOWMINNOACTIVE = 7,

        //Displays the window in its current size and position. This value is similar to <see cref="ShowWindowCommands.SW_SHOW"/>, except the window is not activated.
        SW_SHOWNA = 8,

        //Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
        SW_RESTORE = 9
    }
}

And this was copied from PInvoke.net.

I know it finds the app that I wish to open and it appears to set "focus" to it, but not bring it to the front. Here's an example:

No keypress yet: enter image description here

Key combination is pressed: enter image description here

You can see that one of the small windows has been "moved" to the back but the Whiteboard app remains the same, except it appears to have the focus. So how can I get my app to bring the "Whiteboard" window to be at the front (top-most)?

UPDATE

If I run my app in a normal window state (not minimized to the system tray), then it will bring that window to the front.

Community
  • 1
  • 1
Robert
  • 1,696
  • 3
  • 36
  • 70
  • [`SetForegroundWindow`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx) might not be doing what you think it does (you are not checking return value). Maybe [`SwitchToThisWindow`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633553(v=vs.85).aspx) is more appropriate (see [this](http://stackoverflow.com/a/14965649/1997232) answer). Also read [this](http://stackoverflow.com/q/1544179/1997232). – Sinatr Dec 15 '16 at 13:20
  • 2
    You can bring your own window into the foreground. Another process', no, that needs to follow the rules. Pretty strict ones. Luckily the .NET Framework breaks the rules in [everybody's favorite utility namespace](https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.interaction.appactivate(v=vs.110).aspx). – Hans Passant Dec 15 '16 at 13:49
  • @HansPassant - Thank you for this information. I tried using `AppActivate` but it only flashes the window, it does not bring it to the front. – Robert Dec 15 '16 at 14:54
  • Only other thing I can think of is to indeed bring your own window into the foreground. Now you are the owner and the boss and you can *next* activate the other window. Flashes a bit, keep your window very small. – Hans Passant Dec 15 '16 at 15:01
  • Found the solution with the help of this SO Article http://stackoverflow.com/questions/9235263/move-external-application-to-the-front-of-the-screen – Robert Dec 15 '16 at 16:21

0 Answers0