10

フォームを完成させるための WPF/C# アプリケーションに取り組んでいます。TapTip キーボード (TabTip.exe / windows 8 デスクトップ用のメトロのようなキーボード) が最小化されているか、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 と比較しました。

これについての助けをいただければ幸いです。また、これは私の最初の投稿です。私はこれを正しく行ったと思いますが、そうでない場合は修正方法を教えてください。

4

3 に答える 3

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;
        }
    }
}
于 2014-07-22T14:48:22.200 に答える
2

これは完全に機能します!

//
// 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;
}
于 2014-06-30T22:01:21.910 に答える
1

私の記憶が正しければ、 のウィンドウ クラス名TabTip.exeIPTip_Main_Window. Win32 API を使用してのFindWindowを取得できます。これは、ウィンドウ タイトルを使用するよりも信頼性が高く、一部のウィンドウには空のタイトルがある (またはタイトルが変わる可能性がある) ため、推奨されます。HWNDTabTip.exe

EnumWindows多くのウィンドウ(または子ウィンドウを持つウィンドウ)を持つ単一のプロセスが原因で、使用している現在のアプローチに欠陥がある可能性があります。のようなツールを使用して、必要なSpy++実際のウィンドウとそれぞれのクラス名を見つけることができます。

その時点で引き続きGetWindowHandleThreadProcessIdを取得するために使用できprocessIDますが、単純なウィンドウ状態の監視には必要ないと思います。

また、CLR に組み込まれているものではなく、Win32 API を使用してみてください。たとえばGetWindowPlacement

MSDN からのメモ:

この関数によって取得される WINDOWPLACEMENT の flags メンバーは、常にゼロです。hWnd パラメーターによって識別されるウィンドウが最大化されている場合、showCmd メンバーは SW_SHOWMAXIMIZED です。ウィンドウが最小化されている場合、showCmd は SW_SHOWMINIMIZED です。それ以外の場合は、SW_SHOWNORMAL です。

さらに支援が必要な場合は、コメントを残してください。Win8 マシンに戻ったら編集します。

于 2014-01-02T21:41:57.457 に答える