@@ -81,60 +81,46 @@ namespace Files.App.Data.Commands
8181 [ Keys . Number7 ] = "7" ,
8282 [ Keys . Number8 ] = "8" ,
8383 [ Keys . Number9 ] = "9" ,
84- [ Keys . Pad0 ] = GetLocalizedKey ( "Pad0" ) ,
85- [ Keys . Pad1 ] = GetLocalizedKey ( "Pad1" ) ,
86- [ Keys . Pad2 ] = GetLocalizedKey ( "Pad2" ) ,
87- [ Keys . Pad3 ] = GetLocalizedKey ( "Pad3" ) ,
88- [ Keys . Pad4 ] = GetLocalizedKey ( "Pad4" ) ,
89- [ Keys . Pad5 ] = GetLocalizedKey ( "Pad5" ) ,
90- [ Keys . Pad6 ] = GetLocalizedKey ( "Pad6" ) ,
91- [ Keys . Pad7 ] = GetLocalizedKey ( "Pad7" ) ,
92- [ Keys . Pad8 ] = GetLocalizedKey ( "Pad8" ) ,
93- [ Keys . Pad9 ] = GetLocalizedKey ( "Pad9" ) ,
94- [ Keys . A ] = "A" ,
95- [ Keys . B ] = "B" ,
96- [ Keys . C ] = "C" ,
97- [ Keys . D ] = "D" ,
98- [ Keys . E ] = "E" ,
99- [ Keys . F ] = "F" ,
100- [ Keys . G ] = "G" ,
101- [ Keys . H ] = "H" ,
102- [ Keys . I ] = "I" ,
103- [ Keys . J ] = "J" ,
104- [ Keys . K ] = "K" ,
105- [ Keys . L ] = "L" ,
106- [ Keys . M ] = "M" ,
107- [ Keys . N ] = "N" ,
108- [ Keys . O ] = "O" ,
109- [ Keys . P ] = "P" ,
110- [ Keys . Q ] = "Q" ,
111- [ Keys . R ] = "R" ,
112- [ Keys . S ] = "S" ,
113- [ Keys . T ] = "T" ,
114- [ Keys . U ] = "U" ,
115- [ Keys . V ] = "V" ,
116- [ Keys . W ] = "W" ,
117- [ Keys . X ] = "X" ,
118- [ Keys . Y ] = "Y" ,
119- [ Keys . Z ] = "Z" ,
120- [ Keys . Add ] = "+" ,
121- [ Keys . Subtract ] = "-" ,
122- [ Keys . Multiply ] = "*" ,
123- [ Keys . Divide ] = "/" ,
124- [ Keys . Oem1 ] = GetKeyCharacter ( Forms . Keys . Oem1 ) ,
125- [ Keys . Oem2 ] = GetKeyCharacter ( Forms . Keys . Oem2 ) ,
126- [ Keys . Oem3 ] = GetKeyCharacter ( Forms . Keys . Oem3 ) ,
127- [ Keys . Oem4 ] = GetKeyCharacter ( Forms . Keys . Oem4 ) ,
128- [ Keys . Oem5 ] = GetKeyCharacter ( Forms . Keys . Oem5 ) ,
129- [ Keys . Oem6 ] = GetKeyCharacter ( Forms . Keys . Oem6 ) ,
130- [ Keys . Oem7 ] = GetKeyCharacter ( Forms . Keys . Oem7 ) ,
131- [ Keys . Oem8 ] = GetKeyCharacter ( Forms . Keys . Oem8 ) ,
132- [ Keys . OemPlus ] = GetKeyCharacter ( Forms . Keys . Oemplus ) ,
133- [ Keys . OemComma ] = GetKeyCharacter ( Forms . Keys . Oemcomma ) ,
134- [ Keys . OemMinus ] = GetKeyCharacter ( Forms . Keys . OemMinus ) ,
135- [ Keys . OemPeriod ] = GetKeyCharacter ( Forms . Keys . OemPeriod ) ,
136- [ Keys . Oem102 ] = GetKeyCharacter ( Forms . Keys . Oem102 ) ,
137- [ Keys . OemClear ] = GetKeyCharacter ( Forms . Keys . OemClear ) ,
84+ [ Keys . A ] = GetKeyCharacter ( Forms . Keys . A ) . ToUpper ( ) ,
85+ [ Keys . B ] = GetKeyCharacter ( Forms . Keys . B ) . ToUpper ( ) ,
86+ [ Keys . C ] = GetKeyCharacter ( Forms . Keys . C ) . ToUpper ( ) ,
87+ [ Keys . D ] = GetKeyCharacter ( Forms . Keys . D ) . ToUpper ( ) ,
88+ [ Keys . E ] = GetKeyCharacter ( Forms . Keys . E ) . ToUpper ( ) ,
89+ [ Keys . F ] = GetKeyCharacter ( Forms . Keys . F ) . ToUpper ( ) ,
90+ [ Keys . G ] = GetKeyCharacter ( Forms . Keys . G ) . ToUpper ( ) ,
91+ [ Keys . H ] = GetKeyCharacter ( Forms . Keys . H ) . ToUpper ( ) ,
92+ [ Keys . I ] = GetKeyCharacter ( Forms . Keys . I ) . ToUpper ( ) ,
93+ [ Keys . J ] = GetKeyCharacter ( Forms . Keys . J ) . ToUpper ( ) ,
94+ [ Keys . K ] = GetKeyCharacter ( Forms . Keys . K ) . ToUpper ( ) ,
95+ [ Keys . L ] = GetKeyCharacter ( Forms . Keys . L ) . ToUpper ( ) ,
96+ [ Keys . M ] = GetKeyCharacter ( Forms . Keys . M ) . ToUpper ( ) ,
97+ [ Keys . N ] = GetKeyCharacter ( Forms . Keys . N ) . ToUpper ( ) ,
98+ [ Keys . O ] = GetKeyCharacter ( Forms . Keys . O ) . ToUpper ( ) ,
99+ [ Keys . P ] = GetKeyCharacter ( Forms . Keys . P ) . ToUpper ( ) ,
100+ [ Keys . Q ] = GetKeyCharacter ( Forms . Keys . Q ) . ToUpper ( ) ,
101+ [ Keys . R ] = GetKeyCharacter ( Forms . Keys . R ) . ToUpper ( ) ,
102+ [ Keys . S ] = GetKeyCharacter ( Forms . Keys . S ) . ToUpper ( ) ,
103+ [ Keys . T ] = GetKeyCharacter ( Forms . Keys . T ) . ToUpper ( ) ,
104+ [ Keys . U ] = GetKeyCharacter ( Forms . Keys . U ) . ToUpper ( ) ,
105+ [ Keys . V ] = GetKeyCharacter ( Forms . Keys . V ) . ToUpper ( ) ,
106+ [ Keys . W ] = GetKeyCharacter ( Forms . Keys . W ) . ToUpper ( ) ,
107+ [ Keys . X ] = GetKeyCharacter ( Forms . Keys . X ) . ToUpper ( ) ,
108+ [ Keys . Y ] = GetKeyCharacter ( Forms . Keys . Y ) . ToUpper ( ) ,
109+ [ Keys . Z ] = GetKeyCharacter ( Forms . Keys . Z ) . ToUpper ( ) ,
110+ [ Keys . Oem1 ] = GetKeyCharacter ( Forms . Keys . Oem1 ) . ToUpper ( ) ,
111+ [ Keys . Oem2 ] = GetKeyCharacter ( Forms . Keys . Oem2 ) . ToUpper ( ) ,
112+ [ Keys . Oem3 ] = GetKeyCharacter ( Forms . Keys . Oem3 ) . ToUpper ( ) ,
113+ [ Keys . Oem4 ] = GetKeyCharacter ( Forms . Keys . Oem4 ) . ToUpper ( ) ,
114+ [ Keys . Oem5 ] = GetKeyCharacter ( Forms . Keys . Oem5 ) . ToUpper ( ) ,
115+ [ Keys . Oem6 ] = GetKeyCharacter ( Forms . Keys . Oem6 ) . ToUpper ( ) ,
116+ [ Keys . Oem7 ] = GetKeyCharacter ( Forms . Keys . Oem7 ) . ToUpper ( ) ,
117+ [ Keys . Oem8 ] = GetKeyCharacter ( Forms . Keys . Oem8 ) . ToUpper ( ) ,
118+ [ Keys . Oem102 ] = GetKeyCharacter ( Forms . Keys . Oem102 ) . ToUpper ( ) ,
119+ [ Keys . OemPlus ] = GetKeyCharacter ( Forms . Keys . Oemplus ) . ToUpper ( ) ,
120+ [ Keys . OemComma ] = GetKeyCharacter ( Forms . Keys . Oemcomma ) . ToUpper ( ) ,
121+ [ Keys . OemMinus ] = GetKeyCharacter ( Forms . Keys . OemMinus ) . ToUpper ( ) ,
122+ [ Keys . OemPeriod ] = GetKeyCharacter ( Forms . Keys . OemPeriod ) . ToUpper ( ) ,
123+ [ Keys . OemClear ] = GetKeyCharacter ( Forms . Keys . OemClear ) . ToUpper ( ) ,
138124 [ Keys . Application ] = GetLocalizedKey ( "Application" ) ,
139125 [ Keys . Application1 ] = GetLocalizedKey ( "Application1" ) ,
140126 [ Keys . Application2 ] = GetLocalizedKey ( "Application2" ) ,
@@ -154,6 +140,23 @@ namespace Files.App.Data.Commands
154140 [ Keys . Mute ] = GetLocalizedKey ( "MediaMute" ) ,
155141 [ Keys . VolumeDown ] = GetLocalizedKey ( "MediaVolumeDown" ) ,
156142 [ Keys . VolumeUp ] = GetLocalizedKey ( "MediaVolumeUp" ) ,
143+
144+ // NumPad Keys
145+ [ Keys . Add ] = GetLocalizedNumPadKey ( "+" ) ,
146+ [ Keys . Subtract ] = GetLocalizedNumPadKey ( "-" ) ,
147+ [ Keys . Multiply ] = GetLocalizedNumPadKey ( "*" ) ,
148+ [ Keys . Divide ] = GetLocalizedNumPadKey ( "/" ) ,
149+ [ Keys . Decimal ] = GetLocalizedNumPadKey ( "." ) ,
150+ [ Keys . Pad0 ] = GetLocalizedNumPadKey ( "0" ) ,
151+ [ Keys . Pad1 ] = GetLocalizedNumPadKey ( "1" ) ,
152+ [ Keys . Pad2 ] = GetLocalizedNumPadKey ( "2" ) ,
153+ [ Keys . Pad3 ] = GetLocalizedNumPadKey ( "3" ) ,
154+ [ Keys . Pad4 ] = GetLocalizedNumPadKey ( "4" ) ,
155+ [ Keys . Pad5 ] = GetLocalizedNumPadKey ( "5" ) ,
156+ [ Keys . Pad6 ] = GetLocalizedNumPadKey ( "6" ) ,
157+ [ Keys . Pad7 ] = GetLocalizedNumPadKey ( "7" ) ,
158+ [ Keys . Pad8 ] = GetLocalizedNumPadKey ( "8" ) ,
159+ [ Keys . Pad9 ] = GetLocalizedNumPadKey ( "9" ) ,
157160 } . ToFrozenDictionary ( ) ;
158161
159162 /// <summary>
@@ -278,9 +281,39 @@ public static HotKey Parse(string code, bool localized = true)
278281 var key = Keys . None ;
279282 var modifier = KeyModifiers . None ;
280283 bool isVisible = true ;
284+ var splitCharacter = '+' ;
281285
286+ // Remove leading and trailing whitespace from the code string
282287 code = code . Trim ( ) ;
283- var parts = code . Split ( '+' ) . Select ( part => part . Trim ( ) ) ;
288+
289+ // Split the code by "++" into a list of parts
290+ List < string > parts = [ .. code . Split ( new string ( splitCharacter , 2 ) , StringSplitOptions . None ) ] ;
291+
292+ if ( parts . Count == 2 )
293+ {
294+ // If there are two parts after splitting by "++", split the first part by "+"
295+ // and append the second part prefixed with a "+"
296+ parts = [ .. parts . First ( ) . Split ( splitCharacter ) , splitCharacter + parts . Last ( ) ] ;
297+ }
298+ else
299+ {
300+ // Split the code by a single '+' and trim each part
301+ parts = [ .. code . Split ( splitCharacter ) ] ;
302+
303+ // If the resulting list has two parts and one of them is empty, use the original code as the single element
304+ if ( parts . Count == 2 && ( string . IsNullOrEmpty ( parts . First ( ) ) || string . IsNullOrEmpty ( parts . Last ( ) ) ) )
305+ {
306+ parts = [ code ] ;
307+ }
308+ else if ( parts . Count > 0 && string . IsNullOrEmpty ( parts . Last ( ) ) )
309+ {
310+ // If the last part is empty, remove it and add a "+" to the last non-empty part
311+ parts . RemoveAt ( parts . Count - 1 ) ;
312+ parts [ ^ 1 ] += splitCharacter ;
313+ }
314+ }
315+
316+ parts = [ .. parts . Select ( part => part . Trim ( ) ) ] ;
284317
285318 foreach ( var part in parts )
286319 {
@@ -330,11 +363,31 @@ private static string GetLocalizedKey(string key)
330363 return $ "Key/{ key } ". GetLocalizedResource ( ) ;
331364 }
332365
366+ private static string GetLocalizedNumPadKey ( string key )
367+ {
368+ return "NumPadTypeName" . GetLocalizedResource ( ) + " " + key ;
369+ }
370+
333371 private static string GetKeyCharacter ( Forms . Keys key )
334372 {
335- var buffer = new StringBuilder ( 256 ) ;
373+ var buffer = new StringBuilder ( 4 ) ;
336374 var state = new byte [ 256 ] ;
337- _ = Win32PInvoke . ToUnicode ( ( uint ) key , 0 , state , buffer , 256 , 0 ) ;
375+
376+ // Get the current keyboard state
377+ if ( ! Win32PInvoke . GetKeyboardState ( state ) )
378+ return buffer . ToString ( ) ;
379+
380+ // Convert the key to its virtual key code
381+ var virtualKey = ( uint ) key ;
382+
383+ // Map the virtual key to a scan code
384+ var scanCode = Win32PInvoke . MapVirtualKey ( virtualKey , 0 ) ;
385+
386+ // Get the active keyboard layout
387+ var keyboardLayout = Win32PInvoke . GetKeyboardLayout ( 0 ) ;
388+
389+ if ( Win32PInvoke . ToUnicodeEx ( virtualKey , scanCode , state , buffer , buffer . Capacity , 0 , keyboardLayout ) > 0 )
390+ return buffer [ ^ 1 ] . ToString ( ) ;
338391
339392 return buffer . ToString ( ) ;
340393 }
0 commit comments