[RegistryPreview]Copy context menu, data tooltip, MULTI_SZ fix (#36631)
* add context menus * string resources for contextmenu * fix line break parsing for MULTI_SZ * better presentation of multiline values and value tooltip * cleanup
This commit is contained in:
Родитель
e7abd34778
Коммит
44f170d4ed
|
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class to centralize clipboard actions
|
||||||
|
/// </summary>
|
||||||
|
internal static class ClipboardHelper
|
||||||
|
{
|
||||||
|
internal static void CopyToClipboardAction(string text)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = new DataPackage();
|
||||||
|
data.SetText(text);
|
||||||
|
Clipboard.SetContent(data);
|
||||||
|
Clipboard.Flush();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,10 @@
|
||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// 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
|
namespace RegistryPreviewUILib
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -28,5 +32,19 @@ namespace RegistryPreviewUILib
|
||||||
this.Image = image;
|
this.Image = image;
|
||||||
this.ToolTipText = toolTipText;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace RegistryPreviewUILib
|
||||||
public sealed partial class RegistryPreviewMainPage : Page
|
public sealed partial class RegistryPreviewMainPage : Page
|
||||||
{
|
{
|
||||||
private static SemaphoreSlim _dialogSemaphore = new(1);
|
private static SemaphoreSlim _dialogSemaphore = new(1);
|
||||||
|
private string lastKeyPath;
|
||||||
|
|
||||||
public delegate void UpdateWindowTitleFunction(string title);
|
public delegate void UpdateWindowTitleFunction(string title);
|
||||||
|
|
||||||
|
@ -261,6 +262,7 @@ namespace RegistryPreviewUILib
|
||||||
registryLine = StripFirstAndLast(registryLine);
|
registryLine = StripFirstAndLast(registryLine);
|
||||||
|
|
||||||
treeViewNode = AddTextToTree(registryLine, imageName);
|
treeViewNode = AddTextToTree(registryLine, imageName);
|
||||||
|
lastKeyPath = registryLine;
|
||||||
}
|
}
|
||||||
else if (registryLine.StartsWith('"') && registryLine.EndsWith("=-", StringComparison.InvariantCulture))
|
else if (registryLine.StartsWith('"') && registryLine.EndsWith("=-", StringComparison.InvariantCulture))
|
||||||
{
|
{
|
||||||
|
@ -271,7 +273,7 @@ namespace RegistryPreviewUILib
|
||||||
registryLine = StripFirstAndLast(registryLine);
|
registryLine = StripFirstAndLast(registryLine);
|
||||||
|
|
||||||
// Create a new listview item that will be used to display the delete value and store it
|
// 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);
|
SetValueToolTip(registryValue);
|
||||||
|
|
||||||
// store the ListViewItem, if we have a valid Key to attach to
|
// store the ListViewItem, if we have a valid Key to attach to
|
||||||
|
@ -310,7 +312,7 @@ namespace RegistryPreviewUILib
|
||||||
value = value.Trim();
|
value = value.Trim();
|
||||||
|
|
||||||
// Create a new listview item that will be used to display the value
|
// 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 the first character is a " then this is a string value, so find the last most " which will avoid comments
|
||||||
if (value.StartsWith('"'))
|
if (value.StartsWith('"'))
|
||||||
|
@ -553,19 +555,10 @@ namespace RegistryPreviewUILib
|
||||||
var bytes = value.Split(',').Select(
|
var bytes = value.Split(',').Select(
|
||||||
c => c.Length == 2 ? byte.Parse(c, NumberStyles.HexNumber, CultureInfo.InvariantCulture) : throw null).ToArray();
|
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);
|
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
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
@ -167,6 +167,12 @@
|
||||||
IsTabStop="False"
|
IsTabStop="False"
|
||||||
Orientation="Horizontal"
|
Orientation="Horizontal"
|
||||||
Spacing="8">
|
Spacing="8">
|
||||||
|
<StackPanel.ContextFlyout>
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyName" Command="{Binding Content.CopyToClipboardName_Click}" />
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyKeyPath" Command="{Binding Content.CopyToClipboardKeyPath_Click}" />
|
||||||
|
</MenuFlyout>
|
||||||
|
</StackPanel.ContextFlyout>
|
||||||
<Image
|
<Image
|
||||||
MaxWidth="16"
|
MaxWidth="16"
|
||||||
MaxHeight="16"
|
MaxHeight="16"
|
||||||
|
@ -208,6 +214,14 @@
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Orientation="Horizontal"
|
Orientation="Horizontal"
|
||||||
Spacing="8">
|
Spacing="8">
|
||||||
|
<StackPanel.ContextFlyout>
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyName" Command="{Binding CopyToClipboardName_Click}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyValue" Command="{Binding CopyToClipboardEntry_Click}" />
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyValueWithPath" Command="{Binding CopyToClipboardWithPath_Click}" />
|
||||||
|
</MenuFlyout>
|
||||||
|
</StackPanel.ContextFlyout>
|
||||||
<Image
|
<Image
|
||||||
MaxWidth="16"
|
MaxWidth="16"
|
||||||
MaxHeight="16"
|
MaxHeight="16"
|
||||||
|
@ -226,12 +240,49 @@
|
||||||
x:Uid="TypeColumn"
|
x:Uid="TypeColumn"
|
||||||
Width="Auto"
|
Width="Auto"
|
||||||
Binding="{Binding Type}"
|
Binding="{Binding Type}"
|
||||||
FontSize="{StaticResource CaptionTextBlockFontSize}" />
|
FontSize="{StaticResource CaptionTextBlockFontSize}">
|
||||||
<tk7controls:DataGridTextColumn
|
<tk7controls:DataGridTextColumn.CellStyle>
|
||||||
|
<Style TargetType="tk7controls:DataGridCell">
|
||||||
|
<Setter Property="ContextFlyout">
|
||||||
|
<Setter.Value>
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyType" Command="{Binding CopyToClipboardType_Click}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyValue" Command="{Binding CopyToClipboardEntry_Click}" />
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyValueWithPath" Command="{Binding CopyToClipboardWithPath_Click}" />
|
||||||
|
</MenuFlyout>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</tk7controls:DataGridTextColumn.CellStyle>
|
||||||
|
</tk7controls:DataGridTextColumn>
|
||||||
|
<tk7controls:DataGridTemplateColumn
|
||||||
x:Uid="ValueColumn"
|
x:Uid="ValueColumn"
|
||||||
Width="Auto"
|
Width="Auto"
|
||||||
Binding="{Binding Value}"
|
IsReadOnly="True">
|
||||||
FontSize="{StaticResource CaptionTextBlockFontSize}" />
|
<tk7controls:DataGridTemplateColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel
|
||||||
|
Margin="4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<StackPanel.ContextFlyout>
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyData" Command="{Binding CopyToClipboardData_Click}" />
|
||||||
|
<MenuFlyoutSeparator />
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyValue" Command="{Binding CopyToClipboardEntry_Click}" />
|
||||||
|
<MenuFlyoutItem x:Uid="ContextMenu_CopyValueWithPath" Command="{Binding CopyToClipboardWithPath_Click}" />
|
||||||
|
</MenuFlyout>
|
||||||
|
</StackPanel.ContextFlyout>
|
||||||
|
<TextBlock
|
||||||
|
IsTabStop="False"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{Binding ValueOneLine}"
|
||||||
|
ToolTipService.ToolTip="{Binding Value}" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</tk7controls:DataGridTemplateColumn.CellTemplate>
|
||||||
|
</tk7controls:DataGridTemplateColumn>
|
||||||
</tk7controls:DataGrid.Columns>
|
</tk7controls:DataGrid.Columns>
|
||||||
</tk7controls:DataGrid>
|
</tk7controls:DataGrid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System.IO;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.Windows.ApplicationModel.Resources;
|
using Microsoft.Windows.ApplicationModel.Resources;
|
||||||
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
|
|
||||||
namespace RegistryPreviewUILib
|
namespace RegistryPreviewUILib
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
|
|
||||||
namespace RegistryPreviewUILib
|
namespace RegistryPreviewUILib
|
||||||
{
|
{
|
||||||
|
@ -17,12 +21,16 @@ namespace RegistryPreviewUILib
|
||||||
private static Uri uriDeleteValue = new Uri("ms-appx:///Assets/RegistryPreview/deleted-value32.png");
|
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");
|
private static Uri uriErrorValue = new Uri("ms-appx:///Assets/RegistryPreview/error32.png");
|
||||||
|
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
public string ValueOneLine => Value.Replace('\r', ' ');
|
||||||
|
|
||||||
public string ToolTipText { get; set; }
|
public string ToolTipText { get; set; }
|
||||||
|
|
||||||
public Uri ImageUri
|
public Uri ImageUri
|
||||||
|
@ -46,12 +54,49 @@ namespace RegistryPreviewUILib
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegistryValue(string name, string type, string value)
|
public RegistryValue(string name, string type, string value, string key)
|
||||||
{
|
{
|
||||||
this.Name = name;
|
this.Name = name;
|
||||||
this.Type = type;
|
this.Type = type;
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
this.ToolTipText = string.Empty;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,4 +257,28 @@
|
||||||
<data name="ZeroLength" xml:space="preserve">
|
<data name="ZeroLength" xml:space="preserve">
|
||||||
<value>(zero-length binary value)</value>
|
<value>(zero-length binary value)</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ContextMenu_CopyKeyPath.Text" xml:space="preserve">
|
||||||
|
<value>Copy path</value>
|
||||||
|
<comment>Like "Copy item"</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenu_CopyName.Text" xml:space="preserve">
|
||||||
|
<value>Copy name</value>
|
||||||
|
<comment>Like "Copy item"</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenu_CopyType.Text" xml:space="preserve">
|
||||||
|
<value>Copy type</value>
|
||||||
|
<comment>Like "Copy item"</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenu_CopyData.Text" xml:space="preserve">
|
||||||
|
<value>Copy data</value>
|
||||||
|
<comment>Like "Copy item"</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenu_CopyValue.Text" xml:space="preserve">
|
||||||
|
<value>Copy value</value>
|
||||||
|
<comment>Like "Copy item"</comment>
|
||||||
|
</data>
|
||||||
|
<data name="ContextMenu_CopyValueWithPath.Text" xml:space="preserve">
|
||||||
|
<value>Copy value with key path</value>
|
||||||
|
<comment>Like "Copy item"</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
Загрузка…
Ссылка в новой задаче