【发布时间】: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:新的粘贴窗口。
【问题讨论】:
-
使用 UI 自动化验证工具 (docs.microsoft.com/en-us/windows/desktop/winauto/…) 获取 HWND,然后找到匹配过程。
-
也许这有帮助? (通过类名找到窗口)stackoverflow.com/a/24890595/7034621