Skip to content

Commit

Permalink
Merge pull request #91 from mohammadKarimi/86-the-issue-of-the-keyboa…
Browse files Browse the repository at this point in the history
…rd-not-working-during-program-execution

the issue of the keyboard not working during program execution
  • Loading branch information
mohammadKarimi authored Nov 5, 2024
2 parents 81cbfeb + a80d8e2 commit cb9d20a
Show file tree
Hide file tree
Showing 11 changed files with 261 additions and 385 deletions.
1 change: 0 additions & 1 deletion src/Riter/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ protected override void OnStartup(StartupEventArgs e)

private static void ConfigureServices(ServiceCollection serviceCollection)
{
serviceCollection.AddSingleton<HotKeyLoader>();
serviceCollection.AddSingleton<IInkEditingModeStateHandler, InkEditingModeStateHandler>();
serviceCollection.AddSingleton<IBrushSettingsStateHandler, BrushSettingsStateHandler>();
serviceCollection.AddSingleton<IStrokeVisibilityStateHandler, StrokeVisibilityStateHandler>();
Expand Down
2 changes: 1 addition & 1 deletion src/Riter/Core/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ public class AppSettings
/// </summary>
public const string MyTelegram = "https://t.me/mhakarimi";

public IEnumerable<HotKeysConfig> HotKeysConfig { get; set; }
public List<HotKeysConfig> HotKeysConfig { get; set; }
}
114 changes: 0 additions & 114 deletions src/Riter/Core/HotKey/GlobalHotkeyManager.cs

This file was deleted.

7 changes: 6 additions & 1 deletion src/Riter/Core/HotKey/HotKey.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Riter.Core;
using System.Runtime.InteropServices;
using System.Text;

namespace Riter.Core;
public enum HotKey
{
Drawing = 9000,
Expand Down Expand Up @@ -27,3 +30,5 @@ public enum HotKey
Gray = 9022,
Black = 9023
}

public record struct HotKeiesPressed(string Key, bool CtrlPressed, bool ShiftPressed);
11 changes: 2 additions & 9 deletions src/Riter/Core/HotKey/HotKeysConfig.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
namespace Riter.Core;

public class Value
{
public string Modifiers { get; init; }

public string Key { get; init; }
}

public class HotKeysConfig
{
public string Key { get; set; }
public string Key { get; init; }

public Value Value { get; set; }
public string Value { get; init; }
}
35 changes: 0 additions & 35 deletions src/Riter/Core/HotKey/HotkeyLoader.cs

This file was deleted.

48 changes: 48 additions & 0 deletions src/Riter/Core/HotKey/KeyConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Runtime.InteropServices;
using System.Text;

namespace Riter.Core;

using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Input;

public static class KeyConverter
{
[DllImport("user32.dll")]
private static extern int ToUnicode(
uint wVirtKey,
uint wScanCode,
byte[] lpKeyState,
[Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff,
int cchBuff,
uint wFlags);

[DllImport("user32.dll")]
private static extern bool GetKeyboardState(byte[] lpKeyState);

[DllImport("user32.dll")]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);

public static string VkCodeToString(int vkCode)
{
var keyState = new byte[256];
if (!GetKeyboardState(keyState))
{
return string.Empty;
}

// Ensure the shift key state is set if necessary
if ((vkCode >= 'A' && vkCode <= 'Z') || (vkCode >= '0' && vkCode <= '9'))
{
keyState[(int)Key.LeftShift] = 0x80;
}

var scanCode = MapVirtualKey((uint)vkCode, 0);
var sb = new StringBuilder(5);
int result = ToUnicode((uint)vkCode, scanCode, keyState, sb, sb.Capacity, 0);

return result > 0 ? sb.ToString() : string.Empty;
}
}
113 changes: 89 additions & 24 deletions src/Riter/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
using System.Windows.Controls;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using Riter.Core.Extensions;
using Riter.Core.Interfaces;
using Riter.Core.UI;
using Riter.ViewModel;

namespace Riter;
Expand All @@ -11,21 +15,41 @@ namespace Riter;
/// </summary>
public partial class MainWindow : Window
{
private const int WHKEYBOARDLL = 13;
private const int WMKEYDOWN = 0x0100;
private const int WMKEYUP = 0x0101;

private static readonly LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
private static bool _ctrlPressed = false;
private static bool _shiftPressed = false;
private static PaletteStateOrchestratorViewModel _orchestratorViewModel;

private readonly IStrokeHistoryService _strokeHistoryService;
private readonly HotKeyLoader _hotKeyLoader;
private readonly PaletteStateOrchestratorViewModel _orchestratorViewModel;
private GlobalHotKeyManager _globalHotkeyManager;

public MainWindow(
PaletteStateOrchestratorViewModel orchestratorViewModel,
HotKeyLoader hotKeyLoader,
IStrokeHistoryService strokeHistoryService)

private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);

public MainWindow(PaletteStateOrchestratorViewModel orchestratorViewModel,
IStrokeHistoryService strokeHistoryService)
{
InitializeComponent();
DataContext = orchestratorViewModel;
_orchestratorViewModel = orchestratorViewModel;
_strokeHistoryService = strokeHistoryService;
_hotKeyLoader = hotKeyLoader;
// _hotKeyLoader = hotKeyLoader;

Check warning on line 52 in src/Riter/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build (Release)

_strokeHistoryService.SetMainElementToRedoAndUndo(MainInkCanvasControl.MainInkCanvas);
MainInkCanvasControl.MainInkCanvas.Strokes.StrokesChanged += StrokesChanged;

Expand All @@ -35,28 +59,69 @@ public MainWindow(
Loaded += MainWindow_Loaded;
}

protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
UnhookWindowsHookEx(_hookID);
}

/// <inheritdoc/>
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
_globalHotkeyManager = new GlobalHotKeyManager(this);
var hotkies = _hotKeyLoader.Loads(_orchestratorViewModel);
_hookID = SetHook(_proc);
}

foreach (var hotkey in hotkies)
{
_globalHotkeyManager.RegisterHotkey(
hotkey.Key,
hotkey.Value.modifiers,
hotkey.Value.key,
hotkey.Value.callback);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using var curProcess = Process.GetCurrentProcess();
using var curModule = curProcess.MainModule;
return SetWindowsHookEx(WHKEYBOARDLL, proc, GetModuleHandle(curModule.ModuleName), 0);
}

/// <inheritdoc/>
protected override void OnClosed(EventArgs e)
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
_globalHotkeyManager.Dispose();
base.OnClosed(e);
var isKey = true;
if (nCode >= 0 && (wParam == WMKEYDOWN || wParam == WMKEYUP))
{
var vkCode = Marshal.ReadInt32(lParam);

if (wParam is WMKEYDOWN)
{
if (vkCode == KeyInterop.VirtualKeyFromKey(Key.LeftCtrl) || vkCode == KeyInterop.VirtualKeyFromKey(Key.RightCtrl))
{
_ctrlPressed = true;
isKey = false;
}

if (vkCode == KeyInterop.VirtualKeyFromKey(Key.LeftShift) || vkCode == KeyInterop.VirtualKeyFromKey(Key.RightShift))
{
_shiftPressed = true;
isKey = false;
}

if (isKey)
{
_orchestratorViewModel.HandleHotkey(new HotKeiesPressed(KeyInterop.KeyFromVirtualKey(vkCode).ToString(), _ctrlPressed, _shiftPressed));
_ctrlPressed = false;
_shiftPressed = false;
}
}
else if (wParam == WMKEYUP)
{
if (vkCode == KeyInterop.VirtualKeyFromKey(Key.LeftCtrl) || vkCode == KeyInterop.VirtualKeyFromKey(Key.RightCtrl))
{
_ctrlPressed = false;
}

if (vkCode == KeyInterop.VirtualKeyFromKey(Key.LeftShift) || vkCode == KeyInterop.VirtualKeyFromKey(Key.RightShift))
{
_shiftPressed = false;
}
}
}

return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

/// <summary>
Expand Down
Loading

0 comments on commit cb9d20a

Please sign in to comment.