如何在C#中从控制台窗口返回焦点?

7

我有一个C#控制台应用程序(A),它在黑色Windows控制台中打开。有时在启动时,它会从另一个需要焦点的程序(B)那里窃取焦点。

问题:如何将焦点从A.exe返回给B.exe

A -> Focus -> B


详情:

  • 程序 B 不是我的,我对它无能为力。它有一个图形用户界面、多个窗口和其中一个需要焦点(可能是模态对话框窗口)。
  • 程序 A 不需要任何焦点,也不以任何方式与程序 B 交互。
  • 程序 A 通过启动快捷方式启动,并基本上在后台运行(它已发布但仍在开发中,这就是为什么有控制台窗口的原因)。
  • 我有几分钟的时间来检查并将焦点返回。

一个程序如果没有被聚焦就无法正常运行,那么它就是不好的。我知道这不是你的错。最简单的解决方案是:在另一个程序完成之前不要运行你的应用程序,或者干脆不给你的应用程序任何界面。 - Andrew Barber
你的控制台程序如何知道何时需要将焦点放在它上面?如果你有一些需要检查的东西,你不需要让你的控制台应用程序保持焦点。 - Tarec
@Tarec 我记得可以通过.NET Framework、WinApi或两者结合的方式以各种方式操作控制台窗口。 - Bitterblue
2个回答

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
这可能回答了问题,但它忽略了真正的问题。如果你不想被关注,就不要一开始就去偷东西。这很容易做到。 - David Heffernan
没问题,我曾经遇到过需要控制窗口焦点的情况,这在许多场合对我非常有用。很高兴能帮忙! - phcoding
@DavidHeffernan:如何避免窃取焦点?请参见http://stackoverflow.com/questions/41272078/changing-the-focus-back-to-the-console-window - Lehs
似乎在W10中,它只有在窗口最小化时才能工作。 如果窗口可见但未“聚焦”,则应用程序会在任务栏中“闪烁”。 - ManWithNoName

3
为了在您当前运行的C#控制台应用程序中实现此操作...
[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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接