Skip to content

Commit a336cbb

Browse files
committed
Feature: Remote desktop additional shortcuts
1 parent f1992dd commit a336cbb

10 files changed

Lines changed: 185 additions & 10 deletions

File tree

Source/NETworkManager.Localization/Resources/Strings.Designer.cs

Lines changed: 46 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Source/NETworkManager.Localization/Resources/Strings.resx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2250,6 +2250,21 @@ $$hostname$$ --&gt; Hostname</value>
22502250
<data name="CtrlAltDel" xml:space="preserve">
22512251
<value>Ctrl+Alt+Del</value>
22522252
</data>
2253+
<data name="TaskManager" xml:space="preserve">
2254+
<value>Task Manager (Ctrl+Shift+Esc)</value>
2255+
</data>
2256+
<data name="Lock" xml:space="preserve">
2257+
<value>Lock (Win+L)</value>
2258+
</data>
2259+
<data name="ShowDesktop" xml:space="preserve">
2260+
<value>Show Desktop (Win+D)</value>
2261+
</data>
2262+
<data name="Explorer" xml:space="preserve">
2263+
<value>Explorer (Win+E)</value>
2264+
</data>
2265+
<data name="RunDialog" xml:space="preserve">
2266+
<value>Run dialog (Win+R)</value>
2267+
</data>
22532268
<data name="KeyboardShortcuts" xml:space="preserve">
22542269
<value>Keyboard shortcuts</value>
22552270
</data>

Source/NETworkManager.Models/RemoteDesktop/Keystroke.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,30 @@ public enum Keystroke
88
/// <summary>
99
/// Ctrl + Alt + Del keystroke.
1010
/// </summary>
11-
CtrlAltDel
11+
CtrlAltDel,
12+
13+
/// <summary>
14+
/// Ctrl + Shift + Esc keystroke (opens Task Manager).
15+
/// </summary>
16+
TaskManager,
17+
18+
/// <summary>
19+
/// Win + L keystroke (locks the session).
20+
/// </summary>
21+
Lock,
22+
23+
/// <summary>
24+
/// Win + D keystroke (shows the desktop / minimizes all windows).
25+
/// </summary>
26+
ShowDesktop,
27+
28+
/// <summary>
29+
/// Win + E keystroke (opens File Explorer).
30+
/// </summary>
31+
Explorer,
32+
33+
/// <summary>
34+
/// Win + R keystroke (opens the Run dialog).
35+
/// </summary>
36+
RunDialog
1237
}

Source/NETworkManager.Models/RemoteDesktop/RemoteDesktop.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ public static RemoteDesktopKeystrokeInfo GetKeystroke(Keystroke keystroke)
3838
info.ArrayKeyUp = [false, false, false, true, true, true];
3939
info.KeyData = [0x1d, 0x38, 0x53, 0x53, 0x38, 0x1d];
4040
break;
41+
case Keystroke.TaskManager: // Ctrl + Shift + Esc
42+
info.ArrayKeyUp = [false, false, false, true, true, true];
43+
info.KeyData = [0x1d, 0x2a, 0x01, 0x01, 0x2a, 0x1d];
44+
break;
45+
case Keystroke.Lock: // Win + L
46+
info.ArrayKeyUp = [false, false, true, true];
47+
info.KeyData = [0x15b, 0x26, 0x26, 0x15b];
48+
break;
49+
case Keystroke.ShowDesktop: // Win + D
50+
info.ArrayKeyUp = [false, false, true, true];
51+
info.KeyData = [0x15b, 0x20, 0x20, 0x15b];
52+
break;
53+
case Keystroke.Explorer: // Win + E
54+
info.ArrayKeyUp = [false, false, true, true];
55+
info.KeyData = [0x15b, 0x12, 0x12, 0x15b];
56+
break;
57+
case Keystroke.RunDialog: // Win + R
58+
info.ArrayKeyUp = [false, false, true, true];
59+
info.KeyData = [0x15b, 0x13, 0x13, 0x15b];
60+
break;
4161
}
4262

4363
return info;

Source/NETworkManager/Controls/DragablzTabHostWindow.xaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,26 @@
160160
Header="{x:Static localization:Strings.CtrlAltDel}"
161161
Command="{Binding Data.RemoteDesktop_SendCtrlAltDelCommand, Source={StaticResource BindingProxy}}"
162162
CommandParameter="{Binding View}" />
163+
<MenuItem
164+
Header="{x:Static localization:Strings.TaskManager}"
165+
Command="{Binding Data.RemoteDesktop_SendTaskManagerCommand, Source={StaticResource BindingProxy}}"
166+
CommandParameter="{Binding View}" />
167+
<MenuItem
168+
Header="{x:Static localization:Strings.Lock}"
169+
Command="{Binding Data.RemoteDesktop_SendLockCommand, Source={StaticResource BindingProxy}}"
170+
CommandParameter="{Binding View}" />
171+
<MenuItem
172+
Header="{x:Static localization:Strings.ShowDesktop}"
173+
Command="{Binding Data.RemoteDesktop_SendShowDesktopCommand, Source={StaticResource BindingProxy}}"
174+
CommandParameter="{Binding View}" />
175+
<MenuItem
176+
Header="{x:Static localization:Strings.Explorer}"
177+
Command="{Binding Data.RemoteDesktop_SendExplorerCommand, Source={StaticResource BindingProxy}}"
178+
CommandParameter="{Binding View}" />
179+
<MenuItem
180+
Header="{x:Static localization:Strings.RunDialog}"
181+
Command="{Binding Data.RemoteDesktop_SendRunDialogCommand, Source={StaticResource BindingProxy}}"
182+
CommandParameter="{Binding View}" />
163183
</MenuItem>
164184
</ContextMenu>
165185
</Grid.ContextMenu>

Source/NETworkManager/Controls/DragablzTabHostWindow.xaml.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,31 @@ private void RemoteDesktop_AdjustScreenAction(object view)
222222
}
223223

224224
public ICommand RemoteDesktop_SendCtrlAltDelCommand =>
225-
new RelayCommand(RemoteDesktop_SendCtrlAltDelAction, RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
225+
new RelayCommand(view => RemoteDesktop_SendKeyAction(view, Keystroke.CtrlAltDel), RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
226226

227-
private async void RemoteDesktop_SendCtrlAltDelAction(object view)
227+
public ICommand RemoteDesktop_SendTaskManagerCommand =>
228+
new RelayCommand(view => RemoteDesktop_SendKeyAction(view, Keystroke.TaskManager), RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
229+
230+
public ICommand RemoteDesktop_SendLockCommand =>
231+
new RelayCommand(view => RemoteDesktop_SendKeyAction(view, Keystroke.Lock), RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
232+
233+
public ICommand RemoteDesktop_SendShowDesktopCommand =>
234+
new RelayCommand(view => RemoteDesktop_SendKeyAction(view, Keystroke.ShowDesktop), RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
235+
236+
public ICommand RemoteDesktop_SendExplorerCommand =>
237+
new RelayCommand(view => RemoteDesktop_SendKeyAction(view, Keystroke.Explorer), RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
238+
239+
public ICommand RemoteDesktop_SendRunDialogCommand =>
240+
new RelayCommand(view => RemoteDesktop_SendKeyAction(view, Keystroke.RunDialog), RemoteDesktop_IsConnectedAndNotViewOnly_CanExecute);
241+
242+
private void RemoteDesktop_SendKeyAction(object view, Keystroke keystroke)
228243
{
229244
if (view is not RemoteDesktopControl control)
230245
return;
231246

232247
try
233248
{
234-
control.SendKey(Keystroke.CtrlAltDel);
249+
control.SendKey(keystroke);
235250
}
236251
catch (Exception ex)
237252
{

Source/NETworkManager/Controls/RemoteDesktopControl.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ public void SendKey(Keystroke keystroke)
508508

509509
RdpClient.Focus();
510510

511-
ocx.SendKeys(info.KeyData.Length, info.ArrayKeyUp, info.KeyData);
511+
ocx?.SendKeys(info.KeyData.Length, info.ArrayKeyUp, info.KeyData);
512512
}
513513

514514
/// <summary>

Source/NETworkManager/ViewModels/RemoteDesktopHostViewModel.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,16 +351,31 @@ private void AdjustScreenAction(object view)
351351
}
352352

353353
public ICommand SendCtrlAltDelCommand =>
354-
new RelayCommand(SendCtrlAltDelAction, IsConnectedAndNotViewOnly_CanExecute);
354+
new RelayCommand(view => SendKeyAction(view, Keystroke.CtrlAltDel), IsConnectedAndNotViewOnly_CanExecute);
355355

356-
private async void SendCtrlAltDelAction(object view)
356+
public ICommand SendTaskManagerCommand =>
357+
new RelayCommand(view => SendKeyAction(view, Keystroke.TaskManager), IsConnectedAndNotViewOnly_CanExecute);
358+
359+
public ICommand SendLockCommand =>
360+
new RelayCommand(view => SendKeyAction(view, Keystroke.Lock), IsConnectedAndNotViewOnly_CanExecute);
361+
362+
public ICommand SendShowDesktopCommand =>
363+
new RelayCommand(view => SendKeyAction(view, Keystroke.ShowDesktop), IsConnectedAndNotViewOnly_CanExecute);
364+
365+
public ICommand SendExplorerCommand =>
366+
new RelayCommand(view => SendKeyAction(view, Keystroke.Explorer), IsConnectedAndNotViewOnly_CanExecute);
367+
368+
public ICommand SendRunDialogCommand =>
369+
new RelayCommand(view => SendKeyAction(view, Keystroke.RunDialog), IsConnectedAndNotViewOnly_CanExecute);
370+
371+
private async void SendKeyAction(object view, Keystroke keystroke)
357372
{
358373
if (view is not RemoteDesktopControl control)
359374
return;
360375

361376
try
362377
{
363-
control.SendKey(Keystroke.CtrlAltDel);
378+
control.SendKey(keystroke);
364379
}
365380
catch (Exception ex)
366381
{

Source/NETworkManager/Views/RemoteDesktopHostView.xaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,21 @@
142142
<MenuItem Header="{x:Static localization:Strings.CtrlAltDel}"
143143
Command="{Binding Data.SendCtrlAltDelCommand, Source={StaticResource BindingProxy}}"
144144
CommandParameter="{Binding View}" />
145+
<MenuItem Header="{x:Static localization:Strings.TaskManager}"
146+
Command="{Binding Data.SendTaskManagerCommand, Source={StaticResource BindingProxy}}"
147+
CommandParameter="{Binding View}" />
148+
<MenuItem Header="{x:Static localization:Strings.Lock}"
149+
Command="{Binding Data.SendLockCommand, Source={StaticResource BindingProxy}}"
150+
CommandParameter="{Binding View}" />
151+
<MenuItem Header="{x:Static localization:Strings.ShowDesktop}"
152+
Command="{Binding Data.SendShowDesktopCommand, Source={StaticResource BindingProxy}}"
153+
CommandParameter="{Binding View}" />
154+
<MenuItem Header="{x:Static localization:Strings.Explorer}"
155+
Command="{Binding Data.SendExplorerCommand, Source={StaticResource BindingProxy}}"
156+
CommandParameter="{Binding View}" />
157+
<MenuItem Header="{x:Static localization:Strings.RunDialog}"
158+
Command="{Binding Data.SendRunDialogCommand, Source={StaticResource BindingProxy}}"
159+
CommandParameter="{Binding View}" />
145160
</MenuItem>
146161
</ContextMenu>
147162
</Grid.ContextMenu>

Website/docs/application/remote-desktop.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ Right-clicking a session tab opens a context menu:
3737
| **Adjust screen** | Adjusts the screen size to the current view size; only available if [Display](#display) is set to `Adjust screen automatically` or `Use the current view size as screen size` (only if connected) |
3838
| **View only** | Toggles [view only](#view-only) mode, which blocks keyboard and mouse input to the remote session while the screen keeps updating (only if connected) |
3939
| **Keyboard shortcuts > Ctrl+Alt+Del** | Sends Ctrl+Alt+Del to the remote computer (only if connected and not in view only mode) |
40+
| **Keyboard shortcuts > Task Manager** | Sends Ctrl+Shift+Esc to the remote computer, opening Task Manager directly (only if connected and not in view only mode) |
41+
| **Keyboard shortcuts > Lock** | Sends Win+L to the remote computer, locking the session (only if connected and not in view only mode) |
42+
| **Keyboard shortcuts > Show Desktop** | Sends Win+D to the remote computer, minimizing all windows (only if connected and not in view only mode) |
43+
| **Keyboard shortcuts > Explorer** | Sends Win+E to the remote computer, opening File Explorer (only if connected and not in view only mode) |
44+
| **Keyboard shortcuts > Run dialog** | Sends Win+R to the remote computer, opening the Run dialog (only if connected and not in view only mode) |
4045

4146
## Connect
4247

@@ -127,7 +132,7 @@ Connect to the admin (console) session of the remote computer.
127132

128133
### View only
129134

130-
Connect in view only mode. Keyboard and mouse input to the remote session is blocked while the screen keeps updating, so the session can be monitored without interacting with it. View only mode can also be toggled on the fly via the [tab context menu](#tab-context-menu). While it is active, an eye icon is shown on the tab and the **Fullscreen** and **Ctrl+Alt+Del** actions are disabled to prevent bypassing it.
135+
Connect in view only mode. Keyboard and mouse input to the remote session is blocked while the screen keeps updating, so the session can be monitored without interacting with it. View only mode can also be toggled on the fly via the [tab context menu](#tab-context-menu). While it is active, an eye icon is shown on the tab and the **Fullscreen** action and all **Keyboard shortcuts** are disabled to prevent bypassing it.
131136

132137
**Type:** `Boolean`
133138

0 commit comments

Comments
 (0)