无法使 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 的解决方案。我会回到那个并找出它停止工作的原因。
我需要能够获取 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 的解决方案。我会回到那个并找出它停止工作的原因。