[FHL] New static UX for Keyboard Manager Editor (#37747)

* Set up static new UX for Keyboard Manager Editor

* Improve the formatting and performance

* fix spelling
This commit is contained in:
Hao Liu
2025-03-04 19:09:28 +08:00
committed by GitHub
parent d90215ee8b
commit f7ed043446
24 changed files with 2136 additions and 150 deletions

View File

@@ -8,7 +8,8 @@
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
<ResourceDictionary Source="/Styles/KeyVisual.xaml" />
<ResourceDictionary Source="/Styles/CommonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>

View File

@@ -7,7 +7,10 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.UI;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
@@ -35,8 +38,14 @@ namespace KeyboardManagerEditorUI
public App()
{
this.InitializeComponent();
Logger.InitializeLogger("\\Keyboard Manager\\WinUI3Editor\\Logs");
Logger.LogInfo("keyboard-manager WinUI3 editor logger is initialized");
Task.Run(() =>
{
Logger.InitializeLogger("\\Keyboard Manager\\WinUI3Editor\\Logs");
Logger.LogInfo("keyboard-manager WinUI3 editor logger is initialized");
});
UnhandledException += App_UnhandledException;
}
/// <summary>
@@ -46,10 +55,42 @@ namespace KeyboardManagerEditorUI
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
window = new MainWindow();
window.Activate();
var appWindow = window.AppWindow;
var titleBar = appWindow.TitleBar;
titleBar.ExtendsContentIntoTitleBar = true;
titleBar.BackgroundColor = Colors.Transparent;
var windowSize = new Windows.Graphics.SizeInt32(960, 600);
appWindow.Resize(windowSize);
Task.Run(() =>
{
App.Current.Resources.MergedDictionaries.Add(new ResourceDictionary()
{
Source = new Uri("ms-appx:///Styles/CommonStyle.xaml"),
});
}).ContinueWith(_ =>
{
window.DispatcherQueue.TryEnqueue(() =>
{
window.Activate();
window.DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
(window.Content as FrameworkElement)?.UpdateLayout();
});
});
});
Logger.LogInfo("keyboard-manager WinUI3 editor window is launched");
}
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
{
Logger.LogError("Unhandled exception", e.Exception);
}
private Window? window;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KeyboardManagerEditorUI.Helpers
{
public class Remapping
{
public List<string> OriginalKeys { get; set; } = new List<string>();
public List<string> RemappedKeys { get; set; } = new List<string>();
public bool IsAllApps { get; set; } = true;
public string AppName { get; set; } = "All apps";
public bool IsEnabled { get; set; } = true;
}
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KeyboardManagerEditorUI.Helpers
{
public class URLShortcut
{
public List<string> Shortcut { get; set; } = new List<string>();
public string URL { get; set; } = string.Empty;
}
}

View File

@@ -18,6 +18,22 @@
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\$(MSBuildProjectName)</OutputPath>
</PropertyGroup>
<PropertyGroup>
<EnableDefaultXamlItems>true</EnableDefaultXamlItems>
<EnableXamlJitOptimization>true</EnableXamlJitOptimization>
</PropertyGroup>
<ItemGroup>
<None Remove="Pages\ExistingUI.xaml" />
<None Remove="Pages\Programs.xaml" />
<None Remove="Pages\Shortcuts.xaml" />
<None Remove="Pages\Text.xaml" />
<None Remove="Pages\URLs.xaml" />
<None Remove="Styles\CommonStyle.xaml" />
<None Remove="Styles\InputControl.xaml" />
<None Remove="Styles\KeyVisual.xaml" />
</ItemGroup>
<ItemGroup>
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
@@ -42,6 +58,46 @@
<ItemGroup>
<Folder Include="Assets\" />
</ItemGroup>
<ItemGroup>
<Page Update="Styles\CommonStyle.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Pages\URLs.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Pages\Text.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Pages\Programs.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Pages\Shortcuts.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Styles\InputControl.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Styles\KeyVisual.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Pages\ExistingUI.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution

View File

@@ -6,91 +6,70 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:KeyboardManagerEditorUI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="using:KeyboardManagerEditorUI.Pages"
Title="KeyboardManagerEditorUI"
mc:Ignorable="d">
<Grid Padding="16">
<StackPanel>
<Grid
x:Name="LayoutRoot"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
CornerRadius="4"
RowSpacing="6">
<Grid.RowDefinitions>
<RowDefinition Height="32" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel
Grid.ColumnSpan="2"
Margin="16,8,8,8"
VerticalAlignment="Top"
Orientation="Horizontal">
<Image Width="16" Source="ms-appx:///Assets/FluentIconsKeyboardManager.png" />
<TextBlock
Margin="10"
FontSize="24"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
Text="Remap keys" />
<TextBlock
Margin="10"
FontSize="16"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Select the key you want to change and then configure the key, shortcut or text you want it to send."
TextWrapping="Wrap" />
<TextBlock
Margin="10"
FontSize="16"
FontStyle="Italic"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Example of a remapping: Select A and send &quot;Ctrl+C&quot;, &quot;A&quot; would be your &quot;Select&quot; and &quot;Ctrl+C&quot; would be your &quot;To send&quot; command."
TextWrapping="Wrap" />
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="240" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="240" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Margin="0,12,0,0"
FontSize="16"
FontWeight="Bold"
Text="Selected:" />
<Grid Grid.Row="1" Margin="0,8,0,0">
<StackPanel>
<ToggleButton Click="Button_Click" Content="Select" />
<ComboBox
x:Name="keyComboBox"
Width="250"
PlaceholderText="select keys please" />
</StackPanel>
</Grid>
<TextBlock
Grid.Row="1"
Grid.Column="1"
Margin="24,0,24,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Text="&#xE0AB;" />
<TextBlock
Grid.Column="2"
Margin="0,12,0,0"
FontSize="16"
FontWeight="Bold"
Text="To Send:" />
<Grid
Grid.Row="1"
Grid.Column="2"
Margin="0,8,0,0">
<StackPanel>
<ToggleButton Click="Button_Click" Content="Click to select" />
<ComboBox
x:Name="newKeyComboBox"
Width="250"
PlaceholderText="select keys please" />
</StackPanel>
</Grid>
</Grid>
<Button
Margin="10"
Content="+ Add Key Remapping"
Style="{StaticResource AccentButtonStyle}" />
Margin="12,0,0,0"
Style="{StaticResource CaptionTextBlockStyle}"
Text="Keyboard Manager" />
</StackPanel>
<NavigationView
x:Name="RootView"
Grid.RowSpan="2"
Margin="0,32,0,0"
IsBackButtonVisible="Collapsed"
IsBackEnabled="False"
IsPaneToggleButtonVisible="False"
IsTitleBarAutoPaddingEnabled="True"
OpenPaneLength="240"
PaneDisplayMode="Top"
SelectionChanged="RootView_SelectionChanged">
<NavigationView.MenuItems>
<NavigationViewItem Content="Remappings" Tag="Remappings">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xEDA7;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Content="Programs" Tag="Programs">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xECAA;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Content="Text" Tag="Text">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xE8D2;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem Content="URLs" Tag="URLs">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xE8A7;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
</NavigationView.MenuItems>
<NavigationView.Content>
<Frame x:Name="NavigationFrame" Margin="0,0,0,0" />
</NavigationView.Content>
</NavigationView>
</Grid>
</Window>

View File

@@ -21,83 +21,26 @@ using Windows.Foundation.Collections;
namespace KeyboardManagerEditorUI
{
/// <summary>
/// Window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : Window
{
public class KeyboardKey
{
public int KeyCode { get; set; }
public string KeyName { get; set; } = string.Empty;
public override string ToString() => KeyName;
}
// Struct to hold key code and name pairs
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct KeyNamePair
{
public int KeyCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string KeyName;
}
[DllImport("PowerToys.KeyboardManagerEditorLibraryWrapper.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int GetKeyboardKeysList(bool isShortcut, [Out] KeyNamePair[] keyList, int maxCount);
[DllImport("PowerToys.KeyboardManagerEditorLibraryWrapper.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern bool CheckIfRemappingsAreValid();
public List<KeyboardKey> KeysList { get; private set; } = new List<KeyboardKey>();
public MainWindow()
{
this.InitializeComponent();
LoadKeyboardKeys();
keyComboBox.ItemsSource = KeysList;
keyComboBox.DisplayMemberPath = "KeyName";
newKeyComboBox.ItemsSource = KeysList;
newKeyComboBox.DisplayMemberPath = "KeyCode";
RootView.SelectedItem = RootView.MenuItems[0];
}
private void LoadKeyboardKeys()
private void RootView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
{
const int MaxKeys = 300;
KeyNamePair[] keyNamePairs = new KeyNamePair[MaxKeys];
int count = GetKeyboardKeysList(false, keyNamePairs, MaxKeys);
KeysList = new List<KeyboardKey>(count);
for (int i = 0; i < count; i++)
if (args.SelectedItem is NavigationViewItem selectedItem)
{
KeysList.Add(new KeyboardKey
switch ((string)selectedItem.Tag)
{
KeyCode = keyNamePairs[i].KeyCode,
KeyName = keyNamePairs[i].KeyName,
});
}
}
private void KeyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0 && e.AddedItems[0] is KeyboardKey key)
{
Console.WriteLine($"selected key: {key.KeyName} (code: {key.KeyCode})");
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
if (button == null)
{
// button.Background = (SolidColorBrush)Application.Current.Resources["SystemControlBackgroundAccentBrush"];
return;
case "Remappings": NavigationFrame.Navigate(typeof(Pages.Shortcuts)); break;
case "Programs": NavigationFrame.Navigate(typeof(Pages.Programs)); break;
case "Text": NavigationFrame.Navigate(typeof(Pages.Text)); break;
case "URLs": NavigationFrame.Navigate(typeof(Pages.URLs)); break;
}
}
}
}

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8" ?>
<UserControl
x:Class="KeyboardManagerEditorUI.Pages.ExistingUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:KeyboardManagerEditorUI.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<!-- WinUI3 implementation of the existing Keyboard Manager UI -->
<Grid Padding="16">
<StackPanel>
<TextBlock
Margin="10"
FontSize="24"
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
Text="Remap keys" />
<TextBlock
Margin="10"
FontSize="16"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Select the key you want to change and then configure the key, shortcut or text you want it to send."
TextWrapping="Wrap" />
<TextBlock
Margin="10"
FontSize="16"
FontStyle="Italic"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Example of a remapping: Select A and send &quot;Ctrl+C&quot;, &quot;A&quot; would be your &quot;Select&quot; and &quot;Ctrl+C&quot; would be your &quot;To send&quot; command."
TextWrapping="Wrap" />
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="240" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="240" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Margin="0,12,0,0"
FontSize="16"
FontWeight="Bold"
Text="Selected:" />
<Grid Grid.Row="1" Margin="0,8,0,0">
<StackPanel>
<ToggleButton Click="Button_Click" Content="Select" />
<ComboBox
x:Name="keyComboBox"
Width="250"
PlaceholderText="select keys please" />
</StackPanel>
</Grid>
<TextBlock
Grid.Row="1"
Grid.Column="1"
Margin="24,0,24,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Text="&#xE0AB;" />
<TextBlock
Grid.Column="2"
Margin="0,12,0,0"
FontSize="16"
FontWeight="Bold"
Text="To Send:" />
<Grid
Grid.Row="1"
Grid.Column="2"
Margin="0,8,0,0">
<StackPanel>
<ToggleButton Click="Button_Click" Content="Click to select" />
<ComboBox
x:Name="newKeyComboBox"
Width="250"
PlaceholderText="select keys please" />
</StackPanel>
</Grid>
</Grid>
<Button
Margin="10"
Content="+ Add Key Remapping"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,102 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;
// WinUI3 implementation of the Existing Keyboard Manager UI
namespace KeyboardManagerEditorUI.Pages
{
public sealed partial class ExistingUI : UserControl
{
public class KeyboardKey
{
public int KeyCode { get; set; }
public string KeyName { get; set; } = string.Empty;
public override string ToString() => KeyName;
}
// Struct to hold key code and name pairs
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct KeyNamePair
{
public int KeyCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string KeyName;
}
[DllImport("PowerToys.KeyboardManagerEditorLibraryWrapper.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int GetKeyboardKeysList(bool isShortcut, [Out] KeyNamePair[] keyList, int maxCount);
[DllImport("PowerToys.KeyboardManagerEditorLibraryWrapper.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern bool CheckIfRemappingsAreValid();
public List<KeyboardKey> KeysList { get; private set; } = new List<KeyboardKey>();
public ExistingUI()
{
this.InitializeComponent();
LoadKeyboardKeys();
keyComboBox.ItemsSource = KeysList;
keyComboBox.DisplayMemberPath = "KeyName";
newKeyComboBox.ItemsSource = KeysList;
newKeyComboBox.DisplayMemberPath = "KeyCode";
}
private void LoadKeyboardKeys()
{
const int MaxKeys = 300;
KeyNamePair[] keyNamePairs = new KeyNamePair[MaxKeys];
int count = GetKeyboardKeysList(false, keyNamePairs, MaxKeys);
KeysList = new List<KeyboardKey>(count);
for (int i = 0; i < count; i++)
{
KeysList.Add(new KeyboardKey
{
KeyCode = keyNamePairs[i].KeyCode,
KeyName = keyNamePairs[i].KeyName,
});
}
}
private void KeyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0 && e.AddedItems[0] is KeyboardKey key)
{
Console.WriteLine($"selected key: {key.KeyName} (code: {key.KeyCode})");
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
if (button == null)
{
// button.Background = (SolidColorBrush)Application.Current.Resources["SystemControlBackgroundAccentBrush"];
return;
}
}
}
}

View File

@@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="KeyboardManagerEditorUI.Pages.Programs"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helper="using:KeyboardManagerEditorUI.Helpers"
xmlns:local="using:KeyboardManagerEditorUI.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:styles="using:KeyboardManagerEditorUI.Styles"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid Padding="16">
<StackPanel>
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="Program shortcuts allow you to open specific applications when you use the configured shortcut" />
<Button
x:Name="NewShortcutBtn"
Grid.Column="0"
Height="36"
Margin="0,24,0,0"
VerticalAlignment="Top"
Click="NewShortcutBtn_Click">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
Margin="0,0,0,0"
VerticalAlignment="Center"
FontFamily="Segoe Fluent Icons"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Text="&#xE109;" />
<TextBlock Text="Program shortcut" />
</StackPanel>
</Button>
<StackPanel
Margin="0,12,0,0"
Orientation="Vertical"
Spacing="8">
<Grid
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Background="{ThemeResource LayerFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="236" />
<ColumnDefinition Width="236" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="16,-2,0,0"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Shortcut" />
<AppBarSeparator
Grid.Column="1"
Margin="-6,4,0,4"
HorizontalAlignment="Left" />
<TextBlock
Grid.Column="1"
Margin="12,-2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Program" />
<ListView
Grid.Row="1"
Grid.ColumnSpan="4"
IsItemClickEnabled="True"
ItemClick="ListView_ItemClick"
ItemsSource="{x:Bind Shortcuts}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate x:DataType="helper:URLShortcut">
<Grid Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="232" />
<ColumnDefinition Width="238" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<Rectangle
Grid.ColumnSpan="5"
Height="1"
Margin="-16,0,-16,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Fill="{ThemeResource CardStrokeColorDefaultBrush}"
Opacity="0.8" />
<ItemsControl
Grid.Column="0"
VerticalAlignment="Center"
ItemsSource="{x:Bind Shortcut}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<styles:KeyVisual
HorizontalAlignment="Left"
Content="{Binding}"
VisualType="SmallOutline" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel
Grid.Column="1"
Orientation="Horizontal"
Spacing="8">
<Image Width="16" Source="ms-appx:///Assets/Images/FluentIconsKeyboardManager.png" />
<TextBlock VerticalAlignment="Center" Text="Keyboardmanager.exe" />
<FontIcon
VerticalAlignment="Center"
FontSize="14"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Glyph="&#xE946;">
<ToolTipService.ToolTip>
<TextBlock>
<Run FontWeight="SemiBold" Text="Arguments:" />
<Run Text="-config json" />
<LineBreak />
<Run FontWeight="SemiBold" Text="Starting directory:" />
<Run Text="C:\Users\Dev\PowerToys\bin" />
<LineBreak />
<Run FontWeight="SemiBold" Text="Launch state:" />
<Run Text="Minimized" />
</TextBlock>
</ToolTipService.ToolTip>
</FontIcon>
</StackPanel>
<ToggleSwitch
Grid.ColumnSpan="4"
Margin="0,0,-112,0"
HorizontalAlignment="Right"
IsOn="True"
OffContent=""
OnContent="" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</StackPanel>
</StackPanel>
<ContentDialog
x:Name="KeyDialog"
Title="New program shortcut"
Width="480"
MinWidth="600"
MaxWidth="600"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}"
PrimaryButtonText="Save"
SecondaryButtonText="Cancel">
<StackPanel Width="480" Orientation="Vertical">
<TextBlock Margin="0,12,0,8" Text="Shortcut" />
<ToggleButton
x:Name="OriginalToggleBtn"
Padding="0,24,0,24"
HorizontalAlignment="Stretch"
Style="{StaticResource CustomShortcutToggleButtonStyle}">
<ToggleButton.Content>
<StackPanel Orientation="Horizontal" Spacing="8">
<styles:KeyVisual Content="Win" VisualType="SmallOutline" />
<styles:KeyVisual Content="U" VisualType="SmallOutline" />
</StackPanel>
</ToggleButton.Content>
</ToggleButton>
<Grid
Margin="0,24,0,0"
ColumnSpacing="4"
RowSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Header="Application" Text="Keyboardmanager.exe" />
<Button
Grid.Column="1"
Height="32"
VerticalAlignment="Bottom">
<FontIcon FontSize="14" Glyph="&#xE8DA;" />
</Button>
<TextBox
Grid.Row="1"
Header="Arguments"
Text="-config json" />
<TextBox
Grid.Row="2"
Header="Start in directory"
Text="C:\Users\Dev\PowerToys\bin" />
<Button
Grid.Row="2"
Grid.Column="1"
Height="32"
VerticalAlignment="Bottom">
<FontIcon FontSize="14" Glyph="&#xE8DA;" />
</Button>
<ComboBox
Grid.Row="3"
Header="Launch state"
SelectedIndex="0">
<ComboBoxItem Content="Show window" />
<ComboBoxItem Content="Minimized" />
</ComboBox>
</Grid>
</StackPanel>
</ContentDialog>
</Grid>
</Page>

View File

@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using KeyboardManagerEditorUI.Helpers;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace KeyboardManagerEditorUI.Pages
{
public sealed partial class Programs : Page
{
public ObservableCollection<URLShortcut> Shortcuts { get; set; }
public Programs()
{
this.InitializeComponent();
Shortcuts = new ObservableCollection<URLShortcut>();
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Win", "U", }, URL = "https://www.bing.com" });
}
private async void NewShortcutBtn_Click(object sender, RoutedEventArgs e)
{
await KeyDialog.ShowAsync();
}
private async void ListView_ItemClick(object sender, ItemClickEventArgs e)
{
await KeyDialog.ShowAsync();
}
}
}

View File

@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="KeyboardManagerEditorUI.Pages.Shortcuts"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helper="using:KeyboardManagerEditorUI.Helpers"
xmlns:local="using:KeyboardManagerEditorUI.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:styles="using:KeyboardManagerEditorUI.Styles"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid Padding="16">
<StackPanel>
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="Remappings allow you to reconfigure a single key or shortcut to a new key or shortcut" />
<Button
x:Name="NewShortcutBtn"
Grid.Column="0"
Height="36"
Margin="0,24,0,0"
VerticalAlignment="Top"
Click="NewShortcutBtn_Click">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
Margin="0,0,0,0"
VerticalAlignment="Center"
FontFamily="Segoe Fluent Icons"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Text="&#xE109;" />
<TextBlock Text="New remapping" />
</StackPanel>
</Button>
<StackPanel
Margin="0,12,0,0"
Orientation="Vertical"
Spacing="8">
<Grid
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Background="{ThemeResource LayerFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="236" />
<ColumnDefinition Width="236" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="16,-2,0,0"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Original key(s)" />
<AppBarSeparator
Grid.Column="1"
Margin="-6,4,0,4"
HorizontalAlignment="Left" />
<TextBlock
Grid.Column="1"
Margin="12,-2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="New key(s)" />
<AppBarSeparator
Grid.Column="2"
Margin="-6,4,0,4"
HorizontalAlignment="Left" />
<TextBlock
Grid.Column="2"
Margin="12,-2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Applicable apps" />
<Rectangle
Grid.ColumnSpan="4"
Height="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
<ListView
Grid.Row="1"
Grid.ColumnSpan="4"
IsItemClickEnabled="True"
ItemClick="ListView_ItemClick"
ItemsSource="{x:Bind RemappedShortcuts}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate x:DataType="helper:Remapping">
<Grid Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="232" />
<ColumnDefinition Width="238" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<Rectangle
Grid.ColumnSpan="5"
Height="1"
Margin="-16,0,-16,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Fill="{ThemeResource CardStrokeColorDefaultBrush}"
Opacity="0.8" />
<ItemsControl
Grid.Column="0"
VerticalAlignment="Center"
IsEnabled="{x:Bind IsEnabled, Mode=OneWay}"
ItemsSource="{x:Bind OriginalKeys}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<styles:KeyVisual
HorizontalAlignment="Left"
Content="{Binding}"
VisualType="SmallOutline" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl
Grid.Column="1"
Margin="0,6,0,6"
VerticalAlignment="Center"
IsEnabled="{x:Bind IsEnabled, Mode=OneWay}"
ItemsSource="{x:Bind RemappedKeys}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<styles:KeyVisual Content="{Binding}" VisualType="Small" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock
Grid.Column="2"
Margin="-4,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="12"
Text="{x:Bind AppName}" />
<ToggleSwitch
Grid.ColumnSpan="4"
Margin="0,0,-112,0"
HorizontalAlignment="Right"
IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
OffContent=""
OnContent="" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</StackPanel>
</StackPanel>
<ContentDialog
x:Name="KeyDialog"
Title="Remap a shortcut"
MinWidth="600"
MaxWidth="600"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}"
PrimaryButtonText="Save"
SecondaryButtonText="Cancel">
<Grid>
<styles:InputControl x:Name="ShortcutControl" />
</Grid>
</ContentDialog>
</Grid>
</Page>

View File

@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using KeyboardManagerEditorUI.Helpers;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace KeyboardManagerEditorUI.Pages
{
public sealed partial class Shortcuts : Page
{
public ObservableCollection<Remapping> RemappedShortcuts { get; set; }
public Shortcuts()
{
this.InitializeComponent();
RemappedShortcuts = new ObservableCollection<Remapping>();
RemappedShortcuts.Add(new Remapping() { OriginalKeys = new List<string>() { "Ctrl", "Shift", "F" }, RemappedKeys = new List<string>() { "Shift", "F" }, IsAllApps = true });
RemappedShortcuts.Add(new Remapping() { OriginalKeys = new List<string>() { "Ctrl (Left)" }, RemappedKeys = new List<string>() { "Ctrl (Right)" }, IsAllApps = true });
RemappedShortcuts.Add(new Remapping() { OriginalKeys = new List<string>() { "Shift", "M" }, RemappedKeys = new List<string>() { "Ctrl", "M" }, IsAllApps = true });
RemappedShortcuts.Add(new Remapping() { OriginalKeys = new List<string>() { "Shift", "Alt", "B" }, RemappedKeys = new List<string>() { "Alt", "B" }, IsAllApps = false, AppName = "outlook.exe" });
RemappedShortcuts.Add(new Remapping() { OriginalKeys = new List<string>() { "Numpad 1" }, RemappedKeys = new List<string>() { "Ctrl", "F" }, IsAllApps = true });
RemappedShortcuts.Add(new Remapping() { OriginalKeys = new List<string>() { "Numpad 2" }, RemappedKeys = new List<string>() { "Alt", "F" }, IsAllApps = true, AppName = "outlook.exe" });
}
private async void NewShortcutBtn_Click(object sender, RoutedEventArgs e)
{
await KeyDialog.ShowAsync();
}
private async void ListView_ItemClick(object sender, ItemClickEventArgs e)
{
if (e.ClickedItem is Remapping selectedShortcut)
{
ShortcutControl.SetOriginalKeys(selectedShortcut.OriginalKeys);
ShortcutControl.SetRemappedKeys(selectedShortcut.RemappedKeys);
ShortcutControl.SetApp(!selectedShortcut.IsAllApps, selectedShortcut.AppName);
await KeyDialog.ShowAsync();
}
}
}
}

View File

@@ -0,0 +1,180 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="KeyboardManagerEditorUI.Pages.Text"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helper="using:KeyboardManagerEditorUI.Helpers"
xmlns:local="using:KeyboardManagerEditorUI.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:styles="using:KeyboardManagerEditorUI.Styles"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid Padding="16">
<StackPanel>
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="Text shortcuts allow you to insert text in any inputfield when you use the configured text" />
<Button
x:Name="NewShortcutBtn"
Grid.Column="0"
Height="36"
Margin="0,24,0,0"
VerticalAlignment="Top"
Click="NewShortcutBtn_Click">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
Margin="0,0,0,0"
VerticalAlignment="Center"
FontFamily="Segoe Fluent Icons"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Text="&#xE109;" />
<TextBlock Text="Text shortcut" />
</StackPanel>
</Button>
<StackPanel
Margin="0,12,0,0"
Orientation="Vertical"
Spacing="8">
<Grid
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Background="{ThemeResource LayerFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="236" />
<ColumnDefinition Width="236" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="16,-2,0,0"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Shortcut" />
<AppBarSeparator
Grid.Column="1"
Margin="-6,4,0,4"
HorizontalAlignment="Left" />
<TextBlock
Grid.Column="1"
Margin="12,-2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Text" />
<ListView
Grid.Row="1"
Grid.ColumnSpan="4"
IsItemClickEnabled="True"
ItemClick="ListView_ItemClick"
ItemsSource="{x:Bind Shortcuts}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate x:DataType="helper:URLShortcut">
<Grid Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="232" />
<ColumnDefinition Width="238" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<Rectangle
Grid.ColumnSpan="5"
Height="1"
Margin="-16,0,-16,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Fill="{ThemeResource CardStrokeColorDefaultBrush}"
Opacity="0.8" />
<ItemsControl
Grid.Column="0"
VerticalAlignment="Center"
ItemsSource="{x:Bind Shortcut}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<styles:KeyVisual
HorizontalAlignment="Left"
Content="{Binding}"
VisualType="SmallOutline" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="0,0,0,0"
VerticalAlignment="Center"
FontSize="12"
Text="{x:Bind URL}"
TextTrimming="CharacterEllipsis" />
<ToggleSwitch
Grid.ColumnSpan="4"
Margin="0,0,-112,0"
HorizontalAlignment="Right"
IsOn="True"
OffContent=""
OnContent="" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</StackPanel>
</StackPanel>
<ContentDialog
x:Name="KeyDialog"
Title="New text shortcut"
Width="480"
Height="360"
MinWidth="600"
MaxWidth="600"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}"
PrimaryButtonText="Save"
SecondaryButtonText="Cancel">
<StackPanel
Width="360"
Height="360"
Orientation="Vertical">
<TextBlock Margin="0,12,0,8" Text="Shortcut" />
<ToggleButton
x:Name="OriginalToggleBtn"
Padding="0,24,0,24"
HorizontalAlignment="Stretch"
Style="{StaticResource CustomShortcutToggleButtonStyle}">
<ToggleButton.Content>
<StackPanel Orientation="Horizontal" Spacing="8">
<styles:KeyVisual Content="Shift" VisualType="SmallOutline" />
<styles:KeyVisual Content="Win" VisualType="SmallOutline" />
<styles:KeyVisual Content="M" VisualType="SmallOutline" />
</StackPanel>
</ToggleButton.Content>
</ToggleButton>
<TextBox
Height="200"
Margin="0,24,0,0"
Header="Text to insert"
Text="https://www.microsoft.com"
TextWrapping="Wrap" />
</StackPanel>
</ContentDialog>
</Grid>
</Page>

View File

@@ -0,0 +1,53 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using KeyboardManagerEditorUI.Helpers;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace KeyboardManagerEditorUI.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Text : Page
{
public ObservableCollection<URLShortcut> Shortcuts { get; set; }
public Text()
{
this.InitializeComponent();
Shortcuts = new ObservableCollection<URLShortcut>();
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Shift", "Win", "M" }, URL = "Hello" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Win", "P", }, URL = "Nice!" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Shift", "Win", "M" }, URL = "I like it" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Win", "U", }, URL = "Yes" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Ctrl", "P" }, URL = "OK" });
}
private async void NewShortcutBtn_Click(object sender, RoutedEventArgs e)
{
await KeyDialog.ShowAsync();
}
private async void ListView_ItemClick(object sender, ItemClickEventArgs e)
{
await KeyDialog.ShowAsync();
}
}
}

View File

@@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="KeyboardManagerEditorUI.Pages.URLs"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helper="using:KeyboardManagerEditorUI.Helpers"
xmlns:local="using:KeyboardManagerEditorUI.Pages"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:styles="using:KeyboardManagerEditorUI.Styles"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid Padding="16">
<StackPanel>
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="URL shortcuts allow you to open a URL when you use the configured shortcut" />
<Button
x:Name="NewShortcutBtn"
Grid.Column="0"
Height="36"
Margin="0,24,0,0"
VerticalAlignment="Top"
Click="NewShortcutBtn_Click">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock
Margin="0,0,0,0"
VerticalAlignment="Center"
FontFamily="Segoe Fluent Icons"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Text="&#xE109;" />
<TextBlock Text="URL shortcut" />
</StackPanel>
</Button>
<StackPanel
Margin="0,12,0,0"
Orientation="Vertical"
Spacing="8">
<Grid
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Background="{ThemeResource LayerFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8">
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="236" />
<ColumnDefinition Width="236" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="16,-2,0,0"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="Shortcut" />
<AppBarSeparator
Grid.Column="1"
Margin="-6,4,0,4"
HorizontalAlignment="Left" />
<TextBlock
Grid.Column="1"
Margin="12,-2,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="URL" />
<ListView
Grid.Row="1"
Grid.ColumnSpan="4"
IsItemClickEnabled="True"
ItemClick="ListView_ItemClick"
ItemsSource="{x:Bind Shortcuts}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate x:DataType="helper:URLShortcut">
<Grid Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="232" />
<ColumnDefinition Width="238" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="84" />
</Grid.ColumnDefinitions>
<Rectangle
Grid.ColumnSpan="5"
Height="1"
Margin="-16,0,-16,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
Fill="{ThemeResource CardStrokeColorDefaultBrush}"
Opacity="0.8" />
<ItemsControl
Grid.Column="0"
VerticalAlignment="Center"
ItemsSource="{x:Bind Shortcut}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<styles:KeyVisual
HorizontalAlignment="Left"
Content="{Binding}"
VisualType="SmallOutline" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<HyperlinkButton
Grid.Column="1"
Margin="-12,0,0,0"
Content="{x:Bind URL}" />
<ToggleSwitch
Grid.ColumnSpan="4"
Margin="0,0,-112,0"
HorizontalAlignment="Right"
IsOn="True"
OffContent=""
OnContent="" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</StackPanel>
</StackPanel>
<ContentDialog
x:Name="KeyDialog"
Title="New URL shortcut"
Width="480"
Height="360"
MinWidth="600"
MaxWidth="600"
PrimaryButtonStyle="{StaticResource AccentButtonStyle}"
PrimaryButtonText="Save"
SecondaryButtonText="Cancel">
<StackPanel
Width="320"
Height="264"
Orientation="Vertical">
<TextBlock Margin="0,12,0,8" Text="Shortcut" />
<ToggleButton
x:Name="OriginalToggleBtn"
Padding="0,24,0,24"
HorizontalAlignment="Stretch"
Style="{StaticResource CustomShortcutToggleButtonStyle}">
<ToggleButton.Content>
<StackPanel Orientation="Horizontal" Spacing="8">
<styles:KeyVisual Content="Shift" VisualType="SmallOutline" />
<styles:KeyVisual Content="Win" VisualType="SmallOutline" />
<styles:KeyVisual Content="M" VisualType="SmallOutline" />
</StackPanel>
</ToggleButton.Content>
</ToggleButton>
<TextBox
Margin="0,24,0,0"
Header="URL to open"
Text="https://www.microsoft.com" />
</StackPanel>
</ContentDialog>
</Grid>
</Page>

View File

@@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using KeyboardManagerEditorUI.Helpers;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace KeyboardManagerEditorUI.Pages
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class URLs : Page
{
public ObservableCollection<URLShortcut> Shortcuts { get; set; }
public URLs()
{
this.InitializeComponent();
Shortcuts = new ObservableCollection<URLShortcut>();
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Shift", "Win", "M" }, URL = "https://www.microsoft.com" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Win", "P", }, URL = "https://www.bing.com" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Shift", "Win", "M" }, URL = "https://www.windows.com" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Win", "U", }, URL = "https://www.bing.com" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Ctrl", "P" }, URL = "https://www.surface.com" });
Shortcuts.Add(new URLShortcut() { Shortcut = new List<string>() { "Alt", "Ctrl", "Shift" }, URL = "https://www.bing.com" });
}
private async void NewShortcutBtn_Click(object sender, RoutedEventArgs e)
{
await KeyDialog.ShowAsync();
}
private async void ListView_ItemClick(object sender, ItemClickEventArgs e)
{
await KeyDialog.ShowAsync();
}
}
}

View File

@@ -0,0 +1,203 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:KeyboardManagerEditorUI.Styles">
<x:Double x:Key="ContentDialogMaxWidth">960</x:Double>
<Style x:Key="CustomShortcutToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Background" Value="{ThemeResource ToggleButtonBackground}" />
<Setter Property="Foreground" Value="{ThemeResource ToggleButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource ToggleButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="1,1,1,1" />
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="CornerRadius" Value="4" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<ContentPresenter
x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CornerRadius="{TemplateBinding CornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundChecked}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundChecked}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="1,1,1,4" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundCheckedPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundCheckedPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="1,1,1,4" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundCheckedPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundCheckedPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="1,1,1,4" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundCheckedDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundCheckedDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushCheckedDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundIndeterminate}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundIndeterminate}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushIndeterminate}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminatePointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundIndeterminatePointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushIndeterminatePointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundIndeterminatePointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminatePressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundIndeterminatePressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushIndeterminatePressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundIndeterminatePressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminateDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBackgroundIndeterminateDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonForegroundIndeterminateDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ToggleButtonBorderBrushIndeterminateDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8" ?>
<UserControl
x:Class="KeyboardManagerEditorUI.Styles.InputControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:KeyboardManagerEditorUI.Styles"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Loaded="UserControl_Loaded"
mc:Ignorable="d">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="240" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="240" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Margin="0,12,0,0" Text="Original key(s)" />
<Grid Grid.Row="1" Margin="0,8,0,0">
<ToggleButton
x:Name="OriginalToggleBtn"
Padding="0,24,0,24"
HorizontalAlignment="Stretch"
Checked="OriginalToggleBtn_Checked"
Style="{StaticResource CustomShortcutToggleButtonStyle}">
<ToggleButton.Content>
<ItemsControl x:Name="OriginalKeys">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:KeyVisual Content="{Binding}" VisualType="SmallOutline" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ToggleButton.Content>
</ToggleButton>
</Grid>
<TextBlock
Grid.Row="1"
Grid.Column="1"
Margin="24,0,24,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Text="&#xE0AB;" />
<TextBlock
Grid.Column="2"
Margin="0,12,0,0"
Text="New key(s)" />
<Grid
Grid.Row="1"
Grid.Column="2"
Margin="0,8,0,0">
<ToggleButton
x:Name="RemappedToggleBtn"
Padding="0,24,0,24"
HorizontalAlignment="Stretch"
Checked="RemappedToggleBtn_Checked"
Style="{StaticResource CustomShortcutToggleButtonStyle}">
<ToggleButton.Content>
<ItemsControl x:Name="RemappedKeys">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:KeyVisual Content="{Binding}" VisualType="Small" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ToggleButton.Content>
</ToggleButton>
</Grid>
</Grid>
<CheckBox
x:Name="AllAppsCheckBox"
Margin="0,24,0,12"
Content="Only apply this remapping to a specific application"
IsChecked="True" />
<TextBox
x:Name="AppNameTextBox"
Header="Application name"
IsEnabled="{Binding ElementName=AllAppsCheckBox, Path=IsChecked}"
PlaceholderText="e.g.: outlook.exe" />
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,80 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.Foundation.Collections;
namespace KeyboardManagerEditorUI.Styles
{
public sealed partial class InputControl : UserControl
{
public InputControl()
{
this.InitializeComponent();
}
public void SetOriginalKeys(List<string> keys)
{
OriginalKeys.ItemsSource = keys;
}
public void SetRemappedKeys(List<string> keys)
{
RemappedKeys.ItemsSource = keys;
}
private void OriginalToggleBtn_Checked(object sender, RoutedEventArgs e)
{
RemappedToggleBtn.IsChecked = false;
}
private void RemappedToggleBtn_Checked(object sender, RoutedEventArgs e)
{
OriginalToggleBtn.IsChecked = false;
}
public void SetApp(bool isSpecificApp, string appName)
{
if (isSpecificApp)
{
AllAppsCheckBox.IsChecked = true;
AppNameTextBox.Text = appName;
AppNameTextBox.Visibility = Visibility.Visible;
}
else
{
AllAppsCheckBox.IsChecked = false;
AppNameTextBox.Visibility = Visibility.Collapsed;
}
}
private void AllAppsCheckBox_Checked(object sender, RoutedEventArgs e)
{
AppNameTextBox.Visibility = Visibility.Visible;
}
private void AllAppsCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
AppNameTextBox.Visibility = Visibility.Collapsed;
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
AllAppsCheckBox.Checked += AllAppsCheckBox_Checked;
AllAppsCheckBox.Unchecked += AllAppsCheckBox_Unchecked;
}
}
}

View File

@@ -0,0 +1,198 @@
// Copyright (c) Microsoft Corporation
// 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;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Markup;
using Microsoft.UI.Xaml.Media;
using Windows.System;
namespace KeyboardManagerEditorUI.Styles
{
[TemplatePart(Name = KeyPresenter, Type = typeof(ContentPresenter))]
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Default", GroupName = "StateStates")]
[TemplateVisualState(Name = "Error", GroupName = "StateStates")]
public sealed partial class KeyVisual : Control
{
private const string KeyPresenter = "KeyPresenter";
private KeyVisual? _keyVisual;
private ContentPresenter? _keyPresenter;
public object Content
{
get => (object)GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(KeyVisual), new PropertyMetadata(default(string), OnContentChanged));
public VisualType VisualType
{
get => (VisualType)GetValue(VisualTypeProperty);
set => SetValue(VisualTypeProperty, value);
}
public static readonly DependencyProperty VisualTypeProperty = DependencyProperty.Register("VisualType", typeof(VisualType), typeof(KeyVisual), new PropertyMetadata(default(VisualType), OnSizeChanged));
public bool IsError
{
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
}
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnIsErrorChanged));
public KeyVisual()
{
this.DefaultStyleKey = typeof(KeyVisual);
this.Style = GetStyleSize("TextKeyVisualStyle");
}
protected override void OnApplyTemplate()
{
IsEnabledChanged -= KeyVisual_IsEnabledChanged;
_keyVisual = (KeyVisual)this;
_keyPresenter = (ContentPresenter)_keyVisual.GetTemplateChild(KeyPresenter);
Update();
SetEnabledState();
SetErrorState();
IsEnabledChanged += KeyVisual_IsEnabledChanged;
base.OnApplyTemplate();
}
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((KeyVisual)d).Update();
}
private static void OnSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((KeyVisual)d).Update();
}
private static void OnIsErrorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((KeyVisual)d).SetErrorState();
}
private void Update()
{
if (_keyVisual == null || _keyVisual._keyPresenter == null)
{
return;
}
if (_keyVisual.Content != null)
{
if (_keyVisual.Content.GetType() == typeof(string))
{
_keyVisual.Style = GetStyleSize("TextKeyVisualStyle");
_keyVisual._keyPresenter.Content = _keyVisual.Content;
}
else
{
_keyVisual.Style = GetStyleSize("IconKeyVisualStyle");
switch ((int)_keyVisual.Content)
{
/* We can enable other glyphs in the future
case 13: // The Enter key or button.
_keyVisual._keyPresenter.Content = "\uE751"; break;
case 8: // The Back key or button.
_keyVisual._keyPresenter.Content = "\uE750"; break;
case 16: // The right Shift key or button.
case 160: // The left Shift key or button.
case 161: // The Shift key or button.
_keyVisual._keyPresenter.Content = "\uE752"; break; */
case 38: _keyVisual._keyPresenter.Content = "\uE0E4"; break; // The Up Arrow key or button.
case 40: _keyVisual._keyPresenter.Content = "\uE0E5"; break; // The Down Arrow key or button.
case 37: _keyVisual._keyPresenter.Content = "\uE0E2"; break; // The Left Arrow key or button.
case 39: _keyVisual._keyPresenter.Content = "\uE0E3"; break; // The Right Arrow key or button.
case 91: // The left Windows key
case 92: // The right Windows key
PathIcon winIcon = (PathIcon)XamlReader.Load(@"<PathIcon xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" Data=""M9,17V9h8v8ZM0,17V9H8v8ZM9,8V0h8V8ZM0,8V0H8V8Z"" />") as PathIcon;
Viewbox winIconContainer = new Viewbox();
winIconContainer.Child = winIcon;
winIconContainer.HorizontalAlignment = HorizontalAlignment.Center;
winIconContainer.VerticalAlignment = VerticalAlignment.Center;
double iconDimensions = GetIconSize();
winIconContainer.Height = iconDimensions;
winIconContainer.Width = iconDimensions;
_keyVisual._keyPresenter.Content = winIconContainer;
break;
default: _keyVisual._keyPresenter.Content = ((VirtualKey)_keyVisual.Content).ToString(); break;
}
}
}
}
public Style GetStyleSize(string styleName)
{
if (VisualType == VisualType.Small)
{
return (Style)App.Current.Resources["Small" + styleName];
}
else if (VisualType == VisualType.SmallOutline)
{
return (Style)App.Current.Resources["SmallOutline" + styleName];
}
else if (VisualType == VisualType.LargeOutline)
{
return (Style)App.Current.Resources["LargeOutline" + styleName];
}
else
{
return (Style)App.Current.Resources["Default" + styleName];
}
}
public double GetIconSize()
{
if (VisualType == VisualType.Small || VisualType == VisualType.SmallOutline)
{
return (double)App.Current.Resources["SmallIconSize"];
}
else
{
return (double)App.Current.Resources["DefaultIconSize"];
}
}
private void KeyVisual_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
private void SetErrorState()
{
VisualStateManager.GoToState(this, IsError ? "Error" : "Default", true);
}
private void SetEnabledState()
{
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
}
}
public enum VisualType
{
Small,
SmallOutline,
Large,
LargeOutline,
}
}

View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:KeyboardManagerEditorUI.Styles">
<x:Double x:Key="DefaultIconSize">16</x:Double>
<x:Double x:Key="SmallIconSize">12</x:Double>
<Style x:Key="DefaultTextKeyVisualStyle" TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="32" />
<Setter Property="MinHeight" Value="32" />
<Setter Property="Background" Value="{ThemeResource AccentButtonBackgroundPressed}" />
<Setter Property="Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
<Setter Property="Padding" Value="4,0,0,4" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:KeyVisual">
<Grid>
<Grid Height="{TemplateBinding MinHeight}">
<Border
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4" />
<Rectangle
x:Name="ContentHolder"
Fill="{TemplateBinding Background}"
RadiusX="4"
RadiusY="4" />
<ContentPresenter
x:Name="KeyPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
FontSize="12"
FontWeight="Normal"
Foreground="{TemplateBinding Foreground}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="ContentHolder.Fill" Value="{ThemeResource AccentButtonBackgroundDisabled}" />
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource AccentButtonForegroundDisabled}" />
<Setter Target="ContentHolder.Stroke" Value="{ThemeResource AccentButtonBorderBrushDisabled}" />
<!--<Setter Target="ContentHolder.StrokeThickness" Value="{TemplateBinding BorderThickness}" />-->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="StateStates">
<VisualState x:Name="Default" />
<VisualState x:Name="Error">
<VisualState.Setters>
<Setter Target="ContentHolder.Fill" Value="{ThemeResource InfoBarErrorSeverityBackgroundBrush}" />
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource InfoBarErrorSeverityIconBackground}" />
<Setter Target="ContentHolder.Stroke" Value="{ThemeResource InfoBarErrorSeverityIconBackground}" />
<Setter Target="ContentHolder.StrokeThickness" Value="2" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="SmallTextKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Height" Value="36" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="12,0,12,2" />
<Setter Property="FontSize" Value="14" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="LargeOutlineTextKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="Background" Value="{ThemeResource ControlFillColorDefaultBrush}" />
<Setter Property="Foreground" Value="{ThemeResource ButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource ControlStrongStrokeColorDefaultBrush}" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="SmallOutlineTextKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Background" Value="{ThemeResource ControlFillColorDefaultBrush}" />
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
<Setter Property="BorderBrush" Value="{ThemeResource ControlStrongStrokeColorDefaultBrush}" />
<Setter Property="Height" Value="36" />
<Setter Property="BorderThickness" Value="1,1,1,1" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="8,0,8,2" />
<Setter Property="FontSize" Value="13" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="DefaultIconKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="56" />
<Setter Property="MinHeight" Value="48" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
<Setter Property="Padding" Value="16,8,16,8" />
<Setter Property="FontSize" Value="14" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="SmallIconKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Height" Value="36" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="Padding" Value="0" />
<Setter Property="FontSize" Value="10" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="SmallOutlineIconKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
<Setter Property="Foreground" Value="{ThemeResource ButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
<Setter Property="Height" Value="36" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="0" />
<Setter Property="FontSize" Value="9" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</ResourceDictionary>