From 1bf334bda7a563e667f73364bc54ba8bd47a0c93 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 29 Dec 2024 17:58:29 +0100 Subject: [PATCH 1/5] add context menus --- .../RegistryPreviewUILib/ClipboardHelper.cs | 33 +++++++++++++ .../RegistryPreviewUILib/RegistryKey.xaml.cs | 18 +++++++ .../RegistryPreviewMainPage.Utilities.cs | 6 ++- .../RegistryPreviewMainPage.xaml | 48 ++++++++++++++++++- .../RegistryPreviewMainPage.xaml.cs | 1 + .../RegistryValue.xaml.cs | 45 ++++++++++++++++- 6 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 src/modules/registrypreview/RegistryPreviewUILib/ClipboardHelper.cs diff --git a/src/modules/registrypreview/RegistryPreviewUILib/ClipboardHelper.cs b/src/modules/registrypreview/RegistryPreviewUILib/ClipboardHelper.cs new file mode 100644 index 000000000000..7df10de2fac3 --- /dev/null +++ b/src/modules/registrypreview/RegistryPreviewUILib/ClipboardHelper.cs @@ -0,0 +1,33 @@ +// 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 Windows.ApplicationModel.DataTransfer; + +namespace RegistryPreviewUILib +{ + /// + /// Helper class to centralize clipboard actions + /// + internal static class ClipboardHelper + { + internal static void CopyToClipboardAction(string text) + { + try + { + var data = new DataPackage(); + data.SetText(text); + Clipboard.SetContent(data); + Clipboard.Flush(); + } + catch + { + } + } + } +} diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryKey.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryKey.xaml.cs index 44660000592f..6a190bcdb2b4 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryKey.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryKey.xaml.cs @@ -2,6 +2,10 @@ // 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.Windows.Input; +using CommunityToolkit.Mvvm.Input; +using Windows.ApplicationModel.DataTransfer; + namespace RegistryPreviewUILib { /// @@ -28,5 +32,19 @@ public RegistryKey(string name, string fullPath, string image, string toolTipTex this.Image = image; this.ToolTipText = toolTipText; } + + public ICommand CopyToClipboardName_Click => new RelayCommand(CopyToClipboardName); + + public ICommand CopyToClipboardKeyPath_Click => new RelayCommand(CopyToClipboardKeyPath); + + private void CopyToClipboardName() + { + ClipboardHelper.CopyToClipboardAction(Name); + } + + private void CopyToClipboardKeyPath() + { + ClipboardHelper.CopyToClipboardAction(FullPath); + } } } diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index b3073669f7b7..27d14f973841 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -23,6 +23,7 @@ namespace RegistryPreviewUILib public sealed partial class RegistryPreviewMainPage : Page { private static SemaphoreSlim _dialogSemaphore = new(1); + private string lastKeyPath; public delegate void UpdateWindowTitleFunction(string title); @@ -261,6 +262,7 @@ private bool ParseRegistryFile(string filenameText) registryLine = StripFirstAndLast(registryLine); treeViewNode = AddTextToTree(registryLine, imageName); + lastKeyPath = registryLine; } else if (registryLine.StartsWith('"') && registryLine.EndsWith("=-", StringComparison.InvariantCulture)) { @@ -271,7 +273,7 @@ private bool ParseRegistryFile(string filenameText) registryLine = StripFirstAndLast(registryLine); // Create a new listview item that will be used to display the delete value and store it - registryValue = new RegistryValue(registryLine, string.Empty, string.Empty); + registryValue = new RegistryValue(registryLine, string.Empty, string.Empty, lastKeyPath); SetValueToolTip(registryValue); // store the ListViewItem, if we have a valid Key to attach to @@ -310,7 +312,7 @@ private bool ParseRegistryFile(string filenameText) value = value.Trim(); // Create a new listview item that will be used to display the value - registryValue = new RegistryValue(name, "REG_SZ", string.Empty); + registryValue = new RegistryValue(name, "REG_SZ", string.Empty, lastKeyPath); // if the first character is a " then this is a string value, so find the last most " which will avoid comments if (value.StartsWith('"')) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml index 058663459ec4..8759b224d555 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml @@ -167,6 +167,12 @@ IsTabStop="False" Orientation="Horizontal" Spacing="8"> + + + + + + + + + + + + + + + FontSize="{StaticResource CaptionTextBlockFontSize}"> + + + + + FontSize="{StaticResource CaptionTextBlockFontSize}"> + + + + diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs index 1687a24293d3..06e435c9f0e4 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml.cs @@ -8,6 +8,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.Windows.ApplicationModel.Resources; +using Windows.ApplicationModel.DataTransfer; namespace RegistryPreviewUILib { diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs index 3e0d16c9328f..32f32c07e701 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs @@ -3,6 +3,10 @@ // See the LICENSE file in the project root for more information. using System; +using System.Windows.Input; +using CommunityToolkit.Mvvm.Input; +using Microsoft.UI.Xaml; +using Windows.ApplicationModel.DataTransfer; namespace RegistryPreviewUILib { @@ -17,6 +21,8 @@ public class RegistryValue private static Uri uriDeleteValue = new Uri("ms-appx:///Assets/RegistryPreview/deleted-value32.png"); private static Uri uriErrorValue = new Uri("ms-appx:///Assets/RegistryPreview/error32.png"); + public string Key { get; set; } + public string Name { get; set; } public string Type { get; set; } @@ -46,12 +52,49 @@ public Uri ImageUri } } - public RegistryValue(string name, string type, string value) + public RegistryValue(string name, string type, string value, string key) { this.Name = name; this.Type = type; this.Value = value; this.ToolTipText = string.Empty; + this.Key = key; + } + + // Commands + public ICommand CopyToClipboardEntry_Click => new RelayCommand(CopyToClipboardEntry); + + public ICommand CopyToClipboardWithPath_Click => new RelayCommand(CopyToClipboardEntryWithPath); + + public ICommand CopyToClipboardName_Click => new RelayCommand(CopyToClipboardName); + + public ICommand CopyToClipboardType_Click => new RelayCommand(CopyToClipboardType); + + public ICommand CopyToClipboardData_Click => new RelayCommand(CopyToClipboardData); + + private void CopyToClipboardEntry() + { + ClipboardHelper.CopyToClipboardAction($"{Name}\r\n{Type}\r\n{Value}"); + } + + private void CopyToClipboardEntryWithPath() + { + ClipboardHelper.CopyToClipboardAction($"{Key}\r\n{Name}\r\n{Type}\r\n{Value}"); + } + + private void CopyToClipboardName() + { + ClipboardHelper.CopyToClipboardAction(Name); + } + + private void CopyToClipboardType() + { + ClipboardHelper.CopyToClipboardAction(Type); + } + + private void CopyToClipboardData() + { + ClipboardHelper.CopyToClipboardAction(Value); } } } From aff7121b6604fbf1ad3e3606c89fdc25d8fae690 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:17:48 +0100 Subject: [PATCH 2/5] string resources for contextmenu --- .../RegistryPreviewMainPage.xaml | 22 +++++++-------- .../Strings/en-US/Resources.resw | 28 +++++++++++++++++++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml index 8759b224d555..7f2f9225cbf4 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml @@ -169,8 +169,8 @@ Spacing="8"> - - + + - + - - + + - + - - + + @@ -266,10 +266,10 @@ - + - - + + diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw index 580d108d9a7b..52a1fcb25069 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw +++ b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw @@ -257,4 +257,32 @@ (zero-length binary value) + + Copy + Like "Copy item" + + + Copy path + Like "Copy item" + + + Copy name + Like "Copy item" + + + Copy type + Like "Copy item" + + + Copy data + Like "Copy item" + + + Copy value + Like "Copy item" + + + Copy value with key path + Like "Copy item" + \ No newline at end of file From 7b1bee5a45c48f118b27565b250d37cb815141c7 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:18:39 +0100 Subject: [PATCH 3/5] fix line break parsing for MULTI_SZ --- .../RegistryPreviewMainPage.Utilities.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs index 27d14f973841..b8fc6e4e1d9a 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs @@ -555,19 +555,10 @@ private bool ParseRegistryFile(string filenameText) var bytes = value.Split(',').Select( c => c.Length == 2 ? byte.Parse(c, NumberStyles.HexNumber, CultureInfo.InvariantCulture) : throw null).ToArray(); - if (registryValue.Type == "REG_MULTI_SZ") - { - // Replace zeros (00,00) with spaces - for (int i = 0; i < bytes.Length; i += 2) - { - if (bytes[i] == 0 && bytes[i + 1] == 0) - { - bytes[i] = 0x20; - } - } - } - value = Encoding.Unicode.GetString(bytes); + + // Correctly format line breaks and remove trailing line breaks. (GitHub PowerToys #36629) + value = value.Replace('\0', '\r').TrimEnd('\r'); } catch { From 7b17d6b3b2c8868bc4a90c9926c5dd82a759c934 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:20:18 +0100 Subject: [PATCH 4/5] better presentation of multiline values and value tooltip --- .../RegistryPreviewMainPage.xaml | 31 ++++++++++++------- .../RegistryValue.xaml.cs | 2 ++ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml index 7f2f9225cbf4..a48222e9aa8f 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.xaml @@ -256,26 +256,33 @@ - - - - - + + + + + + diff --git a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs index 32f32c07e701..1bf403c3fab1 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs +++ b/src/modules/registrypreview/RegistryPreviewUILib/RegistryValue.xaml.cs @@ -29,6 +29,8 @@ public class RegistryValue public string Value { get; set; } + public string ValueOneLine => Value.Replace('\r', ' '); + public string ToolTipText { get; set; } public Uri ImageUri From a2cb4a7a4b665b8db0cba334bbbd77f453a61af1 Mon Sep 17 00:00:00 2001 From: htcfreek <61519853+htcfreek@users.noreply.github.com> Date: Mon, 30 Dec 2024 08:22:38 +0100 Subject: [PATCH 5/5] cleanup --- .../RegistryPreviewUILib/Strings/en-US/Resources.resw | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw index 52a1fcb25069..9401908d216e 100644 --- a/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw +++ b/src/modules/registrypreview/RegistryPreviewUILib/Strings/en-US/Resources.resw @@ -257,10 +257,6 @@ (zero-length binary value) - - Copy - Like "Copy item" - Copy path Like "Copy item"