How to monitor focus changes?
Asked Answered
S

2

11

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?)

Symbol answered 29/7, 2012 at 17:33 Comment(0)
A
21

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);
                }
            }
        }
    }
}
Anomalous answered 29/7, 2012 at 21:4 Comment(5)
wow works great! Just it doesn't detect when the focus changed to Internet Explorer but that's not a problem, I know it's not stealing my focus. Now I'm gonna watch for the bastard which hijacks my focus! mwhahaha... ok a bit overacted. Thanks! But when in internet explorer it even detects each clicked button! NICE.Symbol
Why the using statement for GetProcessById?Hornet
@Hornet because Process is disposable and it is good practice to dispose objects you've created when you are done with them.Anomalous
I want to implement this in a Windows Service (C#) application and send data to a database, but the event isn't triggered. Does anyone know if this is possible? Thanks!Telpher
Gabriel - Windows Services run in their own dedicated session. They cannot interact with processes running under the session that contains the current logged in user. There are strategies to deal with this limitation. Here is a good article that explains all this. codeproject.com/Articles/35773/…Sundin
B
2

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.

Boliviano answered 29/7, 2012 at 18:13 Comment(3)
I have some visualbasic codewhich works: pastebin.com/H7prRMQZ but when changing AppDomain.GetCurrentThreadID() to 0& and runnign the application with administrator right it says that the hook fails. Any ideas on that? If you need the full code: pastebin.com/wj5gFMWsSymbol
You are not close. Wrong hook, wrong module handle, wrong language. Do note the specific warning in my answer about using managed code. If you really want to pursue this then you'll need this: codeproject.com/Articles/18638/…Boliviano
That's a really nice piece of code, unfortunately it only detects when the focus changes to the Global Hooks Test, not any other window (I run it as admin)Symbol

© 2022 - 2024 — McMap. All rights reserved.