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:
- Get the foreground window's handle with
GetForegroundWindow
.
- Get the thread ID for your thread and the thread that owns the foreground window with
GetWindowThreadProcessId
.
- Attach your message queue to the foreground window's thread with
AttachThreadInput
.
- Call
GetFocus
which will return window handles from the foreground window's thread.
- 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)