Search code examples
c#pinvokeglobalwindow-handles

How do you retrieve inner window handles in chrome/firefox + applications outside of yours?


There are a few PInvoke functions out there for grabbing window handles, but how do you grab the exact window handle that is in use: for example the richTextBox1 window within an app? or a Notepad.exe's textbox handle? Also text on webpages in chrome/firefox.

An example that grabs all three would be bad ass... most appreciated would be within Google Chrome or Firefox: whether it be textboxes or right on the PAGE.

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

that works for windows within the application itself, but it failed in notepad & in chrome


Solution

  • As you said, GetFocus only works for window handles managed by the current thread's message queue. What you need to do is temporarily attach your message queue to another process:

    1. Get the foreground window's handle with GetForegroundWindow.
    2. Get the thread ID for your thread and the thread that owns the foreground window with GetWindowThreadProcessId.
    3. Attach your message queue to the foreground window's thread with AttachThreadInput.
    4. Call GetFocus which will return window handles from the foreground window's thread.
    5. Disconnect from the foreground window's thread with AttachThreadInput again.

    Something like this:

    using System.Runtime.InteropServices;
    
    public static class WindowUtils {
        [DllImport("user32.dll")]
        static extern IntPtr GetForegroundWindow();
    
        [DllImport("user32.dll")]
        static extern IntPtr GetWindowThreadProcessId(
            IntPtr hWnd,
            IntPtr ProcessId);
    
        [DllImport("user32.dll")]
        static extern IntPtr AttachThreadInput(
            IntPtr idAttach, 
            IntPtr idAttachTo,
            bool fAttach);
    
        [DllImport("user32.dll")]
        static extern IntPtr GetFocus();
    
        public static IntPtr GetFocusedControl() {
            IntPtr activeWindowHandle = GetForegroundWindow();
    
            IntPtr activeWindowThread = 
                GetWindowThreadProcessId(activeWindowHandle, IntPtr.Zero);
            IntPtr thisWindowThread =
                GetWindowThreadProcessId(this.Handle, IntPtr.Zero);
    
            AttachThreadInput(activeWindowThread, thisWindowThread, true);
            IntPtr focusedControlHandle = GetFocus();
            AttachThreadInput(activeWindowThread, thisWindowThread, false);
    
            return focusedControlHandle;
        }
    }
    

    (Source: Control Focus in Other Processes)