65.9K
CodeProject 正在变化。 阅读更多。
Home

其他进程中的焦点控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (5投票s)

2009 年 4 月 1 日

CPOL

1分钟阅读

viewsIcon

57489

downloadIcon

1787

检索其他应用程序中具有焦点的控件的 hWnd。

FocusedControlInOtherProcess

引言

本文将介绍如何通过简单地将焦点设置在其上,来检索任何 Windows 应用程序中任何可聚焦控件的唯一句柄。我们将通过一系列 P/Invoke 调用到 user32.dll 中的 Win32 API 来实现这一点。

背景

使用 Win32 API 函数 GetFocus 的人可能已经注意到,它只会返回自身应用程序中控件的句柄(hWnd),并且如果您尝试在另一个进程中设置焦点,您将得到 NULL。这是因为 GetFocus 仅返回当前线程消息队列中具有键盘焦点的窗口。由于我们的应用程序不在同一个线程中,您将无法获得任何信息。

使用代码

要获取另一个进程中当前具有焦点的控件的 hWnd,我们可以使用 AttachThreadInput 函数将我们的线程消息队列附加到另一个线程中的窗口。

操作方法如下:

  1. 使用 GetForegroundWindow 函数获取用户当前正在使用的窗口。
  2. 使用 GetWindowThreadProcessId 函数获取该窗口和您的窗口的 ID。
  3. 使用 AttachThreadInput 函数临时将您的线程消息队列与拥有另一个窗口的线程关联起来。
  4. 使用 GetFocus 函数获取 hWnd
  5. 再次使用 AttachThreadInput 函数断开与另一个线程的连接。
using System.Runtime.InteropServices;

public partial class FormMain : Form
{
    [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 FormMain()
    {
        InitializeComponent();
    }

    private void timerUpdate_Tick(object sender, EventArgs e)
    {
        labelHandle.Text = "hWnd: " + 
                           FocusedControlInActiveWindow().ToString();
    }

    private IntPtr FocusedControlInActiveWindow()
    {
        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;
    }
}

代码要求,可以使用 Visual Studio 设计器完成

  • 添加一个名为 timerUpdate 的计时器,并将 timerUpdate_Tick 方法添加到 Tick 事件中。将 Interval 设置为 100,将 Enabled 设置为 true
  • 向窗体添加一个名为 labelHandleLabel
  • FormMainTopMost 属性设置为 true

历史

  • 1.0 (2009 年 4 月 1 日) - 初始版本。
© . All rights reserved.