EnumWindows找不到触摸键盘

时间:2019-01-06 17:59:41

标签: c# .net

我正在尝试获取屏幕/触摸键盘的HWND-出现在屏幕底部的键盘。为此,我首先根据名称查找进程ID,然后执行EnumWindows来浏览所有窗口,并找到一个其进程ID与我所知道的进程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无效,因为窗口没有标题,并且其类是通用ApplicationFrameHost。

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

EnumWindows是否有可能忽略某些窗口?如果是这样,我该如何预防呢?还有什么其他解决方案?

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

注意: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从未被调用,即使它适用于任何其他进程。

编辑:

我发现Keyboard进程实际上不是在创建Keyboard。相反,似乎键盘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:新的粘贴窗口。

1 个答案:

答案 0 :(得分:0)

尝试以下替代解决方案:

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