├── RegistryRT ├── pch.cpp ├── README.md ├── RegistryRT.vcxproj.filters ├── LICENSE ├── pch.h └── .gitignore ├── XamlTreeView ├── pch.cpp ├── pch.h ├── TreeViewItem.h ├── IntegerToIndentationConverter.h ├── IntegerToIndentationConverter.cpp ├── TreeViewControl.vcxproj.filters ├── TreeViewItemAutomationPeer.h ├── TreeView.h ├── TreeNode.h ├── ViewModel.h ├── TreeViewItem.cpp ├── TreeNode.cpp ├── TreeViewItemAutomationPeer.cpp └── TreeView.cpp ├── Regedit ├── Assets │ ├── text.png │ ├── folder.png │ ├── numbers.png │ ├── computer.png │ ├── LargeTile.scale-100.png │ ├── LargeTile.scale-125.png │ ├── LargeTile.scale-150.png │ ├── LargeTile.scale-200.png │ ├── LargeTile.scale-400.png │ ├── SmallTile.scale-100.png │ ├── SmallTile.scale-125.png │ ├── SmallTile.scale-150.png │ ├── SmallTile.scale-200.png │ ├── SmallTile.scale-400.png │ ├── StoreLogo.scale-100.png │ ├── StoreLogo.scale-125.png │ ├── StoreLogo.scale-150.png │ ├── StoreLogo.scale-200.png │ ├── StoreLogo.scale-400.png │ ├── SplashScreen.scale-100.png │ ├── SplashScreen.scale-125.png │ ├── SplashScreen.scale-150.png │ ├── SplashScreen.scale-200.png │ ├── SplashScreen.scale-400.png │ ├── Square150x150Logo.scale-100.png │ ├── Square150x150Logo.scale-125.png │ ├── Square150x150Logo.scale-150.png │ ├── Square150x150Logo.scale-200.png │ ├── Square150x150Logo.scale-400.png │ ├── Square44x44Logo.scale-100.png │ ├── Square44x44Logo.scale-125.png │ ├── Square44x44Logo.scale-150.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.scale-400.png │ ├── Wide310x150Logo.scale-100.png │ ├── Wide310x150Logo.scale-125.png │ ├── Wide310x150Logo.scale-150.png │ ├── Wide310x150Logo.scale-200.png │ ├── Wide310x150Logo.scale-400.png │ ├── Square44x44Logo.targetsize-16.png │ ├── Square44x44Logo.targetsize-24.png │ ├── Square44x44Logo.targetsize-32.png │ ├── Square44x44Logo.targetsize-48.png │ ├── Square44x44Logo.targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ └── Square44x44Logo.altform-lightunplated_targetsize-48.png ├── RegistryTreeView │ ├── TreeViewItemInvokedEventArgs.cs │ ├── TreeViewExpandingEventArgs.cs │ ├── UniversalTreeView.properties.cs │ ├── GlyphConverter.cs │ ├── UniversalTreeView.xaml │ ├── UniversalTreeView.xaml.cs │ └── DataBuilder.cs ├── AboutContentDialog.xaml.cs ├── App.xaml ├── GridSplitter │ ├── license.md │ ├── GridSplitter.xaml │ ├── GridSplitter.Data.cs │ ├── GripperHoverWrapper.cs │ ├── GridSplitter.cs │ ├── GridSplitter.Options.cs │ ├── GridSplitter.Helper.cs │ └── GridSplitter.Events.cs ├── Properties │ ├── AssemblyInfo.cs │ └── Default.rd.xml ├── AboutContentDialog.xaml ├── MainPage.xaml.cs ├── Package.appxmanifest ├── App.xaml.cs ├── Controls │ ├── TitlebarControl.xaml │ └── TitlebarControl.xaml.cs └── Regedit.csproj ├── LICENSE ├── .gitattributes ├── Regedit.sln └── .gitignore /RegistryRT/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /XamlTreeView/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /Regedit/Assets/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/text.png -------------------------------------------------------------------------------- /Regedit/Assets/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/folder.png -------------------------------------------------------------------------------- /Regedit/Assets/numbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/numbers.png -------------------------------------------------------------------------------- /Regedit/Assets/computer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/computer.png -------------------------------------------------------------------------------- /Regedit/Assets/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/LargeTile.scale-100.png -------------------------------------------------------------------------------- /Regedit/Assets/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/LargeTile.scale-125.png -------------------------------------------------------------------------------- /Regedit/Assets/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/LargeTile.scale-150.png -------------------------------------------------------------------------------- /Regedit/Assets/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/LargeTile.scale-200.png -------------------------------------------------------------------------------- /Regedit/Assets/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/LargeTile.scale-400.png -------------------------------------------------------------------------------- /Regedit/Assets/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SmallTile.scale-100.png -------------------------------------------------------------------------------- /Regedit/Assets/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SmallTile.scale-125.png -------------------------------------------------------------------------------- /Regedit/Assets/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SmallTile.scale-150.png -------------------------------------------------------------------------------- /Regedit/Assets/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SmallTile.scale-200.png -------------------------------------------------------------------------------- /Regedit/Assets/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SmallTile.scale-400.png -------------------------------------------------------------------------------- /Regedit/Assets/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /Regedit/Assets/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /Regedit/Assets/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /Regedit/Assets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /Regedit/Assets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /Regedit/Assets/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /Regedit/Assets/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /Regedit/Assets/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /Regedit/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Regedit/Assets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /Regedit/Assets/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /Regedit/Assets/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /Regedit/Assets/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /Regedit/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Regedit/Assets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /Regedit/Assets/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /Regedit/Assets/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /Regedit/Assets/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /Regedit/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Regedit/Assets/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png -------------------------------------------------------------------------------- /Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gus33000/Regedit-UWP/HEAD/Regedit/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png -------------------------------------------------------------------------------- /XamlTreeView/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include -------------------------------------------------------------------------------- /Regedit/RegistryTreeView/TreeViewItemInvokedEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace Regedit.RegistryTreeView 2 | { 3 | public sealed class TreeViewItemInvokedEventArgs 4 | { 5 | // 6 | // Summary: 7 | // Gets the TreeView item that is invoked. 8 | // 9 | // Returns: 10 | // The TreeView item that is invoked. 11 | public object InvokedItem { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Regedit/RegistryTreeView/TreeViewExpandingEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace Regedit.RegistryTreeView 2 | { 3 | public sealed class TreeViewExpandingEventArgs 4 | { 5 | // 6 | // Summary: 7 | // Gets the data item for the tree view node that is expanding. 8 | // 9 | // Returns: 10 | // The data item for the tree view node that is expanding. 11 | public object Item { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Regedit/AboutContentDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Controls; 2 | 3 | namespace Regedit 4 | { 5 | public sealed partial class AboutContentDialog : ContentDialog 6 | { 7 | public AboutContentDialog(string OSName, string RegisteredOwner, string RegisteredOrg, string Version, string BuildNumber) 8 | { 9 | this.InitializeComponent(); 10 | this.RegisteredOwner.Text = " " + RegisteredOwner; 11 | this.RegisteredOrg.Text = " " + RegisteredOrg; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /RegistryRT/README.md: -------------------------------------------------------------------------------- 1 | # RegistryRT 2 | 3 | Access the registry from WinRT 4 | 5 | ## Acknowledgements 6 | 7 | - Your app can't access the real registry, it can only access a fake registry built only for the application itself, as Microsoft notes for Project centennial applications (Notice this was reformulated to reflect many different people opinion and not just one person, change made because of complaints by https://twitter.com/Opus_010) --Fall 2017 by someone interested in Xbox and others 8 | - It is impossible to publish an app to the Windows Store that can read the registry --Microsoft 2016 9 | 10 | ## License 11 | 12 | Please see LICENSE under this repository. 13 | -------------------------------------------------------------------------------- /Regedit/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /RegistryRT/RegistryRT.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | c4bdb38d-fa27-424f-bbdc-7a49891e9feb 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /XamlTreeView/TreeViewItem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace TreeViewControl { 4 | [Windows::Foundation::Metadata::WebHostHidden] 5 | [Windows::UI::Xaml::Data::Bindable] 6 | public ref class TreeViewItem sealed : Windows::UI::Xaml::Controls::ListViewItem 7 | { 8 | public: 9 | TreeViewItem(); 10 | 11 | virtual ~TreeViewItem(); 12 | 13 | private: 14 | Windows::UI::Xaml::Controls::ListView^ GetAncestorListView(TreeViewItem^ targetItem); 15 | 16 | protected: 17 | void OnDrop(Windows::UI::Xaml::DragEventArgs^ e) override; 18 | void OnDragEnter(Windows::UI::Xaml::DragEventArgs^ e) override; 19 | void OnDragOver(Windows::UI::Xaml::DragEventArgs^ e) override; 20 | Windows::UI::Xaml::Automation::Peers::AutomationPeer^ OnCreateAutomationPeer() override; 21 | }; 22 | } -------------------------------------------------------------------------------- /XamlTreeView/IntegerToIndentationConverter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace TreeViewControl { 4 | [Windows::Foundation::Metadata::WebHostHidden] 5 | public ref class IntegerToIndentationConverter sealed : Windows::UI::Xaml::Data::IValueConverter 6 | { 7 | public: 8 | property int IndentMultiplier 9 | { 10 | int get() { return indentMultiplier; }; 11 | void set(int i) { indentMultiplier = i; }; 12 | } 13 | 14 | IntegerToIndentationConverter(); 15 | 16 | virtual Platform::Object^ Convert(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Platform::Object^ parameter, Platform::String^ language); 17 | 18 | virtual Platform::Object^ ConvertBack(Object^ value, Windows::UI::Xaml::Interop::TypeName targetType, Platform::Object^ parameter, Platform::String^ language); 19 | private: 20 | int indentMultiplier; 21 | }; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Regedit/RegistryTreeView/UniversalTreeView.properties.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Windows.Foundation; 3 | using Windows.UI.Xaml; 4 | 5 | namespace Regedit.RegistryTreeView 6 | { 7 | public partial class UniversalTreeView 8 | { 9 | public static DependencyProperty DataProperty = DependencyProperty.RegisterAttached 10 | ( 11 | nameof(Data), 12 | typeof(DataBuilder), 13 | typeof(UniversalTreeView), 14 | new PropertyMetadata(null, OnDataChanged) 15 | ); 16 | 17 | private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 18 | { 19 | if (d is UniversalTreeView c) 20 | { 21 | c.OnDataChanged(e); 22 | } 23 | } 24 | 25 | public DataBuilder Data { get => (DataBuilder)GetValue(DataProperty); set => SetValue(DataProperty, value); } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Regedit/RegistryTreeView/GlyphConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Windows.UI.Xaml.Data; 3 | 4 | namespace Regedit.RegistryTreeView 5 | { 6 | public sealed class GlyphConverter : IValueConverter 7 | { 8 | public string ExpandedGlyph { get; set; } 9 | public string CollapsedGlyph { get; set; } 10 | 11 | public object Convert(object value, Type targetType, object parameter, string language) 12 | { 13 | var isExpanded = value as bool?; 14 | 15 | if (isExpanded.HasValue && isExpanded.Value) 16 | { 17 | return ExpandedGlyph; 18 | } 19 | 20 | else 21 | { 22 | return CollapsedGlyph; 23 | } 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, string language) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /XamlTreeView/IntegerToIndentationConverter.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include "IntegerToIndentationConverter.h" 4 | 5 | using namespace Platform; 6 | using namespace Windows::UI::Xaml; 7 | using namespace Windows::UI::Xaml::Interop; 8 | 9 | namespace TreeViewControl { 10 | 11 | IntegerToIndentationConverter::IntegerToIndentationConverter() 12 | { 13 | //default 14 | indentMultiplier = 20; 15 | } 16 | 17 | Object^ IntegerToIndentationConverter::Convert(Object^ value, TypeName targetType, Object^ parameter, String^ language) 18 | { 19 | Thickness indent(0); 20 | if (value != nullptr) 21 | { 22 | indent.Left = (int)value * indentMultiplier; 23 | return indent; 24 | } 25 | 26 | return indent; 27 | } 28 | 29 | Object^ IntegerToIndentationConverter::ConvertBack(Object^ value, TypeName targetType, Object^ parameter, String^ language) 30 | { 31 | throw ref new NotImplementedException(); 32 | } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Gustave Monce 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /RegistryRT/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Gustave Monce - @gus33000 - gus33000.me 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Regedit/GridSplitter/license.md: -------------------------------------------------------------------------------- 1 | # Windows Community Toolkit 2 | 3 | Copyright (c) .NET Foundation and Contributors 4 | 5 | All rights reserved. 6 | 7 | # MIT License (MIT) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | -------------------------------------------------------------------------------- /Regedit/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Regedit")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("An Universal Registry Editor for Windows 10")] 10 | [assembly: AssemblyCompany("IT Dev Team")] 11 | [assembly: AssemblyProduct("Universal Registry Editor")] 12 | [assembly: AssemblyCopyright("Copyright © IT Dev Team 2020")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Version information for an assembly consists of the following four values: 17 | // 18 | // Major Version 19 | // Minor Version 20 | // Build Number 21 | // Revision 22 | // 23 | // You can specify all the values or you can default the Build and Revision Numbers 24 | // by using the '*' as shown below: 25 | // [assembly: AssemblyVersion("1.0.*")] 26 | [assembly: AssemblyVersion("1.0.0.0")] 27 | [assembly: AssemblyFileVersion("1.0.0.0")] 28 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /XamlTreeView/TreeViewControl.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 96c875b2-800f-42e2-aba6-ef897e02ec12 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Regedit/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /XamlTreeView/TreeViewItemAutomationPeer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "TreeViewItem.h" 3 | #include "TreeView.h" 4 | 5 | namespace TreeViewControl { 6 | [Windows::Foundation::Metadata::WebHostHidden] 7 | public ref class TreeViewItemAutomationPeer : Windows::UI::Xaml::Automation::Peers::ListViewItemAutomationPeer, Windows::UI::Xaml::Automation::Provider::IExpandCollapseProvider 8 | { 9 | internal: 10 | TreeViewItemAutomationPeer(TreeViewItem^ owner) :Windows::UI::Xaml::Automation::Peers::ListViewItemAutomationPeer(owner) {}; 11 | 12 | public: 13 | //IExpandCollapseProvider 14 | virtual void Collapse(); 15 | 16 | virtual void Expand(); 17 | 18 | property Windows::UI::Xaml::Automation::ExpandCollapseState ExpandCollapseState 19 | { 20 | virtual Windows::UI::Xaml::Automation::ExpandCollapseState get(); 21 | } 22 | 23 | void RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState newState); 24 | 25 | //Position override 26 | int GetSizeOfSetCore() override; 27 | 28 | int GetPositionInSetCore() override; 29 | 30 | int GetLevelCore() override; 31 | 32 | protected: 33 | Platform::Object^ GetPatternCore(Windows::UI::Xaml::Automation::Peers::PatternInterface patternInterface) override; 34 | 35 | private: 36 | Windows::UI::Xaml::Controls::ListView^ GetParentListView(DependencyObject^ Owner); 37 | }; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /Regedit/AboutContentDialog.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Regedit/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using Regedit.RegistryTreeView; 2 | using RegistryRT; 3 | using System; 4 | using System.Linq; 5 | using System.Threading; 6 | using Windows.ApplicationModel.Core; 7 | using Windows.UI.ViewManagement; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | 11 | #nullable enable 12 | 13 | namespace Regedit 14 | { 15 | public sealed partial class MainPage : Page 16 | { 17 | public DataBuilder Data = new(); 18 | 19 | public MainPage() 20 | { 21 | this.InitializeComponent(); 22 | } 23 | 24 | private string GetRegistryString(RegistryHive hive, string path, string valuename) 25 | { 26 | string result = ""; 27 | if (App.registry.QueryValue(hive, path, valuename, out RegistryType vtype, out byte[] buf) && buf != null && buf.Length > 0 && vtype == RegistryType.String) 28 | { 29 | result = System.Text.Encoding.Unicode.GetString(buf); 30 | } 31 | return result; 32 | } 33 | 34 | private async void MenuFlyoutItem_Click(object sender, RoutedEventArgs e) 35 | { 36 | string vers = string.Join(".", GetRegistryString(RegistryHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "BuildLabEx").Split('.').Take(2)); 37 | string osversion = GetRegistryString(RegistryHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId"); 38 | string osname = GetRegistryString(RegistryHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName"); 39 | string RegisteredOrganization = GetRegistryString(RegistryHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOrganization"); 40 | string RegisteredOwner = GetRegistryString(RegistryHive.HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "RegisteredOwner"); 41 | 42 | AboutContentDialog dialog = new(osname, RegisteredOwner, RegisteredOrganization, osversion, vers); 43 | await dialog.ShowAsync(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Regedit/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 15 | 16 | 17 | 18 | 19 | Universal Registry Editor 20 | IT Dev Team 21 | Assets\StoreLogo.png 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /XamlTreeView/TreeView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "TreeNode.h" 3 | #include "ViewModel.h" 4 | #include "TreeViewItem.h" 5 | 6 | namespace TreeViewControl { 7 | public ref class TreeViewItemClickEventArgs sealed 8 | { 9 | public: 10 | TreeViewItemClickEventArgs() {} 11 | 12 | property Object^ ClickedItem 13 | { 14 | Object^ get() { return clickedItem; }; 15 | void set(Object^ value) { clickedItem = value; }; 16 | } 17 | 18 | property bool IsHandled 19 | { 20 | bool get() { return isHandled; }; 21 | void set(bool value) { isHandled = value; }; 22 | } 23 | private: 24 | Object^ clickedItem = nullptr; 25 | bool isHandled = false; 26 | }; 27 | 28 | ref class TreeView; 29 | [Windows::Foundation::Metadata::WebHostHidden] 30 | public delegate void TreeViewItemClickHandler(TreeView^ sender, TreeViewItemClickEventArgs^ args); 31 | 32 | [Windows::Foundation::Metadata::WebHostHidden] 33 | public ref class TreeView sealed : Windows::UI::Xaml::Controls::ListView 34 | { 35 | public: 36 | TreeView(); 37 | 38 | //This event is used to expose an alternative to itemclick to developers. 39 | event TreeViewItemClickHandler^ TreeViewItemClick; 40 | 41 | //This RootNode property is used by the TreeView to handle additions into the TreeView and 42 | //accurate VectorChange with multiple 'root level nodes'. This node will not be placed 43 | //in the flatViewModel, but has it's vectorchanged event hooked up to flatViewModel's 44 | //handler. 45 | property TreeNode^ RootNode 46 | { 47 | TreeNode^ get() { return rootNode; }; 48 | } 49 | 50 | void TreeView_OnItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ args); 51 | 52 | void TreeView_DragItemsStarting(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e); 53 | 54 | void TreeView_DragItemsCompleted(Windows::UI::Xaml::Controls::ListViewBase^ sender, Windows::UI::Xaml::Controls::DragItemsCompletedEventArgs^ args); 55 | 56 | void ExpandNode(TreeNode^ targetNode); 57 | 58 | void CollapseNode(TreeNode^ targetNode); 59 | 60 | protected: 61 | void PrepareContainerForItemOverride(DependencyObject^ element, Object^ item) override; 62 | Windows::UI::Xaml::DependencyObject^ GetContainerForItemOverride() override; 63 | 64 | void OnDrop(Windows::UI::Xaml::DragEventArgs^ e) override; 65 | void OnDragOver(Windows::UI::Xaml::DragEventArgs^ e) override; 66 | 67 | private: 68 | TreeNode^ rootNode; 69 | ViewModel^ flatViewModel; 70 | 71 | internal: 72 | TreeViewItem^ draggedTreeViewItem; 73 | }; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Regedit/RegistryTreeView/UniversalTreeView.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 51 | 52 | -------------------------------------------------------------------------------- /XamlTreeView/TreeNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace TreeViewControl { 4 | /// 5 | /// The TreeNode class implements the hierarchical layout for the TreeView. 6 | /// It also holds the data that will be bound to in the item template. 7 | /// 8 | [Windows::UI::Xaml::Data::Bindable] 9 | [Windows::Foundation::Metadata::WebHostHidden] 10 | public ref class TreeNode sealed : Windows::UI::Xaml::Interop::IBindableObservableVector, Windows::UI::Xaml::Data::INotifyPropertyChanged 11 | { 12 | public: 13 | TreeNode(); 14 | 15 | virtual void Append(Object^ value); 16 | 17 | virtual void Clear(); 18 | 19 | virtual Windows::UI::Xaml::Interop::IBindableIterator^ First(); 20 | 21 | virtual Object^ GetAt(unsigned int index); 22 | 23 | virtual Windows::UI::Xaml::Interop::IBindableVectorView^ GetView(); 24 | 25 | virtual bool IndexOf(Object^ value, unsigned int* index); 26 | 27 | virtual void InsertAt(unsigned int index, Object^ value); 28 | 29 | virtual void RemoveAt(unsigned int index); 30 | 31 | virtual void RemoveAtEnd(); 32 | 33 | virtual void SetAt(unsigned int index, Object^ value); 34 | 35 | virtual event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ VectorChanged 36 | { 37 | virtual Windows::Foundation::EventRegistrationToken add(Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ e) 38 | { 39 | return TreeNodeChanged += e; 40 | } 41 | 42 | virtual void remove(Windows::Foundation::EventRegistrationToken t) 43 | { 44 | TreeNodeChanged -= t; 45 | } 46 | 47 | internal: virtual void raise(Windows::UI::Xaml::Interop::IBindableObservableVector^ vector, Platform::Object^ e) 48 | { 49 | TreeNodeChanged(vector, e); 50 | } 51 | } 52 | 53 | virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged; 54 | 55 | virtual property unsigned int Size 56 | { 57 | unsigned int get(); 58 | } 59 | 60 | property Object^ Data 61 | { 62 | Object^ get(); 63 | void set(Object^ value); 64 | } 65 | 66 | property TreeNode^ ParentNode 67 | { 68 | TreeNode^ get(); 69 | void set(TreeNode^ value); 70 | } 71 | 72 | property bool IsExpanded 73 | { 74 | bool get(); 75 | void set(bool value); 76 | } 77 | 78 | property bool HasItems 79 | { 80 | bool get(); 81 | } 82 | 83 | //A lone TreeNode will have a depth of -1, this is to show that it is not appended 84 | //under the TreeView's invisible root node. Once added into the TreeView via 85 | //that method, the depth of the node will be calculated appropriately. 86 | property int Depth 87 | { 88 | int get(); 89 | } 90 | 91 | event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ TreeNodeChanged; 92 | 93 | private: 94 | TreeNode^ parentNode = nullptr; 95 | Object^ data = nullptr; 96 | bool isExpanded = false; 97 | Platform::Collections::Vector^ childrenVector = ref new Platform::Collections::Vector(); 98 | void ChildrenVectorChanged(Windows::Foundation::Collections::IObservableVector^ sender, Windows::Foundation::Collections::IVectorChangedEventArgs^ e); 99 | }; 100 | } 101 | -------------------------------------------------------------------------------- /Regedit/RegistryTreeView/UniversalTreeView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Xml.Linq; 3 | using TreeViewControl; 4 | using Windows.UI.Xaml; 5 | using Windows.UI.Xaml.Controls; 6 | 7 | namespace Regedit.RegistryTreeView 8 | { 9 | public sealed partial class UniversalTreeView : UserControl 10 | { 11 | public UniversalTreeView() 12 | { 13 | this.InitializeComponent(); 14 | } 15 | 16 | private void OnDataChanged(DependencyPropertyChangedEventArgs e) 17 | { 18 | if (e.NewValue is DataBuilder Data) 19 | { 20 | if (Data.DataSource.Count > 0) 21 | { 22 | foreach (Item item in Data.DataSource) 23 | { 24 | TreeView.RootNode.Add(CreateTreeNode(item)); 25 | } 26 | } 27 | 28 | Data.DataSource.CollectionChanged += DataSource_CollectionChanged; 29 | } 30 | } 31 | 32 | private void DataSource_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 33 | { 34 | foreach (Item item in e.NewItems) 35 | { 36 | TreeView.RootNode.Add(CreateTreeNode(item)); 37 | } 38 | } 39 | 40 | private TreeNode CreateTreeNode(Item item) 41 | { 42 | TreeNode node = new TreeNode() 43 | { 44 | Data = item, 45 | IsExpanded = item.Expanded 46 | }; 47 | 48 | /*item.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) => 49 | { 50 | if (e.PropertyName == nameof(item.Expanded)) 51 | { 52 | if (node.IsExpanded) 53 | { 54 | node.IsExpanded = item.Expanded; 55 | TreeView.SelectedItem = node; 56 | } 57 | } 58 | };*/ 59 | 60 | node.PropertyChanged += Node_PropertyChanged; 61 | 62 | if (item.Children.Count > 0) 63 | { 64 | foreach (Item newItem in item.Children) 65 | { 66 | node.Add(CreateTreeNode(newItem)); 67 | } 68 | } 69 | 70 | item.Children.CollectionChanged += (object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) => 71 | { 72 | foreach (Item newItem in e.NewItems) 73 | { 74 | node.Add(CreateTreeNode(newItem)); 75 | } 76 | }; 77 | 78 | return node; 79 | } 80 | 81 | private void Node_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 82 | { 83 | TreeNode node = (TreeNode)sender; 84 | Item item = (Item)node.Data; 85 | 86 | if (e.PropertyName == nameof(node.IsExpanded) && node.IsExpanded != item.Expanded) 87 | { 88 | if (node.IsExpanded) 89 | { 90 | Data.ItemExpanded(item); 91 | } 92 | else 93 | { 94 | Data.ItemCollapsed(item); 95 | } 96 | } 97 | } 98 | 99 | private void TreeView_ItemClick(object sender, ItemClickEventArgs e) 100 | { 101 | TreeNode node = (TreeNode)e.ClickedItem; 102 | Item item = (Item)node.Data; 103 | 104 | Data.ItemInvoked(item); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Regedit/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using RegistryRT; 2 | using System; 3 | using Windows.ApplicationModel; 4 | using Windows.ApplicationModel.Activation; 5 | using Windows.UI.Xaml; 6 | using Windows.UI.Xaml.Controls; 7 | using Windows.UI.Xaml.Navigation; 8 | 9 | namespace Regedit 10 | { 11 | /// 12 | /// Provides application-specific behavior to supplement the default Application class. 13 | /// 14 | sealed partial class App : Application 15 | { 16 | public static readonly Registry registry = new(); 17 | 18 | /// 19 | /// Initializes the singleton application object. This is the first line of authored code 20 | /// executed, and as such is the logical equivalent of main() or WinMain(). 21 | /// 22 | public App() 23 | { 24 | this.InitializeComponent(); 25 | this.Suspending += OnSuspending; 26 | registry.InitNTDLLEntryPoints(); 27 | } 28 | 29 | /// 30 | /// Invoked when the application is launched normally by the end user. Other entry points 31 | /// will be used such as when the application is launched to open a specific file. 32 | /// 33 | /// Details about the launch request and process. 34 | protected override void OnLaunched(LaunchActivatedEventArgs e) 35 | { 36 | // Do not repeat app initialization when the Window already has content, 37 | // just ensure that the window is active 38 | if (Window.Current.Content is not Frame rootFrame) 39 | { 40 | // Create a Frame to act as the navigation context and navigate to the first page 41 | rootFrame = new Frame(); 42 | 43 | rootFrame.NavigationFailed += OnNavigationFailed; 44 | 45 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 46 | { 47 | //TODO: Load state from previously suspended application 48 | } 49 | 50 | // Place the frame in the current Window 51 | Window.Current.Content = rootFrame; 52 | } 53 | 54 | if (e.PrelaunchActivated == false) 55 | { 56 | if (rootFrame.Content == null) 57 | { 58 | // When the navigation stack isn't restored navigate to the first page, 59 | // configuring the new page by passing required information as a navigation 60 | // parameter 61 | rootFrame.Navigate(typeof(MainPage), e.Arguments); 62 | } 63 | // Ensure the current window is active 64 | Window.Current.Activate(); 65 | } 66 | } 67 | 68 | /// 69 | /// Invoked when Navigation to a certain page fails 70 | /// 71 | /// The Frame which failed navigation 72 | /// Details about the navigation failure 73 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 74 | { 75 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 76 | } 77 | 78 | /// 79 | /// Invoked when application execution is being suspended. Application state is saved 80 | /// without knowing whether the application will be terminated or resumed with the contents 81 | /// of memory still intact. 82 | /// 83 | /// The source of the suspend request. 84 | /// Details about the suspend request. 85 | private void OnSuspending(object sender, SuspendingEventArgs e) 86 | { 87 | SuspendingDeferral deferral = e.SuspendingOperation.GetDeferral(); 88 | //TODO: Save application state and stop any background activity 89 | deferral.Complete(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Regedit/Controls/TitlebarControl.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 39 | 40 | 47 | 48 | 55 | 56 | 57 | 64 | 65 | 70 | 71 | 76 | 77 | 93 | 94 | -------------------------------------------------------------------------------- /XamlTreeView/ViewModel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "TreeNode.h" 3 | 4 | namespace TreeViewControl { 5 | /// 6 | /// The ViewModel is responsible for flattening the heirarchical data into a flat list. 7 | /// It also tracks changes to the underlying data and updates the flat list accordingly. 8 | /// 9 | [Windows::Foundation::Metadata::WebHostHidden] 10 | ref class ViewModel sealed : Windows::UI::Xaml::Interop::IBindableObservableVector 11 | { 12 | internal: 13 | ViewModel(); 14 | 15 | public: 16 | /// 17 | /// Add root to the view model. In other cases the app should not 18 | /// use this api. 19 | /// 20 | virtual void Append(Object^ value); 21 | 22 | virtual void Clear(); 23 | 24 | virtual Windows::UI::Xaml::Interop::IBindableIterator^ First(); 25 | 26 | virtual Object^ GetAt(unsigned int index); 27 | 28 | virtual Windows::UI::Xaml::Interop::IBindableVectorView^ GetView(); 29 | 30 | virtual bool IndexOf(Object^ value, unsigned int* index); 31 | 32 | virtual void InsertAt(unsigned int index, Object^ value); 33 | 34 | virtual void RemoveAt(unsigned int index); 35 | 36 | virtual void RemoveAtEnd(); 37 | 38 | virtual void SetAt(unsigned int index, Object^ value); 39 | 40 | virtual property unsigned int Size 41 | { 42 | unsigned int get() { return flatVectorRealizedItems->Size; }; 43 | }; 44 | 45 | virtual event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ VectorChanged 46 | { 47 | virtual Windows::Foundation::EventRegistrationToken add(Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ args) 48 | { 49 | return ViewModelChanged += args; 50 | } 51 | 52 | virtual void remove(Windows::Foundation::EventRegistrationToken token) 53 | { 54 | return ViewModelChanged -= token; 55 | } 56 | 57 | virtual void raise(Windows::UI::Xaml::Interop::IBindableObservableVector^ vector, Platform::Object^ e) 58 | { 59 | ViewModelChanged(vector, e); 60 | } 61 | } 62 | 63 | /// 64 | /// ExpandNode adds the children and all open descendants of the targetNode 65 | /// to the ViewModel in their correct flattened index. 66 | /// 67 | void ExpandNode(TreeNode^ targetNode); 68 | 69 | /// 70 | /// Collapse node removes all the descendants of the targetNode from the ViewModel. 71 | /// 72 | void CollapseNode(TreeNode^ targetNode); 73 | 74 | /// 75 | /// This is the collection changed handler for individual TreeNodes. The collection changes 76 | /// from the hierarchical TreeNodes need to be flattened so that we can keep our current 77 | /// flat list in sync. 78 | /// 79 | /// TreeNode that has already been changed 80 | void TreeNodeVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector^ sender, Platform::Object^ e); 81 | 82 | void TreeNodePropertyChanged(Object^ sender, Windows::UI::Xaml::Data::PropertyChangedEventArgs^ e); 83 | 84 | private: 85 | event Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler^ ViewModelChanged; 86 | 87 | Platform::Collections::Vector^ flatVectorRealizedItems = ref new Platform::Collections::Vector(); 88 | 89 | std::vector collectionChangedEventTokenVector; 90 | 91 | std::vector propertyChangedEventTokenVector; 92 | 93 | void AddNodeToView(TreeNode^ targetNode, int index); 94 | 95 | int AddNodeDescendantsToView(TreeNode^ targetNode, int start, int offset); 96 | 97 | void RemoveNodeAndDescendantsFromView(TreeNode^ targetNode); 98 | 99 | int CountDescendants(TreeNode^ targetNode); 100 | 101 | int IndexOf(TreeNode^ targetNode); 102 | 103 | void UpdateTreeView(Windows::Foundation::Collections::IObservableVector^ sender, Windows::Foundation::Collections::IVectorChangedEventArgs^ e); 104 | }; 105 | } -------------------------------------------------------------------------------- /Regedit/GridSplitter/GridSplitter.Data.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | namespace Microsoft.Toolkit.Uwp.UI.Controls 6 | { 7 | /// 8 | /// Represents the control that redistributes space between columns or rows of a Grid control. 9 | /// 10 | public partial class GridSplitter 11 | { 12 | /// 13 | /// Enum to indicate whether GridSplitter resizes Columns or Rows 14 | /// 15 | public enum GridResizeDirection 16 | { 17 | /// 18 | /// Determines whether to resize rows or columns based on its Alignment and 19 | /// width compared to height 20 | /// 21 | Auto, 22 | 23 | /// 24 | /// Resize columns when dragging Splitter. 25 | /// 26 | Columns, 27 | 28 | /// 29 | /// Resize rows when dragging Splitter. 30 | /// 31 | Rows 32 | } 33 | 34 | /// 35 | /// Enum to indicate what Columns or Rows the GridSplitter resizes 36 | /// 37 | public enum GridResizeBehavior 38 | { 39 | /// 40 | /// Determine which columns or rows to resize based on its Alignment. 41 | /// 42 | BasedOnAlignment, 43 | 44 | /// 45 | /// Resize the current and next Columns or Rows. 46 | /// 47 | CurrentAndNext, 48 | 49 | /// 50 | /// Resize the previous and current Columns or Rows. 51 | /// 52 | PreviousAndCurrent, 53 | 54 | /// 55 | /// Resize the previous and next Columns or Rows. 56 | /// 57 | PreviousAndNext 58 | } 59 | 60 | /// 61 | /// Enum to indicate the supported gripper cursor types. 62 | /// 63 | public enum GripperCursorType 64 | { 65 | /// 66 | /// Change the cursor based on the splitter direction 67 | /// 68 | Default = -1, 69 | 70 | /// 71 | /// Standard Arrow cursor 72 | /// 73 | Arrow, 74 | 75 | /// 76 | /// Standard Cross cursor 77 | /// 78 | Cross, 79 | 80 | /// 81 | /// Standard Custom cursor 82 | /// 83 | Custom, 84 | 85 | /// 86 | /// Standard Hand cursor 87 | /// 88 | Hand, 89 | 90 | /// 91 | /// Standard Help cursor 92 | /// 93 | Help, 94 | 95 | /// 96 | /// Standard IBeam cursor 97 | /// 98 | IBeam, 99 | 100 | /// 101 | /// Standard SizeAll cursor 102 | /// 103 | SizeAll, 104 | 105 | /// 106 | /// Standard SizeNortheastSouthwest cursor 107 | /// 108 | SizeNortheastSouthwest, 109 | 110 | /// 111 | /// Standard SizeNorthSouth cursor 112 | /// 113 | SizeNorthSouth, 114 | 115 | /// 116 | /// Standard SizeNorthwestSoutheast cursor 117 | /// 118 | SizeNorthwestSoutheast, 119 | 120 | /// 121 | /// Standard SizeWestEast cursor 122 | /// 123 | SizeWestEast, 124 | 125 | /// 126 | /// Standard UniversalNo cursor 127 | /// 128 | UniversalNo, 129 | 130 | /// 131 | /// Standard UpArrow cursor 132 | /// 133 | UpArrow, 134 | 135 | /// 136 | /// Standard Wait cursor 137 | /// 138 | Wait 139 | } 140 | 141 | /// 142 | /// Enum to indicate the behavior of window cursor on grid splitter hover 143 | /// 144 | public enum SplitterCursorBehavior 145 | { 146 | /// 147 | /// Update window cursor on Grid Splitter hover 148 | /// 149 | ChangeOnSplitterHover, 150 | 151 | /// 152 | /// Update window cursor on Grid Splitter Gripper hover 153 | /// 154 | ChangeOnGripperHover 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /RegistryRT/pch.h: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2019 Gustave Monce - @gus33000 - gus33000.me 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | // 26 | // pch.h 27 | // 28 | 29 | #pragma once 30 | 31 | #include 32 | #include 33 | 34 | #undef WINAPI_PARTITION_SYSTEM 35 | #define WINAPI_PARTITION_SYSTEM 1 36 | #include 37 | #undef WINAPI_PARTITION_SYSTEM 38 | #define WINAPI_PARTITION_SYSTEM 0 39 | 40 | // Redefine PEB structures. The structure definitions in winternl.h are incomplete. 41 | typedef struct _MY_PEB_LDR_DATA { 42 | ULONG Length; 43 | BOOL Initialized; 44 | PVOID SsHandle; 45 | LIST_ENTRY InLoadOrderModuleList; 46 | LIST_ENTRY InMemoryOrderModuleList; 47 | LIST_ENTRY InInitializationOrderModuleList; 48 | } MY_PEB_LDR_DATA, *PMY_PEB_LDR_DATA; 49 | 50 | typedef struct _MY_LDR_DATA_TABLE_ENTRY 51 | { 52 | LIST_ENTRY InLoadOrderLinks; 53 | LIST_ENTRY InMemoryOrderLinks; 54 | LIST_ENTRY InInitializationOrderLinks; 55 | PVOID DllBase; 56 | PVOID EntryPoint; 57 | ULONG SizeOfImage; 58 | UNICODE_STRING FullDllName; 59 | UNICODE_STRING BaseDllName; 60 | } MY_LDR_DATA_TABLE_ENTRY, *PMY_LDR_DATA_TABLE_ENTRY; 61 | 62 | using namespace Platform; 63 | 64 | #include 65 | 66 | inline String^ Str(UNICODE_STRING US) { 67 | wchar_t* str = (wchar_t*)malloc(US.Length + sizeof(wchar_t)); 68 | memcpy(str, US.Buffer, US.Length); 69 | str[US.Length / sizeof(wchar_t)] = 0; 70 | String^ ret = ref new String(str); 71 | free(str); 72 | return ret; 73 | } 74 | 75 | inline String^ Str(const char * char_array) { 76 | std::string s_str = std::string(char_array); 77 | std::wstring wid_str = std::wstring(s_str.begin(), s_str.end()); 78 | const wchar_t* w_char = wid_str.c_str(); 79 | return ref new String(w_char); 80 | } 81 | 82 | inline String^ ToLower(String^ str) { 83 | std::wstring wid_str = str->Data(); 84 | std::transform(wid_str.begin(), wid_str.end(), wid_str.begin(), ::tolower); 85 | return ref new String(wid_str.c_str()); 86 | } 87 | 88 | inline PEB* NtCurrentPeb() { 89 | #ifdef _M_X64 90 | return (PEB*)(__readgsqword(0x60)); 91 | #elif _M_IX86 92 | return (PEB*)(__readfsdword(0x30)); 93 | #elif _M_ARM 94 | return *(PEB**)(_MoveFromCoprocessor(15, 0, 13, 0, 2) + 0x30); 95 | #elif _M_ARM64 96 | return *(PEB**)(__getReg(18) + 0x60); // TEB in x18 97 | #elif _M_IA64 98 | return *(PEB**)(_rdteb() + 0x60); 99 | #elif _M_ALPHA 100 | return *(PEB**)(_rdteb() + 0x30); 101 | #elif _M_MIPS 102 | return *(PEB**)((*(char**)(0x7ffff030)) + 0x30); 103 | #elif _M_PPC 104 | // winnt.h of the period uses __builtin_get_gpr13() or __gregister_get(13) depending on _MSC_VER 105 | return *(PEB**)(__gregister_get(13) + 0x30); 106 | #else 107 | #error "This architecture is currently unsupported" 108 | #endif 109 | }; 110 | 111 | inline FARPROC GetProcAddress(String^ dll, String^ func) { 112 | dll = ToLower(dll); 113 | func = ToLower(func); 114 | auto Ldr = (PMY_PEB_LDR_DATA)(NtCurrentPeb()->Ldr); 115 | auto NextModule = Ldr->InLoadOrderModuleList.Flink; 116 | auto TableEntry = (PMY_LDR_DATA_TABLE_ENTRY)NextModule; 117 | while (TableEntry->DllBase != NULL) { 118 | PVOID base = TableEntry->DllBase; 119 | String^ dllName = ToLower(Str(TableEntry->BaseDllName)); 120 | auto PE = (PIMAGE_NT_HEADERS)((ULONG_PTR)base + ((PIMAGE_DOS_HEADER)base)->e_lfanew); 121 | auto exportdirRVA = PE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 122 | TableEntry = (PMY_LDR_DATA_TABLE_ENTRY)TableEntry->InLoadOrderLinks.Flink; 123 | 124 | if (exportdirRVA == 0) continue; 125 | if (dllName != dll) continue; 126 | 127 | auto Exports = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)base + exportdirRVA); 128 | auto Names = (PDWORD)((PCHAR)base + Exports->AddressOfNames); 129 | auto Ordinals = (PUSHORT)((ULONG_PTR)base + Exports->AddressOfNameOrdinals); 130 | auto Functions = (PDWORD)((ULONG_PTR)base + Exports->AddressOfFunctions); 131 | 132 | for (uint32 iterator = 0; iterator < Exports->NumberOfNames; iterator++) { 133 | String^ funcName = ToLower(Str((PCSTR)(Names[iterator] + (ULONG_PTR)base))); 134 | 135 | if (funcName != func) continue; 136 | 137 | USHORT ordTblIndex = Ordinals[iterator]; 138 | return (FARPROC)((ULONG_PTR)base + Functions[ordTblIndex]); 139 | } 140 | } 141 | return NULL; 142 | } 143 | 144 | #include 145 | 146 | #include -------------------------------------------------------------------------------- /XamlTreeView/TreeViewItem.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include "TreeViewItem.h" 4 | #include "TreeViewItemAutomationPeer.h" 5 | 6 | using namespace Windows::UI::Xaml; 7 | using namespace Platform; 8 | 9 | namespace TreeViewControl { 10 | TreeViewItem::TreeViewItem() 11 | { 12 | } 13 | 14 | TreeViewItem::~TreeViewItem() 15 | { 16 | } 17 | 18 | Windows::UI::Xaml::Controls::ListView^ TreeViewItem::GetAncestorListView(TreeViewItem^ targetItem) 19 | { 20 | DependencyObject^ TreeViewItemAncestor = (DependencyObject^)this; 21 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = nullptr; 22 | while (TreeViewItemAncestor != nullptr && ancestorListView == nullptr) 23 | { 24 | TreeViewItemAncestor = Windows::UI::Xaml::Media::VisualTreeHelper::GetParent(TreeViewItemAncestor); 25 | ancestorListView = dynamic_cast(TreeViewItemAncestor); 26 | } 27 | return ancestorListView; 28 | } 29 | 30 | void TreeViewItem::OnDrop(Windows::UI::Xaml::DragEventArgs^ e) 31 | { 32 | if (e->AcceptedOperation == Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move) 33 | { 34 | TreeViewItem^ droppedOnItem = (TreeViewItem^)this; 35 | 36 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetAncestorListView(droppedOnItem); 37 | 38 | if (ancestorListView) 39 | { 40 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 41 | TreeViewItem^ droppedItem = ancestorTreeView->draggedTreeViewItem; 42 | TreeNode^ droppedNode = (TreeNode^)ancestorTreeView->ItemFromContainer(droppedItem); 43 | TreeNode^ droppedOnNode = (TreeNode^)ancestorTreeView->ItemFromContainer(droppedOnItem); 44 | 45 | //Remove the item that was dragged 46 | unsigned int removeIndex; 47 | droppedNode->ParentNode->IndexOf(droppedNode, &removeIndex); 48 | 49 | if (droppedNode != droppedOnNode) 50 | { 51 | droppedNode->ParentNode->RemoveAt(removeIndex); 52 | 53 | //Append the dragged dropped item as a child of the node it was dropped onto 54 | droppedOnNode->Append(droppedNode); 55 | 56 | //If not set to true then the Reorder code of listview wil override what is being done here. 57 | e->Handled = true; 58 | } 59 | else 60 | { 61 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None; 62 | } 63 | } 64 | } 65 | } 66 | 67 | void TreeViewItem::OnDragEnter(Windows::UI::Xaml::DragEventArgs^ e) 68 | { 69 | TreeViewItem^ draggedOverItem = (TreeViewItem^)this; 70 | 71 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None; 72 | 73 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetAncestorListView(draggedOverItem); 74 | 75 | if (ancestorListView) 76 | { 77 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 78 | TreeViewItem^ draggedTreeViewItem = ancestorTreeView->draggedTreeViewItem; 79 | TreeNode^ draggedNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedTreeViewItem); 80 | TreeNode^ draggedOverNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedOverItem); 81 | TreeNode^ walkNode = draggedOverNode->ParentNode; 82 | 83 | while (walkNode != nullptr && walkNode != draggedNode) 84 | { 85 | walkNode = walkNode->ParentNode; 86 | } 87 | 88 | if (walkNode != draggedNode && draggedNode != draggedOverNode) 89 | { 90 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move; 91 | } 92 | } 93 | } 94 | 95 | void TreeViewItem::OnDragOver(Windows::UI::Xaml::DragEventArgs^ e) 96 | { 97 | e->DragUIOverride->IsGlyphVisible = true; 98 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None; 99 | 100 | TreeViewItem^ draggedOverItem = (TreeViewItem^)this; 101 | 102 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetAncestorListView(draggedOverItem); 103 | if (ancestorListView) 104 | { 105 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 106 | TreeViewItem^ draggedTreeViewItem = ancestorTreeView->draggedTreeViewItem; 107 | TreeNode^ draggedNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedTreeViewItem); 108 | TreeNode^ draggedOverNode = (TreeNode^)ancestorTreeView->ItemFromContainer(draggedOverItem); 109 | TreeNode^ walkNode = draggedOverNode->ParentNode; 110 | 111 | while (walkNode != nullptr && walkNode != draggedNode) 112 | { 113 | walkNode = walkNode->ParentNode; 114 | } 115 | 116 | if (walkNode != draggedNode && draggedNode != draggedOverNode) 117 | { 118 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move; 119 | } 120 | } 121 | } 122 | 123 | Windows::UI::Xaml::Automation::Peers::AutomationPeer^ TreeViewItem::OnCreateAutomationPeer() 124 | { 125 | return ref new TreeViewItemAutomationPeer(this); 126 | } 127 | } -------------------------------------------------------------------------------- /Regedit.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31423.177 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Regedit", "Regedit\Regedit.csproj", "{1DFB2ADA-6291-4EF2-8A18-761673A88BC7}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegistryRT", "RegistryRT\RegistryRT.vcxproj", "{84A7225C-2DAF-410D-AB85-282AB220A89F}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TreeViewControl", "XamlTreeView\TreeViewControl.vcxproj", "{94560D69-A345-4E44-B897-EAA2B0E23238}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|ARM = Debug|ARM 15 | Debug|ARM64 = Debug|ARM64 16 | Debug|x64 = Debug|x64 17 | Debug|x86 = Debug|x86 18 | Release|ARM = Release|ARM 19 | Release|ARM64 = Release|ARM64 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|ARM.ActiveCfg = Debug|ARM 25 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|ARM.Build.0 = Debug|ARM 26 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|ARM.Deploy.0 = Debug|ARM 27 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|ARM64.ActiveCfg = Debug|ARM64 28 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|ARM64.Build.0 = Debug|ARM64 29 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|ARM64.Deploy.0 = Debug|ARM64 30 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|x64.ActiveCfg = Debug|x64 31 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|x64.Build.0 = Debug|x64 32 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|x64.Deploy.0 = Debug|x64 33 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|x86.ActiveCfg = Debug|x86 34 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|x86.Build.0 = Debug|x86 35 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Debug|x86.Deploy.0 = Debug|x86 36 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|ARM.ActiveCfg = Release|ARM 37 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|ARM.Build.0 = Release|ARM 38 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|ARM.Deploy.0 = Release|ARM 39 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|ARM64.ActiveCfg = Release|ARM64 40 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|ARM64.Build.0 = Release|ARM64 41 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|ARM64.Deploy.0 = Release|ARM64 42 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|x64.ActiveCfg = Release|x64 43 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|x64.Build.0 = Release|x64 44 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|x64.Deploy.0 = Release|x64 45 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|x86.ActiveCfg = Release|x86 46 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|x86.Build.0 = Release|x86 47 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7}.Release|x86.Deploy.0 = Release|x86 48 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|ARM.ActiveCfg = Debug|ARM 49 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|ARM.Build.0 = Debug|ARM 50 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|ARM64.ActiveCfg = Debug|ARM64 51 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|ARM64.Build.0 = Debug|ARM64 52 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|x64.ActiveCfg = Debug|x64 53 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|x64.Build.0 = Debug|x64 54 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|x86.ActiveCfg = Debug|Win32 55 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Debug|x86.Build.0 = Debug|Win32 56 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|ARM.ActiveCfg = Release|ARM 57 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|ARM.Build.0 = Release|ARM 58 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|ARM64.ActiveCfg = Release|ARM64 59 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|ARM64.Build.0 = Release|ARM64 60 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|x64.ActiveCfg = Release|x64 61 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|x64.Build.0 = Release|x64 62 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|x86.ActiveCfg = Release|Win32 63 | {84A7225C-2DAF-410D-AB85-282AB220A89F}.Release|x86.Build.0 = Release|Win32 64 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|ARM.ActiveCfg = Debug|ARM 65 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|ARM.Build.0 = Debug|ARM 66 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|ARM64.ActiveCfg = Debug|ARM64 67 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|ARM64.Build.0 = Debug|ARM64 68 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|x64.ActiveCfg = Debug|x64 69 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|x64.Build.0 = Debug|x64 70 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|x86.ActiveCfg = Debug|Win32 71 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Debug|x86.Build.0 = Debug|Win32 72 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|ARM.ActiveCfg = Release|ARM 73 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|ARM.Build.0 = Release|ARM 74 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|ARM64.ActiveCfg = Release|ARM64 75 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|ARM64.Build.0 = Release|ARM64 76 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|x64.ActiveCfg = Release|x64 77 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|x64.Build.0 = Release|x64 78 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|x86.ActiveCfg = Release|Win32 79 | {94560D69-A345-4E44-B897-EAA2B0E23238}.Release|x86.Build.0 = Release|Win32 80 | EndGlobalSection 81 | GlobalSection(SolutionProperties) = preSolution 82 | HideSolutionNode = FALSE 83 | EndGlobalSection 84 | GlobalSection(ExtensibilityGlobals) = postSolution 85 | SolutionGuid = {A7E39C97-EBFF-4604-83E4-AF1B50037C89} 86 | EndGlobalSection 87 | EndGlobal 88 | -------------------------------------------------------------------------------- /Regedit/GridSplitter/GripperHoverWrapper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Windows.UI.Core; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Input; 8 | 9 | namespace Microsoft.Toolkit.Uwp.UI.Controls 10 | { 11 | internal class GripperHoverWrapper 12 | { 13 | private readonly GridSplitter.GridResizeDirection _gridSplitterDirection; 14 | 15 | private CoreCursor _splitterPreviousPointer; 16 | private CoreCursor _previousCursor; 17 | private GridSplitter.GripperCursorType _gripperCursor; 18 | private int _gripperCustomCursorResource; 19 | private bool _isDragging; 20 | private UIElement _element; 21 | 22 | internal GridSplitter.GripperCursorType GripperCursor 23 | { 24 | get 25 | { 26 | return _gripperCursor; 27 | } 28 | 29 | set 30 | { 31 | _gripperCursor = value; 32 | } 33 | } 34 | 35 | internal int GripperCustomCursorResource 36 | { 37 | get 38 | { 39 | return _gripperCustomCursorResource; 40 | } 41 | 42 | set 43 | { 44 | _gripperCustomCursorResource = value; 45 | } 46 | } 47 | 48 | /// 49 | /// Initializes a new instance of the class that add cursor change on hover functionality for GridSplitter. 50 | /// 51 | /// UI element to apply cursor change on hover 52 | /// GridSplitter resize direction 53 | /// GridSplitter gripper on hover cursor type 54 | /// GridSplitter gripper custom cursor resource number 55 | internal GripperHoverWrapper(UIElement element, GridSplitter.GridResizeDirection gridSplitterDirection, GridSplitter.GripperCursorType gripperCursor, int gripperCustomCursorResource) 56 | { 57 | _gridSplitterDirection = gridSplitterDirection; 58 | _gripperCursor = gripperCursor; 59 | _gripperCustomCursorResource = gripperCustomCursorResource; 60 | _element = element; 61 | UnhookEvents(); 62 | _element.PointerEntered += Element_PointerEntered; 63 | _element.PointerExited += Element_PointerExited; 64 | } 65 | 66 | internal void UpdateHoverElement(UIElement element) 67 | { 68 | UnhookEvents(); 69 | _element = element; 70 | _element.PointerEntered += Element_PointerEntered; 71 | _element.PointerExited += Element_PointerExited; 72 | } 73 | 74 | private void Element_PointerExited(object sender, PointerRoutedEventArgs e) 75 | { 76 | if (_isDragging) 77 | { 78 | // if dragging don't update the cursor just update the splitter cursor with the last window cursor, 79 | // because the splitter is still using the arrow cursor and will revert to original case when drag completes 80 | _splitterPreviousPointer = _previousCursor; 81 | } 82 | else 83 | { 84 | Window.Current.CoreWindow.PointerCursor = _previousCursor; 85 | } 86 | } 87 | 88 | private void Element_PointerEntered(object sender, PointerRoutedEventArgs e) 89 | { 90 | // if not dragging 91 | if (!_isDragging) 92 | { 93 | _previousCursor = _splitterPreviousPointer = Window.Current.CoreWindow.PointerCursor; 94 | UpdateDisplayCursor(); 95 | } 96 | 97 | // if dragging 98 | else 99 | { 100 | _previousCursor = _splitterPreviousPointer; 101 | } 102 | } 103 | 104 | private void UpdateDisplayCursor() 105 | { 106 | if (_gripperCursor == GridSplitter.GripperCursorType.Default) 107 | { 108 | if (_gridSplitterDirection == GridSplitter.GridResizeDirection.Columns) 109 | { 110 | Window.Current.CoreWindow.PointerCursor = GridSplitter.ColumnsSplitterCursor; 111 | } 112 | else if (_gridSplitterDirection == GridSplitter.GridResizeDirection.Rows) 113 | { 114 | Window.Current.CoreWindow.PointerCursor = GridSplitter.RowSplitterCursor; 115 | } 116 | } 117 | else 118 | { 119 | CoreCursorType coreCursor = (CoreCursorType)((int)_gripperCursor); 120 | if (_gripperCursor == GridSplitter.GripperCursorType.Custom) 121 | { 122 | if (_gripperCustomCursorResource > GridSplitter.GripperCustomCursorDefaultResource) 123 | { 124 | Window.Current.CoreWindow.PointerCursor = new CoreCursor(coreCursor, (uint)_gripperCustomCursorResource); 125 | } 126 | } 127 | else 128 | { 129 | Window.Current.CoreWindow.PointerCursor = new CoreCursor(coreCursor, 1); 130 | } 131 | } 132 | } 133 | 134 | internal void SplitterManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) 135 | { 136 | if (sender is not GridSplitter splitter) 137 | { 138 | return; 139 | } 140 | 141 | _splitterPreviousPointer = splitter.PreviousCursor; 142 | _isDragging = true; 143 | } 144 | 145 | internal void SplitterManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) 146 | { 147 | if (sender is not GridSplitter splitter) 148 | { 149 | return; 150 | } 151 | 152 | Window.Current.CoreWindow.PointerCursor = splitter.PreviousCursor = _splitterPreviousPointer; 153 | _isDragging = false; 154 | } 155 | 156 | internal void UnhookEvents() 157 | { 158 | if (_element == null) 159 | { 160 | return; 161 | } 162 | 163 | _element.PointerEntered -= Element_PointerEntered; 164 | _element.PointerExited -= Element_PointerExited; 165 | } 166 | } 167 | } -------------------------------------------------------------------------------- /XamlTreeView/TreeNode.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include "TreeNode.h" 4 | 5 | using namespace Platform; 6 | using namespace Platform::Collections; 7 | using namespace Windows::UI::Xaml::Data; 8 | using namespace Windows::UI::Xaml::Interop; 9 | using namespace Windows::Foundation; 10 | using namespace Windows::Foundation::Collections; 11 | 12 | namespace TreeViewControl { 13 | 14 | TreeNode::TreeNode() 15 | { 16 | childrenVector->VectorChanged += ref new VectorChangedEventHandler(this, &TreeNode::ChildrenVectorChanged); 17 | } 18 | 19 | void TreeNode::Append(Object^ value) 20 | { 21 | int count = childrenVector->Size; 22 | TreeNode^ targetNode = (TreeNode^)value; 23 | targetNode->ParentNode = this; 24 | childrenVector->Append(targetNode); 25 | 26 | //If the count was 0 before we appended, then the HasItems property needs to change. 27 | if (count == 0) 28 | { 29 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems")); 30 | } 31 | 32 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size")); 33 | } 34 | 35 | void TreeNode::Clear() 36 | { 37 | int count = childrenVector->Size; 38 | TreeNode^ childNode; 39 | for (int i = 0; i < (int)Size; i++) 40 | { 41 | childNode = (TreeNode^)GetAt(i); 42 | childNode->ParentNode = nullptr; 43 | } 44 | 45 | childrenVector->Clear(); 46 | 47 | //If the count was not 0 before we cleared, then the HasItems property needs to change. 48 | if (count != 0) 49 | { 50 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems")); 51 | } 52 | 53 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size")); 54 | } 55 | 56 | IBindableIterator^ TreeNode::First() 57 | { 58 | return dynamic_cast(childrenVector->First()); 59 | } 60 | 61 | Object^ TreeNode::GetAt(unsigned int index) 62 | { 63 | if ((int)index > -1 && index < childrenVector->Size) 64 | { 65 | return childrenVector->GetAt(index); 66 | } 67 | 68 | return nullptr; 69 | } 70 | 71 | IBindableVectorView^ TreeNode::GetView() 72 | { 73 | return safe_cast(childrenVector->GetView()); 74 | } 75 | 76 | bool TreeNode::IndexOf(Object^ value, unsigned int* index) 77 | { 78 | return childrenVector->IndexOf((TreeNode^)value, index); 79 | } 80 | 81 | void TreeNode::InsertAt(unsigned int index, Object^ value) 82 | { 83 | if ((int)index > -1 && index <= childrenVector->Size) 84 | { 85 | int count = childrenVector->Size; 86 | TreeNode^ targetNode = (TreeNode^)value; 87 | targetNode->ParentNode = this; 88 | return childrenVector->InsertAt(index, (TreeNode^)value); 89 | 90 | //If the count was 0 before we insert, then the HasItems property needs to change. 91 | if (count == 0) 92 | { 93 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems")); 94 | } 95 | 96 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size")); 97 | } 98 | } 99 | 100 | void TreeNode::RemoveAt(unsigned int index) 101 | { 102 | if ((int)index > -1 && index < childrenVector->Size) 103 | { 104 | int count = childrenVector->Size; 105 | TreeNode^ targetNode = childrenVector->GetAt(index); 106 | targetNode->ParentNode = nullptr; 107 | childrenVector->RemoveAt(index); 108 | 109 | //If the count was 1 before we remove, then the HasItems property needs to change. 110 | if (count == 1) 111 | { 112 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems")); 113 | } 114 | 115 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size")); 116 | } 117 | } 118 | 119 | void TreeNode::RemoveAtEnd() 120 | { 121 | int count = childrenVector->Size; 122 | TreeNode^ targetNode = childrenVector->GetAt(childrenVector->Size - 1); 123 | targetNode->ParentNode = nullptr; 124 | childrenVector->RemoveAtEnd(); 125 | 126 | //If the count was 1 before we remove, then the HasItems property needs to change. 127 | if (count == 1) 128 | { 129 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("HasItems")); 130 | } 131 | 132 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Size")); 133 | } 134 | 135 | void TreeNode::SetAt(unsigned int index, Object^ value) 136 | { 137 | if ((int)index > -1 && index <= childrenVector->Size) 138 | { 139 | childrenVector->GetAt(index)->ParentNode = nullptr; 140 | TreeNode^ targetNode = (TreeNode^)value; 141 | targetNode->ParentNode = this; 142 | return childrenVector->SetAt(index, targetNode); 143 | } 144 | } 145 | 146 | void TreeNode::ChildrenVectorChanged(IObservableVector^ sender, IVectorChangedEventArgs^ e) 147 | { 148 | VectorChanged(this, e); 149 | } 150 | 151 | unsigned int TreeNode::Size::get() 152 | { 153 | return childrenVector->Size; 154 | } 155 | 156 | Object^ TreeNode::Data::get() 157 | { 158 | return data; 159 | } 160 | 161 | void TreeNode::Data::set(Object^ value) 162 | { 163 | data = value; 164 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Data")); 165 | } 166 | 167 | TreeNode^ TreeNode::ParentNode::get() 168 | { 169 | return parentNode; 170 | } 171 | 172 | void TreeNode::ParentNode::set(TreeNode^ value) 173 | { 174 | parentNode = value; 175 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("ParentNode")); 176 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("Depth")); 177 | } 178 | 179 | bool TreeNode::IsExpanded::get() 180 | { 181 | return isExpanded; 182 | } 183 | 184 | void TreeNode::IsExpanded::set(bool value) 185 | { 186 | isExpanded = value; 187 | this->PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs("IsExpanded")); 188 | } 189 | 190 | bool TreeNode::HasItems::get() 191 | { 192 | return (Size != 0); 193 | } 194 | 195 | int TreeNode::Depth::get() 196 | { 197 | TreeNode^ ancestorNode = this; 198 | int depth = -1; 199 | while ((ancestorNode->ParentNode) != nullptr) 200 | { 201 | depth++; 202 | ancestorNode = ancestorNode->ParentNode; 203 | } 204 | 205 | return depth; 206 | } 207 | 208 | } -------------------------------------------------------------------------------- /RegistryRT/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /XamlTreeView/TreeViewItemAutomationPeer.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include "TreeViewItemAutomationPeer.h" 4 | #include "TreeNode.h" 5 | 6 | using namespace Windows::UI::Xaml; 7 | using namespace Windows::UI::Xaml::Automation; 8 | using namespace Windows::UI::Xaml::Controls; 9 | using namespace Windows::UI::Xaml::Data; 10 | 11 | 12 | namespace TreeViewControl { 13 | //IExpandCollapseProvider 14 | Windows::UI::Xaml::Automation::ExpandCollapseState TreeViewItemAutomationPeer::ExpandCollapseState::get() 15 | { 16 | Windows::UI::Xaml::Automation::ExpandCollapseState currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed; 17 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner); 18 | 19 | TreeNode^ targetNode; 20 | TreeNode^ targetParentNode; 21 | 22 | if (ancestorListView) 23 | { 24 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 25 | targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner); 26 | 27 | if (Owner->AllowDrop) 28 | { 29 | if (targetNode->IsExpanded) 30 | { 31 | currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded; 32 | } 33 | else 34 | { 35 | currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed; 36 | } 37 | } 38 | else 39 | { 40 | currentState = Windows::UI::Xaml::Automation::ExpandCollapseState::LeafNode; 41 | } 42 | } 43 | 44 | return currentState; 45 | } 46 | 47 | void TreeViewItemAutomationPeer::Collapse() 48 | { 49 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner); 50 | 51 | if (ancestorListView) 52 | { 53 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 54 | TreeNode^ targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner); 55 | ancestorTreeView->CollapseNode(targetNode); 56 | RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed); 57 | } 58 | } 59 | 60 | void TreeViewItemAutomationPeer::Expand() 61 | { 62 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner); 63 | 64 | if (ancestorListView) 65 | { 66 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 67 | TreeNode^ targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner); 68 | ancestorTreeView->ExpandNode(targetNode); 69 | RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded); 70 | } 71 | } 72 | 73 | void TreeViewItemAutomationPeer::RaiseExpandCollapseAutomationEvent(Windows::UI::Xaml::Automation::ExpandCollapseState newState) 74 | { 75 | Windows::UI::Xaml::Automation::ExpandCollapseState oldState; 76 | 77 | if (newState == Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded) 78 | { 79 | oldState = Windows::UI::Xaml::Automation::ExpandCollapseState::Collapsed; 80 | } 81 | else 82 | { 83 | oldState = Windows::UI::Xaml::Automation::ExpandCollapseState::Expanded; 84 | } 85 | 86 | RaisePropertyChangedEvent(ExpandCollapsePatternIdentifiers::ExpandCollapseStateProperty, oldState, newState); 87 | } 88 | 89 | //Position override 90 | 91 | //These methods are being overridden so that the TreeView under narrator reads out 92 | //the position of an item as compared to it's children, not it's overall position 93 | //in the listview. I've included an override for level as well, to give context on 94 | //how deep in the tree an item is. 95 | int TreeViewItemAutomationPeer::GetSizeOfSetCore() 96 | { 97 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner); 98 | 99 | TreeNode^ targetNode; 100 | TreeNode^ targetParentNode; 101 | 102 | int setSize = 0; 103 | 104 | if (ancestorListView) 105 | { 106 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 107 | targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner); 108 | targetParentNode = targetNode->ParentNode; 109 | setSize = targetParentNode->Size; 110 | } 111 | 112 | return setSize; 113 | } 114 | 115 | int TreeViewItemAutomationPeer::GetPositionInSetCore() 116 | { 117 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner); 118 | 119 | TreeNode^ targetNode; 120 | TreeNode^ targetParentNode; 121 | 122 | int positionInSet = 0; 123 | 124 | if (ancestorListView) 125 | { 126 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 127 | targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner); 128 | unsigned int positionInt; 129 | targetParentNode = targetNode->ParentNode; 130 | targetParentNode->IndexOf(targetNode, &positionInt); 131 | positionInSet = (int)positionInt + 1; 132 | } 133 | 134 | return positionInSet; 135 | } 136 | 137 | int TreeViewItemAutomationPeer::GetLevelCore() 138 | { 139 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = GetParentListView((DependencyObject^)Owner); 140 | 141 | TreeNode^ targetNode; 142 | TreeNode^ targetParentNode; 143 | 144 | int levelValue = 0; 145 | 146 | if (ancestorListView) 147 | { 148 | TreeView^ ancestorTreeView = (TreeView^)ancestorListView; 149 | targetNode = (TreeNode^)ancestorTreeView->ItemFromContainer((TreeViewItem^)Owner); 150 | levelValue = targetNode->Depth + 1; 151 | } 152 | 153 | return levelValue; 154 | } 155 | 156 | Platform::Object^ TreeViewItemAutomationPeer::GetPatternCore(Windows::UI::Xaml::Automation::Peers::PatternInterface patternInterface) 157 | { 158 | if (patternInterface == Windows::UI::Xaml::Automation::Peers::PatternInterface::ExpandCollapse) 159 | { 160 | return this; 161 | } 162 | 163 | return ListViewItemAutomationPeer::GetPatternCore(patternInterface); 164 | } 165 | 166 | Windows::UI::Xaml::Controls::ListView^ TreeViewItemAutomationPeer::GetParentListView(DependencyObject^ Owner) 167 | { 168 | DependencyObject^ treeViewItemAncestor = Owner; 169 | Windows::UI::Xaml::Controls::ListView^ ancestorListView = nullptr; 170 | while (treeViewItemAncestor != nullptr && ancestorListView == nullptr) 171 | { 172 | treeViewItemAncestor = Windows::UI::Xaml::Media::VisualTreeHelper::GetParent(treeViewItemAncestor); 173 | ancestorListView = dynamic_cast(treeViewItemAncestor); 174 | } 175 | 176 | return ancestorListView; 177 | } 178 | } -------------------------------------------------------------------------------- /XamlTreeView/TreeView.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pch.h" 3 | #include "TreeView.h" 4 | 5 | using namespace Windows::UI::Xaml; 6 | using namespace Windows::UI::Xaml::Interop; 7 | using namespace Windows::UI::Xaml::Controls; 8 | 9 | namespace TreeViewControl { 10 | 11 | TreeView::TreeView() 12 | { 13 | flatViewModel = ref new ViewModel; 14 | rootNode = ref new TreeNode(); 15 | 16 | flatViewModel->ExpandNode(rootNode); 17 | 18 | CanReorderItems = true; 19 | AllowDrop = true; 20 | CanDragItems = true; 21 | 22 | rootNode->VectorChanged += ref new BindableVectorChangedEventHandler(flatViewModel, &ViewModel::TreeNodeVectorChanged); 23 | ItemClick += ref new Windows::UI::Xaml::Controls::ItemClickEventHandler(this, &TreeView::TreeView_OnItemClick); 24 | DragItemsStarting += ref new Windows::UI::Xaml::Controls::DragItemsStartingEventHandler(this, &TreeView::TreeView_DragItemsStarting); 25 | DragItemsCompleted += ref new Windows::Foundation::TypedEventHandler(this, &TreeView::TreeView_DragItemsCompleted); 26 | ItemsSource = flatViewModel; 27 | } 28 | 29 | void TreeView::TreeView_OnItemClick(Platform::Object^ sender, Windows::UI::Xaml::Controls::ItemClickEventArgs^ args) 30 | { 31 | TreeViewItemClickEventArgs^ treeViewArgs = ref new TreeViewItemClickEventArgs(); 32 | treeViewArgs->ClickedItem = args->ClickedItem; 33 | 34 | TreeViewItemClick(this, treeViewArgs); 35 | 36 | if (!treeViewArgs->IsHandled) 37 | { 38 | TreeNode^ targetNode = (TreeNode^)args->ClickedItem; 39 | if (targetNode->IsExpanded) 40 | { 41 | flatViewModel->CollapseNode(targetNode); 42 | } 43 | else 44 | { 45 | flatViewModel->ExpandNode(targetNode); 46 | } 47 | } 48 | } 49 | 50 | void TreeView::TreeView_DragItemsStarting(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e) 51 | { 52 | draggedTreeViewItem = (TreeViewItem^)this->ContainerFromItem(e->Items->GetAt(0)); 53 | } 54 | 55 | void TreeView::TreeView_DragItemsCompleted(Windows::UI::Xaml::Controls::ListViewBase^ sender, Windows::UI::Xaml::Controls::DragItemsCompletedEventArgs^ args) 56 | { 57 | draggedTreeViewItem = nullptr; 58 | } 59 | 60 | void TreeView::OnDrop(Windows::UI::Xaml::DragEventArgs^ e) 61 | { 62 | if (e->AcceptedOperation == Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move) 63 | { 64 | Panel^ panel = this->ItemsPanelRoot; 65 | Windows::Foundation::Point point = e->GetPosition(panel); 66 | 67 | int aboveIndex = -1; 68 | int belowIndex = -1; 69 | unsigned int relativeIndex; 70 | 71 | IInsertionPanel^ insertionPanel = (IInsertionPanel^)panel; 72 | 73 | if (insertionPanel != nullptr) 74 | { 75 | insertionPanel->GetInsertionIndexes(point, &aboveIndex, &belowIndex); 76 | 77 | TreeNode^ aboveNode = (TreeNode^)flatViewModel->GetAt(aboveIndex); 78 | TreeNode^ belowNode = (TreeNode^)flatViewModel->GetAt(belowIndex); 79 | TreeNode^ targetNode = (TreeNode^)this->ItemFromContainer(draggedTreeViewItem); 80 | 81 | //Between two items 82 | if (aboveNode && belowNode) 83 | { 84 | targetNode->ParentNode->IndexOf(targetNode, &relativeIndex); 85 | targetNode->ParentNode->RemoveAt(relativeIndex); 86 | 87 | if (belowNode->ParentNode == aboveNode) 88 | { 89 | aboveNode->InsertAt(0, targetNode); 90 | } 91 | else 92 | { 93 | aboveNode->ParentNode->IndexOf(aboveNode, &relativeIndex); 94 | aboveNode->ParentNode->InsertAt(relativeIndex + 1, targetNode); 95 | } 96 | } 97 | //Bottom of the list 98 | else if (aboveNode && !belowNode) 99 | { 100 | targetNode->ParentNode->IndexOf(targetNode, &relativeIndex); 101 | targetNode->ParentNode->RemoveAt(relativeIndex); 102 | 103 | aboveNode->ParentNode->IndexOf(aboveNode, &relativeIndex); 104 | aboveNode->ParentNode->InsertAt(relativeIndex + 1, targetNode); 105 | } 106 | //Top of the list 107 | else if (!aboveNode && belowNode) 108 | { 109 | targetNode->ParentNode->IndexOf(targetNode, &relativeIndex); 110 | targetNode->ParentNode->RemoveAt(relativeIndex); 111 | 112 | rootNode->InsertAt(0, targetNode); 113 | } 114 | } 115 | } 116 | 117 | e->Handled = true; 118 | ListViewBase::OnDrop(e); 119 | } 120 | 121 | void TreeView::OnDragOver(Windows::UI::Xaml::DragEventArgs^ e) 122 | { 123 | Windows::ApplicationModel::DataTransfer::DataPackageOperation savedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None; 124 | 125 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::None; 126 | 127 | Panel^ panel = this->ItemsPanelRoot; 128 | Windows::Foundation::Point point = e->GetPosition(panel); 129 | 130 | int aboveIndex = -1; 131 | int belowIndex = -1; 132 | 133 | IInsertionPanel^ insertionPanel = (IInsertionPanel^)panel; 134 | 135 | if (insertionPanel != nullptr) 136 | { 137 | insertionPanel->GetInsertionIndexes(point, &aboveIndex, &belowIndex); 138 | 139 | if (aboveIndex > -1) 140 | { 141 | TreeNode^ aboveNode = (TreeNode^)flatViewModel->GetAt(aboveIndex); 142 | TreeNode^ targetNode = (TreeNode^)this->ItemFromContainer(draggedTreeViewItem); 143 | 144 | TreeNode^ ancestorNode = aboveNode; 145 | while (ancestorNode != nullptr && ancestorNode != targetNode) 146 | { 147 | ancestorNode = ancestorNode->ParentNode; 148 | } 149 | 150 | if (ancestorNode == nullptr) 151 | { 152 | savedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move; 153 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move; 154 | } 155 | } 156 | else 157 | { 158 | savedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move; 159 | e->AcceptedOperation = Windows::ApplicationModel::DataTransfer::DataPackageOperation::Move; 160 | } 161 | } 162 | 163 | ListViewBase::OnDragOver(e); 164 | e->AcceptedOperation = savedOperation; 165 | } 166 | 167 | void TreeView::ExpandNode(TreeNode^ targetNode) 168 | { 169 | flatViewModel->ExpandNode(targetNode); 170 | } 171 | 172 | void TreeView::CollapseNode(TreeNode^ targetNode) 173 | { 174 | flatViewModel->CollapseNode(targetNode); 175 | } 176 | 177 | void TreeView::PrepareContainerForItemOverride(DependencyObject^ element, Object^ item) 178 | { 179 | ((UIElement^)element)->AllowDrop = true; 180 | 181 | ListView::PrepareContainerForItemOverride(element, item); 182 | } 183 | 184 | DependencyObject^ TreeView::GetContainerForItemOverride() 185 | { 186 | TreeViewItem^ targetItem = ref new TreeViewItem(); 187 | return (DependencyObject^)targetItem; 188 | } 189 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /Regedit/Controls/TitlebarControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using Windows.ApplicationModel; 4 | using Windows.ApplicationModel.Core; 5 | using Windows.System; 6 | using Windows.UI; 7 | using Windows.UI.Core; 8 | using Windows.UI.ViewManagement; 9 | using Windows.UI.Xaml; 10 | using Windows.UI.Xaml.Controls; 11 | using Windows.UI.Xaml.Media; 12 | 13 | #nullable enable 14 | 15 | namespace Regedit.Controls 16 | { 17 | public sealed partial class TitlebarControl : UserControl 18 | { 19 | private static string AppName = Package.Current.DisplayName; 20 | 21 | public event RoutedEventHandler? BackButtonClick; 22 | 23 | 24 | private string AppTitle = (!string.IsNullOrEmpty(ApplicationView.GetForCurrentView().Title) ? 25 | ApplicationView.GetForCurrentView().Title + " - " : "") + 26 | AppName; 27 | 28 | public TitlebarControl() 29 | { 30 | InitializeComponent(); 31 | Loaded += TitleBarControl_Loaded; 32 | 33 | CoreApplicationView? coreApplicationView = CoreApplication.GetCurrentView(); 34 | if (coreApplicationView.TitleBar != null) 35 | { 36 | Window.Current.SetTitleBar(TitlebarCanvas); 37 | 38 | SetVisibility(coreApplicationView.TitleBar.IsVisible); 39 | coreApplicationView.TitleBar.ExtendViewIntoTitleBar = true; 40 | Height = coreApplicationView.TitleBar.Height != 0 ? coreApplicationView.TitleBar.Height : 0; 41 | 42 | Thickness margin = CustomTitleBar.Margin; 43 | margin.Right = coreApplicationView.TitleBar.SystemOverlayRightInset; 44 | CustomTitleBar.Margin = margin; 45 | 46 | coreApplicationView.TitleBar.IsVisibleChanged += TitleBar_IsVisibleChanged; 47 | coreApplicationView.TitleBar.LayoutMetricsChanged += TitleBar_LayoutMetricsChanged; 48 | } 49 | 50 | #if DEBUG 51 | if (Debugger.IsAttached) 52 | { 53 | RedIndicator.Visibility = Visibility.Visible; 54 | } 55 | else 56 | { 57 | AttachDebuggerButton.Visibility = Visibility.Visible; 58 | } 59 | 60 | if (Application.Current.DebugSettings.FailFastOnErrors) 61 | { 62 | YellowIndicator.Visibility = Visibility.Visible; 63 | } 64 | #endif 65 | 66 | RefreshColor(); 67 | } 68 | 69 | private void Back_Click(object sender, RoutedEventArgs e) 70 | { 71 | BackButtonClick?.Invoke(this, e); 72 | } 73 | 74 | public void RefreshColor() 75 | { 76 | ApplicationViewTitleBar titlebar = ApplicationView.GetForCurrentView().TitleBar; 77 | if (titlebar != null) 78 | { 79 | SolidColorBrush transparentColorBrush = new() { Opacity = 0 }; 80 | Color transparentColor = transparentColorBrush.Color; 81 | 82 | titlebar.BackgroundColor = transparentColor; 83 | titlebar.ButtonBackgroundColor = transparentColor; 84 | titlebar.InactiveBackgroundColor = transparentColor; 85 | titlebar.ButtonInactiveBackgroundColor = transparentColor; 86 | 87 | SolidColorBrush foregroundThemeBrush = (SolidColorBrush)Resources["ApplicationForegroundThemeBrush"]; 88 | 89 | titlebar.ButtonForegroundColor = foregroundThemeBrush.Color; 90 | titlebar.ForegroundColor = foregroundThemeBrush.Color; 91 | 92 | Color color = foregroundThemeBrush.Color; 93 | color.A = 16; 94 | titlebar.InactiveForegroundColor = color; 95 | titlebar.ButtonInactiveForegroundColor = color; 96 | 97 | Color hovercolor = foregroundThemeBrush.Color; 98 | hovercolor.A = 32; 99 | titlebar.ButtonHoverBackgroundColor = hovercolor; 100 | titlebar.ButtonHoverForegroundColor = foregroundThemeBrush.Color; 101 | hovercolor.A = 64; 102 | titlebar.ButtonPressedBackgroundColor = hovercolor; 103 | titlebar.ButtonPressedForegroundColor = foregroundThemeBrush.Color; 104 | } 105 | } 106 | 107 | private async void TitleBarControl_Loaded(object sender, RoutedEventArgs e) 108 | { 109 | try 110 | { 111 | AppName = (await Package.Current.GetAppListEntriesAsync())[0].DisplayInfo.DisplayName; 112 | } 113 | catch { } 114 | 115 | AppTitle = (!string.IsNullOrEmpty(ApplicationView.GetForCurrentView().Title) ? 116 | ApplicationView.GetForCurrentView().Title + " - " : "") + 117 | AppName; 118 | #if DEBUG 119 | AppTitle += " [DEBUG]"; 120 | #endif 121 | WindowTitle.Text = AppTitle; 122 | } 123 | 124 | private void TitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args) 125 | { 126 | Height = sender.Height != 0 ? sender.Height : 0; 127 | Thickness margin = CustomTitleBar.Margin; 128 | margin.Right = sender.SystemOverlayRightInset; 129 | CustomTitleBar.Margin = margin; 130 | } 131 | 132 | private void TitleBar_IsVisibleChanged(CoreApplicationViewTitleBar sender, object args) 133 | { 134 | SetVisibility(sender.IsVisible); 135 | } 136 | 137 | private void SetVisibility(bool IsVisible) 138 | { 139 | FrameworkElement wincontent = (FrameworkElement)Window.Current.Content; 140 | Thickness margin = wincontent.Margin; 141 | if (IsVisible) 142 | { 143 | Visibility = Visibility.Visible; 144 | margin.Top = 0; 145 | } 146 | else 147 | { 148 | Visibility = Visibility.Collapsed; 149 | margin.Top = -32; 150 | } 151 | wincontent.Margin = margin; 152 | } 153 | 154 | private AppViewBackButtonVisibility _BackButtonVisibility = AppViewBackButtonVisibility.Collapsed; 155 | 156 | public AppViewBackButtonVisibility BackButtonVisibility 157 | { 158 | get => _BackButtonVisibility; 159 | set 160 | { 161 | _BackButtonVisibility = value; 162 | switch (_BackButtonVisibility) 163 | { 164 | case AppViewBackButtonVisibility.Visible: 165 | BackButton.Visibility = Visibility.Visible; 166 | break; 167 | 168 | case AppViewBackButtonVisibility.Collapsed: 169 | BackButton.Visibility = Visibility.Collapsed; 170 | break; 171 | } 172 | } 173 | } 174 | 175 | public void UpdateTitle() 176 | { 177 | AppTitle = (!string.IsNullOrEmpty(ApplicationView.GetForCurrentView().Title) ? 178 | ApplicationView.GetForCurrentView().Title + " - " : "") + 179 | AppName; 180 | #if DEBUG 181 | AppTitle += " [DEBUG]"; 182 | #endif 183 | WindowTitle.Text = AppTitle; 184 | } 185 | 186 | public string Title 187 | { 188 | get => ApplicationView.GetForCurrentView().Title; 189 | set 190 | { 191 | ApplicationView.GetForCurrentView().Title = value; 192 | AppTitle = (!string.IsNullOrEmpty(value) ? 193 | value + " - " : "") + 194 | AppName; 195 | 196 | #if DEBUG 197 | AppTitle += " [DEBUG]"; 198 | #endif 199 | WindowTitle.Text = AppTitle; 200 | } 201 | } 202 | 203 | private void AttachDebuggerButton_Click(object sender, RoutedEventArgs e) 204 | { 205 | Debugger.Launch(); 206 | 207 | if (Debugger.IsAttached) 208 | { 209 | RedIndicator.Visibility = Visibility.Visible; 210 | 211 | AttachDebuggerButton.Visibility = Visibility.Collapsed; 212 | } 213 | else 214 | { 215 | AttachDebuggerButton.Visibility = Visibility.Visible; 216 | } 217 | 218 | if (Application.Current.DebugSettings.FailFastOnErrors) 219 | { 220 | YellowIndicator.Visibility = Visibility.Visible; 221 | } 222 | } 223 | } 224 | } -------------------------------------------------------------------------------- /Regedit/GridSplitter/GridSplitter.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Windows.UI.Core; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls; 8 | using Windows.UI.Xaml.Input; 9 | 10 | namespace Microsoft.Toolkit.Uwp.UI.Controls 11 | { 12 | /// 13 | /// Represents the control that redistributes space between columns or rows of a Grid control. 14 | /// 15 | public partial class GridSplitter : Control 16 | { 17 | internal const int GripperCustomCursorDefaultResource = -1; 18 | internal static readonly CoreCursor ColumnsSplitterCursor = new(CoreCursorType.SizeWestEast, 1); 19 | internal static readonly CoreCursor RowSplitterCursor = new(CoreCursorType.SizeNorthSouth, 1); 20 | 21 | internal CoreCursor PreviousCursor { get; set; } 22 | 23 | private GridResizeDirection _resizeDirection; 24 | private GridResizeBehavior _resizeBehavior; 25 | private GripperHoverWrapper _hoverWrapper; 26 | private TextBlock _gripperDisplay; 27 | 28 | private bool _pressed = false; 29 | private bool _dragging = false; 30 | private bool _pointerEntered = false; 31 | 32 | /// 33 | /// Gets the target parent grid from level 34 | /// 35 | private FrameworkElement TargetControl 36 | { 37 | get 38 | { 39 | if (ParentLevel == 0) 40 | { 41 | return this; 42 | } 43 | 44 | DependencyObject parent = Parent; 45 | for (int i = 2; i < ParentLevel; i++) 46 | { 47 | if (parent is FrameworkElement frameworkElement) 48 | { 49 | parent = frameworkElement.Parent; 50 | } 51 | } 52 | 53 | return parent as FrameworkElement; 54 | } 55 | } 56 | 57 | /// 58 | /// Gets GridSplitter Container Grid 59 | /// 60 | private Grid Resizable => TargetControl?.Parent as Grid; 61 | 62 | /// 63 | /// Gets the current Column definition of the parent Grid 64 | /// 65 | private ColumnDefinition CurrentColumn 66 | { 67 | get 68 | { 69 | if (Resizable == null) 70 | { 71 | return null; 72 | } 73 | 74 | int gridSplitterTargetedColumnIndex = GetTargetedColumn(); 75 | 76 | if ((gridSplitterTargetedColumnIndex >= 0) 77 | && (gridSplitterTargetedColumnIndex < Resizable.ColumnDefinitions.Count)) 78 | { 79 | return Resizable.ColumnDefinitions[gridSplitterTargetedColumnIndex]; 80 | } 81 | 82 | return null; 83 | } 84 | } 85 | 86 | /// 87 | /// Gets the Sibling Column definition of the parent Grid 88 | /// 89 | private ColumnDefinition SiblingColumn 90 | { 91 | get 92 | { 93 | if (Resizable == null) 94 | { 95 | return null; 96 | } 97 | 98 | int gridSplitterSiblingColumnIndex = GetSiblingColumn(); 99 | 100 | if ((gridSplitterSiblingColumnIndex >= 0) 101 | && (gridSplitterSiblingColumnIndex < Resizable.ColumnDefinitions.Count)) 102 | { 103 | return Resizable.ColumnDefinitions[gridSplitterSiblingColumnIndex]; 104 | } 105 | 106 | return null; 107 | } 108 | } 109 | 110 | /// 111 | /// Gets the current Row definition of the parent Grid 112 | /// 113 | private RowDefinition CurrentRow 114 | { 115 | get 116 | { 117 | if (Resizable == null) 118 | { 119 | return null; 120 | } 121 | 122 | int gridSplitterTargetedRowIndex = GetTargetedRow(); 123 | 124 | if ((gridSplitterTargetedRowIndex >= 0) 125 | && (gridSplitterTargetedRowIndex < Resizable.RowDefinitions.Count)) 126 | { 127 | return Resizable.RowDefinitions[gridSplitterTargetedRowIndex]; 128 | } 129 | 130 | return null; 131 | } 132 | } 133 | 134 | /// 135 | /// Gets the Sibling Row definition of the parent Grid 136 | /// 137 | private RowDefinition SiblingRow 138 | { 139 | get 140 | { 141 | if (Resizable == null) 142 | { 143 | return null; 144 | } 145 | 146 | int gridSplitterSiblingRowIndex = GetSiblingRow(); 147 | 148 | if ((gridSplitterSiblingRowIndex >= 0) 149 | && (gridSplitterSiblingRowIndex < Resizable.RowDefinitions.Count)) 150 | { 151 | return Resizable.RowDefinitions[gridSplitterSiblingRowIndex]; 152 | } 153 | 154 | return null; 155 | } 156 | } 157 | 158 | /// 159 | /// Initializes a new instance of the class. 160 | /// 161 | public GridSplitter() 162 | { 163 | DefaultStyleKey = typeof(GridSplitter); 164 | Loaded += GridSplitter_Loaded; 165 | //string automationName = "WCT_GridSplitter_AutomationName".GetLocalized("Microsoft.Toolkit.Uwp.UI.Controls.Layout/Resources"); 166 | //AutomationProperties.SetName(this, automationName); 167 | } 168 | 169 | /// 170 | protected override void OnApplyTemplate() 171 | { 172 | base.OnApplyTemplate(); 173 | 174 | // Unhook registered events 175 | Loaded -= GridSplitter_Loaded; 176 | PointerEntered -= GridSplitter_PointerEntered; 177 | PointerExited -= GridSplitter_PointerExited; 178 | PointerPressed -= GridSplitter_PointerPressed; 179 | PointerReleased -= GridSplitter_PointerReleased; 180 | ManipulationStarted -= GridSplitter_ManipulationStarted; 181 | ManipulationCompleted -= GridSplitter_ManipulationCompleted; 182 | 183 | _hoverWrapper?.UnhookEvents(); 184 | 185 | // Register Events 186 | Loaded += GridSplitter_Loaded; 187 | PointerEntered += GridSplitter_PointerEntered; 188 | PointerExited += GridSplitter_PointerExited; 189 | PointerPressed += GridSplitter_PointerPressed; 190 | PointerReleased += GridSplitter_PointerReleased; 191 | ManipulationStarted += GridSplitter_ManipulationStarted; 192 | ManipulationCompleted += GridSplitter_ManipulationCompleted; 193 | 194 | _hoverWrapper?.UpdateHoverElement(Element); 195 | 196 | ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY; 197 | } 198 | 199 | private void GridSplitter_PointerReleased(object sender, PointerRoutedEventArgs e) 200 | { 201 | _pressed = false; 202 | VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true); 203 | } 204 | 205 | private void GridSplitter_PointerPressed(object sender, PointerRoutedEventArgs e) 206 | { 207 | _pressed = true; 208 | VisualStateManager.GoToState(this, "Pressed", true); 209 | } 210 | 211 | private void GridSplitter_PointerExited(object sender, PointerRoutedEventArgs e) 212 | { 213 | _pointerEntered = false; 214 | 215 | if (!_pressed && !_dragging) 216 | { 217 | VisualStateManager.GoToState(this, "Normal", true); 218 | } 219 | } 220 | 221 | private void GridSplitter_PointerEntered(object sender, PointerRoutedEventArgs e) 222 | { 223 | _pointerEntered = true; 224 | 225 | if (!_pressed && !_dragging) 226 | { 227 | VisualStateManager.GoToState(this, "PointerOver", true); 228 | } 229 | } 230 | 231 | private void GridSplitter_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) 232 | { 233 | _dragging = false; 234 | _pressed = false; 235 | VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true); 236 | } 237 | 238 | private void GridSplitter_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) 239 | { 240 | _dragging = true; 241 | VisualStateManager.GoToState(this, "Pressed", true); 242 | } 243 | } 244 | } -------------------------------------------------------------------------------- /Regedit/GridSplitter/GridSplitter.Options.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Windows.UI.Core; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Media; 8 | 9 | namespace Microsoft.Toolkit.Uwp.UI.Controls 10 | { 11 | /// 12 | /// Represents the control that redistributes space between columns or rows of a Grid control. 13 | /// 14 | public partial class GridSplitter 15 | { 16 | /// 17 | /// Identifies the dependency property. 18 | /// 19 | public static readonly DependencyProperty ElementProperty 20 | = DependencyProperty.Register( 21 | nameof(Element), 22 | typeof(UIElement), 23 | typeof(GridSplitter), 24 | new PropertyMetadata(default(UIElement), OnElementPropertyChanged)); 25 | 26 | /// 27 | /// Identifies the dependency property. 28 | /// 29 | public static readonly DependencyProperty ResizeDirectionProperty 30 | = DependencyProperty.Register( 31 | nameof(ResizeDirection), 32 | typeof(GridResizeDirection), 33 | typeof(GridSplitter), 34 | new PropertyMetadata(GridResizeDirection.Auto)); 35 | 36 | /// 37 | /// Identifies the dependency property. 38 | /// 39 | public static readonly DependencyProperty ResizeBehaviorProperty 40 | = DependencyProperty.Register( 41 | nameof(ResizeBehavior), 42 | typeof(GridResizeBehavior), 43 | typeof(GridSplitter), 44 | new PropertyMetadata(GridResizeBehavior.BasedOnAlignment)); 45 | 46 | /// 47 | /// Identifies the dependency property. 48 | /// 49 | public static readonly DependencyProperty GripperForegroundProperty 50 | = DependencyProperty.Register( 51 | nameof(GripperForeground), 52 | typeof(Brush), 53 | typeof(GridSplitter), 54 | new PropertyMetadata(default(Brush), OnGripperForegroundPropertyChanged)); 55 | 56 | /// 57 | /// Identifies the dependency property. 58 | /// 59 | public static readonly DependencyProperty ParentLevelProperty 60 | = DependencyProperty.Register( 61 | nameof(ParentLevel), 62 | typeof(int), 63 | typeof(GridSplitter), 64 | new PropertyMetadata(default(int))); 65 | 66 | /// 67 | /// Identifies the dependency property. 68 | /// 69 | public static readonly DependencyProperty GripperCursorProperty = 70 | DependencyProperty.RegisterAttached( 71 | nameof(GripperCursor), 72 | typeof(CoreCursorType?), 73 | typeof(GridSplitter), 74 | new PropertyMetadata(GripperCursorType.Default, OnGripperCursorPropertyChanged)); 75 | 76 | /// 77 | /// Identifies the dependency property. 78 | /// 79 | public static readonly DependencyProperty GripperCustomCursorResourceProperty = 80 | DependencyProperty.RegisterAttached( 81 | nameof(GripperCustomCursorResource), 82 | typeof(uint), 83 | typeof(GridSplitter), 84 | new PropertyMetadata(GripperCustomCursorDefaultResource, GripperCustomCursorResourcePropertyChanged)); 85 | 86 | /// 87 | /// Identifies the dependency property. 88 | /// 89 | public static readonly DependencyProperty CursorBehaviorProperty = 90 | DependencyProperty.RegisterAttached( 91 | nameof(CursorBehavior), 92 | typeof(SplitterCursorBehavior), 93 | typeof(GridSplitter), 94 | new PropertyMetadata(SplitterCursorBehavior.ChangeOnSplitterHover, CursorBehaviorPropertyChanged)); 95 | 96 | /// 97 | /// Gets or sets the visual content of this Grid Splitter 98 | /// 99 | public UIElement Element 100 | { 101 | get { return (UIElement)GetValue(ElementProperty); } 102 | set { SetValue(ElementProperty, value); } 103 | } 104 | 105 | /// 106 | /// Gets or sets whether the Splitter resizes the Columns, Rows, or Both. 107 | /// 108 | public GridResizeDirection ResizeDirection 109 | { 110 | get { return (GridResizeDirection)GetValue(ResizeDirectionProperty); } 111 | 112 | set { SetValue(ResizeDirectionProperty, value); } 113 | } 114 | 115 | /// 116 | /// Gets or sets which Columns or Rows the Splitter resizes. 117 | /// 118 | public GridResizeBehavior ResizeBehavior 119 | { 120 | get { return (GridResizeBehavior)GetValue(ResizeBehaviorProperty); } 121 | 122 | set { SetValue(ResizeBehaviorProperty, value); } 123 | } 124 | 125 | /// 126 | /// Gets or sets the foreground color of grid splitter grip 127 | /// 128 | public Brush GripperForeground 129 | { 130 | get { return (Brush)GetValue(GripperForegroundProperty); } 131 | 132 | set { SetValue(GripperForegroundProperty, value); } 133 | } 134 | 135 | /// 136 | /// Gets or sets the level of the parent grid to resize 137 | /// 138 | public int ParentLevel 139 | { 140 | get { return (int)GetValue(ParentLevelProperty); } 141 | 142 | set { SetValue(ParentLevelProperty, value); } 143 | } 144 | 145 | /// 146 | /// Gets or sets the gripper Cursor type 147 | /// 148 | public GripperCursorType GripperCursor 149 | { 150 | get { return (GripperCursorType)GetValue(GripperCursorProperty); } 151 | set { SetValue(GripperCursorProperty, value); } 152 | } 153 | 154 | /// 155 | /// Gets or sets the gripper Custom Cursor resource number 156 | /// 157 | public int GripperCustomCursorResource 158 | { 159 | get { return (int)GetValue(GripperCustomCursorResourceProperty); } 160 | set { SetValue(GripperCustomCursorResourceProperty, value); } 161 | } 162 | 163 | /// 164 | /// Gets or sets splitter cursor on hover behavior 165 | /// 166 | public SplitterCursorBehavior CursorBehavior 167 | { 168 | get { return (SplitterCursorBehavior)GetValue(CursorBehaviorProperty); } 169 | set { SetValue(CursorBehaviorProperty, value); } 170 | } 171 | 172 | private static void OnGripperForegroundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 173 | { 174 | GridSplitter gridSplitter = (GridSplitter)d; 175 | 176 | if (gridSplitter._gripperDisplay == null) 177 | { 178 | return; 179 | } 180 | 181 | gridSplitter._gripperDisplay.Foreground = gridSplitter.GripperForeground; 182 | } 183 | 184 | private static void OnGripperCursorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 185 | { 186 | GridSplitter gridSplitter = (GridSplitter)d; 187 | 188 | if (gridSplitter._hoverWrapper == null) 189 | { 190 | return; 191 | } 192 | 193 | gridSplitter._hoverWrapper.GripperCursor = gridSplitter.GripperCursor; 194 | } 195 | 196 | private static void GripperCustomCursorResourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 197 | { 198 | GridSplitter gridSplitter = (GridSplitter)d; 199 | 200 | if (gridSplitter._hoverWrapper == null) 201 | { 202 | return; 203 | } 204 | 205 | gridSplitter._hoverWrapper.GripperCustomCursorResource = gridSplitter.GripperCustomCursorResource; 206 | } 207 | 208 | private static void CursorBehaviorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 209 | { 210 | GridSplitter gridSplitter = (GridSplitter)d; 211 | 212 | gridSplitter._hoverWrapper?.UpdateHoverElement(gridSplitter.CursorBehavior == 213 | SplitterCursorBehavior.ChangeOnSplitterHover 214 | ? gridSplitter 215 | : gridSplitter.Element); 216 | } 217 | 218 | private static void OnElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 219 | { 220 | GridSplitter gridSplitter = (GridSplitter)d; 221 | 222 | gridSplitter._hoverWrapper?.UpdateHoverElement(gridSplitter.CursorBehavior == 223 | SplitterCursorBehavior.ChangeOnSplitterHover 224 | ? gridSplitter 225 | : gridSplitter.Element); 226 | } 227 | } 228 | } -------------------------------------------------------------------------------- /Regedit/GridSplitter/GridSplitter.Helper.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Windows.UI.Xaml; 6 | using Windows.UI.Xaml.Controls; 7 | 8 | namespace Microsoft.Toolkit.Uwp.UI.Controls 9 | { 10 | /// 11 | /// Represents the control that redistributes space between columns or rows of a Grid control. 12 | /// 13 | public partial class GridSplitter 14 | { 15 | private static bool IsStarColumn(ColumnDefinition definition) 16 | { 17 | return ((GridLength)definition.GetValue(ColumnDefinition.WidthProperty)).IsStar; 18 | } 19 | 20 | private static bool IsStarRow(RowDefinition definition) 21 | { 22 | return ((GridLength)definition.GetValue(RowDefinition.HeightProperty)).IsStar; 23 | } 24 | 25 | private bool SetColumnWidth(ColumnDefinition columnDefinition, double horizontalChange, GridUnitType unitType) 26 | { 27 | double newWidth = columnDefinition.ActualWidth + horizontalChange; 28 | 29 | double minWidth = columnDefinition.MinWidth; 30 | if (!double.IsNaN(minWidth) && newWidth < minWidth) 31 | { 32 | newWidth = minWidth; 33 | } 34 | 35 | double maxWidth = columnDefinition.MaxWidth; 36 | if (!double.IsNaN(maxWidth) && newWidth > maxWidth) 37 | { 38 | newWidth = maxWidth; 39 | } 40 | 41 | if (newWidth > ActualWidth) 42 | { 43 | columnDefinition.Width = new GridLength(newWidth, unitType); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double horizontalChange) 51 | { 52 | double newWidth = columnDefinition.ActualWidth + horizontalChange; 53 | 54 | double minWidth = columnDefinition.MinWidth; 55 | if (!double.IsNaN(minWidth) && newWidth < minWidth) 56 | { 57 | return false; 58 | } 59 | 60 | double maxWidth = columnDefinition.MaxWidth; 61 | if (!double.IsNaN(maxWidth) && newWidth > maxWidth) 62 | { 63 | return false; 64 | } 65 | 66 | if (newWidth <= ActualWidth) 67 | { 68 | return false; 69 | } 70 | 71 | return true; 72 | } 73 | 74 | private bool SetRowHeight(RowDefinition rowDefinition, double verticalChange, GridUnitType unitType) 75 | { 76 | double newHeight = rowDefinition.ActualHeight + verticalChange; 77 | 78 | double minHeight = rowDefinition.MinHeight; 79 | if (!double.IsNaN(minHeight) && newHeight < minHeight) 80 | { 81 | newHeight = minHeight; 82 | } 83 | 84 | double maxWidth = rowDefinition.MaxHeight; 85 | if (!double.IsNaN(maxWidth) && newHeight > maxWidth) 86 | { 87 | newHeight = maxWidth; 88 | } 89 | 90 | if (newHeight > ActualHeight) 91 | { 92 | rowDefinition.Height = new GridLength(newHeight, unitType); 93 | return true; 94 | } 95 | 96 | return false; 97 | } 98 | 99 | private bool IsValidRowHeight(RowDefinition rowDefinition, double verticalChange) 100 | { 101 | double newHeight = rowDefinition.ActualHeight + verticalChange; 102 | 103 | double minHeight = rowDefinition.MinHeight; 104 | if (!double.IsNaN(minHeight) && newHeight < minHeight) 105 | { 106 | return false; 107 | } 108 | 109 | double maxHeight = rowDefinition.MaxHeight; 110 | if (!double.IsNaN(maxHeight) && newHeight > maxHeight) 111 | { 112 | return false; 113 | } 114 | 115 | if (newHeight <= ActualHeight) 116 | { 117 | return false; 118 | } 119 | 120 | return true; 121 | } 122 | 123 | // Return the targeted Column based on the resize behavior 124 | private int GetTargetedColumn() 125 | { 126 | int currentIndex = Grid.GetColumn(TargetControl); 127 | return GetTargetIndex(currentIndex); 128 | } 129 | 130 | // Return the sibling Row based on the resize behavior 131 | private int GetTargetedRow() 132 | { 133 | int currentIndex = Grid.GetRow(TargetControl); 134 | return GetTargetIndex(currentIndex); 135 | } 136 | 137 | // Return the sibling Column based on the resize behavior 138 | private int GetSiblingColumn() 139 | { 140 | int currentIndex = Grid.GetColumn(TargetControl); 141 | return GetSiblingIndex(currentIndex); 142 | } 143 | 144 | // Return the sibling Row based on the resize behavior 145 | private int GetSiblingRow() 146 | { 147 | int currentIndex = Grid.GetRow(TargetControl); 148 | return GetSiblingIndex(currentIndex); 149 | } 150 | 151 | // Gets index based on resize behavior for first targeted row/column 152 | private int GetTargetIndex(int currentIndex) 153 | { 154 | switch (_resizeBehavior) 155 | { 156 | case GridResizeBehavior.CurrentAndNext: 157 | return currentIndex; 158 | case GridResizeBehavior.PreviousAndNext: 159 | return currentIndex - 1; 160 | case GridResizeBehavior.PreviousAndCurrent: 161 | return currentIndex - 1; 162 | default: 163 | return -1; 164 | } 165 | } 166 | 167 | // Gets index based on resize behavior for second targeted row/column 168 | private int GetSiblingIndex(int currentIndex) 169 | { 170 | switch (_resizeBehavior) 171 | { 172 | case GridResizeBehavior.CurrentAndNext: 173 | return currentIndex + 1; 174 | case GridResizeBehavior.PreviousAndNext: 175 | return currentIndex + 1; 176 | case GridResizeBehavior.PreviousAndCurrent: 177 | return currentIndex; 178 | default: 179 | return -1; 180 | } 181 | } 182 | 183 | // Checks the control alignment and Width/Height to detect the control resize direction columns/rows 184 | private GridResizeDirection GetResizeDirection() 185 | { 186 | GridResizeDirection direction = ResizeDirection; 187 | 188 | if (direction == GridResizeDirection.Auto) 189 | { 190 | // When HorizontalAlignment is Left, Right or Center, resize Columns 191 | if (HorizontalAlignment != HorizontalAlignment.Stretch) 192 | { 193 | direction = GridResizeDirection.Columns; 194 | } 195 | 196 | // When VerticalAlignment is Top, Bottom or Center, resize Rows 197 | else if (VerticalAlignment != VerticalAlignment.Stretch) 198 | { 199 | direction = GridResizeDirection.Rows; 200 | } 201 | 202 | // Check Width vs Height 203 | else if (ActualWidth <= ActualHeight) 204 | { 205 | direction = GridResizeDirection.Columns; 206 | } 207 | else 208 | { 209 | direction = GridResizeDirection.Rows; 210 | } 211 | } 212 | 213 | return direction; 214 | } 215 | 216 | // Get the resize behavior (Which columns/rows should be resized) based on alignment and Direction 217 | private GridResizeBehavior GetResizeBehavior() 218 | { 219 | GridResizeBehavior resizeBehavior = ResizeBehavior; 220 | 221 | if (resizeBehavior == GridResizeBehavior.BasedOnAlignment) 222 | { 223 | if (_resizeDirection == GridResizeDirection.Columns) 224 | { 225 | switch (HorizontalAlignment) 226 | { 227 | case HorizontalAlignment.Left: 228 | resizeBehavior = GridResizeBehavior.PreviousAndCurrent; 229 | break; 230 | case HorizontalAlignment.Right: 231 | resizeBehavior = GridResizeBehavior.CurrentAndNext; 232 | break; 233 | default: 234 | resizeBehavior = GridResizeBehavior.PreviousAndNext; 235 | break; 236 | } 237 | } 238 | 239 | // resize direction is vertical 240 | else 241 | { 242 | switch (VerticalAlignment) 243 | { 244 | case VerticalAlignment.Top: 245 | resizeBehavior = GridResizeBehavior.PreviousAndCurrent; 246 | break; 247 | case VerticalAlignment.Bottom: 248 | resizeBehavior = GridResizeBehavior.CurrentAndNext; 249 | break; 250 | default: 251 | resizeBehavior = GridResizeBehavior.PreviousAndNext; 252 | break; 253 | } 254 | } 255 | } 256 | 257 | return resizeBehavior; 258 | } 259 | } 260 | } -------------------------------------------------------------------------------- /Regedit/GridSplitter/GridSplitter.Events.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using Windows.System; 6 | using Windows.UI.Core; 7 | using Windows.UI.Xaml; 8 | using Windows.UI.Xaml.Controls; 9 | using Windows.UI.Xaml.Input; 10 | using Windows.UI.Xaml.Media; 11 | 12 | namespace Microsoft.Toolkit.Uwp.UI.Controls 13 | { 14 | /// 15 | /// Represents the control that redistributes space between columns or rows of a Grid control. 16 | /// 17 | public partial class GridSplitter 18 | { 19 | // Symbols for GripperBar in Segoe MDL2 Assets 20 | private const string GripperBarVertical = "\xE784"; 21 | private const string GripperBarHorizontal = "\xE76F"; 22 | private const string GripperDisplayFont = "Segoe MDL2 Assets"; 23 | 24 | private void GridSplitter_Loaded(object sender, RoutedEventArgs e) 25 | { 26 | _resizeDirection = GetResizeDirection(); 27 | _resizeBehavior = GetResizeBehavior(); 28 | 29 | // Adding Grip to Grid Splitter 30 | if (Element == default(UIElement)) 31 | { 32 | CreateGripperDisplay(); 33 | Element = _gripperDisplay; 34 | } 35 | 36 | if (_hoverWrapper == null) 37 | { 38 | GripperHoverWrapper hoverWrapper = new( 39 | CursorBehavior == SplitterCursorBehavior.ChangeOnSplitterHover 40 | ? this 41 | : Element, 42 | _resizeDirection, 43 | GripperCursor, 44 | GripperCustomCursorResource); 45 | ManipulationStarted += hoverWrapper.SplitterManipulationStarted; 46 | ManipulationCompleted += hoverWrapper.SplitterManipulationCompleted; 47 | 48 | _hoverWrapper = hoverWrapper; 49 | } 50 | } 51 | 52 | private void CreateGripperDisplay() 53 | { 54 | if (_gripperDisplay == null) 55 | { 56 | _gripperDisplay = new TextBlock 57 | { 58 | FontFamily = new FontFamily(GripperDisplayFont), 59 | HorizontalAlignment = HorizontalAlignment.Center, 60 | VerticalAlignment = VerticalAlignment.Center, 61 | Foreground = GripperForeground, 62 | Text = _resizeDirection == GridResizeDirection.Columns ? GripperBarVertical : GripperBarHorizontal 63 | }; 64 | _gripperDisplay.SetValue( 65 | Windows.UI.Xaml.Automation.AutomationProperties.AccessibilityViewProperty, 66 | Windows.UI.Xaml.Automation.Peers.AccessibilityView.Raw); 67 | } 68 | } 69 | 70 | /// 71 | protected override void OnKeyDown(KeyRoutedEventArgs e) 72 | { 73 | int step = 1; 74 | CoreVirtualKeyStates ctrl = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control); 75 | if (ctrl.HasFlag(CoreVirtualKeyStates.Down)) 76 | { 77 | step = 5; 78 | } 79 | 80 | if (_resizeDirection == GridResizeDirection.Columns) 81 | { 82 | if (e.Key == VirtualKey.Left) 83 | { 84 | HorizontalMove(-step); 85 | } 86 | else if (e.Key == VirtualKey.Right) 87 | { 88 | HorizontalMove(step); 89 | } 90 | else 91 | { 92 | return; 93 | } 94 | 95 | e.Handled = true; 96 | return; 97 | } 98 | 99 | if (_resizeDirection == GridResizeDirection.Rows) 100 | { 101 | if (e.Key == VirtualKey.Up) 102 | { 103 | VerticalMove(-step); 104 | } 105 | else if (e.Key == VirtualKey.Down) 106 | { 107 | VerticalMove(step); 108 | } 109 | else 110 | { 111 | return; 112 | } 113 | 114 | e.Handled = true; 115 | } 116 | 117 | base.OnKeyDown(e); 118 | } 119 | 120 | /// 121 | protected override void OnManipulationStarted(ManipulationStartedRoutedEventArgs e) 122 | { 123 | // saving the previous state 124 | PreviousCursor = Window.Current.CoreWindow.PointerCursor; 125 | _resizeDirection = GetResizeDirection(); 126 | _resizeBehavior = GetResizeBehavior(); 127 | 128 | if (_resizeDirection == GridResizeDirection.Columns) 129 | { 130 | Window.Current.CoreWindow.PointerCursor = ColumnsSplitterCursor; 131 | } 132 | else if (_resizeDirection == GridResizeDirection.Rows) 133 | { 134 | Window.Current.CoreWindow.PointerCursor = RowSplitterCursor; 135 | } 136 | 137 | base.OnManipulationStarted(e); 138 | } 139 | 140 | /// 141 | protected override void OnManipulationCompleted(ManipulationCompletedRoutedEventArgs e) 142 | { 143 | Window.Current.CoreWindow.PointerCursor = PreviousCursor; 144 | 145 | base.OnManipulationCompleted(e); 146 | } 147 | 148 | /// 149 | protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e) 150 | { 151 | double horizontalChange = e.Delta.Translation.X; 152 | double verticalChange = e.Delta.Translation.Y; 153 | 154 | if (this.FlowDirection == FlowDirection.RightToLeft) 155 | { 156 | horizontalChange *= -1; 157 | } 158 | 159 | if (_resizeDirection == GridResizeDirection.Columns) 160 | { 161 | if (HorizontalMove(horizontalChange)) 162 | { 163 | return; 164 | } 165 | } 166 | else if (_resizeDirection == GridResizeDirection.Rows) 167 | { 168 | if (VerticalMove(verticalChange)) 169 | { 170 | return; 171 | } 172 | } 173 | 174 | base.OnManipulationDelta(e); 175 | } 176 | 177 | private bool VerticalMove(double verticalChange) 178 | { 179 | if (CurrentRow == null || SiblingRow == null) 180 | { 181 | return true; 182 | } 183 | 184 | // if current row has fixed height then resize it 185 | if (!IsStarRow(CurrentRow)) 186 | { 187 | // No need to check for the row Min height because it is automatically respected 188 | if (!SetRowHeight(CurrentRow, verticalChange, GridUnitType.Pixel)) 189 | { 190 | return true; 191 | } 192 | } 193 | 194 | // if sibling row has fixed width then resize it 195 | else if (!IsStarRow(SiblingRow)) 196 | { 197 | // Would adding to this column make the current column violate the MinWidth? 198 | if (IsValidRowHeight(CurrentRow, verticalChange) == false) 199 | { 200 | return false; 201 | } 202 | 203 | if (!SetRowHeight(SiblingRow, verticalChange * -1, GridUnitType.Pixel)) 204 | { 205 | return true; 206 | } 207 | } 208 | 209 | // if both row haven't fixed height (auto *) 210 | else 211 | { 212 | // change current row height to the new height with respecting the auto 213 | // change sibling row height to the new height relative to current row 214 | // respect the other star row height by setting it's height to it's actual height with stars 215 | 216 | // We need to validate current and sibling height to not cause any unexpected behavior 217 | if (!IsValidRowHeight(CurrentRow, verticalChange) || 218 | !IsValidRowHeight(SiblingRow, verticalChange * -1)) 219 | { 220 | return true; 221 | } 222 | 223 | foreach (RowDefinition rowDefinition in Resizable.RowDefinitions) 224 | { 225 | if (rowDefinition == CurrentRow) 226 | { 227 | SetRowHeight(CurrentRow, verticalChange, GridUnitType.Star); 228 | } 229 | else if (rowDefinition == SiblingRow) 230 | { 231 | SetRowHeight(SiblingRow, verticalChange * -1, GridUnitType.Star); 232 | } 233 | else if (IsStarRow(rowDefinition)) 234 | { 235 | rowDefinition.Height = new GridLength(rowDefinition.ActualHeight, GridUnitType.Star); 236 | } 237 | } 238 | } 239 | 240 | return false; 241 | } 242 | 243 | private bool HorizontalMove(double horizontalChange) 244 | { 245 | if (CurrentColumn == null || SiblingColumn == null) 246 | { 247 | return true; 248 | } 249 | 250 | // if current column has fixed width then resize it 251 | if (!IsStarColumn(CurrentColumn)) 252 | { 253 | // No need to check for the Column Min width because it is automatically respected 254 | if (!SetColumnWidth(CurrentColumn, horizontalChange, GridUnitType.Pixel)) 255 | { 256 | return true; 257 | } 258 | } 259 | 260 | // if sibling column has fixed width then resize it 261 | else if (!IsStarColumn(SiblingColumn)) 262 | { 263 | // Would adding to this column make the current column violate the MinWidth? 264 | if (IsValidColumnWidth(CurrentColumn, horizontalChange) == false) 265 | { 266 | return false; 267 | } 268 | 269 | if (!SetColumnWidth(SiblingColumn, horizontalChange * -1, GridUnitType.Pixel)) 270 | { 271 | return true; 272 | } 273 | } 274 | 275 | // if both column haven't fixed width (auto *) 276 | else 277 | { 278 | // change current column width to the new width with respecting the auto 279 | // change sibling column width to the new width relative to current column 280 | // respect the other star column width by setting it's width to it's actual width with stars 281 | 282 | // We need to validate current and sibling width to not cause any unexpected behavior 283 | if (!IsValidColumnWidth(CurrentColumn, horizontalChange) || 284 | !IsValidColumnWidth(SiblingColumn, horizontalChange * -1)) 285 | { 286 | return true; 287 | } 288 | 289 | foreach (ColumnDefinition columnDefinition in Resizable.ColumnDefinitions) 290 | { 291 | if (columnDefinition == CurrentColumn) 292 | { 293 | SetColumnWidth(CurrentColumn, horizontalChange, GridUnitType.Star); 294 | } 295 | else if (columnDefinition == SiblingColumn) 296 | { 297 | SetColumnWidth(SiblingColumn, horizontalChange * -1, GridUnitType.Star); 298 | } 299 | else if (IsStarColumn(columnDefinition)) 300 | { 301 | columnDefinition.Width = new GridLength(columnDefinition.ActualWidth, GridUnitType.Star); 302 | } 303 | } 304 | } 305 | 306 | return false; 307 | } 308 | } 309 | } -------------------------------------------------------------------------------- /Regedit/RegistryTreeView/DataBuilder.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Controls; 2 | using RegistryRT; 3 | using System; 4 | using System.Collections.ObjectModel; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | using System.Threading; 8 | using Windows.UI.Xaml.Controls.Primitives; 9 | 10 | #nullable enable 11 | 12 | namespace Regedit.RegistryTreeView 13 | { 14 | public class Item : INotifyPropertyChanged 15 | { 16 | public string Name { get; set; } 17 | public string Path { get; set; } 18 | 19 | private bool _Expanded = false; 20 | public bool Expanded 21 | { 22 | get => _Expanded; set 23 | { 24 | if (value != _Expanded) 25 | { 26 | _Expanded = value; 27 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Expanded))); 28 | } 29 | } 30 | } 31 | 32 | public RegistryHive Hive { get; set; } 33 | 34 | public string Image { get; set; } 35 | public ObservableCollection Children { get; set; } = new ObservableCollection(); 36 | 37 | public event PropertyChangedEventHandler? PropertyChanged; 38 | 39 | public override string ToString() 40 | { 41 | return Name; 42 | } 43 | } 44 | 45 | public class ValueItem 46 | { 47 | public string Name { get; set; } 48 | public string Type { get; set; } 49 | public string Data { get; set; } 50 | public string Image { get; set; } 51 | public Item ParentItem { get; set; } 52 | } 53 | 54 | public class DataBuilder : INotifyPropertyChanged 55 | { 56 | public readonly ObservableCollection DataSource = new(); 57 | public readonly ObservableCollection ValueSource = new(); 58 | 59 | private string _Path = "Computer"; 60 | public string Path 61 | { 62 | get => _Path; 63 | set 64 | { 65 | if (_Path != value) 66 | { 67 | OnPathChanged(value); 68 | _Path = value; 69 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Path))); 70 | } 71 | } 72 | } 73 | 74 | private readonly string folderImageSource = "ms-appx:///Assets/folder.png"; 75 | private readonly string computerImageSource = "ms-appx:///Assets/computer.png"; 76 | private readonly string numbersImageSource = "ms-appx:///Assets/numbers.png"; 77 | private readonly string textImageSource = "ms-appx:///Assets/text.png"; 78 | 79 | public event PropertyChangedEventHandler? PropertyChanged; 80 | 81 | public DataBuilder() 82 | { 83 | GetRegistryData(); 84 | } 85 | 86 | private void GetRegistryData() 87 | { 88 | ObservableCollection list = new() 89 | { 90 | new Item() 91 | { 92 | Name = "HKEY_CLASSES_ROOT", 93 | Image = folderImageSource, 94 | Hive = RegistryHive.HKEY_CLASSES_ROOT, 95 | Path = "" 96 | }, 97 | 98 | new Item() 99 | { 100 | Name = "HKEY_CURRENT_USER", 101 | Image = folderImageSource, 102 | Hive = RegistryHive.HKEY_CURRENT_USER, 103 | Path = "" 104 | }, 105 | 106 | new Item() 107 | { 108 | Name = "HKEY_LOCAL_MACHINE", 109 | Image = folderImageSource, 110 | Hive = RegistryHive.HKEY_LOCAL_MACHINE, 111 | Path = "" 112 | }, 113 | 114 | new Item() 115 | { 116 | Name = "HKEY_USERS", 117 | Image = folderImageSource, 118 | Hive = RegistryHive.HKEY_USERS, 119 | Path = "" 120 | }, 121 | 122 | new Item() 123 | { 124 | Name = "HKEY_CURRENT_CONFIG", 125 | Image = folderImageSource, 126 | Hive = RegistryHive.HKEY_CURRENT_CONFIG, 127 | Path = "" 128 | } 129 | }; 130 | 131 | foreach (Item element in list) 132 | { 133 | try 134 | { 135 | App.registry.GetSubKeyList(element.Hive, element.Path, out string[] keys); 136 | foreach (string key in keys) 137 | { 138 | element.Children.Add(new Item() 139 | { 140 | Name = key, 141 | Hive = element.Hive, 142 | Image = folderImageSource, 143 | Path = element.Path + key + "\\" 144 | }); 145 | } 146 | } 147 | catch 148 | { 149 | 150 | } 151 | } 152 | 153 | DataSource.Add(new Item() 154 | { 155 | Name = "Computer", 156 | Children = list, 157 | Image = computerImageSource, 158 | Expanded = true 159 | }); 160 | 161 | lastInvokedItem = DataSource[0]; 162 | } 163 | 164 | public void ItemExpanded(Item selectedItem) 165 | { 166 | if (lastInvokedItem != null) 167 | { 168 | if (GetPath(selectedItem).ToLower().Equals(GetPath(lastInvokedItem).ToLower(), StringComparison.CurrentCultureIgnoreCase)) 169 | { 170 | return; 171 | } 172 | } 173 | 174 | if (selectedItem.Expanded == true) 175 | return; 176 | 177 | lastInvokedItem = selectedItem; 178 | selectedItem.Expanded = true; 179 | 180 | foreach (Item element in selectedItem.Children) 181 | { 182 | if (element.Children.Count > 0) 183 | break; 184 | 185 | App.registry.GetSubKeyList(element.Hive, element.Path, out string[] keys); 186 | 187 | if (keys == null) 188 | continue; 189 | 190 | foreach (string key in keys) 191 | { 192 | Item item = new() 193 | { 194 | Name = key, 195 | Hive = element.Hive, 196 | Image = folderImageSource, 197 | Path = element.Path + key + "\\" 198 | }; 199 | 200 | element.Children.Add(item); 201 | } 202 | } 203 | } 204 | 205 | public void ItemCollapsed(Item selectedItem) 206 | { 207 | selectedItem.Expanded = false; 208 | } 209 | 210 | private Item? lastInvokedItem; 211 | 212 | private void OnPathChanged(string value) 213 | { 214 | if (lastInvokedItem != null) 215 | { 216 | if (value.ToLower().Equals(GetPath(lastInvokedItem).ToLower(), StringComparison.CurrentCultureIgnoreCase)) 217 | { 218 | return; 219 | } 220 | } 221 | 222 | var elements = value.Split('\\'); 223 | int elementIndex = 0; 224 | var treeitems = DataSource; 225 | 226 | while (elementIndex < elements.Length) 227 | { 228 | bool foundItem = false; 229 | foreach (var treeitem in treeitems) 230 | { 231 | if (treeitem.Name.ToLower().Equals(elements[elementIndex].ToLower(), StringComparison.CurrentCultureIgnoreCase)) 232 | { 233 | elementIndex++; 234 | treeitems = treeitem.Children; 235 | foundItem = true; 236 | ItemExpanded(treeitem); 237 | if (elementIndex == elements.Length) 238 | ItemInvoked(treeitem); 239 | break; 240 | } 241 | } 242 | 243 | if (!foundItem) 244 | break; 245 | } 246 | } 247 | 248 | private string GetPath(Item item) 249 | { 250 | if (item.Name == "Computer" && string.IsNullOrEmpty(item.Path)) 251 | { 252 | return item.Name; 253 | } 254 | else if (string.IsNullOrEmpty(item.Path)) 255 | { 256 | return "Computer\\" + item.Hive.ToString(); 257 | } 258 | else 259 | { 260 | return "Computer\\" + item.Hive.ToString() + "\\" + item.Path.TrimEnd('\\'); 261 | } 262 | } 263 | 264 | public void ItemInvoked(Item item) 265 | { 266 | lastInvokedItem = item; 267 | 268 | ValueSource.Clear(); 269 | 270 | Path = GetPath(item); 271 | 272 | if (!(item.Name == "Computer" && string.IsNullOrEmpty(item.Path))) 273 | { 274 | RegistryType dtype = RegistryType.String; 275 | byte[] dbuf = System.Text.Encoding.Unicode.GetBytes("(value not set)"); 276 | 277 | try 278 | { 279 | App.registry.QueryValue(item.Hive, item.Path, null, out dtype, out dbuf); 280 | } 281 | catch { }; 282 | 283 | string ddatastr = "(value not set)"; 284 | 285 | if (dtype == RegistryType.String) 286 | { 287 | ddatastr = System.Text.Encoding.Unicode.GetString(dbuf); 288 | } 289 | else if (dtype == RegistryType.Integer) 290 | { 291 | ddatastr = BitConverter.ToInt32(dbuf, 0).ToString(); 292 | } 293 | else if (dtype == RegistryType.Long) 294 | { 295 | ddatastr = BitConverter.ToInt64(dbuf, 0).ToString(); 296 | } 297 | else 298 | { 299 | ddatastr = BitConverter.ToString(dbuf); 300 | } 301 | 302 | ValueSource.Add(new ValueItem() 303 | { 304 | Name = "(Default)", 305 | Type = dtype.ToString(), 306 | Data = ddatastr, 307 | Image = textImageSource, 308 | ParentItem = item 309 | }); 310 | 311 | App.registry.GetValueList(item.Hive, item.Path, out string[] list); 312 | 313 | if (list != null && list.Length != 0) 314 | { 315 | var valuerange = (list.ToList().OrderBy(x => x).Select(x => 316 | { 317 | RegistryType vtype = App.registry.GetValueInfo(item.Hive, item.Path, x, 0); 318 | 319 | ValueItem vitem = new() 320 | { 321 | Name = x, 322 | Type = vtype.ToString(), 323 | ParentItem = item 324 | }; 325 | 326 | App.registry.QueryValue(item.Hive, item.Path, x, out vtype, out byte[] buf); 327 | 328 | if (vtype == RegistryType.String) 329 | { 330 | vitem.Data = System.Text.Encoding.Unicode.GetString(buf); 331 | vitem.Image = textImageSource; 332 | } 333 | else if (vtype == RegistryType.Integer) 334 | { 335 | vitem.Data = BitConverter.ToInt32(buf, 0).ToString(); 336 | vitem.Image = numbersImageSource; 337 | } 338 | else if (vtype == RegistryType.Long) 339 | { 340 | vitem.Data = BitConverter.ToInt64(buf, 0).ToString(); 341 | vitem.Image = numbersImageSource; 342 | } 343 | else 344 | { 345 | vitem.Data = BitConverter.ToString(buf); 346 | vitem.Image = numbersImageSource; 347 | } 348 | 349 | return vitem; 350 | })); 351 | 352 | foreach (var value in valuerange) 353 | ValueSource.Add(value); 354 | } 355 | } 356 | } 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /Regedit/Regedit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x86 7 | {1DFB2ADA-6291-4EF2-8A18-761673A88BC7} 8 | AppContainerExe 9 | Properties 10 | Regedit 11 | Regedit 12 | en-US 13 | UAP 14 | 10.0.22000.0 15 | 10.0.15063.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | true 20 | True 21 | False 22 | Regedit_TemporaryKey.pfx 23 | SHA256 24 | True 25 | True 26 | True 27 | Always 28 | x86|x64|arm 29 | 0 30 | 31 | 32 | enable 33 | preview 34 | 35 | 36 | true 37 | bin\x86\Debug\ 38 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 39 | ;2008 40 | full 41 | x86 42 | false 43 | prompt 44 | true 45 | 46 | 47 | bin\x86\Release\ 48 | TRACE;NETFX_CORE;WINDOWS_UWP 49 | true 50 | ;2008 51 | pdbonly 52 | x86 53 | false 54 | prompt 55 | true 56 | true 57 | 58 | 59 | true 60 | bin\ARM\Debug\ 61 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 62 | ;2008 63 | full 64 | ARM 65 | false 66 | prompt 67 | true 68 | 69 | 70 | bin\ARM\Release\ 71 | TRACE;NETFX_CORE;WINDOWS_UWP 72 | true 73 | ;2008 74 | pdbonly 75 | ARM 76 | false 77 | prompt 78 | true 79 | true 80 | 81 | 82 | true 83 | bin\ARM64\Debug\ 84 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 85 | ;2008 86 | full 87 | ARM64 88 | false 89 | prompt 90 | true 91 | true 92 | 93 | 94 | bin\ARM64\Release\ 95 | TRACE;NETFX_CORE;WINDOWS_UWP 96 | true 97 | ;2008 98 | pdbonly 99 | ARM64 100 | false 101 | prompt 102 | true 103 | true 104 | 105 | 106 | true 107 | bin\x64\Debug\ 108 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 109 | ;2008 110 | full 111 | x64 112 | false 113 | prompt 114 | true 115 | 116 | 117 | bin\x64\Release\ 118 | TRACE;NETFX_CORE;WINDOWS_UWP 119 | true 120 | ;2008 121 | pdbonly 122 | x64 123 | false 124 | prompt 125 | true 126 | true 127 | 128 | 129 | PackageReference 130 | 131 | 132 | 133 | AboutContentDialog.xaml 134 | 135 | 136 | App.xaml 137 | 138 | 139 | TitlebarControl.xaml 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | MainPage.xaml 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | UniversalTreeView.xaml 158 | 159 | 160 | 161 | 162 | Designer 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | MSBuild:Compile 227 | Designer 228 | 229 | 230 | Designer 231 | MSBuild:Compile 232 | 233 | 234 | MSBuild:Compile 235 | Designer 236 | 237 | 238 | MSBuild:Compile 239 | Designer 240 | 241 | 242 | MSBuild:Compile 243 | Designer 244 | 245 | 246 | Designer 247 | MSBuild:Compile 248 | 249 | 250 | 251 | 252 | 6.2.12 253 | 254 | 255 | 7.0.2 256 | 257 | 258 | 2.8.0-prerelease.210927001 259 | 260 | 261 | 262 | 263 | {84a7225c-2daf-410d-ab85-282ab220a89f} 264 | RegistryRT 265 | 266 | 267 | {94560d69-a345-4e44-b897-eaa2b0e23238} 268 | TreeViewControl 269 | 270 | 271 | 272 | 273 | 274 | 275 | 14.0 276 | 277 | 278 | 285 | --------------------------------------------------------------------------------