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

C# 在c中记录击键时键入特殊字符时显示的双字符#,c#,winforms,logging,character-encoding,keycode,C#,Winforms,Logging,Character Encoding,Keycode,我有一个应用程序,它记录用户按的任何键,但当我用a按特殊字符,如',以获得á,我得到''a;同样,当我想要得到a时,我得到`a,所以所有特殊字符都被键入两次,然后常规字符被键入两次 我已经找了很久,真的找不到任何东西。但是我注意到问题出在ToAscii方法中,没有正确键入字符 public string GetString(IntPtr lParam, int vCode) { try { bool shift = Keys.Shift == Control.Mo

我有一个应用程序,它记录用户按的任何键,但当我用
a
按特殊字符,如
'
,以获得
á
,我得到
''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 "";
    }
}
我是错过了什么还是做错了什么?所有其他角色都工作得很好,但作为双重角色出现的是特殊角色


编辑:

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
            );
namespace Gma.UserActivityMonitor {
    using System.Diagnostics;
    using System.Windows.Forms;

    using System.Collections.Generic;
    using System.Linq;

    partial class HookManager {
        private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) {
            // indicates if any of underlaing events set e.Handled flag
            bool handled=false;

            if(nCode>=0) {
                // read structure KeyboardHookStruct at lParam
                var MyKeyboardHookStruct=
                    (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

                // raise KeyDown
                if(s_KeyDown!=null&&(wParam==WM_KEYDOWN||wParam==WM_SYSKEYDOWN)) {
                    Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                    KeyEventArgs e=new KeyEventArgs(keyData);
                    s_KeyDown.Invoke(null, e);
                    handled=e.Handled;
                }

                // raise KeyPress
                if(s_KeyPress!=null&&wParam==WM_KEYDOWN) {
                    var keyText=GetString(lParam, nCode, ref handled);

                    if(""!=keyText) {
                        var keyChar=keyText.First();
                        Debug.Print("keyText => {0}", keyText);

#if false
                        if(AccentFormatter.Combination.Values.Contains(keyChar)) {
                            SendKeys.Send("\b"+keyText);
                            return -1;
                        }
#endif
                    }
                }

                // raise KeyUp
                if(s_KeyUp!=null&&(wParam==WM_KEYUP||wParam==WM_SYSKEYUP)) {
                    Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                    KeyEventArgs e=new KeyEventArgs(keyData);
                    s_KeyUp.Invoke(null, e);
                    handled=handled||e.Handled;
                }
            }

            // if event handled in application do not handoff to other listeners
            if(handled)
                return -1;

            // forward to other application
            return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
        }

        public static String GetString(IntPtr lParam, int vCode, ref bool handled) {
            var MyKeyboardHookStruct=
                (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

            bool isDownShift=((GetKeyState(VK_SHIFT)&0x80)==0x80?true:false);
            bool isDownCapslock=(GetKeyState(VK_CAPITAL)!=0?true:false);

            byte[] keyState=new byte[256];
            GetKeyboardState(keyState);
            byte[] inBuffer=new byte[2];

            var keyText="";

            var ascii=
                ToAscii(
                    MyKeyboardHookStruct.VirtualKeyCode,
                    MyKeyboardHookStruct.ScanCode,
                    keyState, inBuffer, MyKeyboardHookStruct.Flags
                    );

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

                if((isDownCapslock^isDownShift)&&Char.IsLetter(key))
                    key=Char.ToUpper(key);

                KeyPressEventArgs e=new KeyPressEventArgs(key);
                s_KeyPress.Invoke(null, e);
                handled=handled||e.Handled;

                keyText=new String(new[] { e.KeyChar });
                var sequence=KeySequence.Captured(e.KeyChar);

                if(null!=sequence)
                    keyText=sequence.ToString(AccentFormatter.Default);
            }

            return keyText;
        }
    }

    public class KeySequence {
        public String ToString(IFormatProvider provider) {
            return
                null==provider
                    ?new String(Sequence.Select(x => (char)x).ToArray())
                    :String.Format(provider, "{0}", Sequence);
        }

        public override String ToString() {
            return this.ToString(default(IFormatProvider));
        }

        public bool Captures(int keyValue) {
            for(var i=Sequence.Length; i-->0; ) {
                if(Sequence[i]!=keyValue) {
                    if(0==i)
                        Count=0;

                    continue;
                }

                if(Count!=i)
                    continue;

                ++Count;
                break;
            }

            var x=Sequence.Length==Count;
            Count=x?0:Count;
            return x;
        }

        public KeySequence(int[] newSequence) {
            Sequence=newSequence;
        }

        public static KeySequence Captured(int keyValue) {
            return m_List.FirstOrDefault(x => x.Captures(keyValue));
        }

        public int Count {
            private set;
            get;
        }

        public int[] Sequence {
            set;
            get;
        }

        static KeySequence() {
            m_List.AddRange(
                from x in AccentFormatter.Combination.Keys
                let intArray=x.Select(c => (int)c).ToArray()
                select new KeySequence(intArray)
                );
        }

        static readonly List<KeySequence> m_List=new List<KeySequence>();
    }

    public class AccentFormatter: IFormatProvider, ICustomFormatter {
        String ICustomFormatter.Format(String format, object arg, IFormatProvider formatProvider) {
            return GetAccent(new String((arg as int[]).Select(x => (char)x).ToArray()));
        }

        object IFormatProvider.GetFormat(Type formatType) {
            return typeof(ICustomFormatter)!=formatType?null:this;
        }

        public static String GetAccent(String input) {
            return
                Combination.Keys.Contains(input, StringComparer.OrdinalIgnoreCase)
                    ?Combination[input].ToString()
                    :"";
        }

        static AccentFormatter() {
            AcuteSymbol=((char)0xb4).ToString();
            GraveSymbol=('`').ToString();

            var ae=(char)0xe6;
            var oe=(char)0xf8;
            AcuteCandidates="acegiklmnoprsuwyz".ToArray().Concat(new[] { ae, oe }).ToArray();
            GraveCandidates="aeinouwy".ToArray();

            var lowerAcuteAccents=(
                new[] { 
                    0xe1, 0x107, 
                    0xe9, 0x1f5, 
                    0xed, 0x1e31, 0x13a, 0x1e3f, 0x144, 
                    0xf3, 0x1e55, 0x155, 0x15b, 
                    0xfa, 0x1e83, 0xfd, 0x17a, 
                    0x1fd, 0x1ff
                }
                ).Select(
                    (x, i) => new {
                        Key=AcuteSymbol+AcuteCandidates[i],
                        Value=(char)x
                    }
                    );

            var upperAcuteAccents=(
                new[] { 
                    0xc1, 0x106, 
                    0xc9, 0x1f4, 
                    0xcd, 0x1e30, 0x139, 0x1e3e, 0x143, 
                    0xd3, 0x1e54, 0x154, 0x15a, 
                    0xda, 0x1e82, 0xdd, 0x179, 
                    0x1fc, 0x1fe
                }
                ).Select(
                    (x, i) => new {
                        Key=AcuteSymbol+char.ToUpper(AcuteCandidates[i]),
                        Value=(char)x
                    }
                    );

            var lowerGraveAccents=(
                new[] { 0xe0, 0xe8, 0xec, 0x1f9, 0xf2, 0xf9, 0x1e81, 0x1ef3 }
                ).Select(
                    (x, i) => new {
                        Key=GraveSymbol+GraveCandidates[i],
                        Value=(char)x
                    }
                    );

            var upperGraveAccents=(
                new[] { 0xc0, 0xc8, 0xcc, 0x1f8, 0xd2, 0xd9, 0x1e80, 0x1ef2 }
                ).Select(
                    (x, i) => new {
                        Key=GraveSymbol+char.ToUpper(GraveCandidates[i]),
                        Value=(char)x
                    }
                    );

            Combination=
                lowerAcuteAccents
                    .Concat(upperAcuteAccents)
                    .Concat(lowerGraveAccents)
                    .Concat(upperGraveAccents)
                    .ToDictionary(x => x.Key, x => x.Value);
        }

        public static readonly Dictionary<String, char> Combination;
        public static readonly String AcuteSymbol, GraveSymbol;
        public static readonly char[] AcuteCandidates, GraveCandidates;
        public static readonly AccentFormatter Default=new AccentFormatter();
    }
}
改为尝试使用
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
            );
namespace Gma.UserActivityMonitor {
    using System.Diagnostics;
    using System.Windows.Forms;

    using System.Collections.Generic;
    using System.Linq;

    partial class HookManager {
        private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) {
            // indicates if any of underlaing events set e.Handled flag
            bool handled=false;

            if(nCode>=0) {
                // read structure KeyboardHookStruct at lParam
                var MyKeyboardHookStruct=
                    (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

                // raise KeyDown
                if(s_KeyDown!=null&&(wParam==WM_KEYDOWN||wParam==WM_SYSKEYDOWN)) {
                    Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                    KeyEventArgs e=new KeyEventArgs(keyData);
                    s_KeyDown.Invoke(null, e);
                    handled=e.Handled;
                }

                // raise KeyPress
                if(s_KeyPress!=null&&wParam==WM_KEYDOWN) {
                    var keyText=GetString(lParam, nCode, ref handled);

                    if(""!=keyText) {
                        var keyChar=keyText.First();
                        Debug.Print("keyText => {0}", keyText);

#if false
                        if(AccentFormatter.Combination.Values.Contains(keyChar)) {
                            SendKeys.Send("\b"+keyText);
                            return -1;
                        }
#endif
                    }
                }

                // raise KeyUp
                if(s_KeyUp!=null&&(wParam==WM_KEYUP||wParam==WM_SYSKEYUP)) {
                    Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                    KeyEventArgs e=new KeyEventArgs(keyData);
                    s_KeyUp.Invoke(null, e);
                    handled=handled||e.Handled;
                }
            }

            // if event handled in application do not handoff to other listeners
            if(handled)
                return -1;

            // forward to other application
            return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
        }

        public static String GetString(IntPtr lParam, int vCode, ref bool handled) {
            var MyKeyboardHookStruct=
                (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

            bool isDownShift=((GetKeyState(VK_SHIFT)&0x80)==0x80?true:false);
            bool isDownCapslock=(GetKeyState(VK_CAPITAL)!=0?true:false);

            byte[] keyState=new byte[256];
            GetKeyboardState(keyState);
            byte[] inBuffer=new byte[2];

            var keyText="";

            var ascii=
                ToAscii(
                    MyKeyboardHookStruct.VirtualKeyCode,
                    MyKeyboardHookStruct.ScanCode,
                    keyState, inBuffer, MyKeyboardHookStruct.Flags
                    );

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

                if((isDownCapslock^isDownShift)&&Char.IsLetter(key))
                    key=Char.ToUpper(key);

                KeyPressEventArgs e=new KeyPressEventArgs(key);
                s_KeyPress.Invoke(null, e);
                handled=handled||e.Handled;

                keyText=new String(new[] { e.KeyChar });
                var sequence=KeySequence.Captured(e.KeyChar);

                if(null!=sequence)
                    keyText=sequence.ToString(AccentFormatter.Default);
            }

            return keyText;
        }
    }

    public class KeySequence {
        public String ToString(IFormatProvider provider) {
            return
                null==provider
                    ?new String(Sequence.Select(x => (char)x).ToArray())
                    :String.Format(provider, "{0}", Sequence);
        }

        public override String ToString() {
            return this.ToString(default(IFormatProvider));
        }

        public bool Captures(int keyValue) {
            for(var i=Sequence.Length; i-->0; ) {
                if(Sequence[i]!=keyValue) {
                    if(0==i)
                        Count=0;

                    continue;
                }

                if(Count!=i)
                    continue;

                ++Count;
                break;
            }

            var x=Sequence.Length==Count;
            Count=x?0:Count;
            return x;
        }

        public KeySequence(int[] newSequence) {
            Sequence=newSequence;
        }

        public static KeySequence Captured(int keyValue) {
            return m_List.FirstOrDefault(x => x.Captures(keyValue));
        }

        public int Count {
            private set;
            get;
        }

        public int[] Sequence {
            set;
            get;
        }

        static KeySequence() {
            m_List.AddRange(
                from x in AccentFormatter.Combination.Keys
                let intArray=x.Select(c => (int)c).ToArray()
                select new KeySequence(intArray)
                );
        }

        static readonly List<KeySequence> m_List=new List<KeySequence>();
    }

    public class AccentFormatter: IFormatProvider, ICustomFormatter {
        String ICustomFormatter.Format(String format, object arg, IFormatProvider formatProvider) {
            return GetAccent(new String((arg as int[]).Select(x => (char)x).ToArray()));
        }

        object IFormatProvider.GetFormat(Type formatType) {
            return typeof(ICustomFormatter)!=formatType?null:this;
        }

        public static String GetAccent(String input) {
            return
                Combination.Keys.Contains(input, StringComparer.OrdinalIgnoreCase)
                    ?Combination[input].ToString()
                    :"";
        }

        static AccentFormatter() {
            AcuteSymbol=((char)0xb4).ToString();
            GraveSymbol=('`').ToString();

            var ae=(char)0xe6;
            var oe=(char)0xf8;
            AcuteCandidates="acegiklmnoprsuwyz".ToArray().Concat(new[] { ae, oe }).ToArray();
            GraveCandidates="aeinouwy".ToArray();

            var lowerAcuteAccents=(
                new[] { 
                    0xe1, 0x107, 
                    0xe9, 0x1f5, 
                    0xed, 0x1e31, 0x13a, 0x1e3f, 0x144, 
                    0xf3, 0x1e55, 0x155, 0x15b, 
                    0xfa, 0x1e83, 0xfd, 0x17a, 
                    0x1fd, 0x1ff
                }
                ).Select(
                    (x, i) => new {
                        Key=AcuteSymbol+AcuteCandidates[i],
                        Value=(char)x
                    }
                    );

            var upperAcuteAccents=(
                new[] { 
                    0xc1, 0x106, 
                    0xc9, 0x1f4, 
                    0xcd, 0x1e30, 0x139, 0x1e3e, 0x143, 
                    0xd3, 0x1e54, 0x154, 0x15a, 
                    0xda, 0x1e82, 0xdd, 0x179, 
                    0x1fc, 0x1fe
                }
                ).Select(
                    (x, i) => new {
                        Key=AcuteSymbol+char.ToUpper(AcuteCandidates[i]),
                        Value=(char)x
                    }
                    );

            var lowerGraveAccents=(
                new[] { 0xe0, 0xe8, 0xec, 0x1f9, 0xf2, 0xf9, 0x1e81, 0x1ef3 }
                ).Select(
                    (x, i) => new {
                        Key=GraveSymbol+GraveCandidates[i],
                        Value=(char)x
                    }
                    );

            var upperGraveAccents=(
                new[] { 0xc0, 0xc8, 0xcc, 0x1f8, 0xd2, 0xd9, 0x1e80, 0x1ef2 }
                ).Select(
                    (x, i) => new {
                        Key=GraveSymbol+char.ToUpper(GraveCandidates[i]),
                        Value=(char)x
                    }
                    );

            Combination=
                lowerAcuteAccents
                    .Concat(upperAcuteAccents)
                    .Concat(lowerGraveAccents)
                    .Concat(upperGraveAccents)
                    .ToDictionary(x => x.Key, x => x.Value);
        }

        public static readonly Dictionary<String, char> Combination;
        public static readonly String AcuteSymbol, GraveSymbol;
        public static readonly char[] AcuteCandidates, GraveCandidates;
        public static readonly AccentFormatter Default=new AccentFormatter();
    }
}
因此,现在我尝试调用
ToAscii
ToUnicode
几次来刷新真实角色,但都没有成功。我做错了吗

像ASCII一样,首先调用
'
我得到
-1
,所以我再次调用它,然后得到
1
;然后我按like
a
,得到
a
,但我只得到
a
。同样的事情,如果我在两次之后使用
ToUnicode
,我得到的只是
a
,而不是
a
,依此类推

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

这正是我要猜的。我很感激你为我做了这些工作!:-)

问题是这些“特殊”字符不是ASCII字符。也就是说,它们实际上是某种类型的Unicode字符,不属于ASCII字符集

当您尝试将它们转换为ASCII字符时,该函数可能会尽其所能,将构成
的代码点分解为单独的字符
'
a

显然那不是你想要的。您希望将
视为单个字符,因此需要使用Unicode。这并不是一个真正的问题:Windows在内部使用Unicode至少有十年了。摒弃陈旧的功能;相反,您需要使用或将通过低级键盘挂钩获得的虚拟键代码转换为字符值。

  • 关于
    ToAscii
    ToUnicode
    的神话

    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
                );
    
    namespace Gma.UserActivityMonitor {
        using System.Diagnostics;
        using System.Windows.Forms;
    
        using System.Collections.Generic;
        using System.Linq;
    
        partial class HookManager {
            private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) {
                // indicates if any of underlaing events set e.Handled flag
                bool handled=false;
    
                if(nCode>=0) {
                    // read structure KeyboardHookStruct at lParam
                    var MyKeyboardHookStruct=
                        (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
    
                    // raise KeyDown
                    if(s_KeyDown!=null&&(wParam==WM_KEYDOWN||wParam==WM_SYSKEYDOWN)) {
                        Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                        KeyEventArgs e=new KeyEventArgs(keyData);
                        s_KeyDown.Invoke(null, e);
                        handled=e.Handled;
                    }
    
                    // raise KeyPress
                    if(s_KeyPress!=null&&wParam==WM_KEYDOWN) {
                        var keyText=GetString(lParam, nCode, ref handled);
    
                        if(""!=keyText) {
                            var keyChar=keyText.First();
                            Debug.Print("keyText => {0}", keyText);
    
    #if false
                            if(AccentFormatter.Combination.Values.Contains(keyChar)) {
                                SendKeys.Send("\b"+keyText);
                                return -1;
                            }
    #endif
                        }
                    }
    
                    // raise KeyUp
                    if(s_KeyUp!=null&&(wParam==WM_KEYUP||wParam==WM_SYSKEYUP)) {
                        Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                        KeyEventArgs e=new KeyEventArgs(keyData);
                        s_KeyUp.Invoke(null, e);
                        handled=handled||e.Handled;
                    }
                }
    
                // if event handled in application do not handoff to other listeners
                if(handled)
                    return -1;
    
                // forward to other application
                return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
            }
    
            public static String GetString(IntPtr lParam, int vCode, ref bool handled) {
                var MyKeyboardHookStruct=
                    (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
    
                bool isDownShift=((GetKeyState(VK_SHIFT)&0x80)==0x80?true:false);
                bool isDownCapslock=(GetKeyState(VK_CAPITAL)!=0?true:false);
    
                byte[] keyState=new byte[256];
                GetKeyboardState(keyState);
                byte[] inBuffer=new byte[2];
    
                var keyText="";
    
                var ascii=
                    ToAscii(
                        MyKeyboardHookStruct.VirtualKeyCode,
                        MyKeyboardHookStruct.ScanCode,
                        keyState, inBuffer, MyKeyboardHookStruct.Flags
                        );
    
                if(ascii==1) {
                    char key=(char)inBuffer[0];
    
                    if((isDownCapslock^isDownShift)&&Char.IsLetter(key))
                        key=Char.ToUpper(key);
    
                    KeyPressEventArgs e=new KeyPressEventArgs(key);
                    s_KeyPress.Invoke(null, e);
                    handled=handled||e.Handled;
    
                    keyText=new String(new[] { e.KeyChar });
                    var sequence=KeySequence.Captured(e.KeyChar);
    
                    if(null!=sequence)
                        keyText=sequence.ToString(AccentFormatter.Default);
                }
    
                return keyText;
            }
        }
    
        public class KeySequence {
            public String ToString(IFormatProvider provider) {
                return
                    null==provider
                        ?new String(Sequence.Select(x => (char)x).ToArray())
                        :String.Format(provider, "{0}", Sequence);
            }
    
            public override String ToString() {
                return this.ToString(default(IFormatProvider));
            }
    
            public bool Captures(int keyValue) {
                for(var i=Sequence.Length; i-->0; ) {
                    if(Sequence[i]!=keyValue) {
                        if(0==i)
                            Count=0;
    
                        continue;
                    }
    
                    if(Count!=i)
                        continue;
    
                    ++Count;
                    break;
                }
    
                var x=Sequence.Length==Count;
                Count=x?0:Count;
                return x;
            }
    
            public KeySequence(int[] newSequence) {
                Sequence=newSequence;
            }
    
            public static KeySequence Captured(int keyValue) {
                return m_List.FirstOrDefault(x => x.Captures(keyValue));
            }
    
            public int Count {
                private set;
                get;
            }
    
            public int[] Sequence {
                set;
                get;
            }
    
            static KeySequence() {
                m_List.AddRange(
                    from x in AccentFormatter.Combination.Keys
                    let intArray=x.Select(c => (int)c).ToArray()
                    select new KeySequence(intArray)
                    );
            }
    
            static readonly List<KeySequence> m_List=new List<KeySequence>();
        }
    
        public class AccentFormatter: IFormatProvider, ICustomFormatter {
            String ICustomFormatter.Format(String format, object arg, IFormatProvider formatProvider) {
                return GetAccent(new String((arg as int[]).Select(x => (char)x).ToArray()));
            }
    
            object IFormatProvider.GetFormat(Type formatType) {
                return typeof(ICustomFormatter)!=formatType?null:this;
            }
    
            public static String GetAccent(String input) {
                return
                    Combination.Keys.Contains(input, StringComparer.OrdinalIgnoreCase)
                        ?Combination[input].ToString()
                        :"";
            }
    
            static AccentFormatter() {
                AcuteSymbol=((char)0xb4).ToString();
                GraveSymbol=('`').ToString();
    
                var ae=(char)0xe6;
                var oe=(char)0xf8;
                AcuteCandidates="acegiklmnoprsuwyz".ToArray().Concat(new[] { ae, oe }).ToArray();
                GraveCandidates="aeinouwy".ToArray();
    
                var lowerAcuteAccents=(
                    new[] { 
                        0xe1, 0x107, 
                        0xe9, 0x1f5, 
                        0xed, 0x1e31, 0x13a, 0x1e3f, 0x144, 
                        0xf3, 0x1e55, 0x155, 0x15b, 
                        0xfa, 0x1e83, 0xfd, 0x17a, 
                        0x1fd, 0x1ff
                    }
                    ).Select(
                        (x, i) => new {
                            Key=AcuteSymbol+AcuteCandidates[i],
                            Value=(char)x
                        }
                        );
    
                var upperAcuteAccents=(
                    new[] { 
                        0xc1, 0x106, 
                        0xc9, 0x1f4, 
                        0xcd, 0x1e30, 0x139, 0x1e3e, 0x143, 
                        0xd3, 0x1e54, 0x154, 0x15a, 
                        0xda, 0x1e82, 0xdd, 0x179, 
                        0x1fc, 0x1fe
                    }
                    ).Select(
                        (x, i) => new {
                            Key=AcuteSymbol+char.ToUpper(AcuteCandidates[i]),
                            Value=(char)x
                        }
                        );
    
                var lowerGraveAccents=(
                    new[] { 0xe0, 0xe8, 0xec, 0x1f9, 0xf2, 0xf9, 0x1e81, 0x1ef3 }
                    ).Select(
                        (x, i) => new {
                            Key=GraveSymbol+GraveCandidates[i],
                            Value=(char)x
                        }
                        );
    
                var upperGraveAccents=(
                    new[] { 0xc0, 0xc8, 0xcc, 0x1f8, 0xd2, 0xd9, 0x1e80, 0x1ef2 }
                    ).Select(
                        (x, i) => new {
                            Key=GraveSymbol+char.ToUpper(GraveCandidates[i]),
                            Value=(char)x
                        }
                        );
    
                Combination=
                    lowerAcuteAccents
                        .Concat(upperAcuteAccents)
                        .Concat(lowerGraveAccents)
                        .Concat(upperGraveAccents)
                        .ToDictionary(x => x.Key, x => x.Value);
            }
    
            public static readonly Dictionary<String, char> Combination;
            public static readonly String AcuteSymbol, GraveSymbol;
            public static readonly char[] AcuteCandidates, GraveCandidates;
            public static readonly AccentFormatter Default=new AccentFormatter();
        }
    }
    
    在问题中,您提到您尝试了
    ToAscii
    ToUnicode
    ,但均未成功。我还搜索了一个相对的问题:

    我不是说任何答案是对的或错的。然而,我们可以考虑:

    • 一个(不那么)棘手的游戏

      在这个游戏中,我一次给玩家一枚随机翻转的50美分硬币。如果谁收集了一对50美分的硬币,一个是头,另一个是尾,的话,你可以向我索要一张一美元的钞票

      如果一个人放弃了挑战,那么谁能保留那50美分,游戏就会重新开始。如果谁试过,但没有收集到两个符合规定的,那么我要求退还我给的

      怎样才能从我这里得到一美元而不丢失任何硬币?

    • 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
                  );
      
      namespace Gma.UserActivityMonitor {
          using System.Diagnostics;
          using System.Windows.Forms;
      
          using System.Collections.Generic;
          using System.Linq;
      
          partial class HookManager {
              private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) {
                  // indicates if any of underlaing events set e.Handled flag
                  bool handled=false;
      
                  if(nCode>=0) {
                      // read structure KeyboardHookStruct at lParam
                      var MyKeyboardHookStruct=
                          (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
      
                      // raise KeyDown
                      if(s_KeyDown!=null&&(wParam==WM_KEYDOWN||wParam==WM_SYSKEYDOWN)) {
                          Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                          KeyEventArgs e=new KeyEventArgs(keyData);
                          s_KeyDown.Invoke(null, e);
                          handled=e.Handled;
                      }
      
                      // raise KeyPress
                      if(s_KeyPress!=null&&wParam==WM_KEYDOWN) {
                          var keyText=GetString(lParam, nCode, ref handled);
      
                          if(""!=keyText) {
                              var keyChar=keyText.First();
                              Debug.Print("keyText => {0}", keyText);
      
      #if false
                              if(AccentFormatter.Combination.Values.Contains(keyChar)) {
                                  SendKeys.Send("\b"+keyText);
                                  return -1;
                              }
      #endif
                          }
                      }
      
                      // raise KeyUp
                      if(s_KeyUp!=null&&(wParam==WM_KEYUP||wParam==WM_SYSKEYUP)) {
                          Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                          KeyEventArgs e=new KeyEventArgs(keyData);
                          s_KeyUp.Invoke(null, e);
                          handled=handled||e.Handled;
                      }
                  }
      
                  // if event handled in application do not handoff to other listeners
                  if(handled)
                      return -1;
      
                  // forward to other application
                  return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
              }
      
              public static String GetString(IntPtr lParam, int vCode, ref bool handled) {
                  var MyKeyboardHookStruct=
                      (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
      
                  bool isDownShift=((GetKeyState(VK_SHIFT)&0x80)==0x80?true:false);
                  bool isDownCapslock=(GetKeyState(VK_CAPITAL)!=0?true:false);
      
                  byte[] keyState=new byte[256];
                  GetKeyboardState(keyState);
                  byte[] inBuffer=new byte[2];
      
                  var keyText="";
      
                  var ascii=
                      ToAscii(
                          MyKeyboardHookStruct.VirtualKeyCode,
                          MyKeyboardHookStruct.ScanCode,
                          keyState, inBuffer, MyKeyboardHookStruct.Flags
                          );
      
                  if(ascii==1) {
                      char key=(char)inBuffer[0];
      
                      if((isDownCapslock^isDownShift)&&Char.IsLetter(key))
                          key=Char.ToUpper(key);
      
                      KeyPressEventArgs e=new KeyPressEventArgs(key);
                      s_KeyPress.Invoke(null, e);
                      handled=handled||e.Handled;
      
                      keyText=new String(new[] { e.KeyChar });
                      var sequence=KeySequence.Captured(e.KeyChar);
      
                      if(null!=sequence)
                          keyText=sequence.ToString(AccentFormatter.Default);
                  }
      
                  return keyText;
              }
          }
      
          public class KeySequence {
              public String ToString(IFormatProvider provider) {
                  return
                      null==provider
                          ?new String(Sequence.Select(x => (char)x).ToArray())
                          :String.Format(provider, "{0}", Sequence);
              }
      
              public override String ToString() {
                  return this.ToString(default(IFormatProvider));
              }
      
              public bool Captures(int keyValue) {
                  for(var i=Sequence.Length; i-->0; ) {
                      if(Sequence[i]!=keyValue) {
                          if(0==i)
                              Count=0;
      
                          continue;
                      }
      
                      if(Count!=i)
                          continue;
      
                      ++Count;
                      break;
                  }
      
                  var x=Sequence.Length==Count;
                  Count=x?0:Count;
                  return x;
              }
      
              public KeySequence(int[] newSequence) {
                  Sequence=newSequence;
              }
      
              public static KeySequence Captured(int keyValue) {
                  return m_List.FirstOrDefault(x => x.Captures(keyValue));
              }
      
              public int Count {
                  private set;
                  get;
              }
      
              public int[] Sequence {
                  set;
                  get;
              }
      
              static KeySequence() {
                  m_List.AddRange(
                      from x in AccentFormatter.Combination.Keys
                      let intArray=x.Select(c => (int)c).ToArray()
                      select new KeySequence(intArray)
                      );
              }
      
              static readonly List<KeySequence> m_List=new List<KeySequence>();
          }
      
          public class AccentFormatter: IFormatProvider, ICustomFormatter {
              String ICustomFormatter.Format(String format, object arg, IFormatProvider formatProvider) {
                  return GetAccent(new String((arg as int[]).Select(x => (char)x).ToArray()));
              }
      
              object IFormatProvider.GetFormat(Type formatType) {
                  return typeof(ICustomFormatter)!=formatType?null:this;
              }
      
              public static String GetAccent(String input) {
                  return
                      Combination.Keys.Contains(input, StringComparer.OrdinalIgnoreCase)
                          ?Combination[input].ToString()
                          :"";
              }
      
              static AccentFormatter() {
                  AcuteSymbol=((char)0xb4).ToString();
                  GraveSymbol=('`').ToString();
      
                  var ae=(char)0xe6;
                  var oe=(char)0xf8;
                  AcuteCandidates="acegiklmnoprsuwyz".ToArray().Concat(new[] { ae, oe }).ToArray();
                  GraveCandidates="aeinouwy".ToArray();
      
                  var lowerAcuteAccents=(
                      new[] { 
                          0xe1, 0x107, 
                          0xe9, 0x1f5, 
                          0xed, 0x1e31, 0x13a, 0x1e3f, 0x144, 
                          0xf3, 0x1e55, 0x155, 0x15b, 
                          0xfa, 0x1e83, 0xfd, 0x17a, 
                          0x1fd, 0x1ff
                      }
                      ).Select(
                          (x, i) => new {
                              Key=AcuteSymbol+AcuteCandidates[i],
                              Value=(char)x
                          }
                          );
      
                  var upperAcuteAccents=(
                      new[] { 
                          0xc1, 0x106, 
                          0xc9, 0x1f4, 
                          0xcd, 0x1e30, 0x139, 0x1e3e, 0x143, 
                          0xd3, 0x1e54, 0x154, 0x15a, 
                          0xda, 0x1e82, 0xdd, 0x179, 
                          0x1fc, 0x1fe
                      }
                      ).Select(
                          (x, i) => new {
                              Key=AcuteSymbol+char.ToUpper(AcuteCandidates[i]),
                              Value=(char)x
                          }
                          );
      
                  var lowerGraveAccents=(
                      new[] { 0xe0, 0xe8, 0xec, 0x1f9, 0xf2, 0xf9, 0x1e81, 0x1ef3 }
                      ).Select(
                          (x, i) => new {
                              Key=GraveSymbol+GraveCandidates[i],
                              Value=(char)x
                          }
                          );
      
                  var upperGraveAccents=(
                      new[] { 0xc0, 0xc8, 0xcc, 0x1f8, 0xd2, 0xd9, 0x1e80, 0x1ef2 }
                      ).Select(
                          (x, i) => new {
                              Key=GraveSymbol+char.ToUpper(GraveCandidates[i]),
                              Value=(char)x
                          }
                          );
      
                  Combination=
                      lowerAcuteAccents
                          .Concat(upperAcuteAccents)
                          .Concat(lowerGraveAccents)
                          .Concat(upperGraveAccents)
                          .ToDictionary(x => x.Key, x => x.Value);
              }
      
              public static readonly Dictionary<String, char> Combination;
              public static readonly String AcuteSymbol, GraveSymbol;
              public static readonly char[] AcuteCandidates, GraveCandidates;
              public static readonly AccentFormatter Default=new AccentFormatter();
          }
      }
      
    也许是时间旅行


基于CodeProject上的[]

我的老生常谈是:

为了回答你的问题,我做了一些修改

  • 代码

    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
                );
    
    namespace Gma.UserActivityMonitor {
        using System.Diagnostics;
        using System.Windows.Forms;
    
        using System.Collections.Generic;
        using System.Linq;
    
        partial class HookManager {
            private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) {
                // indicates if any of underlaing events set e.Handled flag
                bool handled=false;
    
                if(nCode>=0) {
                    // read structure KeyboardHookStruct at lParam
                    var MyKeyboardHookStruct=
                        (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
    
                    // raise KeyDown
                    if(s_KeyDown!=null&&(wParam==WM_KEYDOWN||wParam==WM_SYSKEYDOWN)) {
                        Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                        KeyEventArgs e=new KeyEventArgs(keyData);
                        s_KeyDown.Invoke(null, e);
                        handled=e.Handled;
                    }
    
                    // raise KeyPress
                    if(s_KeyPress!=null&&wParam==WM_KEYDOWN) {
                        var keyText=GetString(lParam, nCode, ref handled);
    
                        if(""!=keyText) {
                            var keyChar=keyText.First();
                            Debug.Print("keyText => {0}", keyText);
    
    #if false
                            if(AccentFormatter.Combination.Values.Contains(keyChar)) {
                                SendKeys.Send("\b"+keyText);
                                return -1;
                            }
    #endif
                        }
                    }
    
                    // raise KeyUp
                    if(s_KeyUp!=null&&(wParam==WM_KEYUP||wParam==WM_SYSKEYUP)) {
                        Keys keyData=(Keys)MyKeyboardHookStruct.VirtualKeyCode;
                        KeyEventArgs e=new KeyEventArgs(keyData);
                        s_KeyUp.Invoke(null, e);
                        handled=handled||e.Handled;
                    }
                }
    
                // if event handled in application do not handoff to other listeners
                if(handled)
                    return -1;
    
                // forward to other application
                return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
            }
    
            public static String GetString(IntPtr lParam, int vCode, ref bool handled) {
                var MyKeyboardHookStruct=
                    (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
    
                bool isDownShift=((GetKeyState(VK_SHIFT)&0x80)==0x80?true:false);
                bool isDownCapslock=(GetKeyState(VK_CAPITAL)!=0?true:false);
    
                byte[] keyState=new byte[256];
                GetKeyboardState(keyState);
                byte[] inBuffer=new byte[2];
    
                var keyText="";
    
                var ascii=
                    ToAscii(
                        MyKeyboardHookStruct.VirtualKeyCode,
                        MyKeyboardHookStruct.ScanCode,
                        keyState, inBuffer, MyKeyboardHookStruct.Flags
                        );
    
                if(ascii==1) {
                    char key=(char)inBuffer[0];
    
                    if((isDownCapslock^isDownShift)&&Char.IsLetter(key))
                        key=Char.ToUpper(key);
    
                    KeyPressEventArgs e=new KeyPressEventArgs(key);
                    s_KeyPress.Invoke(null, e);
                    handled=handled||e.Handled;
    
                    keyText=new String(new[] { e.KeyChar });
                    var sequence=KeySequence.Captured(e.KeyChar);
    
                    if(null!=sequence)
                        keyText=sequence.ToString(AccentFormatter.Default);
                }
    
                return keyText;
            }
        }
    
        public class KeySequence {
            public String ToString(IFormatProvider provider) {
                return
                    null==provider
                        ?new String(Sequence.Select(x => (char)x).ToArray())
                        :String.Format(provider, "{0}", Sequence);
            }
    
            public override String ToString() {
                return this.ToString(default(IFormatProvider));
            }
    
            public bool Captures(int keyValue) {
                for(var i=Sequence.Length; i-->0; ) {
                    if(Sequence[i]!=keyValue) {
                        if(0==i)
                            Count=0;
    
                        continue;
                    }
    
                    if(Count!=i)
                        continue;
    
                    ++Count;
                    break;
                }
    
                var x=Sequence.Length==Count;
                Count=x?0:Count;
                return x;
            }
    
            public KeySequence(int[] newSequence) {
                Sequence=newSequence;
            }
    
            public static KeySequence Captured(int keyValue) {
                return m_List.FirstOrDefault(x => x.Captures(keyValue));
            }
    
            public int Count {
                private set;
                get;
            }
    
            public int[] Sequence {
                set;
                get;
            }
    
            static KeySequence() {
                m_List.AddRange(
                    from x in AccentFormatter.Combination.Keys
                    let intArray=x.Select(c => (int)c).ToArray()
                    select new KeySequence(intArray)
                    );
            }
    
            static readonly List<KeySequence> m_List=new List<KeySequence>();
        }
    
        public class AccentFormatter: IFormatProvider, ICustomFormatter {
            String ICustomFormatter.Format(String format, object arg, IFormatProvider formatProvider) {
                return GetAccent(new String((arg as int[]).Select(x => (char)x).ToArray()));
            }
    
            object IFormatProvider.GetFormat(Type formatType) {
                return typeof(ICustomFormatter)!=formatType?null:this;
            }
    
            public static String GetAccent(String input) {
                return
                    Combination.Keys.Contains(input, StringComparer.OrdinalIgnoreCase)
                        ?Combination[input].ToString()
                        :"";
            }
    
            static AccentFormatter() {
                AcuteSymbol=((char)0xb4).ToString();
                GraveSymbol=('`').ToString();
    
                var ae=(char)0xe6;
                var oe=(char)0xf8;
                AcuteCandidates="acegiklmnoprsuwyz".ToArray().Concat(new[] { ae, oe }).ToArray();
                GraveCandidates="aeinouwy".ToArray();
    
                var lowerAcuteAccents=(
                    new[] { 
                        0xe1, 0x107, 
                        0xe9, 0x1f5, 
                        0xed, 0x1e31, 0x13a, 0x1e3f, 0x144, 
                        0xf3, 0x1e55, 0x155, 0x15b, 
                        0xfa, 0x1e83, 0xfd, 0x17a, 
                        0x1fd, 0x1ff
                    }
                    ).Select(
                        (x, i) => new {
                            Key=AcuteSymbol+AcuteCandidates[i],
                            Value=(char)x
                        }
                        );
    
                var upperAcuteAccents=(
                    new[] { 
                        0xc1, 0x106, 
                        0xc9, 0x1f4, 
                        0xcd, 0x1e30, 0x139, 0x1e3e, 0x143, 
                        0xd3, 0x1e54, 0x154, 0x15a, 
                        0xda, 0x1e82, 0xdd, 0x179, 
                        0x1fc, 0x1fe
                    }
                    ).Select(
                        (x, i) => new {
                            Key=AcuteSymbol+char.ToUpper(AcuteCandidates[i]),
                            Value=(char)x
                        }
                        );
    
                var lowerGraveAccents=(
                    new[] { 0xe0, 0xe8, 0xec, 0x1f9, 0xf2, 0xf9, 0x1e81, 0x1ef3 }
                    ).Select(
                        (x, i) => new {
                            Key=GraveSymbol+GraveCandidates[i],
                            Value=(char)x
                        }
                        );
    
                var upperGraveAccents=(
                    new[] { 0xc0, 0xc8, 0xcc, 0x1f8, 0xd2, 0xd9, 0x1e80, 0x1ef2 }
                    ).Select(
                        (x, i) => new {
                            Key=GraveSymbol+char.ToUpper(GraveCandidates[i]),
                            Value=(char)x
                        }
                        );
    
                Combination=
                    lowerAcuteAccents
                        .Concat(upperAcuteAccents)
                        .Concat(lowerGraveAccents)
                        .Concat(upperGraveAccents)
                        .ToDictionary(x => x.Key, x => x.Value);
            }
    
            public static readonly Dictionary<String, char> Combination;
            public static readonly String AcuteSymbol, GraveSymbol;
            public static readonly char[] AcuteCandidates, GraveCandidates;
            public static readonly AccentFormatter Default=new AccentFormatter();
        }
    }
    
    即:

    ÁĆ ÉǴ ÍḰĹḾŃ ÓṔŔŚ ÚẂÝŹ ǼǾ 到

    在条件编译块中,代码片段是

    if(AccentFormatter.Combination.Values.Contains(keyChar)) {
        SendKeys.Send("\b"+keyText);
        return -1;
    }
    
    一旦识别出前一个键入的“`
    ``是一个特定的组合,它就使用一个退格字符来删除它。这里的退格是时间机器


在这个演示之后,我想您将知道如何修改它们以合并到代码中

键盘记录器。。。我完全同意我的朋友,但这不是你想象中的那种键盘记录器。这实际上是一个学校项目,针对那些在记住用户名/密码方面有问题的人,使用这个工具,他们可以将所有东西都保存在一个安全的地方。是的,键盘记录器和密码没有什么不安全的地方。@syncis:所以现在你可以开始工作了。@KenKin事实上没有,我没有=/非常感谢你提供这些信息,但我有一个问题。还有一种方法与ToAsciii类似,名为ToUnicode,这是不是应该或者我应该尝试mapvirtualkey?@syncis是的,您可能会在
ToUnicode
/
Tounicodex
上有一些运气,但这两种方法仍然存在死键问题。一种可能的解决方法是,如果第一次通过时得到一个死键(返回值为-1),则再次调用它。相关阅读:好的,让我们尝试第一个方法,调用它们两次,我首先用ToAscii调用它,如果它返回-1,我会再次调用它,对吗?现在试着这样做,我没有得到双打,但我没有得到a,我只是得到了a,而不是a。也许MapVirtualKeyx解决了这个问题?
ToUnicode
将解决这个问题。您的
ToAscii
问题仍然是
a
不是ASCII字符。您的代码仍然不检查返回值,它只是盲目地调用函数两次。我强烈建议阅读链接文档。+1感谢分享。我做了一系列的研究,发现很多人都被困在了这个问题上。Í无法让它发挥作用,仍然在没有答案的情况下得到a。我做错了什么,我使用的正是你提到的项目,并将两个项目升级到4.0,但它们仍然不起作用。是的,我想我现在知道你的想法了,非常好,我的朋友,非常好!我想实际上我可以通过我的应用程序实现这一点