Compare commits

...

20 Commits

Author SHA1 Message Date
Stefan Markovic
ca4ee2bced Ship icons and assets in nuget packages 2024-04-15 15:25:14 +02:00
Stefan Markovic
f352cf0ead Back to consuming lib 2024-04-12 11:35:43 +02:00
Stefan Markovic
7b51a0eca2 Rename RegistryPreviewUI back to RegistryPreview 2024-04-12 11:35:22 +02:00
Stefan Markovic
4e028510b7 Fix RegistryPreview package creation 2024-04-12 10:52:05 +02:00
Stefan Markovic
d0b1247ed1 Update Hosts package creation 2024-04-12 10:41:14 +02:00
Stefan Markovic
ddf22c106f Consume the lib 2024-04-09 12:24:11 +02:00
Stefan Markovic
0a9e1ce68d Add exe app and move App.xaml and MainWindow.xaml 2024-04-09 12:13:56 +02:00
Stefan Markovic
071ecc5928 Convert to lib
Change namespace to RegistryPreviewUILib
Remove PT deps
2024-04-09 10:41:10 +02:00
Stefan Markovic
bfcc0b002b Extract UI and logic from MainWindow to RegistryPreviewMainPage 2024-04-09 10:26:29 +02:00
Stefan Markovic
f1c78b0c0d Fix build again 2024-03-22 16:52:35 +01:00
Stefan Markovic
126e3f9239 Remove unneeded stuff 2024-03-22 16:40:37 +01:00
Stefan Markovic
7793a19151 Fix installer 2024-03-22 16:22:40 +01:00
Stefan Markovic
b6e79b7f93 Merge remote-tracking branch 'origin/main' into stefan/decouple_wip 2024-03-22 12:37:47 +01:00
Stefan Markovic
a6525a9c46 Dependency injection
Refactor
Explicit page creation
Wire missing dependencies
2024-03-22 12:37:42 +01:00
Stefan Markovic
1aea2a789a Make it work with custom build targets 2024-03-19 17:46:29 +01:00
Stefan Markovic
0835b96b07 Fix errors 2024-03-13 13:33:46 +01:00
Stefan Markovic
11faa7702d Try consume it 2024-03-12 17:24:55 +01:00
Stefan Markovic
a631518680 Move App and MainWindow to Consumer app. Make Hosts dll 2024-03-12 14:29:43 +01:00
Stefan Markovic
fada064917 Add consumer app 2024-03-12 14:06:15 +01:00
Stefan Markovic
2a6d3b2094 WIP Hosts - remove deps 2024-03-12 13:21:38 +01:00
72 changed files with 1497 additions and 905 deletions

View File

@@ -96,7 +96,8 @@
"WinUI3Apps\\PowerToys.HostsModuleInterface.dll",
"WinUI3Apps\\PowerToys.Hosts.dll",
"WinUI3Apps\\PowerToys.Hosts.exe",
"WinUI3Apps\\PowerToys.HostsPackageConsumer.dll",
"WinUI3Apps\\PowerToys.HostsPackageConsumer.exe",
"WinUI3Apps\\PowerToys.FileLocksmithLib.Interop.dll",
"WinUI3Apps\\PowerToys.FileLocksmithExt.dll",

View File

@@ -57,6 +57,8 @@
<PackageVersion Include="NLog" Version="5.0.4" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
<PackageVersion Include="PowerToys.Hosts" Version="0.0.1" />
<PackageVersion Include="PowerToys.RegistryPreviewUILib" Version="0.0.1" />
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
<PackageVersion Include="SharpCompress" Version="0.33.0" />
<PackageVersion Include="StreamJsonRpc" Version="2.14.24" />

View File

@@ -518,7 +518,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PastePlainModuleInterface",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AllExperiments", "src\common\AllExperiments\AllExperiments.csproj", "{9CE59ED5-7087-4353-88EB-788038A73CEC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreviewUI", "src\modules\registrypreview\RegistryPreviewUI\RegistryPreviewUI.csproj", "{FD86C06A-FB54-4D5E-9831-1CDADF60D45F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreviewUILib", "src\modules\registrypreview\RegistryPreviewUILib\RegistryPreviewUILib.csproj", "{FD86C06A-FB54-4D5E-9831-1CDADF60D45F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegistryPreviewExt", "src\modules\registrypreview\RegistryPreviewExt\RegistryPreviewExt.vcxproj", "{697C6AF9-0A48-49A9-866C-67DA12384015}"
EndProject
@@ -568,6 +568,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithContextMenu",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithLib", "src\modules\FileLocksmith\FileLocksmithLib\FileLocksmithLib.vcxproj", "{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostsPackageConsumer", "src\modules\Hosts\HostsPackageConsumer\HostsPackageConsumer.csproj", "{02DD46D3-F761-47D9-8894-2D6DA0124650}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RegistryPreview", "src\modules\registrypreview\RegistryPreview\RegistryPreview.csproj", "{8E23E173-7127-4A5F-9F93-3049F2B68047}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@@ -2494,6 +2498,30 @@ Global
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x64.Build.0 = Release|x64
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x86.ActiveCfg = Release|x64
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F}.Release|x86.Build.0 = Release|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|ARM64.ActiveCfg = Debug|ARM64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|ARM64.Build.0 = Debug|ARM64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|x64.ActiveCfg = Debug|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|x64.Build.0 = Debug|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|x86.ActiveCfg = Debug|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Debug|x86.Build.0 = Debug|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|ARM64.ActiveCfg = Release|ARM64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|ARM64.Build.0 = Release|ARM64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|x64.ActiveCfg = Release|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|x64.Build.0 = Release|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|x86.ActiveCfg = Release|x64
{02DD46D3-F761-47D9-8894-2D6DA0124650}.Release|x86.Build.0 = Release|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|ARM64.Build.0 = Debug|ARM64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|x64.ActiveCfg = Debug|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|x64.Build.0 = Debug|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|x86.ActiveCfg = Debug|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Debug|x86.Build.0 = Debug|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|ARM64.ActiveCfg = Release|ARM64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|ARM64.Build.0 = Release|ARM64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|x64.ActiveCfg = Release|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|x64.Build.0 = Release|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|x86.ActiveCfg = Release|x64
{8E23E173-7127-4A5F-9F93-3049F2B68047}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2703,6 +2731,8 @@ Global
{0014D652-901F-4456-8D65-06FC5F997FB0} = {4C0D0746-BE5B-49EE-BD5D-A7811628AE8B}
{799A50D8-DE89-4ED1-8FF8-AD5A9ED8C0CA} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
{9D52FD25-EF90-4F9A-A015-91EFC5DAF54F} = {AB82E5DD-C32D-4F28-9746-2C780846188E}
{02DD46D3-F761-47D9-8894-2D6DA0124650} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA}
{8E23E173-7127-4A5F-9F93-3049F2B68047} = {929C1324-22E8-4412-A9A8-80E85F3985A5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}

View File

@@ -5,7 +5,7 @@
<?include $(sys.CURRENTDIR)\Common.wxi?>
<?define HostsAssetsFiles=?>
<?define HostsAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\Hosts\?>
<?define HostsAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\HostsPackageConsumer\?>
<Fragment>
<DirectoryRef Id="WinUI3AppsAssetsFolder">

View File

@@ -47,7 +47,7 @@ Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""FileLocksmithAssetsFiles"" -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -regroot $registryroot"
#Hosts
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName HostsAssetsFiles -wxsFilePath $PSScriptRoot\Hosts.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Hosts"""
Invoke-Expression -Command "$PSScriptRoot\generateFileList.ps1 -fileDepsJson """" -fileListName HostsAssetsFiles -wxsFilePath $PSScriptRoot\Hosts.wxs -depsPath ""$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\HostsPackageConsumer"""
Invoke-Expression -Command "$PSScriptRoot\generateFileComponents.ps1 -fileListName ""HostsAssetsFiles"" -wxsFilePath $PSScriptRoot\Hosts.wxs -regroot $registryroot"
#ImageResizer

View File

@@ -1038,7 +1038,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
L"PowerToys.ColorPickerUI.exe",
L"PowerToys.AlwaysOnTop.exe",
L"PowerToys.RegistryPreview.exe",
L"PowerToys.Hosts.exe",
L"PowerToys.HostsPackageConsumer.exe",
L"PowerToys.PowerRename.exe",
L"PowerToys.ImageResizer.exe",
L"PowerToys.GcodeThumbnailProvider.exe",

View File

@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />

View File

@@ -262,7 +262,7 @@ inline registry::ChangeSet getRegistryPreviewChangeSet(const std::wstring instal
changes.push_back({ scope, L"Software\\Classes\\regfile\\shell\\preview\\command", std::nullopt, command });
std::wstring icon_path = installationDir;
icon_path.append(L"\\WinUI3Apps\\Assets\\RegistryPreview\\app.ico");
icon_path.append(L"\\WinUI3Apps\\Assets\\RegistryPreview\\RegistryPreview.ico");
changes.push_back({ scope, L"Software\\Classes\\regfile\\shell\\preview", L"icon", icon_path });
return { changes };

View File

@@ -12,7 +12,6 @@ using Hosts.Settings;
using Hosts.Tests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Settings.UI.Library.Enumerations;
namespace Hosts.Tests
{

View File

@@ -16,9 +16,7 @@ using System.Threading.Tasks;
using Hosts.Exceptions;
using Hosts.Models;
using Hosts.Settings;
using ManagedCommon;
using Microsoft.Win32;
using Settings.UI.Library.Enumerations;
namespace Hosts.Helpers
{
@@ -277,7 +275,7 @@ namespace Hosts.Helpers
}
catch (Exception ex)
{
Logger.LogError("Failed to open default editor", ex);
LoggerInstance.Logger.LogError("Failed to open default editor", ex);
notepadFallback = true;
}
@@ -289,7 +287,7 @@ namespace Hosts.Helpers
}
catch (Exception ex)
{
Logger.LogError("Failed to open notepad", ex);
LoggerInstance.Logger.LogError("Failed to open notepad", ex);
}
}
}

View File

@@ -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.
using System;
namespace Hosts.Helpers
{
public interface ILogger
{
public void LogError(string message);
public void LogError(string message, Exception ex);
public void LogWarning(string message);
public void LogInfo(string message);
public void LogDebug(string message);
public void LogTrace();
}
}

View File

@@ -0,0 +1,10 @@
// 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.
namespace Hosts.Helpers
{
public static class LoggerInstance
{
public static ILogger Logger { get; set; }
}
}

View File

@@ -11,7 +11,7 @@ namespace Hosts.Helpers
static ResourceLoaderInstance()
{
ResourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("PowerToys.Hosts.pri");
ResourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("PowerToys.Hosts.pri", "PowerToys.Hosts/Resources");
}
}
}

View File

@@ -1,71 +1,54 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Version.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<OutputType>Library</OutputType>
<TargetFramework>net8.0-windows10.0.20348</TargetFramework>
<RootNamespace>Hosts</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<WindowsPackageType>None</WindowsPackageType>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
<RootNamespace>Hosts</RootNamespace>
<AssemblyName>PowerToys.Hosts</AssemblyName>
<DefineConstants>DISABLE_XAML_GENERATED_MAIN,TRACE</DefineConstants>
<ApplicationIcon>Assets/Hosts/Hosts.ico</ApplicationIcon>
<SelfContained>true</SelfContained>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>PowerToys.Hosts.pri</ProjectPriFileName>
<GenerateLibraryLayout>true</GenerateLibraryLayout>
<IsPackable>true</IsPackable>
</PropertyGroup>
<ItemGroup>
<Page Remove="HostsXAML\App.xaml" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="HostsXAML\App.xaml" />
<None Include="$(OutDir)\PowerToys.Hosts.pri" Pack="True" PackageCopyToOutput="true" />
<None Include="$(OutDir)\PowerToys.Hosts.pri" Pack="True" PackageCopyToOutput="true" PackagePath="lib/$(TargetFramework)" />
<None Include="$(OutDir)\PowerToys.Hosts.pdb" Pack="True" PackageCopyToOutput="true" PackagePath="lib/$(TargetFramework)" />
</ItemGroup>
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
<PropertyGroup Condition="'$(Platform)'=='x64'">
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
<PropertyGroup>
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\Hosts\AppList.scale-100.png" />
<None Remove="Assets\Hosts\AppList.scale-125.png" />
<None Remove="Assets\Hosts\AppList.scale-150.png" />
<None Remove="Assets\Hosts\AppList.scale-200.png" />
<None Remove="Assets\Hosts\AppList.scale-400.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" />
<PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
<PackageReference Include="CommunityToolkit.WinUI.Collections" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" />
<PackageReference Include="System.IO.Abstractions" />
<PackageReference Include="WinUIEx" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
@@ -73,11 +56,4 @@
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,5 @@
<Page
x:Class="Hosts.Views.MainPage"
x:Class="Hosts.Views.HostsMainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -21,21 +21,182 @@
</i:Interaction.Behaviors>
<Page.Resources>
<tkconverters:StringVisibilityConverter
x:Key="StringVisibilityConverter"
EmptyValue="Collapsed"
NotEmptyValue="Visible" />
<tkconverters:BoolNegationConverter x:Key="BoolNegationConverter" />
<tkconverters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<tkconverters:BoolToVisibilityConverter
x:Key="BoolToInvertedVisibilityConverter"
FalseValue="Visible"
TrueValue="Collapsed" />
<tkconverters:DoubleToVisibilityConverter
x:Key="DoubleToVisibilityConverter"
FalseValue="Visible"
GreaterThan="0"
TrueValue="Collapsed" />
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SystemColorHighlightTextColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SystemControlBackgroundBaseLowBrush" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SystemColorHighlightColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SystemColorHighlightColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SystemColorGrayTextColor" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="SystemColorButtonTextColorBrush" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="SystemControlHighlightBaseHighBrush" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="SystemControlHighlightBaseHighBrush" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<Style x:Key="SubtleButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter
x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AnimatedIcon.State="Normal"
AutomationProperties.AccessibilityView="Raw"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CornerRadius="{TemplateBinding CornerRadius}"
Foreground="{TemplateBinding Foreground}">
<ContentPresenter.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</ContentPresenter.BackgroundTransition>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<tkconverters:StringVisibilityConverter
x:Key="StringVisibilityConverter"
EmptyValue="Collapsed"
NotEmptyValue="Visible" />
<tkconverters:BoolNegationConverter x:Key="BoolNegationConverter" />
<tkconverters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<tkconverters:BoolToVisibilityConverter
x:Key="BoolToInvertedVisibilityConverter"
FalseValue="Visible"
TrueValue="Collapsed" />
<tkconverters:DoubleToVisibilityConverter
x:Key="DoubleToVisibilityConverter"
FalseValue="Visible"
GreaterThan="0"
TrueValue="Collapsed" />
</ResourceDictionary>
</Page.Resources>
<Grid Margin="16" RowSpacing="8">

View File

@@ -8,16 +8,14 @@ using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;
using Hosts.Helpers;
using Hosts.Models;
using Hosts.Settings;
using Hosts.ViewModels;
using ManagedCommon;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
namespace Hosts.Views
{
public sealed partial class MainPage : Page
public partial class HostsMainPage : Page
{
public MainViewModel ViewModel { get; private set; }
@@ -35,10 +33,11 @@ namespace Hosts.Views
public ICommand ExitCommand => new RelayCommand(() => { Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread().TryEnqueue(Application.Current.Exit); });
public MainPage()
public HostsMainPage(MainViewModel viewModel)
{
InitializeComponent();
ViewModel = App.GetService<MainViewModel>();
ViewModel = viewModel;
DataContext = ViewModel;
}
@@ -128,7 +127,9 @@ namespace Hosts.Views
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
var userSettings = App.GetService<IUserSettings>();
ViewModel.ReadHosts();
var userSettings = ViewModel.UserSettings;
if (userSettings.ShowStartupWarning)
{
var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
@@ -219,11 +220,14 @@ namespace Hosts.Views
{
// Based on the template from dev/CommonStyles/ContentDialog_themeresources.xaml in https://github.com/microsoft/microsoft-ui-xaml
var border = VisualTreeUtils.FindVisualChildByName(sender as ContentDialog, "BackgroundElement") as Border;
border.Margin = new Thickness(0, 32, 0, 0); // Should be the size reserved for the title bar as in MainWindow.xaml
if (border is not null)
{
border.Margin = new Thickness(0, 32, 0, 0); // Should be the size reserved for the title bar as in MainWindow.
}
}
catch (Exception ex)
{
Logger.LogError("Couldn't set the margin for a content dialog. It will appear on top of the title bar.", ex);
LoggerInstance.Logger.LogError("Couldn't set the margin for a content dialog. It will appear on top of the title bar.", ex);
}
}
}

View File

@@ -1,166 +0,0 @@
<Application
x:Class="Hosts.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Hosts">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SystemColorHighlightTextColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SystemControlBackgroundBaseLowBrush" />
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SystemColorWindowColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SystemColorHighlightColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SystemColorHighlightColorBrush" />
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SystemColorGrayTextColor" />
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="SystemColorButtonTextColorBrush" />
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="SystemControlHighlightBaseHighBrush" />
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="SystemControlHighlightBaseHighBrush" />
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<Style x:Key="SubtleButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter
x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AnimatedIcon.State="Normal"
AutomationProperties.AccessibilityView="Raw"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CornerRadius="{TemplateBinding CornerRadius}"
Foreground="{TemplateBinding Foreground}">
<ContentPresenter.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</ContentPresenter.BackgroundTransition>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,12 @@
// 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.
namespace Hosts.Settings
{
public enum HostsAdditionalLinesPosition
{
Top = 0,
Bottom = 1,
}
}

View File

@@ -0,0 +1,12 @@
// 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.
namespace Hosts.Settings
{
public enum HostsEncoding
{
Utf8 = 0,
Utf8Bom = 1,
}
}

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using Settings.UI.Library.Enumerations;
using System.Net;
namespace Hosts.Settings
{
@@ -18,5 +18,7 @@ namespace Hosts.Settings
public HostsEncoding Encoding { get; }
event EventHandler LoopbackDuplicatesChanged;
public delegate void OpenSettingsFunction();
}
}

View File

@@ -10,7 +10,6 @@ using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Common.UI;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI;
@@ -19,8 +18,8 @@ using Hosts.Exceptions;
using Hosts.Helpers;
using Hosts.Models;
using Hosts.Settings;
using ManagedCommon;
using Microsoft.UI.Dispatching;
using static Hosts.Settings.IUserSettings;
namespace Hosts.ViewModels
{
@@ -90,13 +89,22 @@ namespace Hosts.ViewModels
public int NextId => _entries?.Count > 0 ? _entries.Max(e => e.Id) + 1 : 0;
public MainViewModel(IHostsService hostService, IUserSettings userSettings)
public IUserSettings UserSettings => _userSettings;
public static MainViewModel Instance { get; set; }
private OpenSettingsFunction _openSettingsFunction;
public MainViewModel(IHostsService hostService, IUserSettings userSettings, ILogger logger, OpenSettingsFunction openSettingsFunction)
{
_hostsService = hostService;
_userSettings = userSettings;
_hostsService.FileChanged += (s, e) => _dispatcherQueue.TryEnqueue(() => FileChanged = true);
_userSettings.LoopbackDuplicatesChanged += (s, e) => ReadHosts();
LoggerInstance.Logger = logger;
_openSettingsFunction = openSettingsFunction;
}
public void Add(Entry entry)
@@ -270,7 +278,7 @@ namespace Hosts.ViewModels
[RelayCommand]
public void OpenSettings()
{
SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.Hosts, true);
_openSettingsFunction();
}
[RelayCommand]
@@ -335,7 +343,7 @@ namespace Hosts.ViewModels
}
catch (OperationCanceledException)
{
Logger.LogInfo("FindDuplicates cancelled");
LoggerInstance.Logger.LogInfo("FindDuplicates cancelled");
return;
}
}
@@ -424,7 +432,7 @@ namespace Hosts.ViewModels
}
catch (Exception ex)
{
Logger.LogError("Failed to save hosts file", ex);
LoggerInstance.Logger.LogError("Failed to save hosts file", ex);
var resourceLoader = ResourceLoaderInstance.ResourceLoader;
errorMessage = resourceLoader.GetString("FileSaveError_Generic");
}

View File

@@ -88,7 +88,7 @@ private:
SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
sei.lpFile = L"WinUI3Apps\\PowerToys.Hosts.exe";
sei.lpFile = L"WinUI3Apps\\PowerToys.HostsPackageConsumer.exe";
sei.nShow = SW_SHOWNORMAL;
sei.lpParameters = executable_args.data();

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

View File

@@ -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.
using System;
using Microsoft.Extensions.Hosting;
namespace HostsPackageConsumer.Helpers
{
public static class Host
{
public static IHost HostInstance
{
get; set;
}
public static T GetService<T>()
where T : class
{
if (HostInstance!.Services.GetService(typeof(T)) is not T service)
{
throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices within App.xaml.cs.");
}
return service;
}
}
}

View File

@@ -0,0 +1,106 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Version.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<RootNamespace>HostsPackageConsumer</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<WindowsPackageType>None</WindowsPackageType>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
<AssemblyName>PowerToys.HostsPackageConsumer</AssemblyName>
<DefineConstants>DISABLE_XAML_GENERATED_MAIN,TRACE</DefineConstants>
<SelfContained>true</SelfContained>
<ApplicationIcon>Assets/HostsPackageConsumer/Hosts.ico</ApplicationIcon>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>PowerToys.HostsPackageConsumer.pri</ProjectPriFileName>
</PropertyGroup>
<ItemGroup>
<None Remove="Assets\HostsPackageConsumer\AppList.scale-100.png" />
<None Remove="Assets\HostsPackageConsumer\AppList.scale-125.png" />
<None Remove="Assets\HostsPackageConsumer\AppList.scale-150.png" />
<None Remove="Assets\HostsPackageConsumer\AppList.scale-200.png" />
<None Remove="Assets\HostsPackageConsumer\AppList.scale-400.png" />
</ItemGroup>
<Target Name="CopyPRIFileToOutputDir" AfterTargets="Build">
<Message Text="Executing CopyPRIFileToOutputDir task" Importance="High" />
<ItemGroup>
<PRIFile Include="$(OutDir)**\PowerToys.Hosts.pri" />
</ItemGroup>
<Copy SourceFiles="@(PRIFile)" DestinationFolder="$(OutDir)" />
<Message Text="Copied CopyPRIFileToOutputDir files" Importance="High" />
</Target>
<ItemGroup>
<Page Remove="HostsPackageConsumerXAML\App.xaml" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="HostsPackageConsumerXAML\App.xaml" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\HostsPackageConsumer\Hosts.ico" />
</ItemGroup>
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
<PropertyGroup Condition="'$(Platform)'=='x64'">
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
</PropertyGroup>
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
<PropertyGroup>
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Windows.CsWinRT" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="WinUIEx" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
<ProjectReference Include="..\Hosts\Hosts.csproj" />
</ItemGroup>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
Explorer "Package and Publish" context menu entry to be enabled for this project even if
the Windows App SDK Nuget package has not yet been restored.
-->
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
</Project>

View File

@@ -1,8 +1,9 @@
<Application
x:Class="RegistryPreview.App"
<?xml version="1.0" encoding="utf-8" ?>
<Application
x:Class="HostsPackageConsumer.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RegistryPreview">
xmlns:local="using:HostsPackageConsumer">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>

View File

@@ -1,48 +1,44 @@
// Copyright (c) Microsoft Corporation
// 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.Abstractions;
using System.Threading;
using Common.UI;
using Hosts.Helpers;
using Hosts.Settings;
using Hosts.ViewModels;
using Hosts.Views;
using HostsPackageConsumer.Helpers;
using ManagedCommon;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using static Hosts.Settings.IUserSettings;
using Host = HostsPackageConsumer.Helpers.Host;
namespace Hosts
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace HostsPackageConsumer
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : Application
{
private Window _window;
public IHost Host
{
get;
}
public static T GetService<T>()
where T : class
{
if ((App.Current as App)!.Host.Services.GetService(typeof(T)) is not T service)
{
throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices within App.xaml.cs.");
}
return service;
}
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
InitializeComponent();
Host = Microsoft.Extensions.Hosting.Host.
Host.HostInstance = Microsoft.Extensions.Hosting.Host.
CreateDefaultBuilder().
UseContentRoot(AppContext.BaseDirectory).
ConfigureServices((context, services) =>
@@ -50,28 +46,33 @@ namespace Hosts
// Core Services
services.AddSingleton<IFileSystem, FileSystem>();
services.AddSingleton<IHostsService, HostsService>();
services.AddSingleton<IUserSettings, UserSettings>();
services.AddSingleton<IUserSettings, HostsPackageConsumer.Settings.UserSettings>();
services.AddSingleton<IElevationHelper, ElevationHelper>();
// Views and ViewModels
services.AddTransient<MainPage>();
services.AddTransient<MainViewModel>();
services.AddSingleton<ILogger, LoggerWrapper>();
services.AddSingleton<IElevationHelper, ElevationHelper>();
services.AddSingleton<OpenSettingsFunction>(() =>
{
SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.Hosts, true);
});
services.AddSingleton<MainViewModel, MainViewModel>();
services.AddSingleton<HostsMainPage, HostsMainPage>();
}).
Build();
UnhandledException += App_UnhandledException;
var cleanupBackupThread = new Thread(() =>
{
// Delete old backups only if running elevated
if (!GetService<IElevationHelper>().IsElevated)
if (!Host.GetService<IElevationHelper>().IsElevated)
{
return;
}
try
{
GetService<IHostsService>().CleanupBackup();
Host.GetService<IHostsService>().CleanupBackup();
}
catch (Exception ex)
{
@@ -81,8 +82,14 @@ namespace Hosts
cleanupBackupThread.IsBackground = true;
cleanupBackupThread.Start();
UnhandledException += App_UnhandledException;
}
/// <summary>
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
var cmdArgs = Environment.GetCommandLineArgs();
@@ -105,15 +112,17 @@ namespace Hosts
Logger.LogInfo($"Hosts started detached from PowerToys Runner.");
}
PowerToysTelemetry.Log.WriteEvent(new Hosts.Telemetry.HostsFileEditorOpenedEvent());
PowerToysTelemetry.Log.WriteEvent(new Telemetry.HostsFileEditorOpenedEvent());
_window = new MainWindow();
_window.Activate();
window = new MainWindow();
window.Activate();
}
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
{
Logger.LogError("Unhandled exception", e.Exception);
}
private Window window;
}
}

View File

@@ -1,9 +1,8 @@
<winuiex:WindowEx
x:Class="Hosts.MainWindow"
<winuiex:WindowEx
x:Class="HostsPackageConsumer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Hosts"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="using:Hosts.Views"
xmlns:winuiex="using:WinUIEx"
@@ -15,7 +14,7 @@
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid>
<Grid x:Name="MainGrid" Loaded="Grid_Loaded">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
@@ -35,14 +34,12 @@
Width="16"
Height="16"
VerticalAlignment="Center"
Source="../Assets/Hosts/Hosts.ico" />
Source="../Assets/HostsPackageConsumer/Hosts.ico" />
<TextBlock
x:Name="AppTitleTextBlock"
Grid.Column="2"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}" />
</Grid>
<views:MainPage Grid.Row="1" />
</Grid>
</winuiex:WindowEx>

View File

@@ -1,34 +1,49 @@
// Copyright (c) Microsoft Corporation
// 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 Hosts.Helpers;
using Hosts.ViewModels;
using Hosts.Views;
using HostsPackageConsumer.Helpers;
using ManagedCommon;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.Windows.ApplicationModel.Resources;
using WinUIEx;
namespace Hosts
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace HostsPackageConsumer
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : WindowEx
{
private HostsMainPage MainPage { get; }
public MainWindow()
{
InitializeComponent();
ExtendsContentIntoTitleBar = true;
SetTitleBar(titleBar);
AppWindow.SetIcon("Assets/Hosts/Hosts.ico");
AppWindow.SetIcon("Assets/HostsPackageConsumer/Hosts.ico");
var loader = ResourceLoaderInstance.ResourceLoader;
var title = App.GetService<IElevationHelper>().IsElevated ? loader.GetString("WindowAdminTitle") : loader.GetString("WindowTitle");
var loader = new ResourceLoader("PowerToys.Hosts.pri", "PowerToys.Hosts/Resources");
var title = Host.GetService<IElevationHelper>().IsElevated ? loader.GetString("WindowAdminTitle") : loader.GetString("WindowTitle");
Title = title;
AppTitleTextBlock.Text = title;
var handle = this.GetWindowHandle();
WindowHelpers.BringToForeground(handle);
WindowHelpers.BringToForeground(handle);
Activated += MainWindow_Activated;
MainPage = Host.GetService<HostsMainPage>();
}
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
@@ -42,5 +57,11 @@ namespace Hosts
AppTitleTextBlock.Foreground = (SolidColorBrush)App.Current.Resources["WindowCaptionForeground"];
}
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
MainGrid.Children.Add(MainPage);
Grid.SetRow(MainPage, 1);
}
}
}

View File

@@ -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.
using System;
using Hosts.Helpers;
using ManagedCommon;
namespace HostsPackageConsumer
{
internal sealed class LoggerWrapper : ILogger
{
public void LogDebug(string message)
{
Logger.LogDebug(message);
}
public void LogError(string message)
{
Logger.LogError(message);
}
public void LogError(string message, Exception ex)
{
Logger.LogError(message, ex);
}
public void LogInfo(string message)
{
Logger.LogInfo(message);
}
public void LogTrace()
{
Logger.LogTrace();
}
public void LogWarning(string message)
{
Logger.LogWarning(message);
}
}
}

View File

@@ -8,7 +8,7 @@ using ManagedCommon;
using Microsoft.UI.Dispatching;
using Microsoft.Windows.AppLifecycle;
namespace Hosts
namespace HostsPackageConsumer
{
public static class Program
{
@@ -16,7 +16,6 @@ namespace Hosts
public static void Main(string[] args)
{
Logger.InitializeLogger("\\Hosts\\Logs");
WinRT.ComWrappersSupport.InitializeComWrappers();
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredHostsFileEditorEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
@@ -25,7 +24,7 @@ namespace Hosts
return;
}
var instanceKey = AppInstance.FindOrRegisterForKey("PowerToys_Hosts_Instance");
var instanceKey = AppInstance.FindOrRegisterForKey("PowerToys_HostsPackageConsumer_Instance");
if (instanceKey.IsCurrent)
{

View File

@@ -5,12 +5,13 @@
using System;
using System.IO.Abstractions;
using System.Threading;
using Hosts.Helpers;
using Hosts.Settings;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Settings.UI.Library.Enumerations;
namespace Hosts.Settings
namespace HostsPackageConsumer.Settings
{
public class UserSettings : IUserSettings
{
@@ -38,8 +39,10 @@ namespace Hosts.Settings
}
}
// Moved from Settings.UI.Library
public HostsAdditionalLinesPosition AdditionalLinesPosition { get; private set; }
// Moved from Settings.UI.Library
public HostsEncoding Encoding { get; set; }
public UserSettings()
@@ -72,6 +75,7 @@ namespace Hosts.Settings
if (!_settingsUtils.SettingsExists(HostsModuleName))
{
// Logger needs to be abstracted
Logger.LogInfo("Hosts settings.json was missing, creating a new one");
var defaultSettings = new HostsSettings();
defaultSettings.Save(_settingsUtils);
@@ -81,8 +85,8 @@ namespace Hosts.Settings
if (settings != null)
{
ShowStartupWarning = settings.Properties.ShowStartupWarning;
AdditionalLinesPosition = settings.Properties.AdditionalLinesPosition;
Encoding = settings.Properties.Encoding;
AdditionalLinesPosition = (HostsAdditionalLinesPosition)settings.Properties.AdditionalLinesPosition;
Encoding = (HostsEncoding)settings.Properties.Encoding;
LoopbackDuplicates = settings.Properties.LoopbackDuplicates;
}

View File

@@ -6,7 +6,7 @@ using System.Diagnostics.Tracing;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Hosts.Telemetry
namespace HostsPackageConsumer.Telemetry
{
[EventData]
public class HostsFileEditorOpenedEvent : EventBase, IEvent

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="Hosts.app"/>
<assembly manifestVersion="1.0"
xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="HostsPackageConsumer.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
@@ -18,4 +19,4 @@
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
</assembly>

View File

@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.UI.Xaml;
using Windows.Data.Json;
using WinUIEx;
namespace RegistryPreview
{
public sealed partial class MainWindow : WindowEx
{
/// <summary>
/// Event handler to grab the main window's size and position before it closes
/// </summary>
private void AppWindow_Closing(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowClosingEventArgs args)
{
jsonWindowPlacement.SetNamedValue("appWindow.Position.X", JsonValue.CreateNumberValue(appWindow.Position.X));
jsonWindowPlacement.SetNamedValue("appWindow.Position.Y", JsonValue.CreateNumberValue(appWindow.Position.Y));
jsonWindowPlacement.SetNamedValue("appWindow.Size.Width", JsonValue.CreateNumberValue(appWindow.Size.Width));
jsonWindowPlacement.SetNamedValue("appWindow.Size.Height", JsonValue.CreateNumberValue(appWindow.Size.Height));
}
/// <summary>
/// Event that is will prevent the app from closing if the "save file" flag is active
/// </summary>
public void Window_Closed(object sender, WindowEventArgs args)
{
// Save window placement
SaveWindowPlacementFile(settingsFolder, windowPlacementFile);
}
}
}

View File

@@ -0,0 +1,95 @@
// 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.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Windows.Storage;
using WinUIEx;
namespace RegistryPreview
{
public sealed partial class MainWindow : WindowEx
{
private void OpenWindowPlacementFile(string path, string filename)
{
string fileContents = string.Empty;
string storageFile = Path.Combine(path, filename);
if (File.Exists(storageFile))
{
try
{
StreamReader reader = new StreamReader(storageFile);
fileContents = reader.ReadToEnd();
reader.Close();
}
catch
{
// set up default JSON blob
fileContents = "{ }";
}
}
else
{
Task.Run(() => SaveWindowPlacementFile(path, filename)).GetAwaiter().GetResult();
}
try
{
jsonWindowPlacement = Windows.Data.Json.JsonObject.Parse(fileContents);
}
catch
{
// set up default JSON blob
fileContents = "{ }";
jsonWindowPlacement = Windows.Data.Json.JsonObject.Parse(fileContents);
}
}
/// <summary>
/// Save the window placement JSON blob out to a local file
/// </summary>
private async void SaveWindowPlacementFile(string path, string filename)
{
StorageFolder storageFolder = null;
StorageFile storageFile = null;
string fileContents = string.Empty;
try
{
storageFolder = await StorageFolder.GetFolderFromPathAsync(path);
}
catch (FileNotFoundException ex)
{
Debug.WriteLine(ex.Message);
Directory.CreateDirectory(path);
storageFolder = await StorageFolder.GetFolderFromPathAsync(path);
}
try
{
storageFile = await storageFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);
}
catch (FileNotFoundException ex)
{
Debug.WriteLine(ex.Message);
storageFile = await storageFolder.CreateFileAsync(filename);
}
try
{
if (jsonWindowPlacement != null)
{
fileContents = jsonWindowPlacement.Stringify();
await Windows.Storage.FileIO.WriteTextAsync(storageFile, fileContents);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
}

View File

@@ -0,0 +1,88 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<RootNamespace>RegistryPreview</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;ARM64</Platforms>
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<WindowsPackageType>None</WindowsPackageType>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<SelfContained>true</SelfContained>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
<AssemblyName>PowerToys.RegistryPreview</AssemblyName>
<ApplicationIcon>Assets\RegistryPreview\RegistryPreview.ico</ApplicationIcon>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>PowerToys.RegistryPreview.pri</ProjectPriFileName>
</PropertyGroup>
<ItemGroup>
<Page Remove="RegistryPreviewXAML\App.xaml" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="RegistryPreviewXAML\App.xaml" />
</ItemGroup>
<ItemGroup>
<Folder Include="RegistryPreviewXAML\" />
</ItemGroup>
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
<PropertyGroup Condition="'$(Platform)'=='x64'">
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="WinUIEx" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<!--
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
Tools extension to be activated for this project even if the Windows App SDK Nuget
package has not yet been restored.
-->
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<ProjectCapability Include="Msix" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\RegistryPreviewUILib\RegistryPreviewUILib.csproj" />
</ItemGroup>
<Target Name="CopyPRIFileToOutputDir" AfterTargets="Build">
<Message Text="Executing CopyDLLs task" Importance="High" />
<ItemGroup>
<PRIFile Include="$(OutDir)**\PowerToys.RegistryPreviewUILib.pri" />
</ItemGroup>
<Copy SourceFiles="@(PRIFile)" DestinationFolder="$(OutDir)" />
<Message Text="Copied build files" Importance="High" />
</Target>
<!--
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
Explorer "Package and Publish" context menu entry to be enabled for this project even if
the Windows App SDK Nuget package has not yet been restored.
-->
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Application
x:Class="RegistryPreview.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RegistryPreview">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other app resources here -->
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -3,14 +3,13 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Web;
using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
using Windows.ApplicationModel.Activation;
using LaunchActivatedEventArgs = Windows.ApplicationModel.Activation.LaunchActivatedEventArgs;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace RegistryPreview
{
/// <summary>
@@ -20,6 +19,8 @@ namespace RegistryPreview
{
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
@@ -27,8 +28,7 @@ namespace RegistryPreview
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// Invoked when the application is launched.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)

View File

@@ -0,0 +1,52 @@
<winuiex:WindowEx
x:Class="RegistryPreview.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:winuiex="using:WinUIEx"
MinWidth="480"
MinHeight="320"
Closed="Window_Closed"
mc:Ignorable="d">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid x:Name="MainGrid" Loaded="Grid_Loaded">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
x:Name="titleBar"
Grid.Row="0"
Height="32"
Margin="16,0"
ColumnSpacing="16"
IsHitTestVisible="True">
<Grid.ColumnDefinitions>
<!--<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>-->
<ColumnDefinition x:Name="IconColumn" Width="Auto" />
<ColumnDefinition x:Name="TitleColumn" Width="Auto" />
<!--<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>-->
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Width="16"
Height="16"
VerticalAlignment="Center"
Source="../Assets/RegistryPreview/RegistryPreview.ico" />
<TextBlock
x:Name="titleBarText"
Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding ApplicationTitle}" />
</Grid>
</Grid>
</winuiex:WindowEx>

View File

@@ -1,16 +1,14 @@
// Copyright (c) Microsoft Corporation
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using ManagedCommon;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.Windows.ApplicationModel.Resources;
using RegistryPreviewUILib;
using Windows.Data.Json;
using Windows.Graphics;
using WinUIEx;
@@ -20,39 +18,31 @@ namespace RegistryPreview
public sealed partial class MainWindow : WindowEx
{
// Const values
private const string REGISTRYHEADER4 = "regedit4";
private const string REGISTRYHEADER5 = "windows registry editor version 5.00";
private const string APPNAME = "RegistryPreview";
private const string KEYIMAGE = "ms-appx:///Assets/RegistryPreview/folder32.png";
private const string DELETEDKEYIMAGE = "ms-appx:///Assets/RegistryPreview/deleted-folder32.png";
private const string ERRORIMAGE = "ms-appx:///Assets/RegistryPreview/error32.png";
// private members
private Microsoft.UI.Windowing.AppWindow appWindow;
private ResourceLoader resourceLoader;
private bool visualTreeReady;
private Dictionary<string, TreeViewNode> mapRegistryKeys;
private List<RegistryValue> listRegistryValues;
private JsonObject jsonWindowPlacement;
private string settingsFolder = string.Empty;
private string windowPlacementFile = "app-placement.json";
private RegistryPreviewMainPage MainPage { get; }
internal MainWindow()
{
this.InitializeComponent();
// Initialize the string table
resourceLoader = ResourceLoaderInstance.ResourceLoader;
// Open settings file; this moved to after the window tweak because it gives the window time to start up
settingsFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\PowerToys\" + APPNAME;
OpenWindowPlacementFile(settingsFolder, windowPlacementFile);
// Update the Win32 looking window with the correct icon (and grab the appWindow handle for later)
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle);
Microsoft.UI.WindowId windowId = Win32Interop.GetWindowIdFromWindow(windowHandle);
appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
appWindow.SetIcon("Assets\\RegistryPreview\\app.ico");
appWindow.SetIcon("Assets\\RegistryPreview\\RegistryPreview.ico");
// TODO(stefan)
appWindow.Closing += AppWindow_Closing;
Activated += MainWindow_Activated;
@@ -92,12 +82,7 @@ namespace RegistryPreview
}
}
// Update Toolbar
if ((App.AppFilename == null) || (File.Exists(App.AppFilename) != true))
{
UpdateToolBarAndUI(false);
UpdateWindowTitle(resourceLoader.GetString("FileNotFound"));
}
MainPage = new RegistryPreviewMainPage(this, this.UpdateWindowTitle, App.AppFilename);
WindowHelpers.BringToForeground(windowHandle);
}
@@ -107,12 +92,44 @@ namespace RegistryPreview
if (args.WindowActivationState == WindowActivationState.Deactivated)
{
titleBarText.Foreground =
(SolidColorBrush)App.Current.Resources["WindowCaptionForegroundDisabled"];
(SolidColorBrush)Application.Current.Resources["WindowCaptionForegroundDisabled"];
}
else
{
titleBarText.Foreground =
(SolidColorBrush)App.Current.Resources["WindowCaptionForeground"];
(SolidColorBrush)Application.Current.Resources["WindowCaptionForeground"];
}
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
MainGrid.Children.Add(MainPage);
Grid.SetRow(MainPage, 1);
}
public void UpdateWindowTitle(string title)
{
string filename = title;
if (string.IsNullOrEmpty(filename))
{
titleBarText.Text = APPNAME;
appWindow.Title = APPNAME;
}
else
{
string[] file = filename.Split('\\');
if (file.Length > 0)
{
titleBarText.Text = file[file.Length - 1] + " - " + APPNAME;
}
else
{
titleBarText.Text = filename + " - " + APPNAME;
}
// Continue to update the window's title, after updating the custom title bar
appWindow.Title = titleBarText.Text;
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root"
xmlns=""
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="RegistryPreview.app"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10.
It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>

View File

@@ -1,84 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Version.props" />
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
<Platforms>x86;x64;arm64</Platforms>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
<UseWinUI>true</UseWinUI>
<UseWindowsForms>False</UseWindowsForms>
<ApplicationIcon>Assets\RegistryPreview\app.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<WindowsPackageType>None</WindowsPackageType>
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
<SelfContained>true</SelfContained>
<Product>$(AssemblyName)</Product>
<AssemblyName>PowerToys.RegistryPreview</AssemblyName>
<AssemblyTitle>PowerToys.RegistryPreview</AssemblyTitle>
<AssemblyDescription>PowerToys RegistryPreview</AssemblyDescription>
<RootNamespace>RegistryPreview</RootNamespace>
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>PowerToys.RegistryPreview.pri</ProjectPriFileName>
</PropertyGroup>
<ItemGroup>
<Page Remove="RegistryPreviewXAML\App.xaml" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="RegistryPreviewXAML\App.xaml" />
</ItemGroup>
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
<PropertyGroup Condition="'$(Platform)'=='x64'">
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<Content Include="Assets\RegistryPreview\app.ico" />
</ItemGroup>
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
<PropertyGroup>
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="WinUIEx" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="Assets\RegistryPreview\data32.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
<Content Update="Assets\RegistryPreview\string32.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
<!--TargetFramework>net6.0-windows10.0.19041.0</TargetFramework-->

View File

@@ -1,310 +0,0 @@
<winuiex:WindowEx
x:Class="RegistryPreview.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:winuiex="using:WinUIEx"
MinWidth="480"
MinHeight="320"
Closed="Window_Closed"
mc:Ignorable="d">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
x:Name="titleBar"
Grid.Row="0"
Height="32"
Margin="16,0"
ColumnSpacing="16"
IsHitTestVisible="True">
<Grid.ColumnDefinitions>
<!--<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>-->
<ColumnDefinition x:Name="IconColumn" Width="Auto" />
<ColumnDefinition x:Name="TitleColumn" Width="Auto" />
<!--<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>-->
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Width="16"
Height="16"
VerticalAlignment="Center"
Source="../Assets/RegistryPreview/app.ico" />
<TextBlock
x:Name="titleBarText"
Grid.Column="1"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding ApplicationTitle}" />
</Grid>
<Grid
x:Name="gridPreview"
Grid.Row="1"
Width="Auto"
Height="Auto"
Margin="12"
x:FieldModifier="public"
Loaded="GridPreview_Loaded"
TabFocusNavigation="Cycle">
<Grid.Resources>
<Style x:Key="GridCardStyle" TargetType="Border">
<Style.Setters>
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
<Setter Property="CornerRadius" Value="{StaticResource OverlayCornerRadius}" />
</Style.Setters>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<!-- Left, Splitter, Right -->
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<!-- CommandBar, Tree, Splitter, List -->
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="8" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="0,0,0,12"
Style="{StaticResource GridCardStyle}">
<CommandBar
Name="commandBar"
HorizontalAlignment="Left"
DefaultLabelPosition="Right">
<AppBarButton
x:Name="openButton"
x:Uid="OpenButton"
Click="OpenButton_Click"
Icon="{ui:FontIcon Glyph=&#xe8e5;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="O" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="refreshButton"
x:Uid="RefreshButton"
Click="RefreshButton_Click"
Icon="{ui:FontIcon Glyph=&#xe72c;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="F5" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarSeparator />
<AppBarButton
x:Name="saveButton"
x:Uid="SaveButton"
Click="SaveButton_Click"
Icon="{ui:FontIcon Glyph=&#xe74e;}"
IsEnabled="False">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="S" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="saveAsButton"
x:Uid="SaveAsButton"
Click="SaveAsButton_Click"
Icon="{ui:FontIcon Glyph=&#xe792;}"
IsEnabled="True">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="S" Modifiers="Control,Shift" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarSeparator />
<AppBarButton
x:Name="editButton"
x:Uid="EditButton"
Click="EditButton_Click"
Icon="{ui:FontIcon Glyph=&#xe8a7;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="E" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="writeButton"
x:Uid="WriteButton"
Click="WriteButton_Click"
Icon="{ui:FontIcon Glyph=&#xe72d;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="W" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="registryButton"
x:Uid="RegistryButton"
Click="RegistryButton_Click"
Icon="{ui:FontIcon Glyph=&#xe8ad;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="R" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="registryJumpToKeyButton"
x:Uid="RegistryJumpToKeyButton"
Click="RegistryJumpToKeyButton_Click"
IsEnabled="True">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="R" Modifiers="Control,Shift" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
</CommandBar>
</Border>
<TextBox
x:Name="textBox"
x:Uid="textBox"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AcceptsReturn="True"
CanBeScrollAnchor="False"
CornerRadius="{StaticResource OverlayCornerRadius}"
FontFamily="Cascadia Mono, Consolas, Courier New"
IsSpellCheckEnabled="False"
IsTabStop="True"
IsTextPredictionEnabled="False"
PlaceholderText="{Binding PlaceholderText}"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.IsHorizontalRailEnabled="True"
ScrollViewer.IsVerticalRailEnabled="True"
ScrollViewer.VerticalScrollBarVisibility="Visible"
TabIndex="0"
TextWrapping="NoWrap" />
<Border
Grid.Row="1"
Grid.Column="2"
Style="{StaticResource GridCardStyle}">
<TreeView
x:Name="treeView"
AllowDrop="False"
AllowFocusOnInteraction="True"
CanDragItems="False"
CanReorderItems="False"
IsEnabled="True"
IsTabStop="False"
ItemInvoked="TreeView_ItemInvoked"
ScrollViewer.BringIntoViewOnFocusChange="True"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollMode="Auto"
TabIndex="1">
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel
VerticalAlignment="Center"
IsTabStop="False"
Orientation="Horizontal"
Spacing="8">
<Image
MaxWidth="16"
MaxHeight="16"
Source="{Binding Path=Content.Image}"
ToolTipService.ToolTip="{Binding Path=Content.ToolTipText}" />
<TextBlock Text="{Binding Path=Content.Name}" />
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Border>
<Border
Grid.Row="3"
Grid.Column="2"
Style="{StaticResource GridCardStyle}">
<tk7controls:DataGrid
x:Name="dataGrid"
AllowDrop="False"
AreRowDetailsFrozen="True"
AutoGenerateColumns="False"
CanDrag="False"
HeadersVisibility="Column"
IsReadOnly="True"
IsTabStop="true"
ItemsSource="{x:Bind listRegistryValues}"
RowDetailsVisibilityMode="Collapsed"
SelectionMode="Single"
TabIndex="2">
<tk7controls:DataGrid.Columns>
<tk7controls:DataGridTemplateColumn
x:Uid="NameColumn"
Width="Auto"
IsReadOnly="True">
<tk7controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel
Margin="4"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<Image
MaxWidth="16"
MaxHeight="16"
IsTabStop="False"
Source="{Binding ImageUri}"
ToolTipService.ToolTip="{Binding ToolTipText}" />
<TextBlock
IsTabStop="False"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</tk7controls:DataGridTemplateColumn.CellTemplate>
</tk7controls:DataGridTemplateColumn>
<tk7controls:DataGridTextColumn
x:Uid="TypeColumn"
Width="Auto"
Binding="{Binding Type}"
FontSize="{StaticResource CaptionTextBlockFontSize}" />
<tk7controls:DataGridTextColumn
x:Uid="ValueColumn"
Width="Auto"
Binding="{Binding Value}"
FontSize="{StaticResource CaptionTextBlockFontSize}" />
</tk7controls:DataGrid.Columns>
</tk7controls:DataGrid>
</Border>
<tkcontrols:GridSplitter
x:Name="verticalSplitter"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
IsTabStop="False" />
<tkcontrols:GridSplitter
x:Name="horizontalSplitter"
Grid.Row="2"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
IsTabStop="False" />
</Grid>
</Grid>
</winuiex:WindowEx>

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View File

@@ -5,7 +5,7 @@
using System;
using System.Runtime.InteropServices;
namespace RegistryPreview
namespace RegistryPreviewUILib
{
// Workaround for File Pickers that don't work while running as admin, per:
// https://github.com/microsoft/WindowsAppSDK/issues/2504

View File

@@ -4,7 +4,7 @@
using System.Runtime.InteropServices;
namespace RegistryPreview
namespace RegistryPreviewUILib
{
// Workaround for File Pickers that don't work while running as admin, per:
// https://github.com/microsoft/WindowsAppSDK/issues/2504

View File

@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace RegistryPreview
namespace RegistryPreviewUILib
{
/// <summary>
/// Class representing an each item in the tree view, each one a Registry Key;

View File

@@ -13,33 +13,17 @@ using CommunityToolkit.WinUI.UI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Media;
using Windows.Data.Json;
using Windows.Foundation.Metadata;
using Windows.Storage;
using Windows.Storage.Pickers;
using WinRT.Interop;
using WinUIEx;
namespace RegistryPreview
namespace RegistryPreviewUILib
{
public sealed partial class MainWindow : WindowEx
public sealed partial class RegistryPreviewMainPage : Page
{
/// <summary>
/// Event handler to grab the main window's size and position before it closes
/// </summary>
private void AppWindow_Closing(Microsoft.UI.Windowing.AppWindow sender, Microsoft.UI.Windowing.AppWindowClosingEventArgs args)
{
jsonWindowPlacement.SetNamedValue("appWindow.Position.X", JsonValue.CreateNumberValue(appWindow.Position.X));
jsonWindowPlacement.SetNamedValue("appWindow.Position.Y", JsonValue.CreateNumberValue(appWindow.Position.Y));
jsonWindowPlacement.SetNamedValue("appWindow.Size.Width", JsonValue.CreateNumberValue(appWindow.Size.Width));
jsonWindowPlacement.SetNamedValue("appWindow.Size.Height", JsonValue.CreateNumberValue(appWindow.Size.Height));
}
/// <summary>
/// Event that is will prevent the app from closing if the "save file" flag is active
/// </summary>
public void Window_Closed(object sender, WindowEventArgs args)
public void MainWindow_Closed(object sender, WindowEventArgs args)
{
// Only block closing if the REG file has been edited but not yet saved
if (saveButton.IsEnabled)
@@ -69,13 +53,10 @@ namespace RegistryPreview
DispatcherQueue.TryEnqueue(async () =>
{
await Task.Delay(100);
App.Current.Exit();
Application.Current.Exit();
});
return;
}
// Save window placement
SaveWindowPlacementFile(settingsFolder, windowPlacementFile);
}
/// <summary>
@@ -87,20 +68,20 @@ namespace RegistryPreview
visualTreeReady = true;
// Check to see if the REG file was opened and parsed successfully
if (OpenRegistryFile(App.AppFilename) == false)
if (OpenRegistryFile(_appFileName) == false)
{
if (File.Exists(App.AppFilename))
if (File.Exists(_appFileName))
{
// Allow Refresh and Edit to be enabled because a broken Reg file might be fixable
UpdateToolBarAndUI(false, true, true);
UpdateWindowTitle(resourceLoader.GetString("InvalidRegistryFileTitle"));
_updateWindowTitleFunction(resourceLoader.GetString("InvalidRegistryFileTitle"));
textBox.TextChanged += TextBox_TextChanged;
return;
}
else
{
UpdateToolBarAndUI(false, false, false);
UpdateWindowTitle();
_updateWindowTitleFunction(string.Empty);
}
}
else
@@ -171,8 +152,8 @@ namespace RegistryPreview
// mute the TextChanged handler to make for clean UI
textBox.TextChanged -= TextBox_TextChanged;
App.AppFilename = storageFile.Path;
UpdateToolBarAndUI(OpenRegistryFile(App.AppFilename));
_appFileName = storageFile.Path;
UpdateToolBarAndUI(OpenRegistryFile(_appFileName));
// disable the Save button as it's a new file
saveButton.IsEnabled = false;
@@ -207,9 +188,9 @@ namespace RegistryPreview
return;
}
App.AppFilename = filename;
_appFileName = filename;
SaveFile();
UpdateToolBarAndUI(OpenRegistryFile(App.AppFilename));
UpdateToolBarAndUI(OpenRegistryFile(_appFileName));
}
/// <summary>
@@ -221,7 +202,7 @@ namespace RegistryPreview
textBox.TextChanged -= TextBox_TextChanged;
// reload the current Registry file and update the toolbar accordingly.
UpdateToolBarAndUI(OpenRegistryFile(App.AppFilename), true, true);
UpdateToolBarAndUI(OpenRegistryFile(_appFileName), true, true);
saveButton.IsEnabled = false;
@@ -301,7 +282,7 @@ namespace RegistryPreview
}
// pass in the filename so we can edit the current file
OpenRegistryEditor(App.AppFilename);
OpenRegistryEditor(_appFileName);
}
/// <summary>
@@ -311,7 +292,7 @@ namespace RegistryPreview
{
// use the REG file's filename and verb so we can respect the selected editor
Process process = new Process();
process.StartInfo.FileName = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", App.AppFilename);
process.StartInfo.FileName = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", _appFileName);
process.StartInfo.Verb = "Edit";
process.StartInfo.UseShellExecute = true;

View File

@@ -11,18 +11,17 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation.Metadata;
using Windows.Storage;
using WinUIEx;
namespace RegistryPreview
namespace RegistryPreviewUILib
{
public sealed partial class MainWindow : WindowEx
public sealed partial class RegistryPreviewMainPage : Page
{
public delegate void UpdateWindowTitleFunction(string title);
/// <summary>
/// Method that opens and processes the passed in file name; expected to be an absolute path and a first time open
/// </summary>
@@ -34,7 +33,7 @@ namespace RegistryPreview
long fileLength = new System.IO.FileInfo(filename).Length;
if (fileLength > 10485760)
{
ShowMessageBox(resourceLoader.GetString("LargeRegistryFileTitle"), App.AppFilename + resourceLoader.GetString("LargeRegistryFile"), resourceLoader.GetString("OkButtonText"));
ShowMessageBox(resourceLoader.GetString("LargeRegistryFileTitle"), _appFileName + resourceLoader.GetString("LargeRegistryFile"), resourceLoader.GetString("OkButtonText"));
ChangeCursor(gridPreview, false);
return false;
}
@@ -53,7 +52,7 @@ namespace RegistryPreview
ClearTable();
// update the current window's title with the current filename
UpdateWindowTitle(filename);
_updateWindowTitleFunction(filename);
// Load in the whole file in one call and plop it all into textBox
FileStream fileStream = null;
@@ -204,7 +203,7 @@ namespace RegistryPreview
case REGISTRYHEADER5:
break;
default:
ShowMessageBox(APPNAME, App.AppFilename + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
ShowMessageBox(APPNAME, _appFileName + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
ChangeCursor(gridPreview, false);
return false;
}
@@ -600,7 +599,7 @@ namespace RegistryPreview
{
AddTextToTree(resourceLoader.GetString("NoNodesFoundInFile"), ERRORIMAGE);
// ShowMessageBox(APPNAME, App.AppFilename + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
// ShowMessageBox(APPNAME, _appFileName + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
}
ChangeCursor(gridPreview, false);
@@ -614,7 +613,7 @@ namespace RegistryPreview
// last check, to see if anything got parsed!
if (treeView.RootNodes.Count <= 0)
{
ShowMessageBox(APPNAME, App.AppFilename + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
ShowMessageBox(APPNAME, _appFileName + resourceLoader.GetString("InvalidRegistryFile"), resourceLoader.GetString("OkButtonText"));
ChangeCursor(gridPreview, false);
return false;
}
@@ -646,34 +645,6 @@ namespace RegistryPreview
registryKey.Tag = arrayList;
}
/// <summary>
/// Adds the REG file that's being currently being viewed to the app's title bar
/// </summary>
private void UpdateWindowTitle(string filename)
{
string[] file = filename.Split('\\');
if (file.Length > 0)
{
titleBarText.Text = file[file.Length - 1] + " - " + APPNAME;
}
else
{
titleBarText.Text = filename + " - " + APPNAME;
}
// Continue to update the window's title, after updating the custom title bar
appWindow.Title = titleBarText.Text;
}
/// <summary>
/// No REG file was opened, so leave the app's title bar alone
/// </summary>
private void UpdateWindowTitle()
{
titleBarText.Text = APPNAME;
appWindow.Title = APPNAME;
}
/// <summary>
/// Helper method that assumes everything is enabled/disabled together
/// </summary>
@@ -861,7 +832,7 @@ namespace RegistryPreview
}
// if we got here, we should try to close again
App.Current.Exit();
Application.Current.Exit();
}
/// <summary>
@@ -939,7 +910,7 @@ namespace RegistryPreview
fileStreamOptions.Share = FileShare.Write;
fileStreamOptions.Mode = FileMode.Create;
fileStream = new FileStream(App.AppFilename, fileStreamOptions);
fileStream = new FileStream(_appFileName, fileStreamOptions);
StreamWriter streamWriter = new StreamWriter(fileStream, System.Text.Encoding.Unicode);
// if we get here, the file is open and writable so dump the whole contents of textBox
@@ -980,85 +951,6 @@ namespace RegistryPreview
ChangeCursor(gridPreview, false);
}
private void OpenWindowPlacementFile(string path, string filename)
{
string fileContents = string.Empty;
string storageFile = Path.Combine(path, filename);
if (File.Exists(storageFile))
{
try
{
StreamReader reader = new StreamReader(storageFile);
fileContents = reader.ReadToEnd();
reader.Close();
}
catch
{
// set up default JSON blob
fileContents = "{ }";
}
}
else
{
Task.Run(() => SaveWindowPlacementFile(path, filename)).GetAwaiter().GetResult();
}
try
{
jsonWindowPlacement = Windows.Data.Json.JsonObject.Parse(fileContents);
}
catch
{
// set up default JSON blob
fileContents = "{ }";
jsonWindowPlacement = Windows.Data.Json.JsonObject.Parse(fileContents);
}
}
/// <summary>
/// Save the window placement JSON blob out to a local file
/// </summary>
private async void SaveWindowPlacementFile(string path, string filename)
{
StorageFolder storageFolder = null;
StorageFile storageFile = null;
string fileContents = string.Empty;
try
{
storageFolder = await StorageFolder.GetFolderFromPathAsync(path);
}
catch (FileNotFoundException ex)
{
Debug.WriteLine(ex.Message);
Directory.CreateDirectory(path);
storageFolder = await StorageFolder.GetFolderFromPathAsync(path);
}
try
{
storageFile = await storageFolder.CreateFileAsync(filename, CreationCollisionOption.OpenIfExists);
}
catch (FileNotFoundException ex)
{
Debug.WriteLine(ex.Message);
storageFile = await storageFolder.CreateFileAsync(filename);
}
try
{
if (jsonWindowPlacement != null)
{
fileContents = jsonWindowPlacement.Stringify();
await Windows.Storage.FileIO.WriteTextAsync(storageFile, fileContents);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
/// <summary>
/// Rip the first and last character off a string,
/// checking that the string is at least 2 characters long to avoid errors

View File

@@ -0,0 +1,270 @@
<Page
x:Class="RegistryPreviewUILib.RegistryPreviewMainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
mc:Ignorable="d">
<Grid
x:Name="gridPreview"
Grid.Row="1"
Width="Auto"
Height="Auto"
Margin="12"
x:FieldModifier="public"
Loaded="GridPreview_Loaded"
TabFocusNavigation="Cycle">
<Grid.Resources>
<Style x:Key="GridCardStyle" TargetType="Border">
<Style.Setters>
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}" />
<Setter Property="CornerRadius" Value="{StaticResource OverlayCornerRadius}" />
</Style.Setters>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<!-- Left, Splitter, Right -->
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<!-- CommandBar, Tree, Splitter, List -->
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="8" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="0,0,0,12"
Style="{StaticResource GridCardStyle}">
<CommandBar
Name="commandBar"
HorizontalAlignment="Left"
DefaultLabelPosition="Right">
<AppBarButton
x:Name="openButton"
x:Uid="OpenButton"
Click="OpenButton_Click"
Icon="{ui:FontIcon Glyph=&#xe8e5;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="O" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="refreshButton"
x:Uid="RefreshButton"
Click="RefreshButton_Click"
Icon="{ui:FontIcon Glyph=&#xe72c;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="F5" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarSeparator />
<AppBarButton
x:Name="saveButton"
x:Uid="SaveButton"
Click="SaveButton_Click"
Icon="{ui:FontIcon Glyph=&#xe74e;}"
IsEnabled="False">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="S" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="saveAsButton"
x:Uid="SaveAsButton"
Click="SaveAsButton_Click"
Icon="{ui:FontIcon Glyph=&#xe792;}"
IsEnabled="True">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="S" Modifiers="Control,Shift" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarSeparator />
<AppBarButton
x:Name="editButton"
x:Uid="EditButton"
Click="EditButton_Click"
Icon="{ui:FontIcon Glyph=&#xe8a7;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="E" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="writeButton"
x:Uid="WriteButton"
Click="WriteButton_Click"
Icon="{ui:FontIcon Glyph=&#xe72d;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="W" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="registryButton"
x:Uid="RegistryButton"
Click="RegistryButton_Click"
Icon="{ui:FontIcon Glyph=&#xe8ad;}">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="R" Modifiers="Control" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
<AppBarButton
x:Name="registryJumpToKeyButton"
x:Uid="RegistryJumpToKeyButton"
Click="RegistryJumpToKeyButton_Click"
IsEnabled="True">
<AppBarButton.KeyboardAccelerators>
<KeyboardAccelerator Key="R" Modifiers="Control,Shift" />
</AppBarButton.KeyboardAccelerators>
</AppBarButton>
</CommandBar>
</Border>
<TextBox
x:Name="textBox"
x:Uid="textBox"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AcceptsReturn="True"
CanBeScrollAnchor="False"
CornerRadius="{StaticResource OverlayCornerRadius}"
FontFamily="Cascadia Mono, Consolas, Courier New"
IsSpellCheckEnabled="False"
IsTabStop="True"
IsTextPredictionEnabled="False"
PlaceholderText="{Binding PlaceholderText}"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.IsHorizontalRailEnabled="True"
ScrollViewer.IsVerticalRailEnabled="True"
ScrollViewer.VerticalScrollBarVisibility="Visible"
TabIndex="0"
TextWrapping="NoWrap" />
<Border
Grid.Row="1"
Grid.Column="2"
Style="{StaticResource GridCardStyle}">
<TreeView
x:Name="treeView"
AllowDrop="False"
AllowFocusOnInteraction="True"
CanDragItems="False"
CanReorderItems="False"
IsEnabled="True"
IsTabStop="False"
ItemInvoked="TreeView_ItemInvoked"
ScrollViewer.BringIntoViewOnFocusChange="True"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollMode="Auto"
TabIndex="1">
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel
VerticalAlignment="Center"
IsTabStop="False"
Orientation="Horizontal"
Spacing="8">
<Image
MaxWidth="16"
MaxHeight="16"
Source="{Binding Path=Content.Image}"
ToolTipService.ToolTip="{Binding Path=Content.ToolTipText}" />
<TextBlock Text="{Binding Path=Content.Name}" />
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Border>
<Border
Grid.Row="3"
Grid.Column="2"
Style="{StaticResource GridCardStyle}">
<tk7controls:DataGrid
x:Name="dataGrid"
AllowDrop="False"
AreRowDetailsFrozen="True"
AutoGenerateColumns="False"
CanDrag="False"
HeadersVisibility="Column"
IsReadOnly="True"
IsTabStop="true"
ItemsSource="{x:Bind listRegistryValues}"
RowDetailsVisibilityMode="Collapsed"
SelectionMode="Single"
TabIndex="2">
<tk7controls:DataGrid.Columns>
<tk7controls:DataGridTemplateColumn
x:Uid="NameColumn"
Width="Auto"
IsReadOnly="True">
<tk7controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel
Margin="4"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<Image
MaxWidth="16"
MaxHeight="16"
IsTabStop="False"
Source="{Binding ImageUri}"
ToolTipService.ToolTip="{Binding ToolTipText}" />
<TextBlock
IsTabStop="False"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</tk7controls:DataGridTemplateColumn.CellTemplate>
</tk7controls:DataGridTemplateColumn>
<tk7controls:DataGridTextColumn
x:Uid="TypeColumn"
Width="Auto"
Binding="{Binding Type}"
FontSize="{StaticResource CaptionTextBlockFontSize}" />
<tk7controls:DataGridTextColumn
x:Uid="ValueColumn"
Width="Auto"
Binding="{Binding Value}"
FontSize="{StaticResource CaptionTextBlockFontSize}" />
</tk7controls:DataGrid.Columns>
</tk7controls:DataGrid>
</Border>
<tkcontrols:GridSplitter
x:Name="verticalSplitter"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Stretch"
IsTabStop="False" />
<tkcontrols:GridSplitter
x:Name="horizontalSplitter"
Grid.Row="2"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
IsTabStop="False" />
</Grid>
</Page>

View File

@@ -0,0 +1,55 @@
// 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.Collections.Generic;
using System.IO;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.ApplicationModel.Resources;
namespace RegistryPreviewUILib
{
public sealed partial class RegistryPreviewMainPage : Page
{
// Const values
private const string REGISTRYHEADER4 = "regedit4";
private const string REGISTRYHEADER5 = "windows registry editor version 5.00";
private const string APPNAME = "RegistryPreview";
private const string KEYIMAGE = "ms-appx:///Assets/RegistryPreviewUILib/folder32.png";
private const string DELETEDKEYIMAGE = "ms-appx:///Assets/RegistryPreviewUILib/deleted-folder32.png";
private const string ERRORIMAGE = "ms-appx:///Assets/RegistryPreviewUILib/error32.png";
// private members
private ResourceLoader resourceLoader;
private bool visualTreeReady;
private Dictionary<string, TreeViewNode> mapRegistryKeys;
private List<RegistryValue> listRegistryValues;
private UpdateWindowTitleFunction _updateWindowTitleFunction;
private string _appFileName;
private Window _mainWindow;
public RegistryPreviewMainPage(Window mainWindow, UpdateWindowTitleFunction updateWindowTitleFunction, string appFilename)
{
// TODO (stefan): check ctor
this.InitializeComponent();
_mainWindow = mainWindow;
_updateWindowTitleFunction = updateWindowTitleFunction;
_appFileName = appFilename;
_mainWindow.Closed += MainWindow_Closed;
// Initialize the string table
resourceLoader = ResourceLoaderInstance.ResourceLoader;
// Update Toolbar
if ((_appFileName == null) || (File.Exists(_appFileName) != true))
{
UpdateToolBarAndUI(false);
_updateWindowTitleFunction(resourceLoader.GetString("FileNotFound"));
}
}
}
}

View File

@@ -0,0 +1,63 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\Version.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net8.0-windows10.0.20348</TargetFramework>
<RootNamespace>RegistryPreviewUILib</RootNamespace>
<UseWinUI>true</UseWinUI>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<RootNamespace>RegistryPreviewUILib</RootNamespace>
<AssemblyName>PowerToys.RegistryPreviewUILib</AssemblyName>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>PowerToys.RegistryPreviewUILib.pri</ProjectPriFileName>
<GenerateLibraryLayout>true</GenerateLibraryLayout>
<IsPackable>true</IsPackable>
</PropertyGroup>
<ItemGroup>
<None Include="$(OutDir)\PowerToys.RegistryPreviewUILib.pri" Pack="True" PackageCopyToOutput="true" />
<None Include="$(OutDir)\PowerToys.RegistryPreviewUILib.pri" Pack="True" PackageCopyToOutput="true" PackagePath="lib/$(TargetFramework)" />
<None Include="$(OutDir)\PowerToys.RegistryPreviewUILib.pdb" Pack="True" PackageCopyToOutput="true" PackagePath="lib/$(TargetFramework)" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.CsWinRT" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="WinUIEx" />
<Manifest Include="$(ApplicationManifest)" />
</ItemGroup>
<ItemGroup>
<Content Update="Assets\RegistryPreviewUILib\data32.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
<Content Update="Assets\RegistryPreviewUILib\string32.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
<!--TargetFramework>net6.0-windows10.0.19041.0</TargetFramework-->

View File

@@ -4,7 +4,7 @@
using System;
namespace RegistryPreview
namespace RegistryPreviewUILib
{
/// <summary>
/// Class representing an each item in the list view, each one a Registry Value.
@@ -12,10 +12,10 @@ namespace RegistryPreview
public class RegistryValue
{
// Static members
private static Uri uriStringValue = new Uri("ms-appx:///Assets/RegistryPreview/string32.png");
private static Uri uriBinaryValue = new Uri("ms-appx:///Assets/RegistryPreview/data32.png");
private static Uri uriDeleteValue = new Uri("ms-appx:///Assets/RegistryPreview/deleted-value32.png");
private static Uri uriErrorValue = new Uri("ms-appx:///Assets/RegistryPreview/error32.png");
private static Uri uriStringValue = new Uri("ms-appx:///Assets/RegistryPreviewUILib/string32.png");
private static Uri uriBinaryValue = new Uri("ms-appx:///Assets/RegistryPreviewUILib/data32.png");
private static Uri uriDeleteValue = new Uri("ms-appx:///Assets/RegistryPreviewUILib/deleted-value32.png");
private static Uri uriErrorValue = new Uri("ms-appx:///Assets/RegistryPreviewUILib/error32.png");
public string Name { get; set; }

View File

@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using Microsoft.Windows.ApplicationModel.Resources;
namespace RegistryPreview
namespace RegistryPreviewUILib
{
internal static class ResourceLoaderInstance
{
@@ -11,7 +11,7 @@ namespace RegistryPreview
static ResourceLoaderInstance()
{
ResourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("PowerToys.RegistryPreview.pri");
ResourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("PowerToys.RegistryPreviewUILib.pri", "PowerToys.RegistryPreviewUILib/Resources");
}
}
}

View File

@@ -4,7 +4,7 @@
using System.Runtime.InteropServices;
namespace RegistryPreview
namespace RegistryPreviewUILib
{
// Workaround for File Pickers that don't work while running as admin, per:
// https://github.com/microsoft/WindowsAppSDK/issues/2504

View File

@@ -23,7 +23,7 @@ std::vector<std::wstring> processes =
L"PowerToys.Update.exe",
L"PowerToys.ActionRunner.exe",
L"PowerToys.AlwaysOnTop.exe",
L"PowerToys.Hosts.exe",
L"PowerToys.HostsPackageConsumer.exe",
L"PowerToys.GcodePreviewHandler.exe",
L"PowerToys.GcodeThumbnailProvider.exe",
L"PowerToys.MarkdownPreviewHandler.exe",