如何确定应用程序的控制台窗口何时获得或失去焦点?

时间:2014-06-05 22:00:06

标签: c# .net console

有一种简单的方法吗? 或者至少检查控制台当前是否处于焦点位置?

想象一下像游戏这样的东西(不是这里的情况,但类比仍然存在) - 如果它可以自动暂停会很有用。我需要类似的东西。

2 个答案:

答案 0 :(得分:4)

如果您感兴趣的窗口不是控制台窗口,只需点击相应的焦点事件就可以非常简单。但是控制台窗口没有焦点事件,所以这里没有简单的出路。

您可以做的是设置一个事件处理程序来接收UI自动化服务生成的WinEvents。窗口焦点改变时会生成一个事件;您可以获得新聚焦窗口的HWND并将其与控制台窗口的HWND进行比较。如果他们匹配,你就会得到关注;如果他们不这样做,你就没有焦点(要么就是失去它,要么从来没有开始)。

利用UI自动化最方便的方法是通过System.Windows.Automation命名空间。您可以使用AddAutomationFocusChangedEventHandler设置事件处理程序,它将为您提供AutomationFocusChangedEventArgs的实例,您可以从中确定哪个窗口已获得焦点。

以下是一些示例代码:

AutomationFocusChangedEventHandler focusHandler = OnFocusChange;
Automation.AddAutomationFocusChangedEventHandler(focusHandler);
MessageBox.Show("Listening to focus changes");
Automation.RemoveAutomationFocusChangedEventHandler(focusHandler);

其中OnFocusChange是:

void OnFocusChange(object source, AutomationFocusChangedEventArgs e)
{
    var focusedHandle = new IntPtr(AutomationElement.FocusedElement.Current.NativeWindowHandle);
    var myConsoleHandle = Process.GetCurrentProcess().MainWindowHandle;

    if (focusedHandle == myConsoleHandle)
    {
        // ...
    }
}

请注意,我假设控制台是您的过程的简单主窗口;如果不是这样的话,你需要以其他方式获得一个HWND到控制台窗口。

另请注意,为了接收自动化事件,您的进程必须运行消息循环(在本例中也称为“调度程序循环”),而这又需要一个专用于运行它的线程。在上面的示例中,这会在调用MessageBox.Show时自动发生,但在一般情况下,您必须妥善处理它。

答案 1 :(得分:1)

我无法添加评论,因此我只能发布回复。您可以像这样测试DJ KRAZE发布的理论:

    /// <summary>Returns true if the current application has focus, false otherwise</summary>
public static bool ApplicationIsActivated()
{
    var activatedHandle = GetForegroundWindow();
    if (activatedHandle == IntPtr.Zero) {
        return false;       // No window is currently activated
    }else{
Console.WriteLine("Application is focused!"); 
}

    var procId = Process.GetCurrentProcess().Id;
    int activeProcId;
    GetWindowThreadProcessId(activatedHandle, out activeProcId);

    return activeProcId == procId;
}


[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);

因此,如果它没有返回false,那么它将打印&#34;应用程序被聚焦!&#34;在申请中。你可以随时添加一些东西,其中&#34;返回false&#34;是在没有集中注意力的情况下做某事。