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
;然后我按likea
,得到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,但它们仍然不起作用。是的,我想我现在知道你的想法了,非常好,我的朋友,非常好!我想实际上我可以通过我的应用程序实现这一点