1

ユーザーが押したものをログに記録するアプリケーションがありますが、withのような特殊文字を押す´aáを取得し´´aます。同じことを取得したい場合はà、を取得します``a。したがって、すべての特殊文字は2回入力され、その後、通常の文字が入力されます。

私はこれまで検索しましたが、実際には何も見つかりません。ToAsciiしかし、問題はメソッドにあり、文字が正しく入力されていないことに気づきました。

public string GetString(IntPtr lParam, int vCode)
{
    try
    {
        bool shift = Keys.Shift == Control.ModifierKeys || Console.CapsLock;

        string value = ""; 

        KeyboardHookStruct MyKeyboardHookStruct = 
            (KeyboardHookStruct)Marshal.PtrToStructure(
                lParam, typeof(KeyboardHookStruct));

        byte[] keyState = new byte[256];
        byte[] inBuffer = new byte[2];

        DllClass.GetKeyboardState(keyState);

        var ascii=
            DllClass.ToAscii(
                MyKeyboardHookStruct.vkCode, 
                MyKeyboardHookStruct.scanCode, 
                keyState, inBuffer, MyKeyboardHookStruct.flags
                );

        if (ascii == 1)
        {
            char key = (char)inBuffer[0];

            if ((shift) && Char.IsLetter(key))
                key = Char.ToUpper(key);

            value = key.ToString();
        }

        return value;
    }
    catch (Exception)
    {
        return "";
    }
}

私は何かを逃しているのですか、それとも何か間違っているのですか?他のすべての文字は完全に機能していますが、二重文字として表示されるのは特殊文字です。


編集:

ToUnicode代わりに試してみてください。

[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern int ToUnicode(
    uint virtualKey, uint scanCode, byte[] keyStates, 
    [MarshalAs(UnmanagedType.LPArray)] [Out] char[] chars, 
    int charMaxCount, uint flags);

public string GetString(IntPtr lParam, int vCode)
{
    try
    {
        bool shift = Keys.Shift == Control.ModifierKeys || Console.CapsLock;

        string value = ""; 

        KeyboardHookStruct MyKeyboardHookStruct = 
            (KeyboardHookStruct)Marshal.PtrToStructure(
                lParam, typeof(KeyboardHookStruct));

        byte[] keyState = new byte[256];
        byte[] inBuffer = new byte[2];

        char[] chars = new char[2];

        DllClass.GetKeyboardState(keyState);

        int val = 0;

        val = ToUnicode(
                (uint)MyKeyboardHookStruct.vkCode, 
                (uint)MyKeyboardHookStruct.scanCode, 
                keyState, chars, chars.Length, 0
                );

        val = ToUnicode(
                (uint)MyKeyboardHookStruct.vkCode, 
                (uint)MyKeyboardHookStruct.scanCode, 
                keyState, chars, chars.Length, 0
                );

        if (val == 1)
        {
            char key = (char)chars[0];

            if ((shift) && Char.IsLetter(key))
                key = Char.ToUpper(key);

            value = key.ToString();
        }

        return value;
    }
    catch (Exception)
    {
        return "";
    }
}

誰かが私を助けてください、私は本当にこれを理解する必要があり=/ます。


編集:

int val = -1;

if (IsDeadKey((uint)vCode))
{
    while (val == -1)
    {
        val = ToUnicode(
                (uint)MyKeyboardHookStruct.vkCode, 
                (uint)MyKeyboardHookStruct.scanCode, 
                keyState, chars, chars.Length, 0
                );
    }
}
else
    val = ToUnicode(
            (uint)MyKeyboardHookStruct.vkCode, 
            (uint)MyKeyboardHookStruct.scanCode, 
            keyState, chars, chars.Length, 0
            );

だから今、私は実際のキャラクターをフラッシュするためにToAsciiまたはを数回呼び出しようとしましたが、成功しませんでした。ToUnicode私はそれを間違っていますか?

ASCIIの場合と同様に、最初にを呼び出すと、´を取得-1するので、もう一度呼び出してから、1;を取得します。次に、のように押しaて取得しますáが、取得するのは。だけですa。同じことをToUnicode2回続けて使用すると、a代わりに取得áします。

4

2 に答える 2

5

しかし、問題はToAsciiiメソッドにあり、文字が正しく入力されていないことに気づきました。

それはまさに私が推測しようとしていたことです。私のために足を運んでくれてありがとう!:-)

問題は、これらの「特殊」文字がASCII文字ではないことです。つまり、これらは実際には、ASCII文字セットの一部ではないある種の派手なパンツのUnicode文字です。

áそれらをASCII文字に変換しようとすると、関数はおそらく可能な限り最善を尽くし、構成するコードポイントを個別の文字´とに分解しますa

明らかに、それはあなたが望むものではありません。á単一の文字として扱いたいので、Unicodeを使用する必要があります。それは実際には問題ではありません。Windowsは少なくとも10年間、内部的にすべてUnicodeでした。時代遅れのToAscii機能を捨てる; 代わりに、MapVirtualKeyまたはMapVirtualKeyExを使用して、低レベルのキーボードフックを介して取得する仮想キーコードを文字値に変換する必要があります。

于 2013-03-18T23:34:11.107 に答える