在c#中记录击键时键入特殊字符时显示的双字符

syn*_*cis 2 c# logging keycode character-encoding winforms

我有一个应用程序,登录任何用户按下,但是当我按下特殊字符,如´a,得到á,我得到的´´a; 同样的事情,当我想得到à,然后我得到``a,所以所有特殊字符输入两次,然后常规字符输入后.

我一直在搜索,真的找不到任何东西.但我注意到问题出在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 "";
    }
}
Run Code Online (Sandbox Code Playgroud)

我错过了什么或做错了什么?所有其他角色都完美地工作,但它是以双重角色形式出现的特殊角色.


编辑:

试着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 "";
    }
}
Run Code Online (Sandbox Code Playgroud)

有人请帮助我,我真的需要弄清楚这一点=/.


编辑:

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
            );
Run Code Online (Sandbox Code Playgroud)

所以现在我已经尝试过调用ToAscii或者ToUnicode几次来冲洗真正的角色,但没有成功.我做错了吗?

就像ASCII一样,第一次打电话给´-1,所以我再次打电话给我,然后我得到1; 然后我按下a,得到á,但后来我才得到a.同样的事情,如果我ToUnicode彼此使用两次,我得到的只是a代替á,等等......

Cod*_*ray 5

但我注意到问题出在ToAsciii方法中,没有正确输入字符.

这正是我要猜的.我很感谢你为我做过腿部工作!:-)

问题是这些"特殊"字符不是 ASCII字符.也就是说,它们实际上是某种类型的花式裤子Unicode字符,它们不属于ASCII字符集.

当您尝试将它们转换为ASCII字符,功能想必做的最好是可以的,分解的代码点组成á成独立的字符´a.

显然这不是你想要的.您希望将其á视为单个字符,因此您需要使用Unicode.这不是一个真正的问题:Windows已经在内部使用了所有Unicode至少十年.抛弃过时的ToAscii功能; 相反,您将要使用MapVirtualKeyMapVirtualKeyEx将您通过低级键盘挂钩获得的虚拟键代码转换为字符值.

  • 您的代码仍然不检查返回值,它只是盲目地调用该函数两次.我强烈建议阅读链接文档. (2认同)