【问题标题】:EnumWindows not finding Touch-KeyboardEnumWindows 找不到触摸键盘
【发布时间】:2019-01-06 17:59:40
【问题描述】:

我正在尝试获取屏幕/触摸键盘的 HWND - 出现在屏幕底部的那个。为此,我首先根据名称查找进程 ID,然后执行 EnumWindows 以查看所有窗口并找到其进程 ID 对应于我知道的一个:

doTheThing(int pid)
{
    EnumWindows(new EnumWindowsProc(Report), (IntPtr)pid);
}

protected delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

[DllImport("user32.dll")]
protected static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);

protected static bool Report(IntPtr hwnd, IntPtr lParam)
{
    IntPtr lpdwProcessId;
    GetWindowThreadProcessId(hwnd, out lpdwProcessId);
    if (lpdwProcessId == lParam)
    {
        MessageBox.Show("True: " + hwnd.ToString());
        return false;
    }
    return true;
}

现在 Report 被调用了几次,但事情从未真正匹配。如果我采用另一个进程,它可以工作,但似乎 OnScreenkeyboard "System.Diagnostics.Process (WindowsInternal.ComposableShell.Experiences.TextInput.InputApp)" 没有出现在 EnumWindows 中。

使用 FindWindow 不起作用,因为窗口没有 Title 并且它的类是通用 ApplicationFrameHost。

在 AHK 中,我可以通过使用 MouseGetPos,,, WinUMID 将鼠标悬停在键盘上来获得 HWND,因此肯定存在 HWND。

EnumWindows 是否有可能忽略某些窗口?如果是这样,我该如何防止这种情况?还有哪些其他解决方案?

作为旁注,它也不会显示在 UI 自动化验证工具中。

注意:Windows 现在显然有两个键盘。我的意思是你可以通过任务栏打开的那个。

澄清我为什么需要这个:

我有以下 AHK 脚本,可以使我将鼠标指向窗口的窗口半透明:

MouseGetPos,,, WinUMID
WinSet, Transparent, 100, ahk_id %WinUMID%

我注意到,当我将它指向触控键盘时,它会使其变得透明,即使键盘消失,这种效果仍然存在,直到我重新启动系统。如果我保存 WinUMID 变量,我什至可以在不使用键盘时更改透明度。

现在我想在 C# 中使键盘半透明,只要我提供 HWND 就可以了。但是如果没有 AHK 的帮助,我无法想出在 C# 中获取 HWND 的方法。

process.MainWindowHandle 返回 0。

我也试过了

ProcessThreadCollection threads = process.Threads;
foreach (ProcessThread thread in threads)
{
    EnumThreadWindows((uint)thread.Id, new EnumThreadDelegate(EnumThreadCallback), IntPtr.Zero);
}

[DllImport("user32.dll")]
static extern bool EnumThreadWindows(uint dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

protected delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam);

protected static bool EnumThreadCallback(IntPtr hwnd, IntPtr lParam)
{
    MessageBox.Show("Try");
    IntPtr lpdwProcessId;
    GetWindowThreadProcessId(hwnd, out lpdwProcessId);
    if (lpdwProcessId == lParam)
    {
        MessageBox.Show("True: " + hwnd.ToString());
        makeTransparent(lParam);
        return false;
    } else
        MessageBox.Show("False: " + hwnd.ToString());
    return true;
}

EnumThreadCallback 从未被调用过,即使它适用于任何其他进程。

编辑:

我发现键盘进程实际上并没有创建键盘。相反,键盘 UI 似乎是由资源管理器创建的。

以下代码确实有效:

Process[] processes = Process.GetProcesses();

IntPtr hWnd = IntPtr.Zero;
while ((hWnd = FindWindowEx(IntPtr.Zero, hWnd, "ApplicationFrameWindow", null)) != IntPtr.Zero)
{
    IntPtr lpdwProcessId;
    GetWindowThreadProcessId(hWnd, out lpdwProcessId);
    foreach (Process process in processes)
    {
        if (process.ToString() == "System.Diagnostics.Process (explorer)")
        {
            if (process.Id == (int)lpdwProcessId)
            {
                doThing(hWnd);
            }
        }
    }
}

但是,使用了多个 hWnd,其中只有一个属于键盘。现在我需要找出如何过滤掉这个特定的。 目前这种方法似乎没有缺点,但在不知道它是否会因此产生任何不利影响的情况下发布它,我感到不舒服。 受害者 1:新的粘贴窗口。

【问题讨论】:

标签: c# .net


【解决方案1】:

试试这个替代解决方案:

var process = Process.GetProcessById(pid);
IntPtr hwnd = process.MainWindowHandle;

【讨论】:

  • process.ToString() 返回正确的名称 (System.Diagnostics.Process (WindowsInternal.ComposableShell.Experiences.TextInput.InputApp)),但 hwnd 是 0
  • 它可能是一个拥有的窗口。查询方法见stackoverflow.com/a/22177830/324260
  • @ EnumThreadWindows 不调用任何东西。我会用这些信息更新我的问题。
猜你喜欢
  • 2011-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 2018-07-13
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
相关资源
最近更新 更多