简体   繁体   中英

How to monitor focus changes?

Well Sometimes I am typing and very rarely it happens that something steals focus, I read some solution (even a VB watch) but they don't apply to me. Is there any windows-wide 'handle' which handles ANY focus changes?

It doesn't matter in which language, C, C++, VB.NET, C#, Anything .NET or windows related, Batch, PoweShell, VBS Script... As Long as I am able to monitor every focus change and log it into a file/cmd window/visual window.

Something like:

   void event_OnWindowsFocusChange(int OldProcID, int NewProcID);

would be very usefull. Or maybe there are tools for this already (which I can't find?)

One way would be to use the windows UI Automation API. It exposes a global focus changed event. Here is a quick sample I came up with (in C#). Note, you need to add references to UIAutomationClient and UIAutomationTypes.

using System.Windows.Automation;
using System.Diagnostics;

namespace FocusChanged
{
    class Program
    {
        static void Main(string[] args)
        {
            Automation.AddAutomationFocusChangedEventHandler(OnFocusChangedHandler);
            Console.WriteLine("Monitoring... Hit enter to end.");
            Console.ReadLine();
        }

        private static void OnFocusChangedHandler(object src, AutomationFocusChangedEventArgs args)
        {
            Console.WriteLine("Focus changed!");
            AutomationElement element = src as AutomationElement;
            if (element != null)
            {
                string name = element.Current.Name;
                string id = element.Current.AutomationId;
                int processId = element.Current.ProcessId;
                using (Process process = Process.GetProcessById(processId))
                {
                    Console.WriteLine("  Name: {0}, Id: {1}, Process: {2}", name, id, process.ProcessName);
                }
            }
        }
    }
}

You can monitor focus changes with a hook. SetWindowsHookEx(), using the WH_SHELL hook gets it done. The callback gets the HSHELL_WINDOWACTIVATED notification.

This isn't easy to get going, particularly in a managed language since it requires a DLL that can be injected. Nor could you reliably tell the difference between an intended focus change or a process shoved the window and stole the focus. Which Windows tries to prevent but there's a backdoor called AttachThreadInput() that fools that code.

It is never difficult to tell what process does this. After all, it tried to activate one of its windows. Uninstalling that program is the simple and best fix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM