-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #91 from mohammadKarimi/86-the-issue-of-the-keyboa…
…rd-not-working-during-program-execution the issue of the keyboard not working during program execution
- Loading branch information
Showing
11 changed files
with
261 additions
and
385 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; } | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
|
@@ -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 GitHub Actions / build (Release)
|
||
_strokeHistoryService.SetMainElementToRedoAndUndo(MainInkCanvasControl.MainInkCanvas); | ||
MainInkCanvasControl.MainInkCanvas.Strokes.StrokesChanged += StrokesChanged; | ||
|
||
|
@@ -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> | ||
|
Oops, something went wrong.