我正在使用WPF / C#应用程序来填写表单。我试图找到一种方法来确定TapTip键盘(用于Windows 8桌面的TabTip.exe /类似地铁的键盘)是否在Windows 8中最小化/不可见。
我已经能够检测到osk键盘(osk.exe / windows可访问性屏幕键盘)是否被最小化,但是相同的过程似乎不适用于TabTip键盘。
检测键盘是否最小化I:
1.找到键盘的过程
2.获取MainWindowHandle
3.使用WINDOWPLACEMENT的showCmd属性(使用MainWindowHandle找到)
4.使用showCmd值确定窗口是否最小化
我遇到的问题是:
- TabTip进程的MainWindowHandle为0(因此我无法使用它来查找WINDOWPLACEMENT信息)
- 当TabTip打开并最小化时,WINDOWPLACEMENT.showCmd的值相同
为了找到TabTip窗口的句柄,我使用ENUMWINDOWS来获取所有窗口句柄,使用GETWINDOWTHREADPROCESSID获取进程ID,然后将id与TabTip进程id进行比较。
任何有关此的帮助将不胜感激。这也是我的第一篇文章。我想我做对了,但如果没有,请告诉我如何解决它。
答案 0 :(得分:12)
在找到一个有效的方法之前,我尝试了几种不同的方法。使用IsWindowVisible()
没有用,我也没有对GetWindowPlacement()
或GetIconic()
感到高兴。最后,我使用了GetWindowLong()
并检查了WS_VISIBLE
的回复情况。一个快速的控制台应用程序演示如下:
using System;
using System.Diagnostics;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Threading;
namespace CSharpTesting
{
class Program
{
/// <summary>
/// The window is initially visible. See http://msdn.microsoft.com/en-gb/library/windows/desktop/ms632600(v=vs.85).aspx.
/// </summary>
public const UInt32 WS_VISIBLE = 0X94000000;
/// <summary>
/// Specifies we wish to retrieve window styles.
/// </summary>
public const int GWL_STYLE = -16;
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
[DllImport("user32.dll", SetLastError = true)]
static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);
static void Main(string[] args)
{
// Crappy loop to poll window state.
while (true)
{
if (IsKeyboardVisible())
{
Console.WriteLine("keyboard is visible");
}
else
{
Console.WriteLine("keyboard is NOT visible");
}
Thread.Sleep(1000);
}
}
/// <summary>
/// Gets the window handler for the virtual keyboard.
/// </summary>
/// <returns>The handle.</returns>
public static IntPtr GetKeyboardWindowHandle()
{
return FindWindow("IPTip_Main_Window", null);
}
/// <summary>
/// Checks to see if the virtual keyboard is visible.
/// </summary>
/// <returns>True if visible.</returns>
public static bool IsKeyboardVisible()
{
IntPtr keyboardHandle = GetKeyboardWindowHandle();
bool visible = false;
if (keyboardHandle != IntPtr.Zero)
{
UInt32 style = GetWindowLong(keyboardHandle, GWL_STYLE);
visible = (style == WS_VISIBLE);
}
return visible;
}
}
}
答案 1 :(得分:1)
如果我没记错的话,TabTip.exe
的窗口类名称为IPTip_Main_Window
。您可以使用Win32 API FindWindow
获取HWND
的{{1}}。这比使用窗口标题更可靠,因为有些窗口可以有空标题(或标题可以更改),因此建议使用。
使用EnumWindows
的当前方法可能存在缺陷,因为单个进程具有许多窗口(或具有子窗口的窗口)。您可以使用TabTip.exe
之类的工具查找所需的实际窗口以及相应的类名。
您仍然可以使用GetWindowHandleThreadProcessId
来检索Spy++
,但我认为您不需要它来进行简单的窗口状态监控。
此外,尝试使用Win32 API而不是CLR中内置的任何API。例如GetWindowPlacement
。
来自MSDN的说明:
此函数检索的WINDOWPLACEMENT的标志成员是 总是零。如果由hWnd参数标识的窗口是 最大化后,showCmd成员为SW_SHOWMAXIMIZED。如果窗口是 最小化,showCmd是SW_SHOWMINIMIZED。否则就是 SW_SHOWNORMAL。
希望有帮助,如果你还需要进一步的帮助,请留下评论,我会在我回到Win8机器后进行编辑。
答案 2 :(得分:1)
这完全有用!
//
// BOOL IsVirtualKeyboardVisible()
//
// Returns TRUE if Virtual Keyboard/Input Pane is visible
// Returns FALSE if Virtual Keyboard/Input Pane is not visible
__declspec(dllexport) BOOL __cdecl IsVirtualKeyboardVisible()
{
BOOL bRet = FALSE;
RECT InputPaneScreenLocation = { 0, 0, 0, 0 };
__try
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
IFrameworkInputPane *IinputPane = NULL;
if (SUCCEEDED(hr))
{
//
// http://msdn.microsoft.com/en-us/library/windows/desktop/hh706967(v=vs.85).aspx
//
hr = CoCreateInstance(__uuidof(FrameworkInputPane), 0, CLSCTX_ALL, __uuidof(IFrameworkInputPane), (LPVOID*)&IinputPane);
IinputPane->Location(&InputPaneScreenLocation);
if (InputPaneScreenLocation.bottom == 0 && InputPaneScreenLocation.left == 0 &&
InputPaneScreenLocation.right == 0 && InputPaneScreenLocation.top == 0)
{
// VKB is not visible
bRet = FALSE;
}
else
{
// VKB is visible
bRet = TRUE;
}
}
} // try
__finally
{
CoUninitialize();
}
return bRet;
}