7

I have a C# console application (A) that opens with the black windows console. Sometimes at startup it steals the focus from another program (B) that needs the focus.

Question: How can I give focus back from A.exe to B.exe ?

A -> Focus -> B


Details:
  • Program B is not mine and I can't do anything about it. It has a GUI, multiple windows and 1 of them needs the focus (it might be a modal dialog window).
  • Program A doesn't need any focus and it doesn't interact in any way with program B.
  • Program A starts via Startup shortcut and runs basically in background (it is released but still in development though, that's why console window)
  • I have a few moments/up to minutes to check and give the focus back.
Bitterblue
  • 13,162
  • 17
  • 86
  • 124
  • A program which cannot operate properly without being focused is... bad. Not your fault, I know. Easiest solution: don't run your app until the other is done, or don't give you app any interface at all. – Andrew Barber Apr 01 '14 at 08:04
  • How would your console program know when would you want to get focus on it? And if you have something to check you don't need your console app to be focussed. – Tarec Apr 01 '14 at 08:08
  • @Tarec I remember it is possible to manipulate the console window in all kinds of ways either via .NET Framework, via WinApi or both. – Bitterblue Apr 01 '14 at 08:10

2 Answers2

7
// this should do the trick....

[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr WindowHandle);

public const int SW_RESTORE = 9;

private void FocusProcess(string procName)
{
    Process[] objProcesses = System.Diagnostics.Process.GetProcessesByName(procName);
    if (objProcesses.Length > 0)
    {
        IntPtr hWnd = IntPtr.Zero;
        hWnd = objProcesses[0].MainWindowHandle;
        ShowWindowAsync(new HandleRef(null,hWnd), SW_RESTORE);
        SetForegroundWindow(objProcesses[0].MainWindowHandle);
    }
}
Bitterblue
  • 13,162
  • 17
  • 86
  • 124
phcoding
  • 608
  • 4
  • 16
  • Good, this works! I need to wait for the next startup to check if it solves **my** problem. But it answers the question. Thanks! – Bitterblue Apr 01 '14 at 09:09
  • This might answer the question but it ignores the real problem. If you don't want the focus, don't steal in the first place. Quite easy to do. – David Heffernan Apr 01 '14 at 09:32
  • No problem, I have come across times when I have needed to control focus of windows and this has proved very useful to me on numerous occasion. Glad to help! – phcoding Apr 01 '14 at 09:35
  • @DavidHeffernan: How to avoid stealing focus? See http://stackoverflow.com/questions/41272078/changing-the-focus-back-to-the-console-window – Lehs Dec 21 '16 at 22:00
  • It seems with W10, it works ONLY when the window is minimised. If the window is visible but not "focused", there is a "blink" of the application in the task bar. – ManWithNoName Aug 22 '21 at 11:06
3

To do this for your current running C# Console app...

[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
public const int SW_RESTORE = 9;
static void FocusMe()
{
    string originalTitle = Console.Title;
    string uniqueTitle = Guid.NewGuid().ToString();
    Console.Title = uniqueTitle;
    Thread.Sleep(50);
    IntPtr handle = FindWindowByCaption(IntPtr.Zero, uniqueTitle);

    Console.Title = originalTitle;

    ShowWindowAsync(new HandleRef(null, handle), SW_RESTORE);
    SetForegroundWindow(handle);
}
Gabe Halsmer
  • 808
  • 1
  • 9
  • 18