From b217ef6767ab2dd1d88f9ac94e08d88d7e31013b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E6=80=A1=E9=A3=9E?= <363301617@qq.com> Date: Sun, 8 Dec 2024 23:08:29 +0800 Subject: [PATCH] Add Context menu item layout Add Context menu item layout --- .../Strings/ContextMenuManager.en-us.restext | 4 +- .../Strings/ContextMenuManager.restext | 4 +- .../ContextMenuManager.zh-hans.restext | 4 +- .../Views/Pages/ContextMenuManager.xaml | 59 ++++++++++++ .../Views/Pages/ContextMenuManager.xaml.cs | 89 ++++++++++++++++--- .../PInvoke/Kernel32/Kernel32Library.cs | 16 +++- 6 files changed, 162 insertions(+), 14 deletions(-) diff --git a/WindowsTools/Strings/ContextMenuManager.en-us.restext b/WindowsTools/Strings/ContextMenuManager.en-us.restext index 0cb52e1..cff24d4 100644 --- a/WindowsTools/Strings/ContextMenuManager.en-us.restext +++ b/WindowsTools/Strings/ContextMenuManager.en-us.restext @@ -6,6 +6,8 @@ LearnContextMenuManager=Learn right-click menu management LearnCustomRightClickMenu=Learn about customizing the right-click menu LoadingContextMenuInformation=Loading right-click menu information, please wait... OpenPackagePathToolTip=Open the app installation folder +Refresh=Refresh SearchAppNamePHText=Search app name SearchEmptyDescription=No matching right-click menu item found -Refresh=Refresh +SelectedToolTip=Selected +UnSelectedToolTip=Unselected \ No newline at end of file diff --git a/WindowsTools/Strings/ContextMenuManager.restext b/WindowsTools/Strings/ContextMenuManager.restext index 0cb52e1..a1267e7 100644 --- a/WindowsTools/Strings/ContextMenuManager.restext +++ b/WindowsTools/Strings/ContextMenuManager.restext @@ -6,6 +6,8 @@ LearnContextMenuManager=Learn right-click menu management LearnCustomRightClickMenu=Learn about customizing the right-click menu LoadingContextMenuInformation=Loading right-click menu information, please wait... OpenPackagePathToolTip=Open the app installation folder +Refresh=Refresh SearchAppNamePHText=Search app name SearchEmptyDescription=No matching right-click menu item found -Refresh=Refresh +SelectedToolTip=Selected +UnSelectedToolTip=Unselected diff --git a/WindowsTools/Strings/ContextMenuManager.zh-hans.restext b/WindowsTools/Strings/ContextMenuManager.zh-hans.restext index 1ffaf39..f1a364b 100644 --- a/WindowsTools/Strings/ContextMenuManager.zh-hans.restext +++ b/WindowsTools/Strings/ContextMenuManager.zh-hans.restext @@ -6,6 +6,8 @@ LearnContextMenuManager=了解右键菜单管理 LearnCustomRightClickMenu=了解自定义右键菜单 LoadingContextMenuInformation=正在加载右键菜单信息中,请稍候... OpenPackagePathToolTip=打开应用安装目录 +Refresh=刷新 SearchAppNamePHText=搜索应用名称 SearchEmptyDescription=没有搜索到复合的右键菜单项 -Refresh=刷新 +SelectedToolTip=已选择 +UnSelectedToolTip=未选择 \ No newline at end of file diff --git a/WindowsTools/Views/Pages/ContextMenuManager.xaml b/WindowsTools/Views/Pages/ContextMenuManager.xaml index b74b449..17b2c46 100644 --- a/WindowsTools/Views/Pages/ContextMenuManager.xaml +++ b/WindowsTools/Views/Pages/ContextMenuManager.xaml @@ -12,6 +12,11 @@ NavigationCacheMode="Enabled" mc:Ignorable="d"> + + + + + @@ -292,6 +297,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WindowsTools/Views/Pages/ContextMenuManager.xaml.cs b/WindowsTools/Views/Pages/ContextMenuManager.xaml.cs index 178734c..7e4b5e9 100644 --- a/WindowsTools/Views/Pages/ContextMenuManager.xaml.cs +++ b/WindowsTools/Views/Pages/ContextMenuManager.xaml.cs @@ -6,12 +6,18 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; using WindowsTools.Models; using WindowsTools.Services.Root; +using WindowsTools.WindowsAPI.PInvoke.Kernel32; + +// 抑制 CA1822 警告 +#pragma warning disable CA1822 namespace WindowsTools.Views.Pages { @@ -81,6 +87,33 @@ public ContextMenuManagerPage() InitializeComponent(); } + /// + /// 打开应用包路径 + /// + private void OnOpenPackagePathExecuteRequested(XamlUICommand sender, ExecuteRequestedEventArgs args) + { + string path = args.Parameter as string; + + Task.Run(() => + { + try + { + Process.Start(path); + } + catch (Exception e) + { + LogService.WriteLog(EventLevel.Error, "Open package path failed", e); + } + }); + } + + /// + /// 点击复选框时使保存按钮处于可选状态 + /// + private void OnCheckExecuteRequested(XamlUICommand sender, ExecuteRequestedEventArgs args) + { + } + #region 第一部分:右键菜单管理页面——挂载的事件 /// @@ -91,7 +124,17 @@ private async void OnLoaded(object sender, RoutedEventArgs args) if (!isInitialized) { isInitialized = true; - await Task.Delay(500); + ContextMenuCollection.Clear(); + List contextMenuList = await Task.Run(async () => + { + await Task.Delay(500); + List contextMenuList = GetContextMenuList(); + return contextMenuList; + }); + foreach (ContextMenuModel contextMenuItem in contextMenuList) + { + ContextMenuCollection.Add(contextMenuItem); + } IsLoadCompleted = true; } } @@ -149,7 +192,12 @@ private void OnSerachAppNameTextChanged(object sender, AutoSuggestBoxTextChanged private async void OnRefreshClicked(object sender, RoutedEventArgs args) { IsLoadCompleted = false; - await Task.Delay(500); + ContextMenuCollection.Clear(); + List contextMenuList = await Task.Run(GetContextMenuList); + foreach (ContextMenuModel contextMenuItem in contextMenuList) + { + ContextMenuCollection.Add(contextMenuItem); + } IsLoadCompleted = true; } @@ -161,6 +209,7 @@ private async void OnRefreshClicked(object sender, RoutedEventArgs args) private List GetContextMenuList() { List contextMenuList = []; + List> blockedList = GetBlockedClsidList(); try { @@ -192,11 +241,13 @@ private List GetContextMenuList() { int serverId = Convert.ToInt32(clsidKey.GetValue("ServerId", 0)); int threading = Convert.ToInt32(clsidKey.GetValue("Threading", 0)); + bool isBlocked = blockedList.Any(item => item.Key.Equals(clsid)); contextMenuItemList.Add(new ContextMenuItemModel() { Clsid = clsid, DllPath = dllPath, + IsEnabled = !isBlocked, ThreadingMode = threading switch { 0 => ApartmentState.STA, @@ -207,25 +258,37 @@ private List GetContextMenuList() } } - classKey.Close(); - classKey.Dispose(); + clsidKey.Close(); + clsidKey.Dispose(); } } + int length = 0; + string packagePath = string.Empty; + + if (Kernel32Library.GetPackagePathByFullName(packageFullName, ref length, null) is 122) + { + StringBuilder packagePathBuilder = new(length + 1); + int result = Kernel32Library.GetPackagePathByFullName(packageFullName, ref length, packagePathBuilder); + packagePath = packagePathBuilder.ToString(); + } + contextMenuList.Add(new() { + PackageDisplayName = string.Empty, PackageFullName = packageFullName, + PackagePath = packagePath, ContextMenuItemCollection = new(contextMenuItemList) }); - } - classKey.Close(); - classKey.Dispose(); + classKey.Close(); + classKey.Dispose(); + } } - } - packageListKey.Close(); - packageListKey.Dispose(); + packageListKey.Close(); + packageListKey.Dispose(); + } } catch (Exception e) { @@ -257,6 +320,9 @@ private List> GetBlockedClsidList() blockClsidList.Add(new KeyValuePair(clsid, Registry.LocalMachine.ToString())); } } + + blockKey.Close(); + blockKey.Dispose(); } } catch (Exception e) @@ -279,6 +345,9 @@ private List> GetBlockedClsidList() blockClsidList.Add(new KeyValuePair(clsid, Registry.CurrentUser.ToString())); } } + + blockKey.Close(); + blockKey.Dispose(); } } catch (Exception e) diff --git a/WindowsTools/WindowsAPI/PInvoke/Kernel32/Kernel32Library.cs b/WindowsTools/WindowsAPI/PInvoke/Kernel32/Kernel32Library.cs index a832578..75fe628 100644 --- a/WindowsTools/WindowsAPI/PInvoke/Kernel32/Kernel32Library.cs +++ b/WindowsTools/WindowsAPI/PInvoke/Kernel32/Kernel32Library.cs @@ -1,4 +1,5 @@ -using System.Runtime.InteropServices; +using System; +using System.Runtime.InteropServices; using System.Text; // 抑制 CA1401 警告 @@ -33,6 +34,19 @@ public static class Kernel32Library [DllImport(Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetCurrentPackageFamilyName", PreserveSig = true, SetLastError = false)] public static extern int GetCurrentPackageFamilyName(ref int packageFamilyNameLength, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder packageFamilyName); + /// + /// 获取指定包的路径。 + /// + /// 包的全名。 + /// + /// 指向包含包路径字符串中 WCHAR) 字符数 (的变量的指针,其中包含 null 终止符。 + /// 首先,将 NULL 传递给 路径 以获取字符数。 使用此数字为 路径分配内存空间。 然后传递此内存空间的地址以填充 路径。 + /// + /// 指向接收包路径字符串(包括 null 终止符)的内存空间的指针。 + /// 如果函数成功,则返回 ERROR_SUCCESS。 否则,函数将返回错误代码。 + [DllImport(Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetPackagePathByFullName", PreserveSig = true, SetLastError = false)] + public static extern int GetPackagePathByFullName([MarshalAs(UnmanagedType.LPWStr)] string packageFullName, ref int pathLength, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path); + /// /// 检索系统的电源状态。 状态指示系统是使用交流还是直流电源运行,电池当前是否正在充电,剩余的电池使用时间,以及节电模式是打开还是关闭。 ///