diff --git a/.gitignore b/.gitignore index fbdc4d0..f40418b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +.idea/ # User-specific files *.suo diff --git a/Bukva/Bukva/Bukva.csproj b/Bukva/Bukva/Bukva.csproj index 381e987..5ac26d1 100644 --- a/Bukva/Bukva/Bukva.csproj +++ b/Bukva/Bukva/Bukva.csproj @@ -56,6 +56,12 @@ MSBuild:Compile Designer + + + + + PackageManager.xaml + MSBuild:Compile @@ -67,12 +73,15 @@ - MainWindow.xaml Code + + Designer + MSBuild:Compile + @@ -100,5 +109,6 @@ + \ No newline at end of file diff --git a/Bukva/Bukva/KeyPressListener.cs b/Bukva/Bukva/KeyPressListener.cs index b86381f..0cf61cc 100644 --- a/Bukva/Bukva/KeyPressListener.cs +++ b/Bukva/Bukva/KeyPressListener.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Text; using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Input; @@ -15,7 +17,12 @@ abstract class KeyPressListener protected void RaiseKeyPressedEvent(string keyPressed) { - OnKeyPressed(this, new KeyPressedEventArgs(keyPressed)); + OnKeyPressed(this, new KeyPressedEventArgs(keyPressed, false)); + } + + protected void RaiseKeyPressedEvent(string keyPressed, bool scrollLockPressed) + { + OnKeyPressed(this, new KeyPressedEventArgs(keyPressed, scrollLockPressed)); } public abstract void DeleteLastKeyPressed(); @@ -24,14 +31,17 @@ protected void RaiseKeyPressedEvent(string keyPressed) class LowLevelKeyboardHook : KeyPressListener , IDisposable { - private Win32.CallBackHandler callBackHandler; private IntPtr hookID = IntPtr.Zero; private bool trap; + private byte[] keyboardState; + private StringBuilder converterBuffer; + public LowLevelKeyboardHook() { + callBackHandler = HookCallback; trap = false; HookKeyboard(); @@ -51,6 +61,19 @@ public void Dispose() Win32.UnhookWindowsHookEx(hookID); } + private string VirtualKeyToString(int virtualKeyCode) + { + keyboardState = new byte[256]; + if (Control.ModifierKeys.HasFlag(Keys.Shift)) + keyboardState[(int) Keys.ShiftKey] = 0xff; + //else + //keyboardState[(int) Keys.ShiftKey] = 0x0; + + converterBuffer = new StringBuilder(256); + Win32.ToUnicode((uint)virtualKeyCode, 0, keyboardState, converterBuffer, 256, 0); + return converterBuffer.ToString(); + } + private bool userKey = true; private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { @@ -62,26 +85,16 @@ private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) if (nCode >= 0 && (wParam == (IntPtr)Win32.WM_KEYDOWN || wParam == (IntPtr)Win32.WM_SYSKEYDOWN) && Listen) { int virtualKeyCode = Marshal.ReadInt32(lParam); - Console.WriteLine(virtualKeyCode.ToString()); - Key pressedKey = KeyInterop.KeyFromVirtualKey(virtualKeyCode); - string key; - - if (Control.ModifierKeys.HasFlag(Keys.Shift)) - { - key = pressedKey.ToString().ToUpper(); - } - else - { - key = pressedKey.ToString().ToLower(); - } + string key = VirtualKeyToString(virtualKeyCode); + Console.WriteLine(key); if (key.ToUpper() == "OEMPERIOD") { key = "."; } - RaiseKeyPressedEvent(key); + RaiseKeyPressedEvent(key, virtualKeyCode == 145 ? true : false); if(trap) { trap = false; @@ -98,6 +111,7 @@ private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) public override void DeleteLastKeyPressed() { trap = true; + //Backspace(); } public override void EmitBackspace() @@ -180,10 +194,12 @@ public override void EmitBackspace() public class KeyPressedEventArgs : EventArgs { public string KeyPressed { get; private set; } + public bool ScrollLockPressed { get; private set; } - public KeyPressedEventArgs(string key) + public KeyPressedEventArgs(string key, bool scrollLockPressed) { KeyPressed = key; + ScrollLockPressed = scrollLockPressed; } } } \ No newline at end of file diff --git a/Bukva/Bukva/KeyTranslator/IKeyTranslator.cs b/Bukva/Bukva/KeyTranslator/IKeyTranslator.cs new file mode 100644 index 0000000..3c96748 --- /dev/null +++ b/Bukva/Bukva/KeyTranslator/IKeyTranslator.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bukva +{ + interface IKeyTranslator + { + void Start(); + void Stop(); + void SetLetterTable(LetterTable newLetterTable); + } +} diff --git a/Bukva/Bukva/KeyTranslator.cs b/Bukva/Bukva/KeyTranslator/KeyStateKeyTranslator.cs similarity index 91% rename from Bukva/Bukva/KeyTranslator.cs rename to Bukva/Bukva/KeyTranslator/KeyStateKeyTranslator.cs index 2dbe604..6fd8353 100644 --- a/Bukva/Bukva/KeyTranslator.cs +++ b/Bukva/Bukva/KeyTranslator/KeyStateKeyTranslator.cs @@ -1,29 +1,33 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Windows.Forms; namespace Bukva { - class KeyTranslator + + class KeyStateKeyTranslator { FixedLengthQueue buffer; LetterTable letterTable; KeyPressListener keyPressListener; - public KeyTranslator(LetterTable letterTable) + public KeyStateKeyTranslator(LetterTable letterTable) { buffer = new FixedLengthQueue(3); buffer.Clear(""); this.letterTable = letterTable; - + //keyPressListener = new KeyStateListener(); - keyPressListener = new LowLevelKeyboardHook(); + keyPressListener = new KeyStateListener(); keyPressListener.Listen = false; keyPressListener.OnKeyPressed += OnKeyPressed; } + public void SetLetterTable(LetterTable newLetterTable) + { + letterTable = newLetterTable; + } + public void Start() { keyPressListener.Listen = true; @@ -42,7 +46,9 @@ private void OnKeyPressed(object sender, KeyPressedEventArgs e) if (Control.ModifierKeys.HasFlag(Keys.Control) || key == "none") return; - if (key == "back") + Console.WriteLine(key); + + if (key == "\b" || key == "back") { HandleUndo(); } diff --git a/Bukva/Bukva/KeyTranslator/LowLevelKeyTranslator.cs b/Bukva/Bukva/KeyTranslator/LowLevelKeyTranslator.cs new file mode 100644 index 0000000..ebbd02e --- /dev/null +++ b/Bukva/Bukva/KeyTranslator/LowLevelKeyTranslator.cs @@ -0,0 +1,140 @@ +using System; +using System.Windows.Forms; + +namespace Bukva +{ + class LowLevelKeyTranslator : IKeyTranslator + { + FixedLengthQueue buffer; + LetterTable letterTable; + + KeyPressListener keyPressListener; + + public LowLevelKeyTranslator(LetterTable letterTable) + { + buffer = new FixedLengthQueue(3); + buffer.Clear(""); + this.letterTable = letterTable; + + //keyPressListener = new KeyStateListener(); + keyPressListener = new LowLevelKeyboardHook(); + keyPressListener.Listen = false; + keyPressListener.OnKeyPressed += OnKeyPressed; + } + + public void SetLetterTable(LetterTable newLetterTable) + { + letterTable = newLetterTable; + } + + public void Start() + { + keyPressListener.Listen = true; + } + + public void Stop() + { + keyPressListener.Listen = false; + buffer.Clear(""); //What if OnKeyPressed is being executed at this time? + } + + private void OnKeyPressed(object sender, KeyPressedEventArgs e) + { + string key = e.KeyPressed; + + + if (Control.ModifierKeys.HasFlag(Keys.Control) || key == "none" || key == "") + return; + + Console.WriteLine(key); + + if (key == "\b" || key == "back") + { + HandleUndo(); + } + else + { + HandleKeyPress(key); + } + + buffer.Insert(key); + } + + private void HandleKeyPress(string key) + { + if (letterTable.ContainsKey(buffer.At(1) + buffer.At(2) + key)) + { + if (letterTable.ContainsKey(buffer.At(2)) || letterTable.ContainsKey(buffer.At(1) + buffer.At(2))) + { + keyPressListener.EmitBackspace(); //Replace previous translation with new one, if it existed + } + + if (!letterTable.ContainsKey(buffer.At(1) + buffer.At(2))) + keyPressListener.EmitBackspace(); + + keyPressListener.DeleteLastKeyPressed(); + + SendKeys.SendWait(letterTable[buffer.At(1) + buffer.At(2) + key]); + } + else if (letterTable.ContainsKey(buffer.At(2) + key)) + { + keyPressListener.DeleteLastKeyPressed(); + + if (letterTable.ContainsKey(buffer.At(2))) + keyPressListener.EmitBackspace(); //Replace previous translation with new one, if it existed + + + SendKeys.SendWait(letterTable[buffer.At(2) + key]); + } + else if (letterTable.ContainsKey(key)) + { + keyPressListener.DeleteLastKeyPressed(); + + SendKeys.SendWait(letterTable[key]); + } + } + + private void HandleUndo() + { + keyPressListener.EmitBackspace(); + keyPressListener.DeleteLastKeyPressed(); + + if (letterTable.ContainsKey(buffer.At(0) + buffer.At(1) + buffer.At(2))) + { + if (letterTable.ContainsKey(buffer.At(0) + buffer.At(1))) + { + SendKeys.SendWait(letterTable[buffer.At(0) + buffer.At(1)]); + + if (letterTable.ContainsKey(buffer.At(2))) + SendKeys.SendWait(letterTable[buffer.At(2)]); + else + SendKeys.SendWait(buffer.At(2)); + } + else + { + if (letterTable.ContainsKey(buffer.At(0))) + SendKeys.SendWait(letterTable[buffer.At(0)]); + else + SendKeys.SendWait(buffer.At(0)); + + + if (letterTable.ContainsKey(buffer.At(1))) + SendKeys.SendWait(letterTable[buffer.At(1)]); + else + SendKeys.SendWait(buffer.At(1)); + + + if (letterTable.ContainsKey(buffer.At(2))) + SendKeys.SendWait(letterTable[buffer.At(2)]); + else + SendKeys.SendWait(buffer.At(2)); + } + } + else if (letterTable.ContainsKey(buffer.At(1) + buffer.At(2))) + { + SendKeys.SendWait(letterTable[buffer.At(1)]); + SendKeys.SendWait(letterTable[buffer.At(2)]); + } + } + } +} diff --git a/Bukva/Bukva/LetterTable.cs b/Bukva/Bukva/LetterTable.cs index b115460..f44db73 100644 --- a/Bukva/Bukva/LetterTable.cs +++ b/Bukva/Bukva/LetterTable.cs @@ -8,11 +8,17 @@ class LetterTable : Dictionary { public string Filename { get; private set; } + + //Empty Letter table public LetterTable() : base() { - List list = GetCandidateFiles(); - Filename = list[0].Split('\\').Last(); - ReadInFromFile(list[0]); + + } + + public LetterTable(string filename) : base() + { + Filename = filename.Split('\\').Last(); + ReadInFromFile(filename); } public void ReadInFromFile(string filename) @@ -34,7 +40,7 @@ public void ReadInFromFile(string filename) } } - List GetCandidateFiles() + public static List GetCandidateFiles() { List languageFiles = new List(); string[] files = Directory.GetFiles("."); diff --git a/Bukva/Bukva/MainWindow.xaml b/Bukva/Bukva/MainWindow.xaml index 839b3fc..d45090e 100644 --- a/Bukva/Bukva/MainWindow.xaml +++ b/Bukva/Bukva/MainWindow.xaml @@ -5,10 +5,13 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Bukva" mc:Ignorable="d" - Title="Bukva" Height="127.768" Width="244.905" ResizeMode="CanMinimize"> + Title="Bukva" Height="150" Width="310" ResizeMode="CanMinimize"> -