How to find out what window has focus

I recently switched to Windows 10, and have found that one really annoying habit it has is that it will randomly switch focus without warning. I can be typing an email, scrolling down through the errors in the event viewer to see what vital parts of Windows crashed today and so on, and suddenly I find that my words are not entered into the email, the events aren’t scrolling, etc.

A quick bit of searching revealed that a lot of people have had the same problem, and very few have managed to solve it. The main problem is finding out what gets the focus.

This issue is very hard to diagnose, partly because it only happens when you are least expecting it. Sometimes it can happen several times in a short space of time, then when you are waiting for it, it doesn’t happen. Putting aside the temptation to think that this is some clever piece of AI that Microsoft included in Windows to annoy you (not beyond the realms of fantasy, given how many other annoying features are in Windows already, and how reluctant Microsoft seem to be to even acknowledge that people might find them annoying), it does seem like a bug (gasp, you don’t mean…).

Being an incurable tinkerer, I decided to see if I could find out what was going on. The Windows API includes a function to get the foreground window, as well as one to get the text of the current window. Armed with some help from a now-extinct blog post (archive can be found here), I came up with the following, rather simple, but effective program…

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Timers;

namespace WhatHasFocus {
  class Program {
    [DllImport("user32.dll")]
    static extern int GetForegroundWindow();

    [DllImport("user32.dll")]
    static extern int GetWindowText(int hWnd, StringBuilder text, int count);

    static void Main(string[] args) {
      Timer timer = new Timer(1000);
      timer.Elapsed += GetActiveWindow;
      timer.AutoReset = true;
      timer.Enabled = true;
      Console.ReadLine();
    }

    private static string lastTitle = "";
    private static int lastHandle;

    private static void GetActiveWindow(object _, ElapsedEventArgs __) {
      const int nChars = 256;
      StringBuilder sb = new StringBuilder(nChars);
      int handle = GetForegroundWindow();
      if (GetWindowText(handle, sb, nChars) > 0) {
        if (handle != lastHandle || sb.ToString() != lastTitle) {
          lastHandle = handle;
          lastTitle = sb.ToString();
          Console.WriteLine($"{DateTime.Now.ToLongTimeString()} ({handle}) {sb}");
        }
      } else {
        if (handle != lastHandle || sb.ToString() != lastTitle) {
          Console.WriteLine($"{DateTime.Now.ToLongTimeString()} (none)");
          lastHandle = handle;
          lastTitle = "";
        }
      }
    }
  }
}

This is just a console application project, using .NET Framework (not Core, although it would probably look the same if you used Core). It checks the current foreground window every second, and it has changed since the last time it reported, it dumps a line into the console window. If there isn’t a current foreground window (say if you click on the desktop), it prints “(none)”. I suspect that’s what I’ll see when the issue next happens.

When you run this, you get a console window that opens, which you can leave running in the background. When your window loses focus, you look in the console window and see what got it. In theory, this should give you a clue as to what’s going on…

In practice, I strongly suspect it won’t help, but it was fun to write!

Predictably, since I set it running, I haven’t encountered the issue. Maybe that’s the answer!

2 Comments

  1. Bennett said:

    Not being a programmer, I don’t know how to compile this so I can run it. How do I go about that?
    Thanks.

    October 10, 2023
    Reply
    • Avrohom Yisroel Silver said:

      You’d need to have Visual Studio installed, and create a new console application.

      Then copy the code into your main class and run it. Should just work!

      October 10, 2023
      Reply

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.