5

Is it possible to set focus on another application's textbox (using its ClassName). I have the window handle as an IntPtr. But just need some guidance as to what functions/APIs are available for this!

Issue is, I use the SetForegroundWindow API to get window focus, but it wouldn't let me send the Ctrl+L keys to focus on the textbox!

Any help would be great!

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Jordan
  • 1,390
  • 2
  • 9
  • 24

1 Answers1

5

...as far as I recall, this is the code I had to use to make that work – and that worked well on my apps, and newer Windows etc.

void SetFocus(IntPtr hwndTarget, string childClassName)
{
    // hwndTarget is the other app's main window 
    // ...
    IntPtr targetThreadID = WindowsAPI.GetWindowThreadProcessId(hwndTarget, IntPtr.Zero); //target thread id
    IntPtr myThreadID = WindowsAPI.GetCurrentThread(); // calling thread id, our thread id
    try
    {
        bool lRet = WindowsAPI.AttachThreadInput(myThreadID, targetThreadID, -1); // attach current thread id to target window

        // if it's not already in the foreground...
        lRet = WindowsAPI.BringWindowToTop(hwndTarget);
        WindowsAPI.SetForegroundWindow(hwndTarget);

        // if you know the child win class name do something like this (enumerate windows using Win API again)...
        var hwndChild = EnumAllWindows(hwndTarget, childClassName).FirstOrDefault();

        if (hwndChild == IntPtr.Zero)
        {
            // or use keyboard etc. to focus, i.e. send keys/input...
            // SendInput (...);
            return;
        }

        // you can use also the edit control's hwnd or some child window (of target) here
        WindowsAPI.SetFocus(hwndChild); // hwndTarget);
    }
    finally
    {
        bool lRet = WindowsAPI.AttachThreadInput(myThreadID, targetThreadID, 0); //detach from foreground window
    }
}

...so something along those lines (it does what you need and in the right order, don't forget to detach etc. – but you'd need to adjust it for your specific conditions, control/edit hwnd etc. – and still you might have other issues related to the target window/app, this works for most, but not in all cases, that's a long story and as I said depends on your specific scenario),

(WindowsAPI are typical P/Invoke wrappers I believe) basically you need to attach to another thread for 'input' operations, I believe this is an official explanation "This also allows threads to share their input states, so they can call the SetFocus function to set the keyboard focus to a window of a different thread." Google for "AttachThreadInput" for more info (to know the reasons), and it's also often associated with the SetFocus and other input/keyboard operations. Also the Automation API could help as suggested – that's the 'cleanest' way to do it – but depends if a target app exposes and handles that properly – which still "isn't there" for most of them, not consistent etc. – if you want to handle your "own application" that's different then, you need to ask yourself what's the best scenario etc. hope this helps

Note: there must be a dozen links to similar solutions (and on SO) as this is quite a known thing, but I'm unable to find a right link

The code is an example for this spec. case and based on working code – but might need testing and working out some details (which seem out of the scope for this question), e.g...
WindowsAPI holds the P/Invoke signatures for Windows API and native calls (similar to MS.Win32.UnsafeNativeMethods) and it's a static class (see that class or https://pinvoke.net/ – also Accessing Microsoft.Win32.UnsafeNativeMethods?), should be named (Safe/Unsafe)NativeMethods (https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2015/code-quality/ca1060-move-p-invokes-to-nativemethods-class) – and also see IntPtr, SafeHandle and HandleRef - Explained (IntPtr is a bit 'old' style)
EnumAllWindows uses EnumChildWindows and GetClassName Win API (and it's for another question I guess) and requires a wrapper method for it to be useful (which EnumAllWindows is – it just enumerates thru windows recursively checking for class names).

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
NSGaga-mostly-inactive
  • 14,052
  • 3
  • 41
  • 51