Я пытаюсь исправить проблему, с которой мы сталкиваемся с Onscreenkeyboard в нашем приложении C # Prism WPF для таргетинга приложений .Net 4.5.2, развернутого через ClickOnce, работающего в Windows 10 версии 1803.
Наше приложение имеет функцию TimeOut, которая запускает событие, и в этом случае я хотел бы либо переключить видимость клавиатуры, либо закрыть ее, если она открыта. Функция Close () в нижеприведенном классе не работает иногда, я вижу в журналах (не отображается в нижнем коде) приложение находит дескриптор (который есть> 0) и выдает команду закрытия на нем, но клавиатура не закрывается.
Этот вопрос связан с двумя вопросами, упомянутыми и приведенными ниже! Но я не могу комментировать, поэтому я должен задать новый вопрос.
У нас было какое-то рабочее решение в версии 1709, как было предложено в разделе « Определить, является ли сенсорная клавиатура Windows 10 видимой или скрытой»
Теперь я пытаюсь внедрить последнее сообщение в этом вопросе, чтобы иметь возможность переключать видимость клавиатуры на тайм-аут или закрытое приложение, если оно обнаруживает открытую клавиатуру, я пытаюсь объединить ее с классом клавиатуры, который вы видите ниже, но У меня проблемы с этим.
Таким образом, у нас есть класс touchkeyboard, объединенный с вышеуказанным сообщением и сенсорной клавиатурой Show (TabTip.exe) в выпуске Windows 10 Anniversary :
static class TouchKeyboard
{
private static void StartTabTip()
{
var p = Process.Start(@"C:Program FilesCommon FilesMicrosoft SharedinkTabTip.exe");
int handle = 0;
while ((handle = NativeMethods.FindWindow("IPTIP_Main_Window", "")) <= 0)
{
Thread.Sleep(100);
}
}
public static void ToggleVisibility()
{
var type = Type.GetTypeFromCLSID(Guid.Parse("4ce576fa-83dc-4F88-951c-9d0782b4e376"));
var instance = (ITipInvocation)Activator.CreateInstance(type);
instance.Toggle(NativeMethods.GetDesktopWindow());
Marshal.ReleaseComObject(instance);
}
public static void Show()
{
int handle = NativeMethods.FindWindow("IPTIP_Main_Window", "");
if (handle <= 0) // nothing found
{
StartTabTip();
Thread.Sleep(100);
}
// on some devices starting TabTip don't show keyboard, on some does ?\_(?)_/?
if (!IsOpen())
{
ToggleVisibility();
}
}
public static void Hide()
{
if (IsOpen())
{
ToggleVisibility();
}
}
public static bool Close()
{
// find it
int handle = NativeMethods.FindWindow("IPTIP_Main_Window", "");
bool active = handle > 0;
if (active)
{
// don't check style - just close
NativeMethods.SendMessage(handle, NativeMethods.WM_SYSCOMMAND, NativeMethods.SC_CLOSE, 0);
}
return active;
}
public static bool GetIsOpen()
{
return GetIsOpen1709() ?? GetIsOpenLegacy();
}
private static bool? GetIsOpen1709()
{
var parent = IntPtr.Zero;
for (;;)
{
parent = FindWindowEx(IntPtr.Zero, parent, WindowParentClass1709);
if (parent == IntPtr.Zero)
return null; // no more windows, keyboard state is unknown
// if it's a child of a WindowParentClass1709 window - the keyboard is open
var wnd = FindWindowEx(parent, IntPtr.Zero, WindowClass1709, WindowCaption1709);
if (wnd != IntPtr.Zero)
return true;
}
}
private static bool GetIsOpenLegacy()
{
var wnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, WindowClass);
if (wnd == IntPtr.Zero)
return false;
var style = GetWindowStyle(wnd);
return style.HasFlag(WindowStyle.Visible)
&& !style.HasFlag(WindowStyle.Disabled);
}
private const string WindowClass = "IPTip_Main_Window";
private const string WindowParentClass1709 = "ApplicationFrameWindow";
private const string WindowClass1709 = "Windows.UI.Core.CoreWindow";
private const string WindowCaption1709 = "Microsoft Text Input Application";
private enum WindowStyle : uint
{
Disabled = 0x08000000,
Visible = 0x10000000,
}
private static WindowStyle GetWindowStyle(IntPtr wnd)
{
return (WindowStyle)GetWindowLong(wnd, -16);
}
[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr FindWindowEx(IntPtr parent, IntPtr after, string className, string title = null);
[DllImport("user32.dll", SetLastError = false)]
private static extern uint GetWindowLong(IntPtr wnd, int index);
Это работало достаточно прилично в 1709 году, но уже не в 1803 году, а требование нового клиента - закрывать клавиатуру по таймауту. Итак, теперь я добавил код из последнего сообщения этого вопроса stackoverflow в указанный класс как функцию (я не думаю, что это правильный путь):
static class TouchKeyboard
{
///Above code omitted
public static bool GetIsOpen1803()
{
// do this once:
var brokerClass = new ImmersiveShellBroker();
var broker = (IImmersiveShellBroker)brokerClass;
var ihm = broker.GetInputHostManagerBroker();
Marshal.ReleaseComObject(broker);
// now ihm reference can be cached and used later:
Rect rect;
DisplayMode mode;
ihm.GetIhmLocation(out rect, out mode);
}
[ComImport, Guid("228826af-02e1-4226-a9e0-99a855e455a6")]
class ImmersiveShellBroker
{
}
[ComImport, Guid("9767060c-9476-42e2-8f7b-2f10fd13765c")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IImmersiveShellBroker
{
void Dummy();
IInputHostManagerBroker GetInputHostManagerBroker();
}
[ComImport, Guid("2166ee67-71df-4476-8394-0ced2ed05274")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IInputHostManagerBroker
{
void GetIhmLocation(out Rect rect, out DisplayMode mode);
}
[StructLayout(LayoutKind.Sequential)]
struct Rect
{
public int Left, Top, Right, Bottom;
}
enum DisplayMode
{
NotSupported = 0,
Floating = 2,
Docked = 3,
}
}
Я думаю, что это неправильно, поскольку он не работает все время, когда я вызываю GetIsOpen1803 из вышеупомянутого события таймаута, он иногда возвращает прямоугольник как 0,0,0,0, пока я вижу, что клавиатура встала. В коде говорится, что «делать это только один раз» и «можно кэшировать и использовать позже» в комментариях, но я не могу понять, как это сделать в классе Touchkeyboard, который у нас есть.
До сих пор методы GetIsOpen надежно возвращались, если клавиатура на экране из любого места приложения и возможность закрыть ее ускользает от меня. Даже завершение всего процесса обработки tabtip не всегда закрывает клавиатуру! Единственное, что работает, это прекращение службы, но я не могу этого сделать из-за повышенных привилегий.
Итак, что бы в действительности сделать мой день, это найти надежный способ увидеть, открыта ли клавиатура для всех версий Windows 10 и надежный способ ее закрыть или переключить ее видимость (если есть!)
Любая помощь будет принята с благодарностью!