无法使 GetWindowRect() API 调用正常工作

Cannot Make GetWindowRect() API Call To Work Properly

我需要能够获取 Windows 8.1 屏幕键盘的高度,"TabTip.exe." 目前我已经设法随意打开和关闭它,但现在我还需要得到它的高度,这样我就可以在我的应用程序中补偿它。我在 Window 的最底部附近有 TextBox 控件,它们被键盘遮住了。

所有利用 Win API 调用 "GetWindowRect" 的尝试都失败了。

代码位于 class 定义的开头:

private const string OnScreenKeyboardName = "TabTip";

DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, ref RECT lpRect);

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
   public int Left;        // x position of upper-left corner
   public int Top;         // y position of upper-left corner
   public int Right;       // x position of lower-right corner
   public int Bottom;      // y position of lower-right corner
}

代码放置在 Window 中的事件处理程序之一中:

RECT rct = new RECT();

if (Process.GetProcessesByName(OnScreenKeyboardName).Length > 0)
{
   Process[] Processes = Process.GetProcessesByName(OnScreenKeyboardName);
   foreach (Process pOnScreenKeyboard in Processes)
   {
      if (!GetWindowRect(new HandleRef(this, pOnScreenKeyboard.Handle), ref rct))
      {
         MessageBox.Show("ERROR");
         return;
      }
      MessageBox.Show(rct.ToString());
   }
}

与大多数示例一致,我最初使用对 "FindWindow" 的调用来获取 TabTip.exe Window 的句柄。这似乎有一段时间很好用,但在最近几天突然停止工作,所以我切换到 "Process.FindByName..."

我的测试用例涉及将上面的代码(第二部分)放入 Window 的 "MouseMove" 事件处理程序中。然后我确保屏幕键盘显示,然后我移动鼠标。这会导致事件触发,然后它始终显示 "ERROR" MessageBox,表明 "GetWindowRect" returns false(或有某种错误?

我在 Google 搜索、p/invoke 等方面花费了大量时间。这令人沮丧,因为关于如何正确执行此操作的示例似乎很少。似乎有一些叫做 HandleRef 的新东西(我使用得当吗?- 基本上也没有这方面的例子!!!)

我真的需要让它工作。有人可以告诉我哪里出错了吗?谢谢!

您正在将进程句柄 (pOnScreenKeyboard.Handle) 传递给 GetWindowRect,其中 GetWindowRect 需要 window 句柄 (HWND)。找到进程是不够的 - 一个进程可以创建许多 windows,因此您需要找到屏幕键盘的 window 句柄。您可以尝试使用 pOnScreenKeyboard.MainWindowHandle,但从 this post 开始,您可能会发现它为空。你说你以前有一个使用 FindWindow 的解决方案。我会回到那个并找出它停止工作的原因。