11

OK、これは少し奇妙な質問です。

タッチスクリーンアプリケーションがあります(つまり、キーボードはありません)。ユーザーがテキストを入力する必要がある場合、アプリケーションは仮想キーボードを表示します-WinFormsで手作りされています。

新しい言語ごとにこれらのものを手作業で作成することは、猿の仕事です。Windowsには、このキーボードレイアウト情報がdllのどこかに隠れている必要があると思います。とにかくこの情報をウィンドウから取得する方法はありますか?

他のアイデアも歓迎します(少なくともxmlファイルから生成する方がVSで手動で生成するよりも優れている必要があると思います)。

(注:すべてを言っても、日本語のキーボード、ステートマシン、その他すべてがあることに注意してください...したがって、XMLでは不十分な場合があります)

更新:この主題に関するかなり良いシリーズ(私は信じています)ここに

4

5 に答える 5

7

Microsoft Keyboard Layout Creatorは、システム キーボードを読み込み、.klc ファイルとしてエクスポートできます。これは .NET で記述されているため、Reflectorを使用してそれがどのように行われるかを確認し、リフレクションを使用してそれを駆動できます。以下のC# コードを使用して作成された、Windows 8 の 187 キーボード用の .klc ファイルの zip ファイルを次に示します。これはもともと Windows XP 用に書いたものですが、現在 Windows 8 とオンスクリーン キーボードを使用すると、非常に遅くなり、タスクバーがクラッシュするようです :/ ただし、動作します :)

using System;
using System.Collections;
using System.IO;
using System.Reflection;

class KeyboardExtractor {

    static Object InvokeNonPublicStaticMethod(Type t, String name,
            Object[] args)
    {
        return t.GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic)
            .Invoke(null, args);
    }

    static void InvokeNonPublicInstanceMethod(Object o, String name,
            Object[] args)
    {
        o.GetType().GetMethod(name, BindingFlags.Instance |
                BindingFlags.NonPublic) .Invoke(o, args);
    }

    static Object GetNonPublicProperty(Object o, String propertyName) {
        return o.GetType().GetField(propertyName,
                BindingFlags.Instance | BindingFlags.NonPublic)
            .GetValue(o);
    }

    static void SetNonPublicField(Object o, String propertyName, Object v) {
        o.GetType().GetField(propertyName,
                BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(o, v);
    }

    [STAThread] public static void Main() {
        System.Console.WriteLine("Keyboard Extractor...");

        KeyboardExtractor ke = new KeyboardExtractor();
        ke.extractAll();

        System.Console.WriteLine("Done.");
    }

    Assembly msklcAssembly;
    Type utilitiesType;
    Type keyboardType;
    String baseDirectory;

    public KeyboardExtractor() {
        msklcAssembly = Assembly.LoadFile("C:\\Program Files\\Microsoft Keyboard Layout Creator 1.4\\MSKLC.exe");
        utilitiesType = msklcAssembly.GetType("Microsoft.Globalization.Tools.KeyboardLayoutCreator.Utilities");
        keyboardType = msklcAssembly.GetType("Microsoft.Globalization.Tools.KeyboardLayoutCreator.Keyboard");

        baseDirectory = Directory.GetCurrentDirectory();
    }

    public void extractAll() {

        DateTime startTime = DateTime.UtcNow;

        SortedList keyboards = (SortedList)InvokeNonPublicStaticMethod(
                utilitiesType, "KeyboardsOnMachine", new Object[] {false});

        DateTime loopStartTime = DateTime.UtcNow;

        int i = 0;
        foreach (DictionaryEntry e in keyboards) {
            i += 1;
            Object k = e.Value;

            String name = (String)GetNonPublicProperty(k, "m_stLayoutName");
            String layoutHexString = ((UInt32)GetNonPublicProperty(k, "m_hkl"))
                .ToString("X");

            TimeSpan elapsed = DateTime.UtcNow - loopStartTime;
            Double ticksRemaining = ((Double)elapsed.Ticks * keyboards.Count)
                        / i - elapsed.Ticks;
            TimeSpan remaining = new TimeSpan((Int64)ticksRemaining);
            String msgTimeRemaining = "";
            if (i > 1) {
                // Trim milliseconds
                remaining = new TimeSpan(remaining.Hours, remaining.Minutes,
                        remaining.Seconds);
                msgTimeRemaining = String.Format(", about {0} remaining",
                        remaining);
            }
            System.Console.WriteLine(
                    "Saving {0} {1}, keyboard {2} of {3}{4}",
                    layoutHexString, name, i, keyboards.Count,
                    msgTimeRemaining);

            SaveKeyboard(name, layoutHexString);

        }

        System.Console.WriteLine("{0} elapsed", DateTime.UtcNow - startTime);

    }

    private void SaveKeyboard(String name, String layoutHexString) {
        Object k = keyboardType.GetConstructors(
                BindingFlags.Instance | BindingFlags.NonPublic)[0]
            .Invoke(new Object[] {
                        new String[] {"", layoutHexString},
                    false});

        SetNonPublicField(k, "m_fSeenOrHeardAboutPropertiesDialog", true);
        SetNonPublicField(k, "m_stKeyboardTextFileName",
                String.Format("{0}\\{1} {2}.klc",
                    baseDirectory, layoutHexString, name));
        InvokeNonPublicInstanceMethod(k, "mnuFileSave_Click",
                new Object[] {new Object(), new EventArgs()});

        ((IDisposable)k).Dispose();
    }

}

基本的に、システム上のすべてのキーボードのリストを取得し、それぞれについて MSKLC にロードし、「名前を付けて保存」ファイル名を設定し、カスタム キーボード プロパティが既に構成されているかどうかについて嘘をつき、次にクリックをシミュレートします。ファイル -> 保存メニュー項目。

于 2009-05-08T01:17:21.537 に答える
2

オンスクリーン キーボード (osk.exe) を使用しないのはなぜですか。車輪の再発明のようです。そして、最も簡単なものではありません!

于 2009-03-19T13:48:47.710 に答える
2

これらの DLL ファイルのパスがどこにあるかはわかっています。

レジストリには、次のように表示されます。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts

各ブランチには のような値があります"Layout File"="KBDSP.dll"。ルートディレクトリは

C:\Windows\System32

C:\Windows\SystemWOW64

これらは、配置されているすべてのキーボード レイアウト ファイルです。たとえば、KBDUS.dll「US 用キーボード」を意味します。

DLL ファイルを MSKLC 製のカスタム DLL に置き換えようとしたところ、「言語」-「入力方法」-「プレビュー」でレイアウト マッピング イメージが自動的に読み込まれることがわかりました。

ここに画像の説明を入力

したがって、マッピングが DLL にあることがわかります。

于 2017-06-06T14:03:41.673 に答える
0

次のWindowsAPIを確認してください

 [DllImport("user32.dll")]
 private static extern long LoadKeyboardLayout(string pwszKLID, uint Flags);

ここでMSDNを確認してください

于 2009-03-19T10:48:27.487 に答える