[Registry Preview] Adds application to Open with list for REG files (#26033)

* 25834

* Asociate Registry Preview with .reg files

* Add setting for making RP default app for .reg files

* Run spellcheck

* Run spellcheck again

* Fix build

---------

Co-authored-by: Stefan Markovic <stefan@janeasystems.com>
This commit is contained in:
Randy
2023-06-10 15:02:53 -07:00
committed by GitHub
parent b6ff97f795
commit eddb617484
13 changed files with 246 additions and 93 deletions

View File

@@ -91,7 +91,6 @@ APPIDS
appium appium
Applets Applets
Applicationcan Applicationcan
applicationconfiguration
applicationframehost applicationframehost
appmanifest appmanifest
APPNAME APPNAME
@@ -158,7 +157,6 @@ BCB
BCCE BCCE
BCCEA BCCEA
bck bck
Bcl
BDB BDB
BDBAD BDBAD
BDCC BDCC
@@ -239,7 +237,6 @@ Cangjie
CANRENAME CANRENAME
CAPTUREBLT CAPTUREBLT
CAPTURECHANGED CAPTURECHANGED
CARRAY
CAtl CAtl
CBA CBA
CBB CBB
@@ -281,7 +278,6 @@ chdir
CHILDACTIVATE CHILDACTIVATE
CHILDWINDOW CHILDWINDOW
chrdavis chrdavis
Chromakey
Chrzan Chrzan
CHT CHT
cidl cidl
@@ -424,7 +420,6 @@ Dac
dacl dacl
DAF DAF
damienleroy damienleroy
DANGEROUSLYCOMMITMERELYTODISKCACHE
DARKPURPLE DARKPURPLE
DARKTEAL DARKTEAL
DARKYELLOW DARKYELLOW
@@ -456,13 +451,11 @@ dcompi
DComposition DComposition
dcr dcr
dcs dcs
Dct
DDCDD DDCDD
DDCE DDCE
DDEIf DDEIf
DDevice DDevice
ddf ddf
Dds
DDxgi DDxgi
Deact Deact
debian debian
@@ -494,8 +487,6 @@ depersist
deprioritized deprioritized
depsfileslistspath depsfileslistspath
deref deref
READOBJECTS
WRITEOBJECTS
DESKTOPABSOLUTEEDITING DESKTOPABSOLUTEEDITING
DESKTOPABSOLUTEPARSING DESKTOPABSOLUTEPARSING
desktopshorcutinstalled desktopshorcutinstalled
@@ -623,6 +614,7 @@ Emoji
ENABLEDELAYEDEXPANSION ENABLEDELAYEDEXPANSION
enabledisable enabledisable
ENABLEDPOPUP ENABLEDPOPUP
encodedlaunch
encryptor encryptor
endpointvolume endpointvolume
endregion endregion
@@ -663,8 +655,6 @@ exabyte
examplehandler examplehandler
examplepowertoy examplepowertoy
EXAND EXAND
Excep
EXCEPINFO
EXCLUDEFROMCAPTURE EXCLUDEFROMCAPTURE
exdisp exdisp
executionpolicy executionpolicy
@@ -789,7 +779,6 @@ GETSTATE
GETTEXT GETTEXT
GETTEXTLENGTH GETTEXTLENGTH
GHND GHND
Globbing
GMEM GMEM
GNumber GNumber
google google
@@ -834,7 +823,6 @@ HCRYPTHASH
HCRYPTPROV HCRYPTPROV
hcwhite hcwhite
hdc hdc
HDR
hdrop hdrop
hdwwiz hdwwiz
HEB HEB
@@ -916,17 +904,12 @@ HWNDPREV
hyjiacan hyjiacan
IBase IBase
IBeam IBeam
IBitmap
IBlock
ICapture ICapture
ICEBLUE ICEBLUE
IClass IClass
IColor
ICONERROR ICONERROR
IContext
IData IData
IDD IDD
IDecoder
IDesktop IDesktop
IDirect IDirect
idl idl
@@ -935,7 +918,6 @@ IDOn
IDR IDR
idx idx
IDXGI IDXGI
IEncoder
IEnum IEnum
IExec IExec
IEXPLORE IEXPLORE
@@ -960,7 +942,6 @@ imageresizerinput
imageresizersettings imageresizersettings
imagingdevices imagingdevices
ime ime
IMetadata
imeutil imeutil
inetcpl inetcpl
Infobar Infobar
@@ -998,8 +979,6 @@ Interlop
INTRESOURCE INTRESOURCE
INVALIDARG INVALIDARG
invalidoperatioexception invalidoperatioexception
invalidkey
IPalette
ipc ipc
ipcmanager ipcmanager
IPlugin IPlugin
@@ -1008,8 +987,6 @@ IPREVIEW
ipreviewhandlervisualssetfont ipreviewhandlervisualssetfont
IProperty IProperty
IPublic IPublic
IQuery
IReader
irprops irprops
isbi isbi
ISearch ISearch
@@ -1017,9 +994,7 @@ ISettings
isfinite isfinite
IShell IShell
isocpp isocpp
ISource
iss iss
ISurface
ITask ITask
ith ith
ITHUMBNAIL ITHUMBNAIL
@@ -1130,8 +1105,6 @@ LOCALPACKAGE
localport localport
LOCALSYSTEM LOCALSYSTEM
LOCATIONCHANGE LOCATIONCHANGE
LOCKBYTES
LOCKTYPE
LOGFONT LOGFONT
LOGFONTW LOGFONTW
logon logon
@@ -1153,12 +1126,12 @@ LPCWSTR
lpdw lpdw
lpfn lpfn
LPINPUT LPINPUT
LPQUERY
lpmi lpmi
LPMINMAXINFO LPMINMAXINFO
LPMONITORINFO LPMONITORINFO
LPOSVERSIONINFOEXW LPOSVERSIONINFOEXW
LPPOINT LPPOINT
LPQUERY
lprc lprc
LPRECT LPRECT
LPSAFEARRAY LPSAFEARRAY
@@ -1326,11 +1299,11 @@ Mul
MULTIPLEUSE MULTIPLEUSE
multizone multizone
mvvm mvvm
mwb
MWBEx
myfile myfile
MYICON MYICON
mysql mysql
mwb
MWBEx
NAMECHANGE NAMECHANGE
nameof nameof
namespaceanddescendants namespaceanddescendants
@@ -1403,7 +1376,6 @@ NONCONVERT
NONELEVATED NONELEVATED
NONINFRINGEMENT NONINFRINGEMENT
nonstd nonstd
NOOPEN
NOOWNERZORDER NOOWNERZORDER
NOPARENTNOTIFY NOPARENTNOTIFY
NOREDIRECTIONBITMAP NOREDIRECTIONBITMAP
@@ -1466,8 +1438,6 @@ OLEDB
OLIVEGREEN OLIVEGREEN
onebranch onebranch
onenote onenote
ONLYIFCURRENT
ONLYONCE
onstd onstd
oobe oobe
OOBEPT OOBEPT
@@ -1568,7 +1538,6 @@ pinvoke
pipename pipename
PKBDLLHOOKSTRUCT PKBDLLHOOKSTRUCT
pkey pkey
PKEY
plib plib
PLK PLK
ploc ploc
@@ -1601,7 +1570,6 @@ ppidl
ppmt ppmt
pprm pprm
pproc pproc
pprop
ppshv ppshv
ppsi ppsi
ppsid ppsid
@@ -1622,7 +1590,6 @@ previouscamera
PREVIOUSINSTALLFOLDER PREVIOUSINSTALLFOLDER
PREVIOUSVERSIONSINSTALLED PREVIOUSVERSIONSINSTALLED
prevpane prevpane
PRGBA
prgms prgms
pri pri
PRINTCLIENT PRINTCLIENT
@@ -1639,9 +1606,7 @@ PROGRAMFILES
projectname projectname
PROPBAG PROPBAG
PROPERTYKEY PROPERTYKEY
PROPERTYNOTFOUND
propkey propkey
PROPVARIANT
propvarutil propvarutil
prvpane prvpane
psapi psapi
@@ -1651,8 +1616,6 @@ psfgao
Psr Psr
psrm psrm
psrree psrree
pstatstg
pstm
pstr pstr
pstream pstream
pstrm pstrm
@@ -1666,7 +1629,6 @@ PToy
ptstr ptstr
pui pui
PULONG PULONG
pvar
pwa pwa
pwcs pwcs
pwsh pwsh
@@ -1706,6 +1668,7 @@ rclsid
RCONTROL RCONTROL
RCtrl RCtrl
READMODE READMODE
READOBJECTS
READWRITE READWRITE
RECTDESTINATION RECTDESTINATION
RECTL RECTL
@@ -1768,7 +1731,6 @@ resw
resx resx
retval retval
rfc rfc
RGBE
RGBQUAD RGBQUAD
rgbs rgbs
rgelt rgelt
@@ -1811,7 +1773,6 @@ rungameid
RUNLEVEL RUNLEVEL
runsettings runsettings
runtimeclass runtimeclass
runtimeconfig
runtimedepsjsonpath runtimedepsjsonpath
runtimeobject runtimeobject
runtimepack runtimepack
@@ -1827,7 +1788,6 @@ ryanbodrug
saahmedm saahmedm
sachaple sachaple
sacl sacl
SAFEARRAY
safeprojectname safeprojectname
SAMEKEYPREVIOUSLYMAPPED SAMEKEYPREVIOUSLYMAPPED
SAMESHORTCUTPREVIOUSLYMAPPED SAMESHORTCUTPREVIOUSLYMAPPED
@@ -1858,7 +1818,6 @@ sendvirtualinput
Seperate Seperate
Seraphima Seraphima
serverside serverside
Ses
SETCONTEXT SETCONTEXT
setcursor setcursor
setenv setenv
@@ -1947,7 +1906,6 @@ SMALLICON
smartphone smartphone
SMTO SMTO
snd snd
sni
snwprintf snwprintf
softline softline
somil somil
@@ -1975,7 +1933,6 @@ SRCPAINT
sre sre
SResize SResize
srf srf
SRGB
srme srme
srre srre
srw srw
@@ -2004,10 +1961,8 @@ STDMETHODCALLTYPE
STDMETHODIMP STDMETHODIMP
stefan stefan
Stereolithography Stereolithography
STGC
STGM STGM
STGMEDIUM STGMEDIUM
STGTY
sticpl sticpl
stl stl
storelogo storelogo
@@ -2081,8 +2036,8 @@ taskschd
tchar tchar
tcl tcl
Tcollab Tcollab
tcs
tcp tcp
tcs
tcscpy tcscpy
TCustom TCustom
tdbuild tdbuild
@@ -2165,6 +2120,7 @@ uipi
UIs UIs
ULARGE ULARGE
ULONGLONG ULONGLONG
unapply
unassign unassign
uncompilable uncompilable
UNCPRIORITY UNCPRIORITY
@@ -2196,7 +2152,6 @@ Usb
USEDEFAULT USEDEFAULT
USEFILEATTRIBUTES USEFILEATTRIBUTES
USERDATA USERDATA
USERDEFINED
USERDOMAIN USERDOMAIN
userprofile userprofile
USESHOWWINDOW USESHOWWINDOW
@@ -2213,7 +2168,6 @@ vabdq
validmodulename validmodulename
Vanara Vanara
variantassignment variantassignment
VARTYPE
vcamp vcamp
vccorlib vccorlib
vcdl vcdl
@@ -2233,7 +2187,6 @@ VERBSONLY
VERBW VERBW
VERIFYCONTEXT VERIFYCONTEXT
verrsrc verrsrc
VERSIONED
VERSIONINFO VERSIONINFO
Versioning Versioning
VFT VFT
@@ -2333,8 +2286,8 @@ winget
wingetcreate wingetcreate
Winhook Winhook
winkey winkey
winlogon
WINL WINL
winlogon
winmd winmd
winmm winmm
WINNT WINNT
@@ -2391,6 +2344,7 @@ wregex
WReserved WReserved
WResize WResize
writefile writefile
WRITEOBJECTS
Wrk Wrk
wrl wrl
WSAEADDRINUSE WSAEADDRINUSE
@@ -2402,7 +2356,6 @@ wsh
wsl wsl
wss wss
wstr wstr
wsystem
wsz wsz
wtoi wtoi
WTS WTS
@@ -2446,7 +2399,6 @@ yinyue
YOffset YOffset
YPels YPels
ypescript ypescript
YQuantized
YResolution YResolution
YStr YStr
YUY YUY

View File

@@ -123,6 +123,8 @@ UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
changeSet.unApply(); changeSet.unApply();
} }
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
ExitOnFailure(hr, "Failed to extract msix"); ExitOnFailure(hr, "Failed to extract msix");
LExit: LExit:

View File

@@ -8,6 +8,7 @@
#include <strsafe.h> #include <strsafe.h>
#include <msiquery.h> #include <msiquery.h>
#include <Msi.h> #include <Msi.h>
#include <shlobj_core.h>
// WiX Header Files: // WiX Header Files:
#include <wcautil.h> #include <wcautil.h>

View File

@@ -192,6 +192,28 @@ inline registry::ChangeSet getStlThumbnailHandlerChangeSet(const std::wstring in
NonLocalizable::ExtSTL); NonLocalizable::ExtSTL);
} }
inline registry::ChangeSet getRegistryPreviewSetDefaultAppChangeSet(const std::wstring installationDir, const bool perUser)
{
const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
using vec_t = std::vector<registry::ValueChange>;
vec_t changes;
std::wstring appName = L"Registry Preview";
std::wstring fullAppName = L"PowerToys.RegistryPreview";
std::wstring registryKeyPrefix = L"Software\\Classes\\";
std::wstring appPath = installationDir + L"\\modules\\RegistryPreview\\PowerToys.RegistryPreview.exe";
std::wstring command = appPath + L" \"----ms-protocol:ms-encodedlaunch:App?ContractId=Windows.File&Verb=open&File=%1\"";
changes.push_back({ scope, registryKeyPrefix + fullAppName + L"\\" + L"Application", L"ApplicationName", appName });
changes.push_back({ scope, registryKeyPrefix + fullAppName + L"\\" + L"DefaultIcon", std::nullopt, appPath });
changes.push_back({ scope, registryKeyPrefix + fullAppName + L"\\" + L"shell\\open\\command", std::nullopt, command });
changes.push_back({ scope, registryKeyPrefix + L".reg\\OpenWithProgIDs", fullAppName, L"" });
return { changes };
}
inline registry::ChangeSet getRegistryPreviewChangeSet(const std::wstring installationDir,const bool perUser) inline registry::ChangeSet getRegistryPreviewChangeSet(const std::wstring installationDir,const bool perUser)
{ {
const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
@@ -235,5 +257,6 @@ inline std::vector<registry::ChangeSet> getAllModulesChangeSets(const std::wstri
getPdfThumbnailHandlerChangeSet(installationDir, PER_USER), getPdfThumbnailHandlerChangeSet(installationDir, PER_USER),
getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER), getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER),
getStlThumbnailHandlerChangeSet(installationDir, PER_USER), getStlThumbnailHandlerChangeSet(installationDir, PER_USER),
getRegistryPreviewChangeSet(installationDir, PER_USER) }; getRegistryPreviewChangeSet(installationDir, PER_USER),
getRegistryPreviewSetDefaultAppChangeSet(installationDir, PER_USER) };
} }

View File

@@ -37,11 +37,19 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lp
const static wchar_t* MODULE_NAME = L"RegistryPreview"; const static wchar_t* MODULE_NAME = L"RegistryPreview";
const static wchar_t* MODULE_DESC = L"A quick little utility to visualize and edit complex Windows Registry files."; const static wchar_t* MODULE_DESC = L"A quick little utility to visualize and edit complex Windows Registry files.";
namespace
{
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
const wchar_t JSON_KEY_ENABLED[] = L"enabled";
const wchar_t JSON_KEY_DEFAULT_APP[] = L"default_reg_app";
}
class RegistryPreviewModule : public PowertoyModuleIface class RegistryPreviewModule : public PowertoyModuleIface
{ {
private: private:
bool m_enabled = false; bool m_enabled = false;
bool m_default_app = false;
//Hotkey m_hotkey; //Hotkey m_hotkey;
HANDLE m_hProcess; HANDLE m_hProcess;
@@ -87,23 +95,70 @@ private:
TerminateProcess(m_hProcess, 1); TerminateProcess(m_hProcess, 1);
} }
void parse_default_app_settings(PowerToysSettings::PowerToyValues settings)
{
const std::wstring installationDir = get_module_folderpath();
auto changeSet = getRegistryPreviewSetDefaultAppChangeSet(installationDir, true);
auto settingsObject = settings.get_raw_json();
if (settingsObject.GetView().Size())
{
auto default_app = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedBoolean(JSON_KEY_DEFAULT_APP);
if (default_app != m_default_app)
{
m_default_app = default_app;
auto result = default_app ? changeSet.apply() : changeSet.unApply();
if (!result)
{
Logger::error(L"Failed to {} default app registry change set.", default_app ? L"apply" : L"unapply");
}
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
}
else
{
Logger::info("Registry Preview settings are empty");
}
}
// Load the settings file.
void init_settings()
{
try
{
// Load and parse the settings file for this PowerToy.
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(get_key());
auto enabled = settings.get_bool_value(JSON_KEY_ENABLED);
auto result = true;
const std::wstring installationDir = get_module_folderpath();
auto enabledChangeSet = getRegistryPreviewChangeSet(installationDir, true);
result = enabled ? enabledChangeSet.apply() : enabledChangeSet.unApply();
if (!result)
{
Logger::error(L"Failed to {} enabled registry change set.", enabled ? L"apply" : L"unapply");
}
parse_default_app_settings(settings);
}
catch (std::exception&)
{
Logger::error("Invalid json when trying to load the Registry Preview settings json from file.");
}
}
public: public:
RegistryPreviewModule() RegistryPreviewModule()
{ {
LoggerHelpers::init_logger(GET_RESOURCE_STRING(IDS_REGISTRYPREVIEW_NAME), L"ModuleInterface", "RegistryPreview"); LoggerHelpers::init_logger(GET_RESOURCE_STRING(IDS_REGISTRYPREVIEW_NAME), L"ModuleInterface", "RegistryPreview");
Logger::info("Registry Preview object is constructing"); Logger::info("Registry Preview object is constructing");
if (!m_enabled) init_settings();
{
const std::wstring installationDir = get_module_folderpath();
auto regChanges = getRegistryPreviewChangeSet(installationDir, true);
if (!regChanges.unApply())
{
Logger::error(L"Unapplying registry changes failed");
}
}
triggerEvent = CreateEvent(nullptr, false, false, CommonSharedConstants::REGISTRY_PREVIEW_TRIGGER_EVENT); triggerEvent = CreateEvent(nullptr, false, false, CommonSharedConstants::REGISTRY_PREVIEW_TRIGGER_EVENT);
triggerEventWaiter = EventWaiter(CommonSharedConstants::REGISTRY_PREVIEW_TRIGGER_EVENT, [this](int) { triggerEventWaiter = EventWaiter(CommonSharedConstants::REGISTRY_PREVIEW_TRIGGER_EVENT, [this](int) {
@@ -184,13 +239,13 @@ public:
// Parse the input JSON string. // Parse the input JSON string.
PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues::from_json_string(config, get_key()); PowerToysSettings::PowerToyValues values = PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
// If you don't need to do any custom processing of the settings, proceed parse_default_app_settings(values);
// to persists the values.
values.save_to_settings_file(); values.save_to_settings_file();
} }
catch (std::exception&) catch (std::exception&)
{ {
// Improper JSON. Logger::error(L"Invalid json when trying to parse Registry Preview settings json.");
} }
} }
@@ -226,6 +281,8 @@ public:
{ {
Logger::error(L"Unapplying registry changes failed"); Logger::error(L"Unapplying registry changes failed");
} }
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
} }
m_enabled = false; m_enabled = false;

View File

@@ -6,6 +6,7 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Activation;
using LaunchActivatedEventArgs = Windows.ApplicationModel.Activation.LaunchActivatedEventArgs; using LaunchActivatedEventArgs = Windows.ApplicationModel.Activation.LaunchActivatedEventArgs;
@@ -31,23 +32,47 @@ namespace RegistryPreview
/// <param name="args">Details about the launch request and process.</param> /// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{ {
// Grab the command line parameters directly from the Environment since this is expected to be run // Keeping commented out but this is invaluable for protocol activation testing.
// via Context Menu of a REG file. // #if DEBUG
string[] cmdArgs = Environment.GetCommandLineArgs(); // System.Diagnostics.Debugger.Launch();
if (cmdArgs == null) // #endif
// Open With... handler - gets activation arguments if they are available.
AppActivationArguments activatedArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
if (activatedArgs.Kind == ExtendedActivationKind.File)
{ {
// Covers the double click exe scenario and treated as no file loaded // Covers the double click exe scenario and treated as no file loaded
AppFilename = string.Empty; AppFilename = string.Empty;
} if (activatedArgs.Data != null)
else if (cmdArgs.Length == 2) {
{ IFileActivatedEventArgs eventArgs = (IFileActivatedEventArgs)activatedArgs.Data;
// GetCommandLineArgs() send in the called EXE as 0 and the selected filename as 1 if (eventArgs.Files.Count > 0)
AppFilename = cmdArgs[1]; {
AppFilename = eventArgs.Files[0].Path;
}
}
} }
else else
{ {
// Anything else should be treated as no file loaded // Right click on a REG file and selected Preview
AppFilename = string.Empty; // Grab the command line parameters directly from the Environment since this is expected to be run
// via Context Menu of a REG file.
string[] cmdArgs = Environment.GetCommandLineArgs();
if (cmdArgs == null)
{
// Covers the double click exe scenario and treated as no file loaded
AppFilename = string.Empty;
}
else if (cmdArgs.Length == 2)
{
// GetCommandLineArgs() send in the called EXE as 0 and the selected filename as 1
AppFilename = cmdArgs[1];
}
else
{
// Anything else should be treated as no file loaded
AppFilename = string.Empty;
}
} }
// Start the application // Start the application

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class RegistryPreviewProperties
{
public RegistryPreviewProperties()
{
DefaultRegApp = false;
}
[JsonPropertyName("default_reg_app")]
public bool DefaultRegApp { get; set; }
}
}

View File

@@ -11,8 +11,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{ {
public const string ModuleName = "RegistryPreview"; public const string ModuleName = "RegistryPreview";
[JsonPropertyName("properties")]
public RegistryPreviewProperties Properties { get; set; }
public RegistryPreviewSettings() public RegistryPreviewSettings()
{ {
Properties = new RegistryPreviewProperties();
Version = "1"; Version = "1";
Name = ModuleName; Name = ModuleName;
} }

View File

@@ -0,0 +1,29 @@
// 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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class SndRegistryPreviewSettings
{
[JsonPropertyName("RegistryPreview")]
public RegistryPreviewSettings RegistryPreview { get; set; }
public SndRegistryPreviewSettings()
{
}
public SndRegistryPreviewSettings(RegistryPreviewSettings settings)
{
RegistryPreview = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -3502,6 +3502,13 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="RegistryPreview_LaunchButtonControl.Header" xml:space="preserve"> <data name="RegistryPreview_LaunchButtonControl.Header" xml:space="preserve">
<value>Launch Registry Preview</value> <value>Launch Registry Preview</value>
</data> </data>
<data name="RegistryPreview_DefaultRegApp.Header" xml:space="preserve">
<value>Default app</value>
</data>
<data name="RegistryPreview_DefaultRegApp.Description" xml:space="preserve">
<value>Make Registry Preview default app for opening .reg files</value>
<comment>Registry Preview is app name. Do not localize.</comment>
</data>
<data name="PastePlain_ShortcutWarning.Title" xml:space="preserve"> <data name="PastePlain_ShortcutWarning.Title" xml:space="preserve">
<value>Using this shortcut may prevent non-text paste actions (e.g. images, files) or built-in paste plain text actions in other applications from functioning.</value> <value>Using this shortcut may prevent non-text paste actions (e.g. images, files) or built-in paste plain text actions in other applications from functioning.</value>
</data> </data>

View File

@@ -3,6 +3,8 @@
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Globalization;
using System.Text.Json;
using global::PowerToys.GPOWrapper; using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers; using Microsoft.PowerToys.Settings.UI.Library.Helpers;
@@ -17,7 +19,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
public ButtonClickCommand LaunchEventHandler => new ButtonClickCommand(Launch); public ButtonClickCommand LaunchEventHandler => new ButtonClickCommand(Launch);
public RegistryPreviewViewModel(ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc) public RegistryPreviewViewModel(ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<RegistryPreviewSettings> registryPreviewSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
{ {
// To obtain the general settings configurations of PowerToys Settings. // To obtain the general settings configurations of PowerToys Settings.
if (settingsRepository == null) if (settingsRepository == null)
@@ -27,6 +29,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GeneralSettingsConfig = settingsRepository.SettingsConfig; GeneralSettingsConfig = settingsRepository.SettingsConfig;
_settings = registryPreviewSettingsRepository.SettingsConfig;
InitializeEnabledValue(); InitializeEnabledValue();
// set the callback functions value to hangle outgoing IPC message. // set the callback functions value to hangle outgoing IPC message.
@@ -71,6 +75,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
} }
} }
public bool IsRegistryPreviewDefaultRegApp
{
get => _settings.Properties.DefaultRegApp;
set
{
if (_settings.Properties.DefaultRegApp != value)
{
_settings.Properties.DefaultRegApp = value;
OnPropertyChanged(nameof(IsRegistryPreviewDefaultRegApp));
NotifySettingsChanged();
}
}
}
public bool IsEnabledGpoConfigured public bool IsEnabledGpoConfigured
{ {
get => _enabledStateIsGPOConfigured; get => _enabledStateIsGPOConfigured;
@@ -88,11 +107,23 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private GpoRuleConfigured _enabledGpoRuleConfiguration; private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured; private bool _enabledStateIsGPOConfigured;
private bool _isRegistryPreviewEnabled; private bool _isRegistryPreviewEnabled;
private RegistryPreviewSettings _settings;
public void RefreshEnabledState() public void RefreshEnabledState()
{ {
InitializeEnabledValue(); InitializeEnabledValue();
OnPropertyChanged(nameof(IsRegistryPreviewEnabled)); OnPropertyChanged(nameof(IsRegistryPreviewEnabled));
} }
private void NotifySettingsChanged()
{
// Using InvariantCulture as this is an IPC message
SendConfigMSG(
string.Format(
CultureInfo.InvariantCulture,
"{{ \"powertoys\": {{ \"{0}\": {1} }} }}",
RegistryPreviewSettings.ModuleName,
JsonSerializer.Serialize(_settings)));
}
} }
} }

View File

@@ -11,11 +11,9 @@
AutomationProperties.LandmarkType="Main" AutomationProperties.LandmarkType="Main"
mc:Ignorable="d"> mc:Ignorable="d">
<controls:SettingsPageControl <controls:SettingsPageControl x:Uid="RegistryPreview" ModuleImageSource="ms-appx:///Assets/Modules/RegistryPreview.png">
x:Uid="RegistryPreview"
ModuleImageSource="ms-appx:///Assets/Modules/RegistryPreview.png">
<controls:SettingsPageControl.ModuleContent> <controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical" ChildrenTransitions="{StaticResource SettingsCardsAnimations}"> <StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<labs:SettingsCard <labs:SettingsCard
x:Uid="RegistryPreview_Enable_RegistryPreview" x:Uid="RegistryPreview_Enable_RegistryPreview"
HeaderIcon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsRegistryPreview.png}" HeaderIcon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsRegistryPreview.png}"
@@ -40,15 +38,17 @@
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily}, HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xEA37;}" Glyph=&#xEA37;}"
IsClickEnabled="True" /> IsClickEnabled="True" />
<labs:SettingsCard x:Uid="RegistryPreview_DefaultRegApp" HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily}, Glyph=&#xE7AC;}">
<ToggleSwitch x:Uid="RegistryPreview_DefaultRegApp_ToggleSwitch" IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.IsRegistryPreviewDefaultRegApp}" />
</labs:SettingsCard>
</controls:SettingsGroup> </controls:SettingsGroup>
</StackPanel> </StackPanel>
</controls:SettingsPageControl.ModuleContent> </controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks> <controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink <controls:PageLink x:Uid="LearnMore_RegistryPreview" Link="https://aka.ms/PowerToysOverview_RegistryPreview" />
x:Uid="LearnMore_RegistryPreview"
Link="https://aka.ms/PowerToysOverview_RegistryPreview" />
</controls:SettingsPageControl.PrimaryLinks> </controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl> </controls:SettingsPageControl>
</Page> </Page>

View File

@@ -16,7 +16,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
public RegistryPreviewPage() public RegistryPreviewPage()
{ {
var settingsUtils = new SettingsUtils(); var settingsUtils = new SettingsUtils();
ViewModel = new RegistryPreviewViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); ViewModel = new RegistryPreviewViewModel(
SettingsRepository<GeneralSettings>.GetInstance(settingsUtils),
SettingsRepository<RegistryPreviewSettings>.GetInstance(settingsUtils),
ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel; DataContext = ViewModel;
InitializeComponent(); InitializeComponent();
} }