mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-03 10:56:36 +01:00
Compare commits
12 Commits
shawn/comS
...
issue/4179
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a91f2000ec | ||
|
|
5355d99d60 | ||
|
|
3c632e9d9e | ||
|
|
d84c91db8a | ||
|
|
9c0997a81b | ||
|
|
818db17838 | ||
|
|
a575cd00e0 | ||
|
|
5747e5e537 | ||
|
|
2a98211240 | ||
|
|
48ca0cc2d1 | ||
|
|
d60106539f | ||
|
|
d8de2e5c1c |
@@ -132,6 +132,39 @@ steps:
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
#### END MSI
|
||||
|
||||
#### BUILDING AND SIGNING SilentFilesInUseBAFunction DLL
|
||||
- task: VSBuild@1
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build SilentFilesInUseBAFunction
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:SilentFilesInUseBAFunction
|
||||
/p:RunBuildEvents=true;PerUser=${{parameters.buildUserInstaller}};RestorePackagesConfig=true;CIBuild=true
|
||||
/p:InstallerSuffix=${{ parameters.installerSuffix }}
|
||||
-restore -graph
|
||||
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-SilentFilesInUseBAFunction.binlog
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: false # don't undo our hard work above by deleting the msi
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
|
||||
- ${{ if eq(parameters.codeSign, true) }}:
|
||||
- template: steps-esrp-signing.yml
|
||||
parameters:
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign SilentFilesInUseBAFunction
|
||||
signingIdentity: ${{ parameters.signingIdentity }}
|
||||
inputs:
|
||||
FolderPath: 'installer/$(BuildPlatform)/$(BuildConfiguration)'
|
||||
signType: batchSigning
|
||||
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
|
||||
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
|
||||
|
||||
#### END BUILDING AND SIGNING SilentFilesInUseBAFunction DLL
|
||||
|
||||
#### BOOTSTRAP BUILDING AND SIGNING
|
||||
- task: VSBuild@1
|
||||
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build VNext Bootstrapper
|
||||
@@ -148,7 +181,7 @@ steps:
|
||||
${{ parameters.additionalBuildOptions }}
|
||||
platform: $(BuildPlatform)
|
||||
configuration: $(BuildConfiguration)
|
||||
clean: false # don't undo our hard work above by deleting the MSI
|
||||
clean: false # don't undo our hard work above by deleting the MSI nor SilentFilesInUseBAFunction
|
||||
msbuildArchitecture: x64
|
||||
maximumCpuCount: true
|
||||
|
||||
|
||||
@@ -2932,7 +2932,6 @@ Global
|
||||
{D1D6BC88-09AE-4FB4-AD24-5DED46A791DD} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||
{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9} = {264B412F-DB8B-4CF8-A74B-96998B183045}
|
||||
{1AFB6476-670D-4E80-A464-657E01DFF482} = {557C4636-D7E1-4838-A504-7D19B725EE95}
|
||||
{1A066C63-64B3-45F8-92FE-664E1CCE8077} = {1AFB6476-670D-4E80-A464-657E01DFF482}
|
||||
{5CCC8468-DEC8-4D36-99D4-5C891BEBD481} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||
{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<TargetName>SilentFilesInUseBAFunction</TargetName>
|
||||
<ProjectName>PowerToysSetupCustomActionsVNext</ProjectName>
|
||||
<ProjectModuleDefinitionFile>bafunctions.def</ProjectModuleDefinitionFile>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
@@ -91,5 +92,31 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- C++ source compile-specific things for Debug/Release configurations -->
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -121,8 +121,8 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,166,306,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,223,306,50,14
|
||||
LTEXT "ZoomIt v9.0",IDC_VERSION,42,7,73,10
|
||||
LTEXT "Copyright <EFBFBD> 2006-2024 Mark Russinovich",IDC_COPYRIGHT,42,17,166,8
|
||||
LTEXT "ZoomIt v9.01",IDC_VERSION,42,7,73,10
|
||||
LTEXT "Copyright © 2006-2025 Mark Russinovich",IDC_COPYRIGHT,42,17,166,8
|
||||
CONTROL "<a HREF=""https://www.sysinternals.com"">Sysinternals - www.sysinternals.com</a>",IDC_LINK,
|
||||
"SysLink",WS_TABSTOP,42,26,150,9
|
||||
ICON "APPICON",IDC_STATIC,12,9,20,20
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
@@ -117,36 +118,46 @@ public partial class ContextMenuViewModel : ObservableObject,
|
||||
/// Generates a mapping of key -> command item for this particular item's
|
||||
/// MoreCommands. (This won't include the primary Command, but it will
|
||||
/// include the secondary one). This map can be used to quickly check if a
|
||||
/// shortcut key was pressed
|
||||
/// shortcut key was pressed. In case there are duplicate keybindings, the first
|
||||
/// one is used and the rest are ignored.
|
||||
/// </summary>
|
||||
/// <returns>a dictionary of KeyChord -> Context commands, for all commands
|
||||
/// that have a shortcut key set.</returns>
|
||||
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
|
||||
private Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
|
||||
{
|
||||
if (CurrentContextMenu is null)
|
||||
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
|
||||
|
||||
var menu = CurrentContextMenu;
|
||||
if (menu is null)
|
||||
{
|
||||
return [];
|
||||
return result;
|
||||
}
|
||||
|
||||
return CurrentContextMenu
|
||||
.OfType<CommandContextItemViewModel>()
|
||||
.Where(c => c.HasRequestedShortcut)
|
||||
.ToDictionary(
|
||||
c => c.RequestedShortcut ?? new KeyChord(0, 0, 0),
|
||||
c => c);
|
||||
foreach (var item in menu)
|
||||
{
|
||||
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
|
||||
{
|
||||
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
|
||||
var added = result.TryAdd(key, cmd);
|
||||
if (!added)
|
||||
{
|
||||
Logger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ContextKeybindingResult? CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key)
|
||||
{
|
||||
var keybindings = Keybindings();
|
||||
if (keybindings is not null)
|
||||
|
||||
// Does the pressed key match any of the keybindings?
|
||||
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
|
||||
if (keybindings.TryGetValue(pressedKeyChord, out var item))
|
||||
{
|
||||
// Does the pressed key match any of the keybindings?
|
||||
var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0);
|
||||
if (keybindings.TryGetValue(pressedKeyChord, out var item))
|
||||
{
|
||||
return InvokeCommand(item);
|
||||
}
|
||||
return InvokeCommand(item);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.ComponentModel;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
|
||||
|
||||
@@ -32,12 +34,28 @@ public interface IContextMenuContext : INotifyPropertyChanged
|
||||
/// that have a shortcut key set.</returns>
|
||||
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
|
||||
{
|
||||
return MoreCommands
|
||||
.OfType<CommandContextItemViewModel>()
|
||||
.Where(c => c.HasRequestedShortcut)
|
||||
.ToDictionary(
|
||||
c => c.RequestedShortcut ?? new KeyChord(0, 0, 0),
|
||||
c => c);
|
||||
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
|
||||
|
||||
var menu = MoreCommands;
|
||||
if (menu is null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var item in menu)
|
||||
{
|
||||
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
|
||||
{
|
||||
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
|
||||
var added = result.TryAdd(key, cmd);
|
||||
if (!added)
|
||||
{
|
||||
Logger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<Rectangle
|
||||
Height="1"
|
||||
Margin="-16,-12,-12,-12"
|
||||
Fill="{ThemeResource MenuFlyoutSeparatorThemeBrush}" />
|
||||
Fill="{ThemeResource MenuFlyoutSeparatorBackground}" />
|
||||
</DataTemplate>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -68,6 +68,7 @@
|
||||
<ComboBox
|
||||
Name="FiltersComboBox"
|
||||
x:Uid="FiltersComboBox"
|
||||
MinWidth="200"
|
||||
VerticalAlignment="Center"
|
||||
ItemTemplateSelector="{StaticResource FilterTemplateSelector}"
|
||||
ItemsSource="{x:Bind ViewModel.Filters, Mode=OneWay}"
|
||||
|
||||
@@ -131,6 +131,11 @@ public sealed partial class SearchBar : UserControl,
|
||||
WeakReferenceMessenger.Default.Send<OpenContextMenuMessage>(new OpenContextMenuMessage(null, null, null, ContextMenuFilterLocation.Bottom));
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (ctrlPressed && e.Key == VirtualKey.I)
|
||||
{
|
||||
// Today you learned that Ctrl+I in a TextBox will insert a tab
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == VirtualKey.Escape)
|
||||
{
|
||||
if (string.IsNullOrEmpty(FilterBox.Text))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.CmdPal.Core.ViewModels;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
@@ -14,6 +15,7 @@ internal sealed partial class FilterTemplateSelector : DataTemplateSelector
|
||||
|
||||
public DataTemplate? Separator { get; set; }
|
||||
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, "Microsoft.UI.Xaml.Controls.ComboBoxItem", "Microsoft.WinUI")]
|
||||
protected override DataTemplate? SelectTemplateCore(object item, DependencyObject dependencyObject)
|
||||
{
|
||||
DataTemplate? dataTemplate = Default;
|
||||
|
||||
@@ -327,11 +327,6 @@
|
||||
x:Name="FiltersDropDown"
|
||||
HorizontalAlignment="Right"
|
||||
CurrentPageViewModel="{x:Bind ViewModel.CurrentPage, Mode=OneWay}" />
|
||||
<Grid.Transitions>
|
||||
<TransitionCollection>
|
||||
<RepositionThemeTransition />
|
||||
</TransitionCollection>
|
||||
</Grid.Transitions>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -88,11 +88,11 @@ public static class ServiceHelper
|
||||
];
|
||||
}
|
||||
|
||||
IconInfo icon = Icons.GreenCircleIcon;
|
||||
IconInfo icon = Icons.PlayIcon;
|
||||
switch (s.Status)
|
||||
{
|
||||
case ServiceControllerStatus.Stopped:
|
||||
icon = Icons.RedCircleIcon;
|
||||
icon = Icons.StopIcon;
|
||||
break;
|
||||
case ServiceControllerStatus.Running:
|
||||
break;
|
||||
|
||||
@@ -10,17 +10,13 @@ internal sealed class Icons
|
||||
{
|
||||
internal static IconInfo ServicesIcon { get; } = IconHelpers.FromRelativePath("Assets\\Services.svg");
|
||||
|
||||
internal static IconInfo StopIcon { get; } = new IconInfo("\xE71A"); // Stop icon
|
||||
internal static IconInfo StopIcon { get; } = IconHelpers.FromRelativePath("Assets\\service_stopped.png");
|
||||
|
||||
internal static IconInfo PlayIcon { get; } = new IconInfo("\xEDB5"); // PlayBadge12 icon
|
||||
internal static IconInfo PlayIcon { get; } = IconHelpers.FromRelativePath("Assets\\service_running.png");
|
||||
|
||||
internal static IconInfo RefreshIcon { get; } = new IconInfo("\xE72C"); // Refresh icon
|
||||
|
||||
internal static IconInfo OpenIcon { get; } = new IconInfo("\xE8A7"); // OpenInNewWindow icon
|
||||
|
||||
internal static IconInfo GreenCircleIcon { get; } = new("\U0001f7e2"); // unicode LARGE GREEN CIRCLE
|
||||
|
||||
internal static IconInfo RedCircleIcon { get; } = new("\U0001F534"); // unicode LARGE RED CIRCLE
|
||||
|
||||
internal static IconInfo PauseIcon { get; } = new("\u23F8"); // unicode DOUBLE VERTICAL BAR, aka, "Pause"
|
||||
internal static IconInfo PauseIcon { get; } = IconHelpers.FromRelativePath("Assets\\service_paused.png");
|
||||
}
|
||||
|
||||
@@ -35,6 +35,15 @@
|
||||
<Content Update="Assets\Services.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\service_paused.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\service_running.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\service_stopped.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
|
||||
@@ -18,8 +18,8 @@ public partial class ServiceFilters : Filters
|
||||
return [
|
||||
new Filter() { Id = "all", Name = "All Services" },
|
||||
new Separator(),
|
||||
new Filter() { Id = "running", Name = "Running", Icon = Icons.GreenCircleIcon },
|
||||
new Filter() { Id = "stopped", Name = "Stopped", Icon = Icons.RedCircleIcon },
|
||||
new Filter() { Id = "running", Name = "Running", Icon = Icons.PlayIcon },
|
||||
new Filter() { Id = "stopped", Name = "Stopped", Icon = Icons.StopIcon },
|
||||
new Filter() { Id = "paused", Name = "Paused", Icon = Icons.PauseIcon },
|
||||
];
|
||||
}
|
||||
|
||||
@@ -219,7 +219,12 @@ public partial class EvilSamplesPage : ListPage
|
||||
}
|
||||
],
|
||||
},
|
||||
|
||||
new ListItem(new EvilDuplicateRequestedShortcut())
|
||||
{
|
||||
Title = "Evil keyboard shortcuts",
|
||||
Subtitle = "Two commands with the same shortcut and more...",
|
||||
Icon = new IconInfo("\uE765"),
|
||||
}
|
||||
];
|
||||
|
||||
public EvilSamplesPage()
|
||||
@@ -414,3 +419,42 @@ internal sealed partial class EvilFastUpdatesPage : DynamicListPage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Sample code")]
|
||||
internal sealed partial class EvilDuplicateRequestedShortcut : ListPage
|
||||
{
|
||||
private readonly IListItem[] _items =
|
||||
[
|
||||
new ListItem(new NoOpCommand())
|
||||
{
|
||||
Title = "I'm evil!",
|
||||
Subtitle = "I have multiple commands sharing the same keyboard shortcut",
|
||||
MoreCommands = [
|
||||
new CommandContextItem(new AnonymousCommand(() => new ToastStatusMessage("Me too executed").Show())
|
||||
{
|
||||
Result = CommandResult.KeepOpen(),
|
||||
})
|
||||
{
|
||||
Title = "Me too",
|
||||
RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1),
|
||||
},
|
||||
new CommandContextItem(new AnonymousCommand(() => new ToastStatusMessage("Me three executed").Show())
|
||||
{
|
||||
Result = CommandResult.KeepOpen(),
|
||||
})
|
||||
{
|
||||
Title = "Me three",
|
||||
RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
public override IListItem[] GetItems() => _items;
|
||||
|
||||
public EvilDuplicateRequestedShortcut()
|
||||
{
|
||||
Icon = new IconInfo(string.Empty);
|
||||
Name = "Open";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public partial class SampleFilters : Filters
|
||||
[
|
||||
new Filter() { Id = "all", Name = "All" },
|
||||
new Filter() { Id = "mod2", Name = "Every 2nd", Icon = new IconInfo("2") },
|
||||
new Filter() { Id = "mod3", Name = "Every 3rd", Icon = new IconInfo("3") },
|
||||
new Filter() { Id = "mod3", Name = "Every 3rd (and long name)", Icon = new IconInfo("3") },
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using Windows.System;
|
||||
|
||||
namespace Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
public partial class KeyChordHelpers
|
||||
public static partial class KeyChordHelpers
|
||||
{
|
||||
public static KeyChord FromModifiers(
|
||||
bool ctrl = false,
|
||||
@@ -34,4 +34,28 @@ public partial class KeyChordHelpers
|
||||
{
|
||||
return FromModifiers(ctrl, alt, shift, win, (int)vkey, scanCode);
|
||||
}
|
||||
|
||||
public static string FormatForDebug(KeyChord value)
|
||||
{
|
||||
var result = string.Empty;
|
||||
|
||||
if (value.Modifiers.HasFlag(VirtualKeyModifiers.Control))
|
||||
{
|
||||
result += "Ctrl+";
|
||||
}
|
||||
|
||||
if (value.Modifiers.HasFlag(VirtualKeyModifiers.Shift))
|
||||
{
|
||||
result += "Shift+";
|
||||
}
|
||||
|
||||
if (value.Modifiers.HasFlag(VirtualKeyModifiers.Menu))
|
||||
{
|
||||
result += "Alt+";
|
||||
}
|
||||
|
||||
result += (VirtualKey)value.Vkey;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user