2014-01-02 4 views
9

Я работаю над приложением WPF/C# для заполнения форм. Я пытаюсь найти способ определить, сглажена ли клавиатура TapTip (клавиатура TabTip.exe/метрополитена для рабочего стола Windows 8)/не видна в окнах 8.Обнаруживать, если экранная клавиатура открыта (TabTip.exe)

Я смог обнаружить, если osk-клавиатура (экранная клавиатура osk.exe/windows) минимизирована, но такой же процесс не работает с клавиатурой TabTip.

Чтобы обнаружить, если клавиатура минимизируется I:
1. Найдите процесс музыкального инструмента
2. Получить MainWindowHandle
3. Используйте свойство showCmd из WINDOWPLACEMENT (найдено с помощью MainWindowHandle)
4. Использование showCmd значение, чтобы определить, если окно свернуто

проблемы я столкнулся являются:
- процесс TabTip имеет MainWindowHandle 0 (так что я не могу использовать его, чтобы найти информацию WINDOWPLACEMENT)
- значения для WINDOWPLACEMENT.showCmd одинаковы, когда TabTip открыто и свести к минимуму

Для того, чтобы найти дескриптор окна TabTip я использовал EnumWindows, чтобы получить все окна ручки, GetWindowThreadProcessId получить идентификаторы процессов, а затем по сравнению идентификаторы идентификатора процесса TabTip.

Любая помощь с этим была бы оценена. Также это мой первый пост. Я думаю, что я сделал это правильно, но если нет, то дайте мне знать, как это исправить.

ответ

0

Если я правильно помню, имя класса окна для TabTip.exe - IPTip_Main_Window. Вы можете использовать Win32 API FindWindow, чтобы получить HWND от TabTip.exe. Это более надежно, чем использование заголовка окна, и рекомендуется, поскольку некоторые окна могут иметь пустые заголовки (или заголовок может измениться).

Ваш текущий подход с использованием EnumWindows может быть испорчен из-за одного процесса, имеющего много окон (или окон с дочерними окнами). Вы можете использовать инструмент, например Spy++, чтобы найти нужное окно и соответствующее имя класса.

Вы можете использовать GetWindowHandleThreadProcessId для получения processID в этот момент, хотя я не думаю, что вам понадобится его для простого мониторинга состояния окна.

Кроме того, попробуйте использовать API Win32 вместо того, что встроено в CLR. Например, GetWindowPlacement.

Примечание от MSDN:

Флагов член WINDOWPLACEMENT извлекается с помощью этой функции является всегда равна нулю. Если окно, идентифицированное параметром hWnd, имеет значение , то элемент showCmd является SW_SHOWMAXIMIZED. Если окно сведено к минимуму, showCmd SW_SHOWMINIMIZED. В противном случае это SW_SHOWNORMAL.

Надеюсь, что это поможет, если вам по-прежнему нужна дополнительная помощь, оставляйте комментарий, и я сделаю редактирование, как только вернусь к своей машине Win8.

+0

Спасибо за быстрый ответ. Я переключился на использование FindWindow, как вы предполагали. Затем я использовал Spy ++, чтобы убедиться, что найдено правильное окно. К сожалению, при использовании GetWindowPlacement showCmd имеет значение 0 (SW_HIDE), когда процесс клавиатуры был убит. Остальное время showCmd имеет значение 1 (SW_NORMAL) независимо от того, было ли оно видимым. Я также попытался использовать GetWindowRect, чтобы увидеть, было ли окно скрыто от экрана. Когда не видно, возвращаемые координаты были такими же, как и последняя видимая позиция на экране. – user

+0

Вы когда-нибудь это выясняли? Я пробовал оба метода и, похоже, не работал. Я думаю, что TabTip.exe - это особый процесс, который связан со службой, поэтому стандартные методы определения того, минимизируется/закрывается ли hwnd, кажется, не работают. – YasharBahman

+0

У меня никогда не было возможности заглянуть в нее дальше, извините! – Erik

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; 
} 
+3

... и почему это работает? Пожалуйста, объясните, почему этот код работает, поскольку это препятствует простому копированию и вставке без полного понимания. OP должен быть в состоянии понять последствия вашего выбора при разработке этого кода и определить, подходит ли этот код для решения задачи. – rayryeng

10

Я пробовал несколько разных методов, прежде чем найти тот, который работает. Использование IsWindowVisible() не помогло, и у меня также не было радости с GetWindowPlacement() или GetIconic(). В конце я использовал GetWindowLong() и проверял на возвращение WS_DISABLED. Быстрое консольное приложение для демонстрации выглядит следующим образом:

using System; 
using System.Diagnostics; 
using Microsoft.Win32; 
using System.Runtime.InteropServices; 
using System.Threading; 

namespace CSharpTesting 
{ 
    class Program 
    { 
     /// <summary> 
     /// The window is disabled. See http://msdn.microsoft.com/en-gb/library/windows/desktop/ms632600(v=vs.85).aspx. 
     /// </summary> 
     public const UInt32 WS_DISABLED = 0x8000000; 
     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; 
     } 
    } 
} 
+0

Это не работает, если экранная клавиатура находится на другом экране, чем там, где находится курсор. Я нахожусь на машине с Windows 10. –

+1

Он не работает после первого входа пользователя в Windows. Он сообщает, что клавиатура видна, когда она отсутствует. Однако, если пользователь открывает клавиатуру вручную, а затем закрывает ее, он начинает правильно сообщать. У кого-нибудь есть исправление для этого? – mikesl

+0

Для меня это то, что работает все время сразу после входа в систему и в другое время: UInt32 WS_VISIBLE = 0X94000000; ... visible = (style == WS_VISIBLE); – mikesl

Смежные вопросы