mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-14 18:57:55 +01:00
[RegistryPreview] Extended preview for value data (#37689)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Add a button to the data grid that shows a windows for complex value preview. ### Screenshots **Button**  **Context menu** (Usefull on long data, if button is scrolled out of view.)  **Preview: REG_SZ**  **Preview: REG_MULTI_SZ**  **Preview: REG_EXPAND_SZ**  **Preview: REG_DWORD and REG_QWORD**  **Preview: REG_BINARY**   <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] **Closes:** #36877 - [x] **Communication:** I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end user facing strings can be localized => missing yet - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments Additionally this PR updates the context menu for values. <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Tested code with a local build.
This commit is contained in:
3
.github/actions/spell-check/allow/names.txt
vendored
3
.github/actions/spell-check/allow/names.txt
vendored
@@ -91,6 +91,7 @@ Hemmerlein
|
||||
hlaueriksson
|
||||
Horvalds
|
||||
Howett
|
||||
hotkidfamily
|
||||
htcfreek
|
||||
Huynh
|
||||
Ionut
|
||||
@@ -98,6 +99,7 @@ jamrobot
|
||||
Jaswal
|
||||
Jaylyn
|
||||
jefflord
|
||||
Jeremic
|
||||
Jordi
|
||||
jyuwono
|
||||
kai
|
||||
@@ -222,6 +224,7 @@ openai
|
||||
Quickime
|
||||
regedit
|
||||
roslyn
|
||||
Skia
|
||||
Spotify
|
||||
Vanara
|
||||
wangyi
|
||||
|
||||
1
.github/actions/spell-check/excludes.txt
vendored
1
.github/actions/spell-check/excludes.txt
vendored
@@ -126,3 +126,4 @@
|
||||
^src/common/sysinternals/Eula/
|
||||
^tools/Verification scripts/Check preview handler registration\.ps1$
|
||||
ignore$
|
||||
^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
|
||||
|
||||
1
.github/actions/spell-check/expect.txt
vendored
1
.github/actions/spell-check/expect.txt
vendored
@@ -1513,6 +1513,7 @@ SICHINT
|
||||
SIDs
|
||||
siex
|
||||
sigdn
|
||||
Signedness
|
||||
SIGNINGSCENARIO
|
||||
signtool
|
||||
SINGLEKEY
|
||||
|
||||
@@ -41,6 +41,9 @@ Write-Output ""
|
||||
Write-Output "Restoring dotnet tools..."
|
||||
dotnet tool restore --disable-parallel --no-cache
|
||||
|
||||
# Use Regex syntax
|
||||
$PathExcludes = "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)|(\\RegistryPreviewUILib\\Controls\\HexBox\\)"
|
||||
|
||||
if (-not $Passive)
|
||||
{
|
||||
# Look for unstaged changed files by default
|
||||
@@ -87,7 +90,7 @@ if (-not $Passive)
|
||||
}
|
||||
|
||||
Write-Output "Running Git Diff: $gitDiffCommand"
|
||||
$files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$"
|
||||
$files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$" | Where-Object { $_ -notmatch $PathExcludes }
|
||||
|
||||
if (-not $Passive -and -not $Main -and -not $Unstaged -and -not $Staged -and -not $LastCommit)
|
||||
{
|
||||
@@ -107,7 +110,7 @@ if (-not $Passive)
|
||||
else
|
||||
{
|
||||
Write-Output "Checking all files (passively)"
|
||||
$files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)" }
|
||||
$files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch $PathExcludes }
|
||||
|
||||
if ($files.count -gt 0)
|
||||
{
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.37.2" />
|
||||
<!-- Don't update SkiaSharp.Views.WinUI to version 3.* branch as this brakes the HexBox control in Registry Preview. -->
|
||||
<PackageVersion Include="SkiaSharp.Views.WinUI" Version="2.88.9" />
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
|
||||
33
NOTICE.md
33
NOTICE.md
@@ -1427,6 +1427,37 @@ EXHIBIT A -Mozilla Public License.
|
||||
|
||||
## Utility: Registry Preview
|
||||
|
||||
### HexBox.WinUI
|
||||
|
||||
We use HexBox.WinUI to show a preview of binary values.
|
||||
|
||||
**Source**: https://github.com/hotkidfamily/HexBox.WinUI
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Filip Jeremic
|
||||
Copyright (c) 2024~2025 hotkidfamily@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
@@ -1457,6 +1488,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
|
||||
## NuGet Packages used by PowerToys
|
||||
|
||||
- AdaptiveCards.ObjectModel.WinUI3 2.0.0-beta
|
||||
@@ -1517,6 +1549,7 @@ SOFTWARE.
|
||||
- ReverseMarkdown 4.1.0
|
||||
- ScipBe.Common.Office.OneNote 3.0.1
|
||||
- SharpCompress 0.37.2
|
||||
- SkiaSharp.Views.WinUI 2.88.9
|
||||
- StreamJsonRpc 2.21.69
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 9.0.6
|
||||
|
||||
@@ -76,3 +76,47 @@ using System.Diagnostics.CodeAnalysis;
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.INotifyPropertyChangedGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "type", Target = "~T:Peek.UI.Views.TitleBar")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")]
|
||||
|
||||
// HexBox control in RegistryPreviewUILib (We decided to copy the original code and not fix all theses problems for easier updating.)
|
||||
[assembly: SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Naming", "CA1720:Identifiers should not contain type names", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Performance", "CA1805:Do not initialize unnecessarily", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1642:Constructor summary documentation should begin with standard text", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1648:<inheritdoc> has been used on an element that doesn't inherit from a base class or implement an interface.", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1500:Braces for multi-line statements should not share line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1502:Element should not be on a single line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1505:Opening braces should not be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1507:Code should not contain multiple blank lines in a row", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1508:Closing braces should not be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1509:Opening braces should not be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:Single-line comments should not be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1514:Element documentation header should be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment should be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1119:Statement should not use unnecessary parenthesis", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1407:Arithmetic expressions should declare precedence", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1413:Use trailing comma in multi-line initializers", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1312:Variable names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives should be placed correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1108:Block statements should not contain embedded comments", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1129:Do not use default value type constructor", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1000:Keywords should be spaced correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:Symbols should be spaced correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:Single line comments should begin with single space", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1024:Colons Should Be Spaced Correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1028:Code should not contain trailing whitespace", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Usage", "CsWinRT1028:Class is not marked partial", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<ItemGroup>
|
||||
<Folder Include="RegistryPreviewXAML\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" />
|
||||
|
||||
@@ -10,7 +10,31 @@
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<SolidColorBrush x:Key="HexBox_SelectionTextBrush" Color="{ThemeResource TextOnAccentFillColorSelectedText}" />
|
||||
<SolidColorBrush x:Key="HexBox_SelectionBackgroundBrush" Color="{ThemeResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="HexBox_VerticalLineBrush" Color="{ThemeResource DividerStrokeColorDefault}" />
|
||||
<StaticResource x:Key="HexBox_ControlBorderBrush" ResourceKey="TextControlElevationBorderBrush" />
|
||||
<StaticResource x:Key="HexBox_ControlBorderFocusedBrush" ResourceKey="TextControlElevationBorderFocusedBrush" />
|
||||
<Thickness x:Key="HexBox_ControlBorderThickness">1</Thickness>
|
||||
<Thickness x:Key="HexBox_ControlBorderFocusedThickness">1,1,1,2</Thickness>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<SolidColorBrush x:Key="HexBox_SelectionTextBrush" Color="{ThemeResource SystemColorHighlightTextColor}" />
|
||||
<SolidColorBrush x:Key="HexBox_SelectionBackgroundBrush" Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="HexBox_VerticalLineBrush" Color="{ThemeResource SystemColorWindowTextColor}" />
|
||||
<LinearGradientBrush x:Key="HexBox_ControlBorderBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Offset="0" Color="{ThemeResource SystemColorButtonTextColor}" />
|
||||
</LinearGradientBrush>
|
||||
<LinearGradientBrush x:Key="HexBox_ControlBorderFocusedBrush" StartPoint="0,0" EndPoint="1,1">
|
||||
<GradientStop Offset="0" Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
</LinearGradientBrush>
|
||||
<Thickness x:Key="HexBox_ControlBorderThickness">1</Thickness>
|
||||
<Thickness x:Key="HexBox_ControlBorderFocusedThickness">2</Thickness>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerates the address column formatting options.
|
||||
/// </summary>
|
||||
public enum AddressFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// 16 bit HEX address "0000".
|
||||
/// </summary>
|
||||
Address16,
|
||||
|
||||
/// <summary>
|
||||
/// 24 bit HEX address "00:0000".
|
||||
/// </summary>
|
||||
Address24,
|
||||
|
||||
/// <summary>
|
||||
/// 32 bit HEX address "0000:0000".
|
||||
/// </summary>
|
||||
Address32,
|
||||
|
||||
/// <summary>
|
||||
/// 48 bit HEX address "0000:00000000".
|
||||
/// </summary>
|
||||
Address48,
|
||||
|
||||
/// <summary>
|
||||
/// 64 bit HEX address "00000000:00000000".
|
||||
/// </summary>
|
||||
Address64,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
public class RelayCommand : ICommand
|
||||
{
|
||||
private readonly Action<object> _execute;
|
||||
private readonly Func<object, bool> _canExecute;
|
||||
|
||||
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
|
||||
public bool CanExecute(object parameter)
|
||||
{
|
||||
return _canExecute == null || _canExecute(parameter);
|
||||
}
|
||||
|
||||
public void Execute(object parameter)
|
||||
{
|
||||
_execute(parameter);
|
||||
}
|
||||
|
||||
public void RaiseCanExecuteChanged()
|
||||
{
|
||||
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerates the format to display integral data in.
|
||||
/// </summary>
|
||||
public enum DataFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Display the data in decimal format.
|
||||
/// </summary>
|
||||
Decimal,
|
||||
|
||||
/// <summary>
|
||||
/// Display the data in hexadecimal format.
|
||||
/// </summary>
|
||||
Hexadecimal,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerates the signedness of the data to display.
|
||||
/// </summary>
|
||||
public enum DataSignedness
|
||||
{
|
||||
/// <summary>
|
||||
/// Display the data as signed values.
|
||||
/// </summary>
|
||||
Signed,
|
||||
|
||||
/// <summary>
|
||||
/// Display the data as unsigned values.
|
||||
/// </summary>
|
||||
Unsigned,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerates how the data (bytes read from the buffer) is to be interpreted when displayed.
|
||||
/// </summary>
|
||||
public enum DataType
|
||||
{
|
||||
/// <summary>
|
||||
/// Display the data as integral (integer) values.
|
||||
/// </summary>
|
||||
Int_1 = 1,
|
||||
/// <summary>
|
||||
/// Display the data as integral (integer) values.
|
||||
/// </summary>
|
||||
Int_2 = 2,
|
||||
/// <summary>
|
||||
/// Display the data as integral (integer) values.
|
||||
/// </summary>
|
||||
Int_4 = 4,
|
||||
/// <summary>
|
||||
/// Display the data as integral (integer) values.
|
||||
/// </summary>
|
||||
Int_8 = 8,
|
||||
/// <summary>
|
||||
/// Display the data as floating point values.
|
||||
/// </summary>
|
||||
Float_32 = 32,
|
||||
/// <summary>
|
||||
/// Display the data as floating point values.
|
||||
/// </summary>
|
||||
Float_64 = 64,
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,231 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox.Library.EndianConvert
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Reads primitive data types as binary values in a specific encoding and endianness.
|
||||
/// </summary>
|
||||
public class EndianBinaryReader : BinaryReader
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EndianBinaryReader"/> class based on the specified stream, endianness, and using UTF-8
|
||||
/// encoding.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="input">
|
||||
/// The input stream.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of the data in the input stream.
|
||||
/// </param>
|
||||
///
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// The stream does not support reading, is null, or is already closed.
|
||||
/// </exception>
|
||||
public EndianBinaryReader(Stream input, Endianness endianness)
|
||||
: this(input, endianness, Encoding.UTF8)
|
||||
{
|
||||
// Void
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EndianBinaryReader"/> class based on the specified stream, endianness, and character
|
||||
/// encoding.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="input">
|
||||
/// The input stream.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of the data in the input stream.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="encoding">
|
||||
/// The character encoding to use.
|
||||
/// </param>
|
||||
///
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// The stream does not support reading, is null, or is already closed.
|
||||
/// </exception>
|
||||
public EndianBinaryReader(Stream input, Endianness endianness, Encoding encoding)
|
||||
: this(input, endianness, encoding, false)
|
||||
{
|
||||
// Void
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EndianBinaryReader"/> class based on the specified stream, endianness, and character
|
||||
/// encoding, and optionally leaves the stream open.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="input">
|
||||
/// The input stream.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of the data in the input stream.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="encoding">
|
||||
/// The character encoding to use.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="leaveOpen">
|
||||
/// <c>true</c> to leave the stream open after the <see cref="EndianBinaryReader"/> object is disposed; <c>false</c> otherwise.
|
||||
/// </param>
|
||||
///
|
||||
/// <exception cref="System.ArgumentException">
|
||||
/// The stream does not support reading, is null, or is already closed.
|
||||
/// </exception>
|
||||
public EndianBinaryReader(Stream input, Endianness endianness, Encoding encoding, bool leaveOpen)
|
||||
: base(input, encoding, leaveOpen)
|
||||
{
|
||||
Endianness = endianness;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the endianness of the data in the input stream.
|
||||
/// </summary>
|
||||
public Endianness Endianness
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a decimal value from the current stream and advances the current position of the stream by sixteen bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A decimal value read from the current stream.
|
||||
/// </returns>
|
||||
public override decimal ReadDecimal()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an 8-byte floating point value from the current stream and advances the current position of the stream by eight bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// An 8-byte floating point value read from the current stream.
|
||||
/// </returns>
|
||||
public override double ReadDouble()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 2-byte signed integer from the current stream and advances the current position of the stream by two bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A 2-byte signed integer read from the current stream.
|
||||
/// </returns>
|
||||
public override short ReadInt16()
|
||||
{
|
||||
return EndianBitConverter.Convert(base.ReadInt16(), Endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte signed integer from the current stream and advances the current position of the stream by four bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A 4-byte signed integer read from the current stream.
|
||||
/// </returns>
|
||||
public override int ReadInt32()
|
||||
{
|
||||
return EndianBitConverter.Convert(base.ReadInt32(), Endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an 8-byte signed integer from the current stream and advances the current position of the stream by eight bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// An 8-byte signed integer read from the current stream.
|
||||
/// </returns>
|
||||
public override long ReadInt64()
|
||||
{
|
||||
return EndianBitConverter.Convert(base.ReadInt64(), Endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte floating point value from the current stream and advances the current position of the stream by four bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A 4-byte floating point value read from the current stream.
|
||||
/// </returns>
|
||||
public override float ReadSingle()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a string from the current stream. The string is prefixed with the length, encoded as an integer seven bits at a time.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// The string being read.
|
||||
/// </returns>
|
||||
public override string ReadString()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 2-byte unsigned integer from the current stream using little-endian encoding and advances the position of the stream by
|
||||
/// two bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A 2-byte unsigned integer read from this stream.
|
||||
/// </returns>
|
||||
public override ushort ReadUInt16()
|
||||
{
|
||||
return EndianBitConverter.Convert(base.ReadUInt16(), Endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a 4-byte unsigned integer from the current stream using little-endian encoding and advances the position of the stream by
|
||||
/// four bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// A 4-byte unsigned integer read from this stream.
|
||||
/// </returns>
|
||||
public override uint ReadUInt32()
|
||||
{
|
||||
return EndianBitConverter.Convert(base.ReadUInt32(), Endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads an 8-byte unsigned integer from the current stream using little-endian encoding and advances the position of the stream by
|
||||
/// eight bytes.
|
||||
/// </summary>
|
||||
///
|
||||
/// <returns>
|
||||
/// An 8-byte unsigned integer read from this stream.
|
||||
/// </returns>
|
||||
public override ulong ReadUInt64()
|
||||
{
|
||||
return EndianBitConverter.Convert(base.ReadUInt64(), Endianness);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox.Library.EndianConvert
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Converts integral values to the native endianness of this computer architecture.
|
||||
/// </summary>
|
||||
public static class EndianBitConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the native endianness of this computer architecture.
|
||||
/// </summary>
|
||||
public static readonly Endianness NativeEndianness = BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value from the specified endianness to the native endianness.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="value">
|
||||
/// The value to convert.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of <paramref name="value"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The value converted from the specified endianness to the native endianness (<see cref="NativeEndianness"/>).
|
||||
/// </returns>
|
||||
public static ushort Convert(ushort value, Endianness endianness)
|
||||
{
|
||||
if (endianness == NativeEndianness)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (ushort)((value & 0x00FFU) << 8 |
|
||||
(value & 0xFF00U) >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value from the specified endianness to the native endianness.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="value">
|
||||
/// The value to convert.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of <paramref name="value"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The value converted from the specified endianness to the native endianness (<see cref="NativeEndianness"/>).
|
||||
/// </returns>
|
||||
public static uint Convert(uint value, Endianness endianness)
|
||||
{
|
||||
if (endianness == NativeEndianness)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (value & 0x000000FFU) << 24 |
|
||||
(value & 0xFF000000U) >> 24 |
|
||||
(value & 0x0000FF00U) << 8 |
|
||||
(value & 0x00FF0000U) >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value from the specified endianness to the native endianness.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="value">
|
||||
/// The value to convert.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of <paramref name="value"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The value converted from the specified endianness to the native endianness (<see cref="NativeEndianness"/>).
|
||||
/// </returns>
|
||||
public static ulong Convert(ulong value, Endianness endianness)
|
||||
{
|
||||
if (endianness == NativeEndianness)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (value & 0x00000000000000FFUL) << 56 |
|
||||
(value & 0xFF00000000000000UL) >> 56 |
|
||||
(value & 0x000000000000FF00UL) << 40 |
|
||||
(value & 0x00FF000000000000UL) >> 40 |
|
||||
(value & 0x0000000000FF0000UL) << 24 |
|
||||
(value & 0x0000FF0000000000UL) >> 24 |
|
||||
(value & 0x00000000FF000000UL) << 8 |
|
||||
(value & 0x000000FF00000000UL) >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value from the specified endianness to the native endianness.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="value">
|
||||
/// The value to convert.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of <paramref name="value"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The value converted from the specified endianness to the native endianness (<see cref="NativeEndianness"/>).
|
||||
/// </returns>
|
||||
public static short Convert(short value, Endianness endianness)
|
||||
{
|
||||
return (short)Convert((ushort)value, endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value from the specified endianness to the native endianness.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="value">
|
||||
/// The value to convert.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of <paramref name="value"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The value converted from the specified endianness to the native endianness (<see cref="NativeEndianness"/>).
|
||||
/// </returns>
|
||||
public static int Convert(int value, Endianness endianness)
|
||||
{
|
||||
return (int)Convert((uint)value, endianness);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a value from the specified endianness to the native endianness.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="value">
|
||||
/// The value to convert.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="endianness">
|
||||
/// The endianness of <paramref name="value"/>.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The value converted from the specified endianness to the native endianness (<see cref="NativeEndianness"/>).
|
||||
/// </returns>
|
||||
public static long Convert(long value, Endianness endianness)
|
||||
{
|
||||
return (long)Convert((ulong)value, endianness);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox.Library.EndianConvert
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the endianness of a value in a computer architecture.
|
||||
/// </summary>
|
||||
public enum Endianness
|
||||
{
|
||||
/// <summary>
|
||||
/// Most significant byte first.
|
||||
/// </summary>
|
||||
BigEndian,
|
||||
|
||||
/// <summary>
|
||||
/// Least significant byte first.
|
||||
/// </summary>
|
||||
LittleEndian,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox.Library.EndianConvert
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// The exception that is thrown when an input file or a data stream is malformed.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class FileFormatException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileFormatException"/> class.
|
||||
/// </summary>
|
||||
public FileFormatException()
|
||||
{
|
||||
// Void
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileFormatException"/> class with a specified error message.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="message">
|
||||
/// The message that describes the error.
|
||||
/// </param>
|
||||
public FileFormatException(string message)
|
||||
: base(message)
|
||||
{
|
||||
// Void
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileFormatException"/> class with a specified error message and a reference to the inner
|
||||
/// exception that is the cause of this exception.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="message">
|
||||
/// The message that describes the error.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="innerException">
|
||||
/// The exception that is the cause of the current exception, or a null reference if no inner exception is specified.
|
||||
/// </param>
|
||||
public FileFormatException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
// Void
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumerates the text section encodings/formats that the control is able to display.
|
||||
/// </summary>
|
||||
public enum TextFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Display data in ASCII (ISO-8859-1) encoding.
|
||||
/// </summary>
|
||||
Ascii,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:convert="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:local="using:RegistryPreviewUILib.HexBox"
|
||||
xmlns:skia="using:SkiaSharp.Views.Windows">
|
||||
|
||||
<Style TargetType="local:HexBox">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:HexBox">
|
||||
<Grid
|
||||
Margin="{TemplateBinding Margin}"
|
||||
Padding="4"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsTabStop="False">
|
||||
<Grid.Resources>
|
||||
<convert:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
<local:BigEndianConverter x:Key="BigEndianConverter" />
|
||||
<local:HexboxDataFormatConverter x:Key="HexboxDataFormatConverter" />
|
||||
<local:HexboxDataSignednessConverter x:Key="HexboxDataSignednessConverter" />
|
||||
<local:HexboxDataFormatBoolConverter x:Key="HexboxDataFormatBoolConverter" />
|
||||
<local:HexboxDataTypeConverter x:Key="HexboxDataTypeConverter" />
|
||||
<MenuFlyout x:Key="DataMenuFlyout">
|
||||
<!-- New code for PowerToys implementation -->
|
||||
<MenuFlyoutItem
|
||||
x:Uid="/PowerToys.RegistryPreviewUILib/Resources/HexBox_CopyCommand"
|
||||
Command="{Binding CopyCommand, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Icon="Copy">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="C" Modifiers="Control" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="/PowerToys.RegistryPreviewUILib/Resources/HexBox_CopyTextCommand"
|
||||
Command="{Binding CopyTextCommand, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Icon="Font">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="C" Modifiers="Control,Shift" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
x:Uid="/PowerToys.RegistryPreviewUILib/Resources/HexBox_SelectAllCommand"
|
||||
Command="{Binding SelectAllCommand, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Icon="SelectAll">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="A" Modifiers="Control" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<!-- Original source code from HexBox.WinUI.HexBox
|
||||
<MenuFlyoutItem
|
||||
Command="{Binding CopyCommand, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Icon="Copy"
|
||||
Text="Copy">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="C" Modifiers="Control" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
Command="{Binding CopyTextCommand, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Icon="Font"
|
||||
Text="Copy text">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="C" Modifiers="Control,Shift"/>
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem
|
||||
Command="{Binding SelectAllCommand, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Icon="SelectAll"
|
||||
Text="Select all">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="A" Modifiers="Control" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutSubItem IsEnabled="{Binding EnforceProperties, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" Text="Address properties">
|
||||
<ToggleMenuFlyoutItem IsChecked="{Binding ShowAddress, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource BoolNegationConverter}}" Text="No Address" />
|
||||
</MenuFlyoutSubItem>
|
||||
<MenuFlyoutSubItem IsEnabled="{Binding EnforceProperties, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" Text="Data properties">
|
||||
<ToggleMenuFlyoutItem IsChecked="{Binding ShowData, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource BoolNegationConverter}}" Text="No Data" />
|
||||
<RadioMenuFlyoutItem
|
||||
GroupName="DataType"
|
||||
IsChecked="{Binding DataType, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataTypeConverter}, ConverterParameter=Int_1}"
|
||||
IsEnabled="{Binding ShowData, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Text="1 byte-integer" />
|
||||
<RadioMenuFlyoutItem
|
||||
GroupName="DataType"
|
||||
IsChecked="{Binding DataType, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataTypeConverter}, ConverterParameter=Int_2}"
|
||||
IsEnabled="{Binding ShowData, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Text="2 byte-integer" />
|
||||
<RadioMenuFlyoutItem
|
||||
GroupName="DataType"
|
||||
IsChecked="{Binding DataType, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataTypeConverter}, ConverterParameter=Int_4}"
|
||||
IsEnabled="{Binding ShowData, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Text="4 byte-integer" />
|
||||
<RadioMenuFlyoutItem
|
||||
GroupName="DataType"
|
||||
IsChecked="{Binding DataType, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataTypeConverter}, ConverterParameter=Int_8}"
|
||||
IsEnabled="{Binding ShowData, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Text="8 byte-integer" />
|
||||
<RadioMenuFlyoutItem
|
||||
GroupName="DataType"
|
||||
IsChecked="{Binding DataType, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataTypeConverter}, ConverterParameter=Float_32}"
|
||||
IsEnabled="{Binding ShowData, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Text="32-bit Floating Point" />
|
||||
<RadioMenuFlyoutItem
|
||||
GroupName="DataType"
|
||||
IsChecked="{Binding DataType, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataTypeConverter}, ConverterParameter=Float_64}"
|
||||
IsEnabled="{Binding ShowData, RelativeSource={RelativeSource Mode=TemplatedParent}}"
|
||||
Text="64-bit Floating Point" />
|
||||
<MenuFlyoutSeparator />
|
||||
<ToggleMenuFlyoutItem
|
||||
IsChecked="{Binding DataSignedness, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataSignednessConverter}, ConverterParameter=Signed}"
|
||||
IsEnabled="{Binding DataFormat, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource HexboxDataFormatBoolConverter}, ConverterParameter={Binding DataFormat}}"
|
||||
Text="Signed" />
|
||||
<ToggleMenuFlyoutItem
|
||||
IsChecked="{Binding DataSignedness, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataSignednessConverter}, ConverterParameter=Unsigned}"
|
||||
IsEnabled="{Binding DataFormat, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource HexboxDataFormatBoolConverter}, ConverterParameter={Binding DataFormat}}"
|
||||
Text="Unsigned" />
|
||||
<MenuFlyoutSeparator />
|
||||
<ToggleMenuFlyoutItem IsChecked="{Binding DataFormat, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataFormatConverter}, ConverterParameter=Decimal}" Text="Decimal" />
|
||||
<ToggleMenuFlyoutItem IsChecked="{Binding DataFormat, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource HexboxDataFormatConverter}, ConverterParameter=Hexadecimal}" Text="Hexadecimal" />
|
||||
<MenuFlyoutSeparator />
|
||||
<ToggleMenuFlyoutItem IsChecked="{Binding Endianness, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource BigEndianConverter}, ConverterParameter=BigEndian}" Text="Big-Endian" />
|
||||
<ToggleMenuFlyoutItem IsChecked="{Binding Endianness, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource BigEndianConverter}, ConverterParameter=LittleEndian}" Text="Little-Endian" />
|
||||
</MenuFlyoutSubItem>
|
||||
<MenuFlyoutSubItem IsEnabled="{Binding EnforceProperties, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" Text="Text properties">
|
||||
<ToggleMenuFlyoutItem IsChecked="{Binding ShowText, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay, Converter={StaticResource BoolNegationConverter}}" Text="No Text" />
|
||||
<ToggleMenuFlyoutItem
|
||||
IsChecked="{Binding ShowText, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay}"
|
||||
IsEnabled="False"
|
||||
Text="ASCII" />
|
||||
</MenuFlyoutSubItem>-->
|
||||
</MenuFlyout>
|
||||
</Grid.Resources>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="24" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<skia:SKXamlCanvas
|
||||
Name="ElementCanvas"
|
||||
Grid.Column="0"
|
||||
Margin="2,0,2,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
ContextFlyout="{StaticResource DataMenuFlyout}" />
|
||||
|
||||
<ScrollBar
|
||||
Name="ElementScrollBar"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,2,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
IndicatorMode="MouseIndicator"
|
||||
Orientation="Vertical" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,264 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
#pragma warning disable SA1210 // Using directives should be ordered alphabetically by namespace
|
||||
#pragma warning disable SA1208 // System using directives should be placed before other using directives
|
||||
using RegistryPreviewUILib.HexBox.Library.EndianConvert;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
#pragma warning restore SA1208 // System using directives should be placed before other using directives
|
||||
#pragma warning restore SA1210 // Using directives should be ordered alphabetically by namespace
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
public partial class HexboxDataTypeConverter : IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert a DataType value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataType"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is DataType b)
|
||||
{
|
||||
if (parameter is string c)
|
||||
{
|
||||
return c == b.ToString();
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert back a DataType value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataType"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool b && parameter is string c)
|
||||
{
|
||||
if(c == "Int_1")
|
||||
{
|
||||
return DataType.Int_1;
|
||||
}
|
||||
else if (c == "Int_2")
|
||||
{
|
||||
return DataType.Int_2;
|
||||
}
|
||||
else if (c == "Int_4")
|
||||
{
|
||||
return DataType.Int_4;
|
||||
}
|
||||
else if (c == "Int_8")
|
||||
{
|
||||
return DataType.Int_8;
|
||||
}
|
||||
else if (c == "Float_32")
|
||||
{
|
||||
return DataType.Float_32;
|
||||
}
|
||||
else /*if (c == "Float_64")*/
|
||||
{
|
||||
return DataType.Float_64;
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class HexboxDataSignednessConverter : IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert a DataSignedness value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataSignedness"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is DataSignedness b)
|
||||
{
|
||||
if (parameter is string c)
|
||||
{
|
||||
var end = c == "Signed" ? DataSignedness.Signed : DataSignedness.Unsigned;
|
||||
return (b == end);
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert back a DataSignedness value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataSignedness"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool b && parameter is string c)
|
||||
{
|
||||
var end = c == "Signed" ? DataSignedness.Signed : DataSignedness.Unsigned;
|
||||
if (b)
|
||||
{
|
||||
return end;
|
||||
}
|
||||
else
|
||||
{
|
||||
return c == "Signed" ? DataSignedness.Unsigned : DataSignedness.Signed;
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class HexboxDataFormatBoolConverter : IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert a DataFormat value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataFormat"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if(value is DataFormat f)
|
||||
{
|
||||
return f != DataFormat.Hexadecimal;
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert back a DataFormat value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataFormat"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class HexboxDataFormatConverter : IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert a DataFormat value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataFormat"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is DataFormat b)
|
||||
{
|
||||
if (parameter is string c)
|
||||
{
|
||||
var end = c == "Decimal" ? DataFormat.Decimal: DataFormat.Hexadecimal;
|
||||
return (b == end);
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert back a DataFormat value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="DataFormat"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool b && parameter is string c)
|
||||
{
|
||||
var end = c == "Decimal" ? DataFormat.Decimal : DataFormat.Hexadecimal;
|
||||
if (b)
|
||||
{
|
||||
return end;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end == DataFormat.Decimal ? DataFormat.Hexadecimal : DataFormat.Decimal;
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class BigEndianConverter : IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert a Endian value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Endian"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is Endianness b)
|
||||
{
|
||||
if (parameter is string c)
|
||||
{
|
||||
var end = c == "BigEndian" ? Endianness.BigEndian : Endianness.LittleEndian;
|
||||
return (b == end);
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert back a Endian value to its negation.
|
||||
/// </summary>
|
||||
/// <param name="value">The <see cref="Endian"/> value to negate.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool b && parameter is string c)
|
||||
{
|
||||
var end = c == "BigEndian" ? Endianness.BigEndian : Endianness.LittleEndian;
|
||||
if (b)
|
||||
{
|
||||
return end;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end == Endianness.BigEndian ? Endianness.LittleEndian : Endianness.BigEndian;
|
||||
}
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// 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.
|
||||
|
||||
// <history>
|
||||
// 2020-... created by Filip Jeremic (fjeremic) as "HexView.Wpf".
|
||||
// 2024-... republished by @hotkidfamily as "HexBox.WinUI".
|
||||
// 2025 Included in PowerToys. (Branch master; commit 72dcf64dc858c693a7a16887004c8ddbab61fce7.)
|
||||
// </history>
|
||||
|
||||
namespace RegistryPreviewUILib.HexBox
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// A utility class with miscellaneous methods.
|
||||
/// </summary>
|
||||
internal static class Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Clamps the <paramref name="value"/> to the range [<paramref name="min"/>, <paramref name="max"/>].
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="T">
|
||||
/// The type of the value to clamp.
|
||||
/// </typeparam>
|
||||
///
|
||||
/// <param name="value">
|
||||
/// The value to clamp.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="min">
|
||||
/// The upper bound on the clamped value.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="max">
|
||||
/// The lower bound on the clmaped value.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The nearest value of <paramref name="value"/> in the range [<paramref name="min"/>,
|
||||
/// <paramref name="max"/>].
|
||||
/// </returns>
|
||||
public static T Clamp<T>(this T value, T min, T max)
|
||||
where T : IComparable<T>
|
||||
{
|
||||
return value.CompareTo(min) < 0 ? min : value.CompareTo(max) > 0 ? max : value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the arithmetic modulus of <paramref name="n"/> modulo <paramref name="m"/>.
|
||||
/// </summary>
|
||||
///
|
||||
/// <typeparam name="T">
|
||||
/// The type of the values.
|
||||
/// </typeparam>
|
||||
///
|
||||
/// <param name="n">
|
||||
/// The value to compute the modulus of.
|
||||
/// </param>
|
||||
///
|
||||
/// <param name="m">
|
||||
/// The modulus.
|
||||
/// </param>
|
||||
///
|
||||
/// <returns>
|
||||
/// The non-negative value <c>r</c> such that for some integral value <c>q</c>:
|
||||
/// <c><paramref name="n"/> = q*m + r</c>.
|
||||
/// </returns>
|
||||
public static T Mod<T>(this T n, T m)
|
||||
where T : IComparable<T>
|
||||
{
|
||||
dynamic dn = n;
|
||||
dynamic dm = m;
|
||||
|
||||
dynamic dr = dn % dm;
|
||||
|
||||
return dr.CompareTo(0) < 0 ? dr + dm : dr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
// 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.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
using Windows.Foundation.Metadata;
|
||||
using HB = RegistryPreviewUILib.HexBox;
|
||||
|
||||
namespace RegistryPreviewUILib
|
||||
{
|
||||
public sealed partial class RegistryPreviewMainPage : Page
|
||||
{
|
||||
private static bool _isDataPreviewHexBoxLoaded;
|
||||
|
||||
internal async Task ShowExtendedDataPreview(string name, string type, string value)
|
||||
{
|
||||
// Create dialog
|
||||
_isDataPreviewHexBoxLoaded = false;
|
||||
var panel = new StackPanel()
|
||||
{
|
||||
Spacing = 16,
|
||||
Padding = new Thickness(0),
|
||||
};
|
||||
ContentDialog contentDialog = new ContentDialog()
|
||||
{
|
||||
Title = resourceLoader.GetString("DataPreviewTitle") + " - " + name,
|
||||
Content = panel,
|
||||
CloseButtonText = resourceLoader.GetString("DataPreviewClose"),
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
Padding = new Thickness(0),
|
||||
};
|
||||
contentDialog.Opened += ExtendedDataPreview_Opened;
|
||||
|
||||
// Add content based on value type
|
||||
switch (type)
|
||||
{
|
||||
case "REG_DWORD":
|
||||
case "REG_QWORD":
|
||||
AddHexView(ref panel, ref resourceLoader, value);
|
||||
break;
|
||||
case "REG_NONE":
|
||||
case "REG_BINARY":
|
||||
// Convert value to BinaryReader
|
||||
byte[] byteArray = Convert.FromHexString(value.Replace(" ", string.Empty));
|
||||
MemoryStream memoryStream = new MemoryStream(byteArray);
|
||||
BinaryReader binaryData = new BinaryReader(memoryStream);
|
||||
binaryData.ReadBytes(byteArray.Length);
|
||||
|
||||
// Convert value to text
|
||||
// For more printable asci characters the following code lines are required:
|
||||
// var cpW1252 = CodePagesEncodingProvider.Instance.GetEncoding(1252);
|
||||
// || b == 128 || (b >= 130 && b <= 140) || b == 142 || (b >= 145 & b <= 156) || b >= 158
|
||||
// cpW1252.GetString([b]);
|
||||
string binaryDataText = string.Empty;
|
||||
foreach (byte b in byteArray)
|
||||
{
|
||||
// ASCII codes:
|
||||
// 9, 10, 13: Space, Line Feed, Carriage Return
|
||||
// 32-126: Printable characters
|
||||
// 128, 130-140, 142, 145-156, 158-255: Extended printable characters
|
||||
if (b == 9 || b == 10 || b == 13 || (b >= 32 && b <= 126))
|
||||
{
|
||||
binaryDataText += Convert.ToChar(b);
|
||||
}
|
||||
}
|
||||
|
||||
// Add controls
|
||||
AddBinaryView(ref panel, ref resourceLoader, ref binaryData, binaryDataText);
|
||||
break;
|
||||
case "REG_MULTI_SZ":
|
||||
var multiLineBox = new TextBox()
|
||||
{
|
||||
IsReadOnly = true,
|
||||
AcceptsReturn = true,
|
||||
TextWrapping = TextWrapping.NoWrap,
|
||||
MaxHeight = 200,
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
Text = value,
|
||||
};
|
||||
ScrollViewer.SetVerticalScrollBarVisibility(multiLineBox, ScrollBarVisibility.Auto);
|
||||
ScrollViewer.SetHorizontalScrollBarVisibility(multiLineBox, ScrollBarVisibility.Auto);
|
||||
AutomationProperties.SetName(multiLineBox, resourceLoader.GetString("DataPreview_AutomationPropertiesName_MultilineTextValue"));
|
||||
panel.Children.Add(multiLineBox);
|
||||
break;
|
||||
case "REG_EXPAND_SZ":
|
||||
AddExpandStringView(ref panel, ref resourceLoader, value);
|
||||
break;
|
||||
default: // REG_SZ
|
||||
var stringBox = new TextBox()
|
||||
{
|
||||
IsReadOnly = true,
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
Text = value,
|
||||
};
|
||||
AutomationProperties.SetName(stringBox, resourceLoader.GetString("DataPreview_AutomationPropertiesName_TextValue"));
|
||||
panel.Children.Add(stringBox);
|
||||
break;
|
||||
}
|
||||
|
||||
// Use this code to associate the dialog to the appropriate AppWindow by setting
|
||||
// the dialog's XamlRoot to the same XamlRoot as an element that is already present in the AppWindow.
|
||||
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
|
||||
{
|
||||
contentDialog.XamlRoot = this.Content.XamlRoot;
|
||||
}
|
||||
|
||||
// Show dialog and wait.
|
||||
ChangeCursor(gridPreview, false);
|
||||
_ = await contentDialog.ShowAsync();
|
||||
}
|
||||
|
||||
private static void AddHexView(ref StackPanel panel, ref ResourceLoader resourceLoader, string value)
|
||||
{
|
||||
var hexBox = new TextBox()
|
||||
{
|
||||
Header = resourceLoader.GetString("DataPreviewHex"),
|
||||
IsReadOnly = true,
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
Text = value.Split(" ")[0],
|
||||
};
|
||||
var decimalBox = new TextBox()
|
||||
{
|
||||
Header = resourceLoader.GetString("DataPreviewDec"),
|
||||
IsReadOnly = true,
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
Text = value.Split(" ")[1].TrimStart('(').TrimEnd(')'),
|
||||
};
|
||||
panel.Children.Add(hexBox);
|
||||
panel.Children.Add(decimalBox);
|
||||
}
|
||||
|
||||
private static void AddBinaryView(ref StackPanel panel, ref ResourceLoader resourceLoader, ref BinaryReader data, string dataText)
|
||||
{
|
||||
// Create SelectorBar
|
||||
var navBar = new SelectorBar()
|
||||
{
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
};
|
||||
navBar.SelectionChanged += BinaryPreview_SelectorChanged;
|
||||
navBar.Items.Add(new SelectorBarItem()
|
||||
{
|
||||
Text = resourceLoader.GetString("DataPreviewDataView"),
|
||||
Tag = "DataView",
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
IsSelected = true,
|
||||
});
|
||||
navBar.Items.Add(new SelectorBarItem()
|
||||
{
|
||||
Text = resourceLoader.GetString("DataPreviewVisibleText"),
|
||||
Tag = "TextView",
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
IsSelected = false,
|
||||
IsEnabled = !string.IsNullOrWhiteSpace(dataText),
|
||||
});
|
||||
|
||||
// Create HexBox
|
||||
var binaryPreviewBox = new HB.HexBox()
|
||||
{
|
||||
Height = 300,
|
||||
Width = 495,
|
||||
ShowAddress = true,
|
||||
ShowData = true,
|
||||
ShowText = true,
|
||||
Columns = 8,
|
||||
FontSize = 13,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
AddressBrush = (SolidColorBrush)Application.Current.Resources["AccentTextFillColorPrimaryBrush"],
|
||||
AlternatingDataColumnTextBrush = (SolidColorBrush)Application.Current.Resources["TextFillColorSecondaryBrush"],
|
||||
SelectionTextBrush = (SolidColorBrush)Application.Current.Resources["HexBox_SelectionTextBrush"],
|
||||
SelectionBrush = (SolidColorBrush)Application.Current.Resources["HexBox_SelectionBackgroundBrush"],
|
||||
VerticalSeparatorLineBrush = (SolidColorBrush)Application.Current.Resources["HexBox_VerticalLineBrush"],
|
||||
BorderBrush = (LinearGradientBrush)Application.Current.Resources["HexBox_ControlBorderBrush"],
|
||||
BorderThickness = (Thickness)Application.Current.Resources["HexBox_ControlBorderThickness"],
|
||||
CornerRadius = (CornerRadius)Application.Current.Resources["ControlCornerRadius"],
|
||||
DataFormat = HB.DataFormat.Hexadecimal,
|
||||
DataSignedness = HB.DataSignedness.Unsigned,
|
||||
DataType = HB.DataType.Int_1,
|
||||
EnforceProperties = true,
|
||||
Visibility = Visibility.Collapsed,
|
||||
DataSource = data,
|
||||
};
|
||||
AutomationProperties.SetName(binaryPreviewBox, resourceLoader.GetString("DataPreview_AutomationPropertiesName_BinaryDataPreview"));
|
||||
binaryPreviewBox.Loaded += BinaryPreview_HexBoxLoaded;
|
||||
binaryPreviewBox.GotFocus += BinaryPreview_HexBoxFocused;
|
||||
binaryPreviewBox.LostFocus += BinaryPreview_HexBoxFocusLost;
|
||||
|
||||
// Create TextBox
|
||||
var visibleText = new TextBox()
|
||||
{
|
||||
IsReadOnly = true,
|
||||
AcceptsReturn = true,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Height = 300,
|
||||
Width = 495,
|
||||
FontSize = 13,
|
||||
Text = dataText,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
Visibility = Visibility.Collapsed,
|
||||
};
|
||||
AutomationProperties.SetName(visibleText, resourceLoader.GetString("DataPreview_AutomationPropertiesName_VisibleTextPreview"));
|
||||
|
||||
// Add controls: 0 = SelectorBar, 1 = ProgressRing, 2 = HexBox, 3 = TextBox
|
||||
panel.Children.Add(navBar);
|
||||
panel.Children.Add(new ProgressRing());
|
||||
panel.Children.Add(binaryPreviewBox);
|
||||
panel.Children.Add(visibleText);
|
||||
}
|
||||
|
||||
private static void AddExpandStringView(ref StackPanel panel, ref ResourceLoader resourceLoader, string value)
|
||||
{
|
||||
var stringBoxRaw = new TextBox()
|
||||
{
|
||||
Header = resourceLoader.GetString("DataPreviewRawValue"),
|
||||
IsReadOnly = true,
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
Text = value,
|
||||
};
|
||||
var stringBoxExp = new TextBox()
|
||||
{
|
||||
Header = resourceLoader.GetString("DataPreviewExpandedValue"),
|
||||
IsReadOnly = true,
|
||||
FontSize = 14,
|
||||
RequestedTheme = panel.ActualTheme,
|
||||
Text = Environment.ExpandEnvironmentVariables(value),
|
||||
};
|
||||
panel.Children.Add(stringBoxRaw);
|
||||
panel.Children.Add(stringBoxExp);
|
||||
}
|
||||
|
||||
private static void BinaryPreview_SelectorChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)
|
||||
{
|
||||
// Child controls: 0 = SelectorBar, 1 = ProgressRing, 2 = HexBox, 3 = TextBox
|
||||
var stackPanel = sender.Parent as StackPanel;
|
||||
var progressRing = (ProgressRing)stackPanel.Children[1];
|
||||
var hexBox = (HB.HexBox)stackPanel.Children[2];
|
||||
var textBox = (TextBox)stackPanel.Children[3];
|
||||
|
||||
if (sender.SelectedItem.Tag.ToString() == "DataView")
|
||||
{
|
||||
textBox.Visibility = Visibility.Collapsed;
|
||||
if (_isDataPreviewHexBoxLoaded)
|
||||
{
|
||||
progressRing.Visibility = Visibility.Collapsed;
|
||||
hexBox.Visibility = Visibility.Visible;
|
||||
|
||||
// Clear selection aligned to TextBox
|
||||
hexBox.ClearSelection();
|
||||
hexBox.Focus(FocusState.Programmatic);
|
||||
}
|
||||
else
|
||||
{
|
||||
hexBox.Visibility = Visibility.Collapsed;
|
||||
progressRing.Visibility = Visibility.Visible;
|
||||
progressRing.Focus(FocusState.Programmatic);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
progressRing.Visibility = Visibility.Collapsed;
|
||||
|
||||
hexBox.Visibility = Visibility.Collapsed;
|
||||
textBox.Visibility = Visibility.Visible;
|
||||
|
||||
// Workaround for wrong text selection (color) after switching back to "Visible text"
|
||||
textBox.Focus(FocusState.Programmatic);
|
||||
textBox.Select(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void BinaryPreview_HexBoxLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_isDataPreviewHexBoxLoaded = true;
|
||||
|
||||
// Child controls: 0 = SelectorBar, 1 = ProgressRing, 2 = HexBox, 3 = TextBox
|
||||
var hexBox = (HB.HexBox)sender;
|
||||
var stackPanel = hexBox.Parent as StackPanel;
|
||||
var selectorBar = stackPanel.Children[0] as SelectorBar;
|
||||
var progressRing = stackPanel.Children[1] as ProgressRing;
|
||||
|
||||
if (selectorBar.SelectedItem.Tag.ToString() == "DataView")
|
||||
{
|
||||
progressRing.Visibility = Visibility.Collapsed;
|
||||
hexBox.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler to set correct control border if focused.
|
||||
/// </summary>
|
||||
private static void BinaryPreview_HexBoxFocused(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var hexBox = (HB.HexBox)sender;
|
||||
|
||||
hexBox.BorderThickness = (Thickness)Application.Current.Resources["HexBox_ControlBorderFocusedThickness"];
|
||||
hexBox.BorderBrush = (LinearGradientBrush)Application.Current.Resources["HexBox_ControlBorderFocusedBrush"];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event handler to set correct control border if not focused.
|
||||
/// </summary>
|
||||
private static void BinaryPreview_HexBoxFocusLost(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var hexBox = (HB.HexBox)sender;
|
||||
|
||||
// Workaround: Verify that the newly focused control isn't the context menu of the HexBox control
|
||||
if (FocusManager.GetFocusedElement(hexBox.XamlRoot).GetType() != typeof(MenuFlyoutPresenter))
|
||||
{
|
||||
hexBox.BorderThickness = (Thickness)Application.Current.Resources["HexBox_ControlBorderThickness"];
|
||||
hexBox.BorderBrush = (LinearGradientBrush)Application.Current.Resources["HexBox_ControlBorderBrush"];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure that for REG_Binary preview the HexBox control is focused after opening.
|
||||
/// </summary>
|
||||
private static void ExtendedDataPreview_Opened(ContentDialog sender, ContentDialogOpenedEventArgs e)
|
||||
{
|
||||
// If <_isDataPreviewHexBoxLoaded == true> then we have the right content on the dialog.
|
||||
if (_isDataPreviewHexBoxLoaded)
|
||||
{
|
||||
// Child controls: 0 = SelectorBar, 1 = ProgressRing, 2 = HexBox, 3 = TextBox
|
||||
(sender.Content as StackPanel).Children[2].Focus(FocusState.Programmatic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
using CommunityToolkit.WinUI.UI.Controls;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
@@ -415,5 +414,48 @@ namespace RegistryPreviewUILib
|
||||
saveButton.IsEnabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Commands to show data preview
|
||||
public void ButtonExtendedPreview_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var data = ((Button)sender).DataContext as RegistryValue;
|
||||
InvokeExtendedDataPreview(data);
|
||||
}
|
||||
|
||||
public void MenuExtendedPreview_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var data = ((MenuFlyoutItem)sender).DataContext as RegistryValue;
|
||||
InvokeExtendedDataPreview(data);
|
||||
}
|
||||
|
||||
private async void InvokeExtendedDataPreview(RegistryValue valueData)
|
||||
{
|
||||
// Only one content dialog can be open at the same time and multiple instances of data preview can crash the app.
|
||||
if (_dialogSemaphore.CurrentCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Lock ui and request dialog lock
|
||||
_dialogSemaphore.Wait();
|
||||
ChangeCursor(gridPreview, true);
|
||||
|
||||
await ShowExtendedDataPreview(valueData.Name, valueData.Type, valueData.Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
#if DEBUG
|
||||
throw;
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Unblock ui and release dialog lock
|
||||
ChangeCursor(gridPreview, false);
|
||||
_dialogSemaphore.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,6 +503,7 @@ namespace RegistryPreviewUILib
|
||||
case "REG_NONE":
|
||||
if (value.Length <= 0)
|
||||
{
|
||||
registryValue.IsEmptyBinary = true;
|
||||
value = resourceLoader.GetString("ZeroLength");
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
x:Class="RegistryPreviewUILib.RegistryPreviewMainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converter="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:RegistryPreviewUILib"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
@@ -10,6 +11,12 @@
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
<ResourceDictionary>
|
||||
<converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
|
||||
<Grid
|
||||
x:Name="gridPreview"
|
||||
Grid.Row="1"
|
||||
@@ -178,7 +185,7 @@
|
||||
Spacing="8">
|
||||
<StackPanel.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyName" Command="{Binding Content.CopyToClipboardName_Click}" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyKeyName" Command="{Binding Content.CopyToClipboardName_Click}" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyKeyPath" Command="{Binding Content.CopyToClipboardKeyPath_Click}" />
|
||||
</MenuFlyout>
|
||||
</StackPanel.ContextFlyout>
|
||||
@@ -225,10 +232,18 @@
|
||||
Spacing="8">
|
||||
<StackPanel.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyName" Command="{Binding CopyToClipboardName_Click}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ContextMenu_CopyName"
|
||||
Command="{Binding CopyToClipboardName_Click}"
|
||||
Icon="Copy" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyValue" Command="{Binding CopyToClipboardEntry_Click}" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyValueWithPath" Command="{Binding CopyToClipboardWithPath_Click}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ContextMenu_DataPreview"
|
||||
Click="MenuExtendedPreview_Click"
|
||||
Icon="Zoom"
|
||||
IsEnabled="{Binding ShowPreviewButton}" />
|
||||
</MenuFlyout>
|
||||
</StackPanel.ContextFlyout>
|
||||
<Image
|
||||
@@ -255,10 +270,18 @@
|
||||
<Setter Property="ContextFlyout">
|
||||
<Setter.Value>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyType" Command="{Binding CopyToClipboardType_Click}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ContextMenu_CopyType"
|
||||
Command="{Binding CopyToClipboardType_Click}"
|
||||
Icon="Copy" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyValue" Command="{Binding CopyToClipboardEntry_Click}" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyValueWithPath" Command="{Binding CopyToClipboardWithPath_Click}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ContextMenu_DataPreview"
|
||||
Click="MenuExtendedPreview_Click"
|
||||
Icon="Zoom"
|
||||
IsEnabled="{Binding ShowPreviewButton}" />
|
||||
</MenuFlyout>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
@@ -274,20 +297,36 @@
|
||||
<StackPanel
|
||||
Margin="4"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
Orientation="Horizontal"
|
||||
Spacing="6">
|
||||
<StackPanel.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyData" Command="{Binding CopyToClipboardData_Click}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ContextMenu_CopyData"
|
||||
Command="{Binding CopyToClipboardData_Click}"
|
||||
Icon="Copy" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyValue" Command="{Binding CopyToClipboardEntry_Click}" />
|
||||
<MenuFlyoutItem x:Uid="ContextMenu_CopyValueWithPath" Command="{Binding CopyToClipboardWithPath_Click}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="ContextMenu_DataPreview"
|
||||
Click="MenuExtendedPreview_Click"
|
||||
Icon="Zoom"
|
||||
IsEnabled="{Binding ShowPreviewButton}" />
|
||||
</MenuFlyout>
|
||||
</StackPanel.ContextFlyout>
|
||||
<Button
|
||||
x:Uid="ShowDataPreviewButton"
|
||||
Padding="2"
|
||||
Click="ButtonExtendedPreview_Click"
|
||||
Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
Visibility="{Binding ShowPreviewButton, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
IsTabStop="False"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{Binding ValueOneLine}"
|
||||
ToolTipService.ToolTip="{Binding Value}" />
|
||||
Text="{Binding ValueOneLine}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</tk7controls:DataGridTemplateColumn.CellTemplate>
|
||||
|
||||
@@ -40,7 +40,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="MonacoEditorControl.xaml" />
|
||||
<None Remove="Controls\MonacoEditor\MonacoEditorControl.xaml" />
|
||||
<None Remove="Controls\HexBox\Themes\Generic.xaml" />
|
||||
<None Remove="Themes\Generic.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -51,6 +53,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="SkiaSharp.Views.WinUI" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -59,10 +62,21 @@
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="MonacoEditorControl.xaml">
|
||||
<Page Update="Controls\MonacoEditor\MonacoEditorControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Controls\HexBox\Themes\Generic.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Update="Themes\Generic.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Controls\MonacoEditor\" />
|
||||
<Folder Include="Controls\HexBox\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
|
||||
namespace RegistryPreviewUILib
|
||||
{
|
||||
@@ -29,6 +28,8 @@ namespace RegistryPreviewUILib
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public bool IsEmptyBinary { private get; set; }
|
||||
|
||||
public string ValueOneLine => Value.Replace('\r', ' ');
|
||||
|
||||
public string ToolTipText { get; set; }
|
||||
@@ -54,6 +55,10 @@ namespace RegistryPreviewUILib
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowPreviewButton =>
|
||||
Type != "ERROR" && Type != string.Empty &&
|
||||
Value != string.Empty && IsEmptyBinary != true;
|
||||
|
||||
public RegistryValue(string name, string type, string value, string key)
|
||||
{
|
||||
this.Name = name;
|
||||
|
||||
@@ -277,16 +277,20 @@
|
||||
<value>Copy path</value>
|
||||
<comment>Like "Copy item"</comment>
|
||||
</data>
|
||||
<data name="ContextMenu_CopyName.Text" xml:space="preserve">
|
||||
<data name="ContextMenu_CopyKeyName.Text" xml:space="preserve">
|
||||
<value>Copy name</value>
|
||||
<comment>Like "Copy item"</comment>
|
||||
</data>
|
||||
<data name="ContextMenu_CopyName.Text" xml:space="preserve">
|
||||
<value>Copy</value>
|
||||
<comment>Like "Copy item"</comment>
|
||||
</data>
|
||||
<data name="ContextMenu_CopyType.Text" xml:space="preserve">
|
||||
<value>Copy type</value>
|
||||
<value>Copy</value>
|
||||
<comment>Like "Copy item"</comment>
|
||||
</data>
|
||||
<data name="ContextMenu_CopyData.Text" xml:space="preserve">
|
||||
<value>Copy data</value>
|
||||
<value>Copy</value>
|
||||
<comment>Like "Copy item"</comment>
|
||||
</data>
|
||||
<data name="ContextMenu_CopyValue.Text" xml:space="preserve">
|
||||
@@ -297,6 +301,65 @@
|
||||
<value>Copy value with key path</value>
|
||||
<comment>Like "Copy item"</comment>
|
||||
</data>
|
||||
<data name="ShowDataPreviewButton.ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Show extended preview</value>
|
||||
</data>
|
||||
<data name="ShowDataPreviewButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Show extended preview</value>
|
||||
</data>
|
||||
<data name="DataPreviewTitle" xml:space="preserve">
|
||||
<value>View data</value>
|
||||
</data>
|
||||
<data name="DataPreviewClose" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
<comment>like "Close window"</comment>
|
||||
</data>
|
||||
<data name="DataPreviewHex" xml:space="preserve">
|
||||
<value>Hexadecimal</value>
|
||||
</data>
|
||||
<data name="DataPreviewDec" xml:space="preserve">
|
||||
<value>Decimal</value>
|
||||
</data>
|
||||
<data name="DataPreviewRawValue" xml:space="preserve">
|
||||
<value>Raw value</value>
|
||||
</data>
|
||||
<data name="DataPreviewExpandedValue" xml:space="preserve">
|
||||
<value>Expanded value</value>
|
||||
</data>
|
||||
<data name="DataPreviewVisibleText" xml:space="preserve">
|
||||
<value>Readable text</value>
|
||||
<comment>Means text that is human readable and not only control characters.</comment>
|
||||
</data>
|
||||
<data name="DataPreviewDataView" xml:space="preserve">
|
||||
<value>Data</value>
|
||||
<comment>Like "binary data"</comment>
|
||||
</data>
|
||||
<data name="DataPreview_AutomationPropertiesName_MultilineTextValue" xml:space="preserve">
|
||||
<value>Multiline text value</value>
|
||||
</data>
|
||||
<data name="DataPreview_AutomationPropertiesName_TextValue" xml:space="preserve">
|
||||
<value>Text value</value>
|
||||
</data>
|
||||
<data name="DataPreview_AutomationPropertiesName_BinaryDataPreview" xml:space="preserve">
|
||||
<value>Binary data preview</value>
|
||||
</data>
|
||||
<data name="DataPreview_AutomationPropertiesName_VisibleTextPreview" xml:space="preserve">
|
||||
<value>Preview of readable text</value>
|
||||
</data>
|
||||
<data name="HexBox_CopyCommand.Text" xml:space="preserve">
|
||||
<value>Copy</value>
|
||||
<comment>Like "copy the value"</comment>
|
||||
</data>
|
||||
<data name="HexBox_CopyTextCommand.Text" xml:space="preserve">
|
||||
<value>Copy text</value>
|
||||
<comment>Like "Copy the text"</comment>
|
||||
</data>
|
||||
<data name="HexBox_SelectAllCommand.Text" xml:space="preserve">
|
||||
<value>Select all</value>
|
||||
</data>
|
||||
<data name="ContextMenu_DataPreview.Text" xml:space="preserve">
|
||||
<value>Extended data preview</value>
|
||||
</data>
|
||||
<data name="NewButton.Label" xml:space="preserve">
|
||||
<value>New</value>
|
||||
</data>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?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:RegistryPreviewUILib">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="/PowerToys.RegistryPreviewUILib/Controls/HexBox/Themes/Generic.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
Reference in New Issue
Block a user