├── .gitattributes ├── .gitignore ├── ContextMenuManager.sln ├── ContextMenuManager ├── App.config ├── BluePointLilac.Controls │ ├── BackupDialog.cs │ ├── DownloadDialog.cs │ ├── IconDialog.cs │ ├── InputDialog.cs │ ├── MyCheckBox.cs │ ├── MyListBox.cs │ ├── MyMainForm.cs │ ├── MySideBar.cs │ ├── MyStatusBar.cs │ ├── MyToolBar.cs │ ├── PictureButton.cs │ ├── ReadOnlyTextBox.cs │ ├── ResizeLimitedForm.cs │ ├── SelectDialog.cs │ └── UAWebClient.cs ├── BluePointLilac.Methods │ ├── ComboBoxExtension.cs │ ├── ControlExtension.cs │ ├── DirectoryEx.cs │ ├── ElevatedFileDroper.cs │ ├── EncodingType.cs │ ├── ExternalProgram.cs │ ├── FileExtension.cs │ ├── FormExtension.cs │ ├── GuidEx.cs │ ├── HighDpi.cs │ ├── ImageExtension.cs │ ├── IniReader.cs │ ├── IniWriter.cs │ ├── MessageBoxEx.cs │ ├── RegTrustedInstaller.cs │ ├── RegistryEx.cs │ ├── ResourceIcon.cs │ ├── ResourceString.cs │ ├── RichTextBoxExtension.cs │ ├── ShellLink.cs │ ├── SingleInstance.cs │ ├── StringExtension.cs │ ├── TextBoxExtension.cs │ ├── ToolTipBox.cs │ └── WinOsVersion.cs ├── ContextMenuManager.csproj ├── Controls │ ├── AppSettingBox.cs │ ├── BackupListBox.cs │ ├── DetailedEditDialog.cs │ ├── DetailedEditList.cs │ ├── DictionariesBox.cs │ ├── DonateBox.cs │ ├── EnhanceMenuList.cs │ ├── EnhanceMenusDialog.cs │ ├── EnhanceMenusItem.cs │ ├── ExplorerRestarter.cs │ ├── FileExtensionDialog.cs │ ├── FoldSubItem.cs │ ├── GuidBlockedItem.cs │ ├── GuidBlockedList.cs │ ├── IEItem.cs │ ├── IEList.cs │ ├── Interfaces │ │ ├── IBtnDeleteItem.cs │ │ ├── IBtnMoveUpDownItem.cs │ │ ├── IBtnShowMenuItem.cs │ │ ├── IChkVisibleItem.cs │ │ ├── IProtectOpenItem.cs │ │ ├── ITsiAdministratorItem.cs │ │ ├── ITsiCommandItem.cs │ │ ├── ITsiDeleteItem.cs │ │ ├── ITsiFilePathItem.cs │ │ ├── ITsiGuidItem.cs │ │ ├── ITsiIconItem.cs │ │ ├── ITsiRegExportItem.cs │ │ ├── ITsiRegPathItem.cs │ │ ├── ITsiRestoreItem.cs │ │ ├── ITsiShortcutCommandItem.cs │ │ ├── ITsiTextItem.cs │ │ └── ITsiWebSearchItem.cs │ ├── LanguagesBox.cs │ ├── NewIEDialog.cs │ ├── NewItem.cs │ ├── NewItemForm.cs │ ├── NewLnkFileDialog.cs │ ├── NewOpenWithDialog.cs │ ├── NewShellDialog.cs │ ├── OpenWithItem.cs │ ├── OpenWithList.cs │ ├── RComboBox.cs │ ├── RForm.cs │ ├── RToolStripMenuItem.cs │ ├── RestoreItem.cs │ ├── RestoreListDialog.cs │ ├── RuleItem.cs │ ├── SendToItem.cs │ ├── SendToList.cs │ ├── ShellExItem.cs │ ├── ShellExecuteDialog.cs │ ├── ShellItem.cs │ ├── ShellList.cs │ ├── ShellNewItem.cs │ ├── ShellNewList.cs │ ├── ShellStoreDialog.cs │ ├── ShellSubMenuDialog.cs │ ├── SubItemsForm.cs │ ├── SwitchDicList.cs │ ├── UwpModeItem.cs │ ├── WinXGroupItem.cs │ ├── WinXItem.cs │ └── WinXList.cs ├── MainForm.cs ├── Methods │ ├── AppConfig.cs │ ├── AppImage.cs │ ├── AppMessageBox.cs │ ├── AppString.cs │ ├── BackupHelper.cs │ ├── DesktopIni.cs │ ├── GuidInfo.cs │ ├── ObjectPath.cs │ ├── Updater.cs │ ├── UwpHelper.cs │ ├── WinXHasher.cs │ └── XmlDicHelper.cs ├── Program.cs └── Properties │ ├── App.manifest │ ├── AppIcon.ico │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Resources │ ├── Images │ │ ├── About.png │ │ ├── Add.png │ │ ├── AddExisting.png │ │ ├── AddSeparator.png │ │ ├── BackupItem.png │ │ ├── CheckUpdate.png │ │ ├── ContextMenuStyle.png │ │ ├── Custom.png │ │ ├── Delete.png │ │ ├── Donate.png │ │ ├── DownLoad.png │ │ ├── Enhance.png │ │ ├── Home.png │ │ ├── Jump.png │ │ ├── MicrosoftStore.png │ │ ├── NewFolder.png │ │ ├── NewItem.png │ │ ├── Open.png │ │ ├── Refresh.png │ │ ├── Select.png │ │ ├── Setting.png │ │ ├── Sort.png │ │ ├── Star.png │ │ ├── SubItems.png │ │ ├── Translate.png │ │ ├── Type.png │ │ ├── Up.png │ │ ├── User.png │ │ └── Web.png │ ├── ShellNew │ │ ├── 0.c │ │ ├── 0.html │ │ ├── 0.rar │ │ ├── 0.reg │ │ ├── 0.rtf │ │ ├── 0.xlsx │ │ ├── 0.xml │ │ └── 0.zip │ └── Texts │ │ ├── AppLanguageDic.ini │ │ ├── DetailedEditDic.xml │ │ ├── EnhanceMenusDic.xml │ │ ├── GuidInfosDic.ini │ │ └── UwpModeItemsDic.xml │ ├── Settings.Designer.cs │ └── Settings.settings ├── Donate.md ├── LICENSE ├── Logo └── Logo.png ├── README-en.md ├── README.md ├── Screenshot ├── AppImage-dark.png ├── AppImage.png ├── Screenshot-dark.png ├── Screenshot-en-dark.png ├── Screenshot-en.png └── Screenshot.png └── languages ├── ar-DZ عربية ├── de-DE.ini ├── en-US.ini ├── ja-JP.ini ├── ko-KR.ini ├── pt-BR.ini ├── ru-RU.ini ├── zh-CN.ini └── zh-TW.ini /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /ContextMenuManager.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35527.113 d17.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContextMenuManager", "ContextMenuManager\ContextMenuManager.csproj", "{EF7E60E9-3565-42BA-AFB3-7FE73A1B011C}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CE0AD55A-5ABF-40A7-931E-FC04B0FFC6FA}" 9 | ProjectSection(SolutionItems) = preProject 10 | .gitattributes = .gitattributes 11 | .gitignore = .gitignore 12 | Screenshot\AppImage.png = Screenshot\AppImage.png 13 | Donate.md = Donate.md 14 | LICENSE = LICENSE 15 | Logo\Logo.png = Logo\Logo.png 16 | Logo\Logo2.png = Logo\Logo2.png 17 | README-en.md = README-en.md 18 | README.md = README.md 19 | Screenshot\Screenshot-en.png = Screenshot\Screenshot-en.png 20 | Screenshot\Screenshot.png = Screenshot\Screenshot.png 21 | EndProjectSection 22 | EndProject 23 | Global 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|Any CPU = Debug|Any CPU 26 | Release|Any CPU = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {EF7E60E9-3565-42BA-AFB3-7FE73A1B011C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {EF7E60E9-3565-42BA-AFB3-7FE73A1B011C}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {EF7E60E9-3565-42BA-AFB3-7FE73A1B011C}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {EF7E60E9-3565-42BA-AFB3-7FE73A1B011C}.Release|Any CPU.Build.0 = Release|Any CPU 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | GlobalSection(ExtensibilityGlobals) = postSolution 38 | SolutionGuid = {A0E97C81-86B8-4360-8251-DF6FD4494EDA} 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /ContextMenuManager/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/DownloadDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.IO; 6 | using System.Windows.Forms; 7 | 8 | namespace BluePointLilac.Controls 9 | { 10 | sealed class DownloadDialog : CommonDialog 11 | { 12 | public string Text { get; set; } 13 | public string Url { get; set; } 14 | public string FilePath { get; set; } 15 | public override void Reset() { } 16 | 17 | protected override bool RunDialog(IntPtr hwndOwner) 18 | { 19 | using(Process process = Process.GetCurrentProcess()) 20 | using(DownloadForm frm = new DownloadForm()) 21 | { 22 | frm.Url = Url; 23 | frm.Text = Text; 24 | frm.FilePath = FilePath; 25 | return frm.ShowDialog() == DialogResult.OK; 26 | } 27 | } 28 | 29 | sealed class DownloadForm : RForm 30 | { 31 | public DownloadForm() 32 | { 33 | SuspendLayout(); 34 | Font = SystemFonts.MessageBoxFont; 35 | FormBorderStyle = FormBorderStyle.FixedSingle; 36 | MinimizeBox = MaximizeBox = ShowInTaskbar = false; 37 | Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); 38 | Controls.AddRange(new Control[] { pgbDownload, btnCancel }); 39 | Load += (sender, e) => DownloadFile(Url, FilePath); 40 | InitializeComponents(); 41 | ResumeLayout(); 42 | InitTheme(); 43 | } 44 | 45 | readonly ProgressBar pgbDownload = new ProgressBar 46 | { 47 | Width = 200.DpiZoom(), 48 | Maximum = 100 49 | }; 50 | readonly Button btnCancel = new Button 51 | { 52 | DialogResult = DialogResult.Cancel, 53 | Text = ResourceString.Cancel, 54 | AutoSize = true 55 | }; 56 | 57 | public string Url { get; set; } 58 | public string FilePath { get; set; } 59 | 60 | private void InitializeComponents() 61 | { 62 | int a = 20.DpiZoom(); 63 | pgbDownload.Left = pgbDownload.Top = btnCancel.Top = a; 64 | pgbDownload.Height = btnCancel.Height; 65 | btnCancel.Left = pgbDownload.Right + a; 66 | ClientSize = new Size(btnCancel.Right + a, btnCancel.Bottom + a); 67 | } 68 | 69 | private void DownloadFile(string url, string filePath) 70 | { 71 | try 72 | { 73 | using(UAWebClient client = new UAWebClient()) 74 | { 75 | client.DownloadProgressChanged += (sender, e) => 76 | { 77 | int value = e.ProgressPercentage; 78 | Text = $"Downloading: {value}%"; 79 | pgbDownload.Value = value; 80 | if(DialogResult == DialogResult.Cancel) 81 | { 82 | client.CancelAsync(); 83 | File.Delete(FilePath); 84 | } 85 | }; 86 | client.DownloadFileCompleted += (sender, e) => 87 | { 88 | DialogResult = DialogResult.OK; 89 | }; 90 | client.DownloadFileAsync(new Uri(url), filePath); 91 | } 92 | } 93 | catch(Exception e) 94 | { 95 | MessageBox.Show(e.Message, Text, MessageBoxButtons.OK, MessageBoxIcon.Warning); 96 | DialogResult = DialogResult.Cancel; 97 | } 98 | } 99 | 100 | protected override void OnLoad(EventArgs e) 101 | { 102 | if(Owner == null && Form.ActiveForm != this) Owner = Form.ActiveForm; 103 | if(Owner == null) StartPosition = FormStartPosition.CenterScreen; 104 | else 105 | { 106 | TopMost = Owner.TopMost; 107 | StartPosition = FormStartPosition.CenterParent; 108 | } 109 | base.OnLoad(e); 110 | } 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/IconDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | using System.Windows.Forms; 5 | 6 | namespace BluePointLilac.Controls 7 | { 8 | public sealed class IconDialog : CommonDialog 9 | { 10 | [DllImport("shell32.dll", CharSet = CharSet.Unicode, EntryPoint = "#62", SetLastError = true)] 11 | private static extern bool PickIconDlg(IntPtr hWnd, StringBuilder pszFileName, int cchFileNameMax, ref int pnIconIndex); 12 | 13 | private const int MAXLENGTH = 260; 14 | private int iconIndex; 15 | public int IconIndex { get => iconIndex; set => iconIndex = value; } 16 | public string IconPath { get; set; } 17 | 18 | public override void Reset() { } 19 | 20 | protected override bool RunDialog(IntPtr hwndOwner) 21 | { 22 | StringBuilder sb = new StringBuilder(IconPath, MAXLENGTH); 23 | bool flag = PickIconDlg(hwndOwner, sb, MAXLENGTH, ref iconIndex); 24 | IconPath = flag ? sb.ToString() : null; 25 | return flag; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/InputDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | namespace BluePointLilac.Controls 7 | { 8 | public sealed class InputDialog : CommonDialog 9 | { 10 | /// 输入对话框标题 11 | public string Title { get; set; } = Application.ProductName; 12 | /// 输入对话框文本框文本 13 | public string Text { get; set; } 14 | public Size Size { get; set; } 15 | 16 | public override void Reset() { } 17 | 18 | protected override bool RunDialog(IntPtr hwndOwner) 19 | { 20 | using(InputBox frm = new InputBox()) 21 | { 22 | frm.Text = Title; 23 | frm.InputedText = Text; 24 | frm.Size = Size; 25 | if (Control.FromHandle(hwndOwner) is Form owner) frm.TopMost = owner.TopMost; 26 | bool flag = frm.ShowDialog() == DialogResult.OK; 27 | Text = flag ? frm.InputedText : null; 28 | return flag; 29 | } 30 | } 31 | 32 | sealed class InputBox : RForm 33 | { 34 | public InputBox() 35 | { 36 | AcceptButton = btnOK; 37 | CancelButton = btnCancel; 38 | Font = SystemFonts.MessageBoxFont; 39 | SizeGripStyle = SizeGripStyle.Hide; 40 | StartPosition = FormStartPosition.CenterParent; 41 | MaximizeBox = MinimizeBox = ShowIcon = ShowInTaskbar = false; 42 | Controls.AddRange(new Control[] { txtInput, btnOK, btnCancel }); 43 | txtInput.Font = new Font(txtInput.Font.FontFamily, txtInput.Font.Size + 2F); 44 | txtInput.CanResizeFont(); 45 | InitializeComponents(); 46 | InitTheme(); 47 | } 48 | 49 | public string InputedText 50 | { 51 | get => txtInput.Text; 52 | set => txtInput.Text = value; 53 | } 54 | 55 | readonly TextBox txtInput = new TextBox 56 | { 57 | Font = SystemFonts.MenuFont, 58 | ScrollBars = ScrollBars.Vertical, 59 | Multiline = true 60 | }; 61 | readonly Button btnOK = new Button 62 | { 63 | Anchor = AnchorStyles.Bottom | AnchorStyles.Right, 64 | DialogResult = DialogResult.OK, 65 | Text = ResourceString.OK, 66 | AutoSize = true 67 | }; 68 | readonly Button btnCancel = new Button 69 | { 70 | Anchor = AnchorStyles.Bottom | AnchorStyles.Right, 71 | DialogResult = DialogResult.Cancel, 72 | Text = ResourceString.Cancel, 73 | AutoSize = true 74 | }; 75 | 76 | private void InitializeComponents() 77 | { 78 | SuspendLayout(); 79 | int a = 20.DpiZoom(); 80 | txtInput.Location = new Point(a, a); 81 | txtInput.Size = new Size(340, 24).DpiZoom(); 82 | ClientSize = new Size(txtInput.Width + a * 2, txtInput.Height + btnOK.Height + a * 3); 83 | btnCancel.Top = btnOK.Top = txtInput.Bottom + a; 84 | btnCancel.Left = txtInput.Right - btnCancel.Width; 85 | btnOK.Left = btnCancel.Left - btnOK.Width - a; 86 | ResumeLayout(); 87 | MinimumSize = Size; 88 | Resize += (sender, e) => 89 | { 90 | txtInput.Width = ClientSize.Width - 2 * a; 91 | txtInput.Height = btnCancel.Top - 2 * a; 92 | }; 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/MyCheckBox.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | using System.Windows.Forms; 7 | 8 | namespace BluePointLilac.Controls 9 | { 10 | [DefaultProperty("Checked")] 11 | public class MyCheckBox : PictureBox 12 | { 13 | public MyCheckBox() 14 | { 15 | Image = TurnOff; 16 | Cursor = Cursors.Hand; 17 | SizeMode = PictureBoxSizeMode.AutoSize; 18 | } 19 | 20 | private bool? _Checked = null; 21 | public bool Checked 22 | { 23 | get => _Checked == true; 24 | set 25 | { 26 | if (_Checked == value) return; 27 | Image = SwitchImage(value); 28 | if (_Checked == null) 29 | { 30 | _Checked = value; 31 | return; 32 | } 33 | if (PreCheckChanging != null && !PreCheckChanging.Invoke()) 34 | { 35 | Image = SwitchImage(!value); 36 | return; 37 | } 38 | CheckChanging?.Invoke(); 39 | if (PreCheckChanged != null && !PreCheckChanged.Invoke()) 40 | { 41 | Image = SwitchImage(!value); 42 | return; 43 | } 44 | _Checked = value; 45 | CheckChanged?.Invoke(); 46 | } 47 | } 48 | 49 | public Func PreCheckChanging; 50 | public Func PreCheckChanged; 51 | public Action CheckChanging; 52 | public Action CheckChanged; 53 | 54 | public Image TurnOnImage { get; set; } = TurnOn; 55 | public Image TurnOffImage { get; set; } = TurnOff; 56 | 57 | private Image SwitchImage(bool value) => value ? TurnOnImage : TurnOffImage; 58 | 59 | protected override void OnMouseDown(MouseEventArgs e) 60 | { 61 | base.OnMouseDown(e); 62 | if (e.Button == MouseButtons.Left) Checked = !Checked; 63 | } 64 | 65 | private static readonly Image TurnOn = DrawImage(true); 66 | private static readonly Image TurnOff = DrawImage(false); 67 | 68 | private static Image DrawImage(bool value) 69 | { 70 | int w = 80.DpiZoom(), h = 40.DpiZoom(); 71 | int r = h / 2, padding = 4.DpiZoom(); 72 | var bitmap = new Bitmap(w, h); 73 | 74 | using (Graphics g = Graphics.FromImage(bitmap)) 75 | { 76 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 77 | g.CompositingQuality = CompositingQuality.HighQuality; 78 | g.PixelOffsetMode = PixelOffsetMode.HighQuality; 79 | g.SmoothingMode = SmoothingMode.AntiAlias; 80 | 81 | // 背景渐变 82 | using (var bgPath = CreateRoundedRect(0, 0, w, h, r)) 83 | { 84 | Color startColor = value ? MyMainForm.MainColor : Color.FromArgb(200, 200, 200); 85 | Color endColor = value ? Color.FromArgb(160, MyMainForm.MainColor.R, MyMainForm.MainColor.G, MyMainForm.MainColor.B) : 86 | Color.FromArgb(160, 160, 160); 87 | using (var bgBrush = new LinearGradientBrush(new Rectangle(0, 0, w, h), startColor, endColor, 90f)) 88 | { 89 | g.FillPath(bgBrush, bgPath); 90 | } 91 | } 92 | 93 | // 按钮位置计算 94 | int buttonX = value ? w - h + padding : padding; 95 | int buttonY = padding; 96 | 97 | // 按钮绘制(带阴影) 98 | using (var shadowPath = CreateRoundedRect(buttonX - 2, buttonY - 2, h - padding * 2 + 4, h - padding * 2 + 4, (h - padding * 2) / 2)) 99 | using (var shadowBrush = new SolidBrush(Color.FromArgb(50, 0, 0, 0))) 100 | { 101 | g.FillPath(shadowBrush, shadowPath); 102 | } 103 | 104 | using (var buttonPath = CreateRoundedRect(buttonX, buttonY, h - padding * 2, h - padding * 2, (h - padding * 2) / 2)) 105 | { 106 | using (var buttonBrush = new SolidBrush(Color.White)) 107 | { 108 | g.FillPath(buttonBrush, buttonPath); 109 | } 110 | } 111 | 112 | // 高光效果 113 | using (var highlightPath = CreateRoundedRect(buttonX + 2, buttonY + 2, (h - padding * 2) / 2, (h - padding * 2) / 2, (h - padding * 2) / 4)) 114 | using (var highlightBrush = new SolidBrush(Color.FromArgb(100, 255, 255, 255))) 115 | { 116 | g.FillPath(highlightBrush, highlightPath); 117 | } 118 | } 119 | return bitmap; 120 | } 121 | 122 | private static GraphicsPath CreateRoundedRect(float x, float y, float width, float height, float radius) 123 | { 124 | var path = new GraphicsPath(); 125 | path.AddArc(x, y, radius * 2, radius * 2, 180, 90); // 左上角 126 | path.AddArc(x + width - radius * 2, y, radius * 2, radius * 2, 270, 90); // 右上角 127 | path.AddArc(x + width - radius * 2, y + height - radius * 2, radius * 2, radius * 2, 0, 90); // 右下角 128 | path.AddArc(x, y + height - radius * 2, radius * 2, radius * 2, 90, 90); // 左下角 129 | path.CloseFigure(); 130 | return path; 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/MyStatusBar.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | namespace BluePointLilac.Controls 8 | { 9 | public sealed class MyStatusBar : Panel 10 | { 11 | public static readonly string DefaultText = $"Ver: {Application.ProductVersion} {Application.CompanyName}"; 12 | 13 | public MyStatusBar() 14 | { 15 | Text = DefaultText; 16 | Height = 30.DpiZoom(); 17 | Dock = DockStyle.Bottom; 18 | Font = SystemFonts.StatusFont; 19 | BackColor = MyMainForm.ButtonMain; 20 | ForeColor = MyMainForm.FormFore; 21 | } 22 | 23 | [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] 24 | public override string Text { get => base.Text; set => base.Text = value; } 25 | 26 | protected override void OnPaint(PaintEventArgs e) 27 | { 28 | base.OnPaint(e); 29 | string txt = Text; 30 | int left = Height / 3; 31 | for(int i = Text.Length - 1; i >= 0; i--) 32 | { 33 | Size size = TextRenderer.MeasureText(txt, Font); 34 | if(size.Width < ClientSize.Width - 2 * left) 35 | { 36 | using(Brush brush = new SolidBrush(ForeColor)) 37 | { 38 | int top = (Height - size.Height) / 2; 39 | e.Graphics.Clear(BackColor); 40 | e.Graphics.DrawString(txt, Font, brush, left, top); 41 | break; 42 | } 43 | } 44 | txt = Text.Substring(0, i) + "..."; 45 | } 46 | } 47 | 48 | protected override void OnResize(EventArgs e) 49 | { 50 | base.OnResize(e); Refresh(); 51 | } 52 | protected override void OnTextChanged(EventArgs e) 53 | { 54 | base.OnTextChanged(e); Refresh(); 55 | } 56 | protected override void OnFontChanged(EventArgs e) 57 | { 58 | base.OnFontChanged(e); Refresh(); 59 | } 60 | protected override void OnForeColorChanged(EventArgs e) 61 | { 62 | base.OnForeColorChanged(e); Refresh(); 63 | } 64 | protected override void OnBackColorChanged(EventArgs e) 65 | { 66 | base.OnBackColorChanged(e); Refresh(); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/PictureButton.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace BluePointLilac.Controls 6 | { 7 | public class PictureButton : PictureBox 8 | { 9 | public PictureButton(Image image) 10 | { 11 | BaseImage = image; 12 | SizeMode = PictureBoxSizeMode.AutoSize; 13 | Cursor = Cursors.Hand; 14 | } 15 | 16 | private Image baseImage; 17 | public Image BaseImage 18 | { 19 | get => baseImage; 20 | set 21 | { 22 | baseImage = value; 23 | Image = ToolStripRenderer.CreateDisabledImage(value); 24 | } 25 | } 26 | 27 | protected override void OnMouseEnter(EventArgs e) 28 | { 29 | base.OnMouseEnter(e); Image = BaseImage; 30 | } 31 | 32 | protected override void OnMouseLeave(EventArgs e) 33 | { 34 | base.OnMouseLeave(e); 35 | Image = ToolStripRenderer.CreateDisabledImage(BaseImage); 36 | } 37 | 38 | protected override void OnMouseDown(MouseEventArgs e) 39 | { 40 | if(e.Button == MouseButtons.Left) base.OnMouseDown(e); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/ReadOnlyTextBox.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | namespace BluePointLilac.Controls 7 | { 8 | public sealed class ReadOnlyTextBox : TextBox 9 | { 10 | public ReadOnlyTextBox() 11 | { 12 | ReadOnly = true; 13 | Multiline = true; 14 | ShortcutsEnabled = false; 15 | ForeColor = MyMainForm.FormFore; 16 | BackColor = MyMainForm.FormBack; 17 | Font = SystemFonts.MenuFont; 18 | Font = new Font(Font.FontFamily, Font.Size + 1F); 19 | } 20 | 21 | const int WM_SETFOCUS = 0x0007; 22 | const int WM_KILLFOCUS = 0x0008; 23 | protected override void WndProc(ref Message m) 24 | { 25 | switch(m.Msg) 26 | { 27 | case WM_SETFOCUS: 28 | m.Msg = WM_KILLFOCUS; break; 29 | } 30 | base.WndProc(ref m); 31 | } 32 | 33 | private bool firstEnter = true; 34 | 35 | protected override void OnMouseEnter(EventArgs e) 36 | { 37 | base.OnMouseEnter(e); 38 | if(firstEnter) Focus(); 39 | firstEnter = false; 40 | } 41 | } 42 | 43 | public sealed class ReadOnlyRichTextBox : RichTextBox 44 | { 45 | public ReadOnlyRichTextBox() 46 | { 47 | ReadOnly = true; 48 | Dock = DockStyle.Fill; 49 | BorderStyle = BorderStyle.None; 50 | ForeColor = MyMainForm.FormFore; 51 | BackColor = MyMainForm.FormBack; 52 | Font = SystemFonts.MenuFont; 53 | Font = new Font(Font.FontFamily, Font.Size + 1F); 54 | } 55 | 56 | const int WM_SETFOCUS = 0x0007; 57 | const int WM_KILLFOCUS = 0x0008; 58 | 59 | protected override void WndProc(ref Message m) 60 | { 61 | switch(m.Msg) 62 | { 63 | case WM_SETFOCUS: 64 | m.Msg = WM_KILLFOCUS; break; 65 | } 66 | base.WndProc(ref m); 67 | } 68 | 69 | private bool firstEnter = true; 70 | 71 | protected override void OnMouseEnter(EventArgs e) 72 | { 73 | base.OnMouseEnter(e); 74 | if(firstEnter) Focus(); 75 | firstEnter = false; 76 | } 77 | 78 | protected override void OnLinkClicked(LinkClickedEventArgs e) 79 | { 80 | base.OnLinkClicked(e); 81 | ExternalProgram.OpenWebUrl(e.LinkText); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/ResizeLimitedForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace BluePointLilac.Controls 5 | { 6 | /// 限制水平、竖直方向调整大小的窗体 7 | public class ResizeLimitedForm : RForm 8 | { 9 | /// 水平方向可调整大小 10 | public bool HorizontalResizable { get; set; } = true; 11 | 12 | /// 竖直方向可调整大小 13 | public bool VerticalResizable { get; set; } = true; 14 | 15 | public ResizeLimitedForm() 16 | { 17 | InitTheme(); 18 | } 19 | 20 | protected override void WndProc(ref Message m) 21 | { 22 | base.WndProc(ref m); 23 | if(m.Msg == WM_NCHITTEST && WindowState == FormWindowState.Normal) 24 | { 25 | IntPtr hNowhere = new IntPtr((int)HitTest.Nowhere); 26 | switch((HitTest)m.Result) 27 | { 28 | case HitTest.Top: 29 | case HitTest.Bottom: 30 | if(!VerticalResizable) m.Result = hNowhere; 31 | break; 32 | case HitTest.Left: 33 | case HitTest.Right: 34 | if(!HorizontalResizable) m.Result = hNowhere; 35 | break; 36 | case HitTest.TopLeft: 37 | case HitTest.TopRight: 38 | case HitTest.BottomLeft: 39 | case HitTest.BottomRight: 40 | if(!VerticalResizable || !HorizontalResizable) m.Result = hNowhere; 41 | break; 42 | } 43 | } 44 | } 45 | 46 | const int WM_NCHITTEST = 0x84;//光标移动或鼠标按下、释放时的消息 47 | /// 鼠标击中位置 48 | enum HitTest : int 49 | { 50 | Error = -2, 51 | Transparent = -1, 52 | Nowhere = 0, 53 | Client = 1, 54 | TitleBar = 2, 55 | SysMenu = 3, 56 | Size = 4, 57 | GrowBox = 5, 58 | Hscroll = 6, 59 | Vscroll = 7, 60 | MinButton = 8, 61 | MaxButton = 9, 62 | Left = 10, 63 | Right = 11, 64 | Top = 12, 65 | TopLeft = 13, 66 | TopRight = 14, 67 | Bottom = 15, 68 | BottomLeft = 16, 69 | BottomRight = 17, 70 | Border = 18, 71 | Close = 20, 72 | Help = 21 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/SelectDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | namespace BluePointLilac.Controls 7 | { 8 | public class SelectDialog : CommonDialog 9 | { 10 | public string Title { get; set; } 11 | public string Selected { get; set; } 12 | public int SelectedIndex { get; set; } 13 | public string[] Items { get; set; } 14 | public bool CanEdit { get; set; } 15 | 16 | public override void Reset() { } 17 | 18 | protected override bool RunDialog(IntPtr hwndOwner) 19 | { 20 | using(SelectForm frm = new SelectForm()) 21 | { 22 | frm.Text = Title; 23 | frm.Items = Items; 24 | if(Selected != null) frm.Selected = Selected; 25 | else frm.SelectedIndex = SelectedIndex; 26 | frm.CanEdit = CanEdit; 27 | if (Control.FromHandle(hwndOwner) is Form owner) frm.TopMost = owner.TopMost; 28 | bool flag = frm.ShowDialog() == DialogResult.OK; 29 | if(flag) 30 | { 31 | Selected = frm.Selected; 32 | SelectedIndex = frm.SelectedIndex; 33 | } 34 | return flag; 35 | } 36 | } 37 | 38 | sealed class SelectForm : RForm 39 | { 40 | public SelectForm() 41 | { 42 | SuspendLayout(); 43 | AcceptButton = btnOK; 44 | CancelButton = btnCancel; 45 | Font = SystemFonts.MenuFont; 46 | ShowIcon = ShowInTaskbar = false; 47 | MaximizeBox = MinimizeBox = false; 48 | FormBorderStyle = FormBorderStyle.FixedSingle; 49 | StartPosition = FormStartPosition.CenterParent; 50 | InitializeComponents(); 51 | ResumeLayout(); 52 | InitTheme(); 53 | } 54 | 55 | public string Selected 56 | { 57 | get => cmbItems.Text; 58 | set => cmbItems.Text = value; 59 | } 60 | 61 | public string[] Items 62 | { 63 | get 64 | { 65 | string[] value = new string[cmbItems.Items.Count]; 66 | cmbItems.Items.CopyTo(value, 0); 67 | return value; 68 | } 69 | set 70 | { 71 | cmbItems.Items.Clear(); 72 | cmbItems.Items.AddRange(value); 73 | } 74 | } 75 | 76 | public bool CanEdit 77 | { 78 | get => cmbItems.DropDownStyle == ComboBoxStyle.DropDown; 79 | set => cmbItems.DropDownStyle = value ? ComboBoxStyle.DropDown : ComboBoxStyle.DropDownList; 80 | } 81 | 82 | public int SelectedIndex 83 | { 84 | get => cmbItems.SelectedIndex; 85 | set => cmbItems.SelectedIndex = value; 86 | } 87 | 88 | readonly Button btnOK = new Button 89 | { 90 | DialogResult = DialogResult.OK, 91 | Text = ResourceString.OK, 92 | AutoSize = true 93 | }; 94 | readonly Button btnCancel = new Button 95 | { 96 | DialogResult = DialogResult.Cancel, 97 | Text = ResourceString.Cancel, 98 | AutoSize = true 99 | }; 100 | readonly RComboBox cmbItems = new RComboBox 101 | { 102 | AutoCompleteMode = AutoCompleteMode.SuggestAppend, 103 | AutoCompleteSource = AutoCompleteSource.ListItems, 104 | DropDownHeight = 294.DpiZoom(), 105 | ImeMode = ImeMode.Disable 106 | }; 107 | 108 | private void InitializeComponents() 109 | { 110 | Controls.AddRange(new Control[] { cmbItems, btnOK, btnCancel }); 111 | int a = 20.DpiZoom(); 112 | cmbItems.Left = a; 113 | cmbItems.Width = 85.DpiZoom(); 114 | cmbItems.Top = btnOK.Top = btnCancel.Top = a; 115 | btnOK.Left = cmbItems.Right + a; 116 | btnCancel.Left = btnOK.Right + a; 117 | ClientSize = new Size(btnCancel.Right + a, btnCancel.Bottom + a); 118 | cmbItems.AutosizeDropDownWidth(); 119 | } 120 | } 121 | } 122 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Controls/UAWebClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Runtime.Serialization.Json; 5 | using System.Text; 6 | using System.Xml; 7 | 8 | namespace BluePointLilac.Controls 9 | { 10 | public sealed class UAWebClient : WebClient 11 | { 12 | public UAWebClient() 13 | { 14 | //此类主要为了解决访问Github的一些问题 15 | //请求被中止: 未能创建 SSL/TLS 安全通道; 基础连接已经关闭: 发送时发生错误,一般添加TLS12即可 16 | //TLS12------0xc00,TLS11------0x300,TLS------0xc0,SSL------0x30; 17 | ServicePointManager.SecurityProtocol = (SecurityProtocolType)(0xc00 | 0x300 | 0xc0 | 0x30); 18 | //网络传输默认文本编码 UTF-8 19 | Encoding = Encoding.UTF8; 20 | //远程服务器返回错误: (403) 已禁止 21 | //浏览器 F12 console 输入 console.log(navigator.userAgent); 获取 User Agent 22 | Headers.Add("User-Agent", 23 | "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " + 24 | "Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66"); 25 | } 26 | 27 | protected override WebRequest GetWebRequest(Uri address) 28 | { 29 | WebRequest request = base.GetWebRequest(address); 30 | request.Timeout = 6 * 1000; 31 | return request; 32 | } 33 | 34 | /// 获取网页文本 35 | public string GetWebString(string url) 36 | { 37 | try 38 | { 39 | string str = DownloadString(url); 40 | str = str?.Replace("\n", Environment.NewLine);//换行符转换 41 | return str; 42 | } 43 | catch { return null; } 44 | } 45 | 46 | /// 将网络文本写入本地文件 47 | /// 本地文件路径 48 | /// 网络文件Raw路径 49 | public bool WebStringToFile(string filePath, string fileUrl) 50 | { 51 | string contents = GetWebString(fileUrl); 52 | bool flag = contents != null; 53 | if(flag) File.WriteAllText(filePath, contents, Encoding.Unicode); 54 | return flag; 55 | } 56 | 57 | /// 获取网页Json文本并加工为Xml 58 | public XmlDocument GetWebJsonToXml(string url) 59 | { 60 | try 61 | { 62 | byte[] bytes = DownloadData(url); 63 | using(XmlReader xReader = JsonReaderWriterFactory.CreateJsonReader(bytes, XmlDictionaryReaderQuotas.Max)) 64 | { 65 | XmlDocument doc = new XmlDocument(); 66 | doc.Load(xReader); 67 | return doc; 68 | } 69 | } 70 | catch { return null; } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/ComboBoxExtension.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using System; 3 | using System.Windows.Forms; 4 | 5 | namespace BluePointLilac.Methods 6 | { 7 | public static class ComboBoxExtension 8 | { 9 | public static void AutosizeDropDownWidth(this RComboBox box) 10 | { 11 | box.DropDown += (sender, e) => 12 | { 13 | int maxWidth = 0; 14 | foreach(var item in box.Items) 15 | { 16 | maxWidth = Math.Max(maxWidth, TextRenderer.MeasureText(item.ToString(), box.Font).Width); 17 | } 18 | maxWidth = Math.Max(maxWidth, box.Width); 19 | box.DropDownWidth = maxWidth; 20 | }; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/ControlExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows.Forms; 4 | 5 | namespace BluePointLilac.Methods 6 | { 7 | public static class ControlExtension 8 | { 9 | [DllImport("user32.dll")] 10 | private static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 11 | 12 | [DllImport("user32.dll")] 13 | private static extern bool ReleaseCapture(); 14 | 15 | /// 使控件能够移动所属窗体 16 | /// 目标控件 17 | public static void CanMoveForm(this Control ctr) 18 | { 19 | const int WM_NCLBUTTONDOWN = 0xA1; 20 | const int HT_CAPTION = 0x2; 21 | ctr.MouseMove += (sender, e) => 22 | { 23 | if(e.Button != MouseButtons.Left) return; 24 | ReleaseCapture(); 25 | PostMessage(ctr.FindForm().Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0); 26 | }; 27 | } 28 | 29 | [DllImport("user32.dll")] 30 | private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int wndproc); 31 | 32 | [DllImport("user32.dll")] 33 | private static extern int GetWindowLong(IntPtr hWnd, int nIndex); 34 | 35 | /// 通过Win32API禁用/启用目标控件 36 | /// 控件被禁用时仍可更改字体颜色,不需要同时设置ctr.Enabled=false 37 | /// 目标控件 38 | /// 启用为true,禁用为false 39 | public static void SetEnabled(this Control ctr, bool enabled) 40 | { 41 | const int GWL_STYLE = -16; 42 | const int WS_DISABLED = 0x8000000; 43 | int value = GetWindowLong(ctr.Handle, GWL_STYLE); 44 | if(enabled) value &= ~WS_DISABLED; 45 | else value |= WS_DISABLED; 46 | SetWindowLong(ctr.Handle, GWL_STYLE, value); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/DirectoryEx.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace BluePointLilac.Methods 4 | { 5 | public static class DirectoryEx 6 | { 7 | public static void CopyTo(string srcDirPath, string dstDirPath) 8 | { 9 | DirectoryInfo srcDi = new DirectoryInfo(srcDirPath); 10 | DirectoryInfo dstDi = new DirectoryInfo(dstDirPath); 11 | dstDi.Create(); 12 | foreach(FileInfo srcFi in srcDi.GetFiles()) 13 | { 14 | string dstFilePath = $@"{dstDirPath}\{srcFi.Name}"; 15 | srcFi.CopyTo(dstFilePath, true); 16 | } 17 | foreach(DirectoryInfo srcSubDi in srcDi.GetDirectories()) 18 | { 19 | DirectoryInfo dstSubDi = dstDi.CreateSubdirectory(srcSubDi.Name); 20 | CopyTo(srcSubDi.FullName, dstSubDi.FullName); 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/ElevatedFileDroper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Drawing; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Windows.Forms; 7 | 8 | namespace BluePointLilac.Methods 9 | { 10 | /// 代码用途:管理员UAC进程窗口拖放文件 11 | /// 代码来源1:https://zhuanlan.zhihu.com/p/48735364 12 | /// 代码来源2:https://github.com/volschin/sdimager/blob/master/ElevatedDragDropManager.cs 13 | /// 代码作者:雨少主(知乎)、volschin(Github)、蓝点lilac(转载、修改) 14 | /// 调用方法:var droper = new ElevatedFileDroper(control); 15 | /// droper.DragDrop += (sender, e) => MessageBox.Show(droper.DropFilePaths[0]); 16 | /// 备注:此类只能生效一个实例,不能将control.AllowDrop设为true,droper.DragDrop与control.DragDrop不共存 17 | 18 | public sealed class ElevatedFileDroper : IMessageFilter 19 | { 20 | [DllImport("user32.dll", SetLastError = true)] 21 | [return: MarshalAs(UnmanagedType.Bool)] 22 | private static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint message, ChangeFilterAction action, in ChangeFilterStruct pChangeFilterStruct); 23 | 24 | [DllImport("user32.dll", SetLastError = true)] 25 | [return: MarshalAs(UnmanagedType.Bool)] 26 | private static extern bool ChangeWindowMessageFilter(uint msg, ChangeWindowMessageFilterFlags flags); 27 | 28 | [DllImport("shell32.dll", SetLastError = false)] 29 | private static extern void DragAcceptFiles(IntPtr hWnd, bool fAccept); 30 | 31 | [DllImport("shell32.dll", SetLastError = false, CharSet = CharSet.Unicode)] 32 | private static extern uint DragQueryFile(IntPtr hWnd, uint iFile, StringBuilder lpszFile, int cch); 33 | 34 | [DllImport("shell32.dll", SetLastError = false)] 35 | private static extern bool DragQueryPoint(IntPtr hDrop, out Point lppt); 36 | 37 | [DllImport("shell32.dll", SetLastError = false)] 38 | private static extern void DragFinish(IntPtr hDrop); 39 | 40 | [StructLayout(LayoutKind.Sequential)] 41 | struct ChangeFilterStruct 42 | { 43 | public uint CbSize; 44 | public ChangeFilterStatu ExtStatus; 45 | } 46 | 47 | enum ChangeWindowMessageFilterFlags : uint 48 | { 49 | MSGFLT_ADD = 1, 50 | MSGFLT_REMOVE = 2 51 | } 52 | 53 | enum ChangeFilterAction : uint 54 | { 55 | MSGFLT_RESET, 56 | MSGFLT_ALLOW, 57 | MSGFLT_DISALLOW 58 | } 59 | 60 | enum ChangeFilterStatu : uint 61 | { 62 | MSGFLTINFO_NONE, 63 | MSGFLTINFO_ALREADYALLOWED_FORWND, 64 | MSGFLTINFO_ALREADYDISALLOWED_FORWND, 65 | MSGFLTINFO_ALLOWED_HIGHER 66 | } 67 | 68 | const uint WM_COPYGLOBALDATA = 0x0049; 69 | const uint WM_COPYDATA = 0x004A; 70 | const uint WM_DROPFILES = 0x0233; 71 | 72 | public event EventHandler DragDrop; 73 | public string[] DropFilePaths { get; private set; } 74 | public Point DropPoint { get; private set; } 75 | 76 | public ElevatedFileDroper(Control ctr) 77 | { 78 | ctr.AllowDrop = false; 79 | DragAcceptFiles(ctr.Handle, true); 80 | Application.AddMessageFilter(this); 81 | ctr.Disposed += (sender, e) => Application.RemoveMessageFilter(this); 82 | 83 | if(ctr is Form frm) 84 | { 85 | double opacity = frm.Opacity; 86 | frm.Paint += (sender, e) => 87 | { 88 | if(frm.Opacity != opacity) 89 | { 90 | //窗体透明度变化时需要重新注册接受文件拖拽标识符 91 | DragAcceptFiles(ctr.Handle, true); 92 | opacity = frm.Opacity; 93 | } 94 | }; 95 | } 96 | 97 | Version ver = Environment.OSVersion.Version; 98 | bool isVistaOrHigher = ver >= new Version(6, 0); 99 | bool isWin7OrHigher = ver >= new Version(6, 1); 100 | var status = new ChangeFilterStruct { CbSize = 8 }; 101 | if(isVistaOrHigher) 102 | { 103 | foreach(uint msg in new[] { WM_DROPFILES, WM_COPYGLOBALDATA, WM_COPYDATA }) 104 | { 105 | bool error = false; 106 | if(isWin7OrHigher) 107 | { 108 | error = !ChangeWindowMessageFilterEx(ctr.Handle, msg, ChangeFilterAction.MSGFLT_ALLOW, in status); 109 | } 110 | else 111 | { 112 | error = !ChangeWindowMessageFilter(msg, ChangeWindowMessageFilterFlags.MSGFLT_ADD); 113 | } 114 | if(error) throw new Win32Exception(Marshal.GetLastWin32Error()); 115 | } 116 | } 117 | } 118 | 119 | public bool PreFilterMessage(ref Message m) 120 | { 121 | if(m.Msg != WM_DROPFILES) return false; 122 | IntPtr handle = m.WParam; 123 | uint fileCount = DragQueryFile(handle, uint.MaxValue, null, 0); 124 | string[] filePaths = new string[fileCount]; 125 | for(uint i = 0; i < fileCount; i++) 126 | { 127 | StringBuilder sb = new StringBuilder(260); 128 | uint result = DragQueryFile(handle, i, sb, sb.Capacity); 129 | if(result > 0) filePaths[i] = sb.ToString(); 130 | } 131 | DragQueryPoint(handle, out Point point); 132 | DragFinish(handle); 133 | DropPoint = point; 134 | DropFilePaths = filePaths; 135 | DragDrop?.Invoke(this, null); 136 | return true; 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/EncodingType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace BluePointLilac.Methods 7 | { 8 | /* 获取文本文件编码类型 9 | * 代码参考:https://www.cnblogs.com/guyun/p/4262587.html (Napoléon)*/ 10 | public static class EncodingType 11 | { 12 | /// 各种带BOM的编码BOM值 13 | private static readonly Dictionary EncodingBomBytes = new Dictionary 14 | { 15 | { new byte[] { 0xEF, 0xBB, 0xBF }, Encoding.UTF8 }, //UTF-8 EF BB BF 16 | { new byte[] { 0xFF, 0xFE, 0x00, 0x00 }, Encoding.UTF32 }, //UTF-32LE FF FE 00 00 17 | { new byte[] { 0xFF, 0xFE }, Encoding.Unicode }, //UTF-16LE FF FE 18 | { new byte[] { 0xFE, 0xFF }, Encoding.BigEndianUnicode }, //UTF-16BE FE FF 19 | { new byte[] { 0x2B, 0x2F, 0x76 }, Encoding.UTF7 }, //UTF-7 2B 2F 76 20 | { new byte[] { 0x00, 0x00, 0xFE, 0xFF }, new UTF32Encoding(true, true) }, //UTF-32BE 00 00 FE FF 21 | }; 22 | 23 | /// 获取给定的文件的编码类型 24 | /// 文件路径 25 | /// 文件的编码类型 26 | public static Encoding GetType(string filePath) 27 | { 28 | byte[] fs = File.ReadAllBytes(filePath); 29 | foreach(var kv in EncodingBomBytes) 30 | { 31 | if(fs.Length < kv.Key.Length) continue; 32 | int i = -1; 33 | bool flag = kv.Key.All(s => { i++; return s == fs[i]; }); 34 | if(flag) return kv.Value; 35 | } 36 | if(IsUTF8Bytes(fs)) return Encoding.UTF8; //不带BOM的UTF-8 37 | return Encoding.Default; 38 | } 39 | 40 | /// 判断是否是不带 BOM 的 UTF8 格式 41 | /// 42 | private static bool IsUTF8Bytes(byte[] bytes) 43 | { 44 | int count = 1; //计算当前正分析的字符应还有的字节数 45 | for(int i = 0; i < bytes.Length; i++) 46 | { 47 | byte curByte = bytes[i];//当前分析的字节. 48 | if(count == 1) 49 | { 50 | if(curByte >= 0x80) 51 | { 52 | //计算当前字符所占的字节数 53 | //修复了EncodingType内造成en语言下debug错误的问题(算术溢出) 54 | int byteCount = 7; 55 | if (curByte < 0xC0) 56 | { 57 | byteCount = 0; 58 | } 59 | else if (curByte < 0xE0) 60 | { 61 | byteCount = 1; 62 | } 63 | else if (curByte < 0xF0) 64 | { 65 | byteCount = 2; 66 | } 67 | else if (curByte < 0xF8) 68 | { 69 | byteCount = 3; 70 | } 71 | else if (curByte < 0xFC) 72 | { 73 | byteCount = 4; 74 | } 75 | else if (curByte < 0xFE) 76 | { 77 | byteCount = 5; 78 | } 79 | else if (curByte < 0xFF) 80 | { 81 | byteCount = 6; 82 | } 83 | count += byteCount; 84 | /*while (((curByte <<= 1) & 0x80) != 0) 85 | { 86 | count++; 87 | }*/ 88 | //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 89 | if (count == 1 || count > 6) return false; 90 | } 91 | } 92 | else 93 | { 94 | //若是UTF-8 此时第一位必须为1 95 | if((curByte & 0xC0) != 0x80) return false; 96 | else count--; 97 | } 98 | } 99 | //if(count > 1) throw new Exception("非预期的byte格式"); 100 | return true; 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/FileExtension.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace BluePointLilac.Methods 7 | { 8 | public static class FileExtension 9 | { 10 | [Flags] 11 | enum AssocF 12 | { 13 | Init_NoRemapCLSID = 0x1, 14 | Init_ByExeName = 0x2, 15 | Open_ByExeName = 0x2, 16 | Init_DefaultToStar = 0x4, 17 | Init_DefaultToFolder = 0x8, 18 | NoUserSettings = 0x10, 19 | NoTruncate = 0x20, 20 | Verify = 0x40, 21 | RemapRunDll = 0x80, 22 | NoFixUps = 0x100, 23 | IgnoreBaseClass = 0x200 24 | } 25 | 26 | public enum AssocStr 27 | { 28 | Command = 1, 29 | Executable, 30 | FriendlyDocName, 31 | FriendlyAppName, 32 | NoOpen, 33 | ShellNewValue, 34 | DDECommand, 35 | DDEIfExec, 36 | DDEApplication, 37 | DDETopic 38 | } 39 | 40 | [DllImport("shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)] 41 | private static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, ref uint pcchOut); 42 | 43 | public const string FILEEXTSPATH = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts"; 44 | private const string HKCRCLASSES = @"HKEY_CURRENT_USER\SOFTWARE\Classes"; 45 | private const string HKLMCLASSES = @"HKEY_LOCAL_MACHINE\SOFTWARE\Classes"; 46 | 47 | public static string GetExtentionInfo(AssocStr assocStr, string extension) 48 | { 49 | uint pcchOut = 0; 50 | AssocQueryString(AssocF.Verify, assocStr, extension, null, null, ref pcchOut); 51 | StringBuilder pszOut = new StringBuilder((int)pcchOut); 52 | AssocQueryString(AssocF.Verify, assocStr, extension, null, pszOut, ref pcchOut); 53 | return pszOut.ToString(); 54 | } 55 | 56 | public static string GetOpenMode(string extension) 57 | { 58 | if(string.IsNullOrEmpty(extension)) return null; 59 | string mode; 60 | bool CheckMode() 61 | { 62 | if(mode.IsNullOrWhiteSpace()) return false; 63 | if(mode.Length > 255) return false; 64 | if(mode.ToLower().StartsWith(@"applications\")) return false; 65 | using(RegistryKey root = Registry.ClassesRoot) 66 | using(RegistryKey key = root.OpenSubKey(mode)) 67 | { 68 | return key != null; 69 | } 70 | } 71 | mode = Registry.GetValue($@"{FILEEXTSPATH}\{extension}\UserChoice", "ProgId", null)?.ToString(); 72 | if(CheckMode()) return mode; 73 | mode = Registry.GetValue($@"{HKLMCLASSES}\{extension}", "", null)?.ToString(); 74 | if(CheckMode()) return mode; 75 | mode = Registry.GetValue($@"{HKCRCLASSES}\{extension}", "", null)?.ToString(); 76 | if(CheckMode()) return mode; 77 | return null; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/FormExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Windows.Forms; 3 | 4 | namespace BluePointLilac.Methods 5 | { 6 | public static class FormExtension 7 | { 8 | /// 移动窗体时同时移动另一个窗体 9 | /// 主动移动的窗体 10 | /// 同时被移动的窗体 11 | public static void MoveAsMove(this Form frm1, Form frm2) 12 | { 13 | if(frm2 == null) return; 14 | Point pLast = Point.Empty; 15 | frm1.Load += (sender, e) => pLast = frm1.Location; 16 | frm1.LocationChanged += (sender, e) => 17 | { 18 | if(pLast == Point.Empty) return; 19 | frm2.Left += frm1.Left - pLast.X; 20 | frm2.Top += frm1.Top - pLast.Y; 21 | pLast = frm1.Location; 22 | }; 23 | } 24 | 25 | /// 给窗体添加ESC键关闭功能 26 | /// 指定窗口 27 | /// 关闭窗口时的对话框返回值 28 | /// 也可以重写Form的ProcessDialogKey事件, 29 | /// 这个方法更简单,但遍历窗体控件时切记多了一个不可见的关闭按钮 30 | public static void AddEscapeButton(this Form frm, DialogResult dr = DialogResult.Cancel) 31 | { 32 | Button btn = new Button 33 | { 34 | Parent = frm, 35 | Size = Size.Empty, 36 | DialogResult = dr 37 | }; 38 | frm.CancelButton = btn; 39 | frm.Disposed += (sender, e) => btn.Dispose(); 40 | frm.FormClosing += (sender, e) => btn.PerformClick(); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/GuidEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace BluePointLilac.Methods 5 | { 6 | //为兼容.Net Framework 3.5,无法引用Microsoft.CSharp.dll(中的Guid.TryParse)写了这个扩展方法 7 | public static class GuidEx 8 | { 9 | public static bool TryParse(string str, out Guid guid) 10 | { 11 | if(IsGuid(str)) 12 | { 13 | guid = new Guid(str); 14 | return true; 15 | } 16 | else 17 | { 18 | guid = Guid.Empty; 19 | return false; 20 | } 21 | } 22 | 23 | private static readonly Regex GuidRegex = new Regex(@"[A-F0-9]{8}(\-[A-F0-9]{4}){3}\-[A-F0-9]{12}", RegexOptions.IgnoreCase); 24 | 25 | public static bool IsGuid(string str) 26 | { 27 | if(string.IsNullOrEmpty(str)) return false; 28 | if(str.Length == 38 && str.StartsWith("{") && str.EndsWith("}") && GuidRegex.IsMatch(str)) return true; 29 | if(str.Length == 36 && GuidRegex.IsMatch(str)) return true; 30 | return false; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/HighDpi.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Windows; 3 | using System.Windows.Forms; 4 | 5 | namespace BluePointLilac.Methods 6 | { 7 | /// 处理不同DPI缩放比下的像素绘制和字体显示问题 8 | /// 使用此类需要添加引用 PresentationFramework 9 | /// 还应在配置清单App.manifest中启用DPI感知自动缩放 10 | /// Font为矢量类型,Point、Size、Rectangle、Padding等为像素类型。 11 | /// 在不同DPI缩放下,矢量类型等比缩放,像素类型保持不变,故会出现排版显示问题。 12 | /// 解决方案一:项目中所有用到的像素类型实例值都取与缩放比之积,矢量类型不变。 13 | /// 解决方案二:项目中所有用到的矢量类型实例都取与缩放比之商,像素类型不变 14 | public static class HighDpi 15 | { 16 | /// DPI缩放比 17 | public static readonly double DpiScale = Screen.PrimaryScreen.Bounds.Width / SystemParameters.PrimaryScreenWidth; 18 | 19 | public static Point DpiZoom(this Point point) => new Point(DpiZoom(point.X), DpiZoom(point.Y)); 20 | 21 | public static PointF DpiZoom(this PointF point) => new PointF(DpiZoom(point.X), DpiZoom(point.Y)); 22 | 23 | public static Size DpiZoom(this Size size) => new Size(DpiZoom(size.Width), DpiZoom(size.Height)); 24 | 25 | public static SizeF DpiZoom(this SizeF size) => new SizeF(DpiZoom(size.Width), DpiZoom(size.Height)); 26 | 27 | public static Rectangle DpiZoom(this Rectangle r) => new Rectangle(DpiZoom(r.Location), DpiZoom(r.Size)); 28 | 29 | public static RectangleF DpiZoom(this RectangleF r) => new RectangleF(DpiZoom(r.Location), DpiZoom(r.Size)); 30 | 31 | public static Padding DpiZoom(this Padding p) => new Padding(DpiZoom(p.Left), DpiZoom(p.Top), DpiZoom(p.Right), DpiZoom(p.Bottom)); 32 | 33 | public static Font DpiZoom(this Font font) => new Font(font.FontFamily, font.Size / DpiZoom(1F), font.Style); 34 | 35 | public static int DpiZoom(this int num) => (int)(num * DpiScale); 36 | 37 | public static float DpiZoom(this float num) => (float)(num * DpiScale); 38 | 39 | public static double DpiZoom(this double num) => num * DpiScale; 40 | } 41 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/ImageExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Drawing.Drawing2D; 3 | using System.Drawing.Imaging; 4 | 5 | namespace BluePointLilac.Methods 6 | { 7 | public static class ImageExtension 8 | { 9 | public static Image ToTransparent(this Image image, float opacity = 0.5F) 10 | { 11 | Bitmap bitmap = new Bitmap(image.Width, image.Height); 12 | using(Graphics g = Graphics.FromImage(bitmap)) 13 | using(ImageAttributes attributes = new ImageAttributes()) 14 | { 15 | ColorMatrix matrix = new ColorMatrix { Matrix33 = opacity }; 16 | attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); 17 | g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height), 18 | 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); 19 | } 20 | return bitmap; 21 | } 22 | 23 | public static Image ResizeImage(this Image image, int width, int height) 24 | { 25 | //return image.GetThumbnailImage(width, height, null, System.IntPtr.Zero);//质量稍微低一点 26 | if(image.Width == width && image.Height == height) return image; 27 | Bitmap destImage = new Bitmap(width, height); 28 | destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); 29 | using(Graphics g = Graphics.FromImage(destImage)) 30 | { 31 | g.CompositingMode = CompositingMode.SourceCopy; 32 | g.InterpolationMode = InterpolationMode.HighQualityBicubic; 33 | g.CompositingQuality = CompositingQuality.HighQuality; 34 | g.PixelOffsetMode = PixelOffsetMode.HighQuality; 35 | g.SmoothingMode = SmoothingMode.HighQuality; 36 | 37 | using(ImageAttributes attributes = new ImageAttributes()) 38 | { 39 | attributes.SetWrapMode(WrapMode.TileFlipXY); 40 | g.DrawImage(image, new Rectangle(0, 0, width, height), 41 | 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); 42 | } 43 | } 44 | return destImage; 45 | } 46 | 47 | public static Image ResizeImage(this Image image, double scale) 48 | { 49 | if(scale == 1) return image; 50 | int width = (int)(image.Width * scale); 51 | int height = (int)(image.Height * scale); 52 | return image.ResizeImage(width, height); 53 | } 54 | 55 | public static Image ResizeImage(this Image image, Size newSize) 56 | { 57 | if(newSize == image.Size) return image; 58 | return image.ResizeImage(newSize.Width, newSize.Height); 59 | } 60 | 61 | public static Image RotateImage(this Image image, RotateFlipType rotateType) 62 | { 63 | Bitmap bitmap = new Bitmap(image); 64 | bitmap.RotateFlip(rotateType); 65 | return bitmap; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/ResourceString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | namespace BluePointLilac.Methods 6 | { 7 | public static class ResourceString 8 | { 9 | //MSDN文档: https://docs.microsoft.com/windows/win32/api/shlwapi/nf-shlwapi-shloadindirectstring 10 | //提取.pri文件资源: https://docs.microsoft.com/windows/uwp/app-resources/makepri-exe-command-options 11 | //.pri转储.xml资源列表: MakePri.exe dump /if [priPath] /of [xmlPath] 12 | 13 | [DllImport("shlwapi.dll", BestFitMapping = false, CharSet = CharSet.Unicode, 14 | ExactSpelling = true, SetLastError = false, ThrowOnUnmappableChar = true)] 15 | private static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, uint cchOutBuf, IntPtr ppvReserved); 16 | 17 | /// 获取格式为"@[filename],-[strID]"或"@{[packageName]?ms-resource://[resPath]}"的直接字符串 18 | /// 要转换的字符串 19 | /// resStr为Null时返回值为string.Empty; resStr首字符为@但解析失败时返回string.Empty 20 | /// [fileName]:文件路径; [strID]:字符串资源索引; [packageName]:UWP带版本号包名; [resPath]:pri资源路径 21 | public static string GetDirectString(string resStr) 22 | { 23 | StringBuilder outBuff = new StringBuilder(1024); 24 | SHLoadIndirectString(resStr, outBuff, 1024, IntPtr.Zero); 25 | return outBuff.ToString(); 26 | } 27 | 28 | public static readonly string OK = GetDirectString("@shell32.dll,-9752"); 29 | public static readonly string Cancel = GetDirectString("@shell32.dll,-9751"); 30 | } 31 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/SingleInstance.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | 9 | namespace BluePointLilac.Methods 10 | { 11 | public static class SingleInstance 12 | { 13 | [DllImport("user32.dll")] 14 | private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); 15 | 16 | [DllImport("user32.dll")] 17 | private static extern bool SetForegroundWindow(IntPtr hWnd); 18 | 19 | /// 判断单实例程序是否正在运行 20 | /// 若正在运行激活窗口 21 | public static bool IsRunning() 22 | { 23 | using(Process current = Process.GetCurrentProcess()) 24 | { 25 | foreach(Process process in Process.GetProcessesByName(current.ProcessName)) 26 | { 27 | using(process) 28 | { 29 | if(process.Id == current.Id) continue; 30 | if(process.MainModule.FileName == current.MainModule.FileName) 31 | { 32 | const int SW_RESTORE = 9; 33 | ShowWindowAsync(process.MainWindowHandle, SW_RESTORE); 34 | SetForegroundWindow(process.MainWindowHandle); 35 | return true; 36 | } 37 | } 38 | } 39 | return false; 40 | } 41 | } 42 | 43 | /// 重启单实例程序 44 | /// 重启程序时传入参数 45 | /// 用于更新程序的新版本文件路径,为null则为普通重启 46 | public static void Restart(string[] args = null, string updatePath = null) 47 | { 48 | string appPath = Application.ExecutablePath; 49 | string command = appPath; 50 | if(args != null && args.Length > 0) command += "," + string.Join(" ", args); 51 | List contents = new List(); 52 | //vbs命令逐行执行不等待,故加些代码确定上一条命令执行是否完成 53 | contents.AddRange(new[] 54 | { 55 | "On Error Resume Next", 56 | "WScript.Sleep 1000",//等待程序结束 57 | "Dim wsh, fso", 58 | "Set wsh = CreateObject(\"WScript.Shell\")", 59 | "Set fso = CreateObject(\"Scripting.FileSystemObject\")", 60 | }); 61 | 62 | if(File.Exists(updatePath)) 63 | { 64 | contents.AddRange(new[] 65 | { 66 | $"fso.DeleteFile \"{appPath}\"", 67 | $"Do While fso.FileExists(\"{appPath}\")", 68 | "WScript.Sleep 100", 69 | "Loop",//确定文件删除完成 70 | $"fso.MoveFile \"{updatePath}\",\"{appPath}\"",//更新文件 71 | $"Do While fso.FileExists(\"{updatePath}\")",//确定文件已被移动 72 | "WScript.Sleep 100", 73 | $"Loop", 74 | }); 75 | } 76 | contents.AddRange(new[] 77 | { 78 | $"wsh.Run \"{command}\"", 79 | "fso.DeleteFile(WScript.ScriptFullName)",//vbs自删命令 80 | "Set wsh = Nothing", 81 | "Set fso = Nothing", 82 | }); 83 | 84 | string vbsPath = Path.GetTempPath() + Guid.NewGuid() + ".vbs"; 85 | File.WriteAllLines(vbsPath, contents.ToArray(), Encoding.Unicode); 86 | Application.Exit(); 87 | using(Process process = new Process()) 88 | { 89 | process.StartInfo.FileName = "wscript.exe"; 90 | process.StartInfo.Arguments = vbsPath; 91 | process.Start(); 92 | } 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/StringExtension.cs: -------------------------------------------------------------------------------- 1 | namespace BluePointLilac.Methods 2 | { 3 | //为兼容.Net Framework 3.5,无法引用Microsoft.CSharp.dll(中的string.IsNullOrWhiteSpace)写了这个扩展方法 4 | public static class StringExtension 5 | { 6 | public static bool IsNullOrWhiteSpace(this string str) 7 | { 8 | if(string.IsNullOrEmpty(str)) return true; 9 | return str.Trim().Length == 0; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/TextBoxExtension.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Windows.Forms; 3 | 4 | namespace BluePointLilac.Methods 5 | { 6 | public static class TextBoxExtension 7 | { 8 | /// TextBox仿RichTextBox按住Ctrl加鼠标滚轮放缩字体 9 | public static void CanResizeFont(this TextBox box) 10 | { 11 | box.MouseWheel += (sender, e) => 12 | { 13 | if(Control.ModifierKeys != Keys.Control) return; 14 | float size = box.Font.Size; 15 | if(size < 8F && e.Delta < 0) return; 16 | if(size > 40F && e.Delta > 0) return; 17 | box.Font = new Font(box.Font.FontFamily, size + (e.Delta > 0 ? 1F : -1F)); 18 | }; 19 | } 20 | 21 | /// TextBox在文字未超出边界时隐藏滚动条,超出时显示 22 | public static void SetAutoShowScroll(this TextBox box, ScrollBars scrollBars) 23 | { 24 | 25 | void SetScrollVisible() 26 | { 27 | Size szBox = box.ClientSize; 28 | Size szText = TextRenderer.MeasureText(box.Text, box.Font); 29 | if((scrollBars | ScrollBars.Vertical) == ScrollBars.Vertical) 30 | { 31 | if(szText.Height > szBox.Height) 32 | { 33 | box.ScrollBars = scrollBars | ScrollBars.Vertical; 34 | } 35 | else 36 | { 37 | box.ScrollBars = scrollBars & ~ScrollBars.Vertical; 38 | } 39 | } 40 | if((scrollBars | ScrollBars.Horizontal) == ScrollBars.Horizontal) 41 | { 42 | if(szText.Width > szBox.Width) 43 | { 44 | box.ScrollBars = scrollBars | ScrollBars.Horizontal; 45 | } 46 | else 47 | { 48 | box.ScrollBars = scrollBars & ~ScrollBars.Horizontal; 49 | } 50 | } 51 | }; 52 | box.TextChanged += (sender, e) => SetScrollVisible(); 53 | box.FontChanged += (sender, e) => SetScrollVisible(); 54 | box.ClientSizeChanged += (sender, e) => SetScrollVisible(); 55 | } 56 | 57 | /// TextBox只读时可以使用Ctrl+A全选快捷键 58 | public static void CanSelectAllWhenReadOnly(this TextBox box) 59 | { 60 | box.KeyDown += (sender, e) => 61 | { 62 | if(box.ReadOnly && e.Control && e.KeyCode == Keys.A) box.SelectAll(); 63 | }; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/ToolTipBox.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace BluePointLilac.Methods 4 | { 5 | public static class ToolTipBox 6 | { 7 | public static void SetToolTip(Control ctr, string tip) 8 | { 9 | if(tip.IsNullOrWhiteSpace()) return; 10 | ToolTip toolTip = new ToolTip { InitialDelay = 1 }; 11 | toolTip.SetToolTip(ctr, tip); 12 | ctr.Disposed += (sender, e) => toolTip.Dispose(); 13 | } 14 | 15 | public static void SetToolTip(ToolStripItem item, string tip) 16 | { 17 | //必须先设置item的Owner 18 | item.Owner.ShowItemToolTips = true; 19 | item.ToolTipText = tip; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /ContextMenuManager/BluePointLilac.Methods/WinOsVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BluePointLilac.Methods 4 | { 5 | // 判断Windows系统版本 6 | // https://docs.microsoft.com/windows/release-health/release-information 7 | public static class WinOsVersion 8 | { 9 | public static readonly Version Current = Environment.OSVersion.Version; 10 | public static readonly Version Win11 = new Version(10, 0, 22000); 11 | public static readonly Version Win10 = new Version(10, 0); 12 | public static readonly Version Win8_1 = new Version(6, 3); 13 | public static readonly Version Win8 = new Version(6, 2); 14 | public static readonly Version Win7 = new Version(6, 1); 15 | public static readonly Version Vista = new Version(6, 0); 16 | public static readonly Version XP = new Version(5, 1); 17 | 18 | public static readonly Version Win10_1507 = new Version(10, 0, 10240); 19 | public static readonly Version Win10_1511 = new Version(10, 0, 10586); 20 | public static readonly Version Win10_1607 = new Version(10, 0, 14393); 21 | public static readonly Version Win10_1703 = new Version(10, 0, 15063); 22 | public static readonly Version Win10_1709 = new Version(10, 0, 16299); 23 | public static readonly Version Win10_1803 = new Version(10, 0, 17134); 24 | public static readonly Version Win10_1809 = new Version(10, 0, 17763); 25 | public static readonly Version Win10_1903 = new Version(10, 0, 18362); 26 | public static readonly Version Win10_1909 = new Version(10, 0, 18363); 27 | public static readonly Version Win10_2004 = new Version(10, 0, 19041); 28 | public static readonly Version Win10_20H2 = new Version(10, 0, 19042); 29 | } 30 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/DetailedEditDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System; 4 | using System.Windows.Forms; 5 | 6 | namespace ContextMenuManager.Controls 7 | { 8 | sealed class DetailedEditDialog : CommonDialog 9 | { 10 | public Guid GroupGuid { get; set; } 11 | 12 | public override void Reset() { } 13 | 14 | protected override bool RunDialog(IntPtr hwndOwner) 15 | { 16 | using(SubItemsForm frm = new SubItemsForm()) 17 | using(DetailedEditList list = new DetailedEditList()) 18 | { 19 | var location = GuidInfo.GetIconLocation(GroupGuid); 20 | frm.Icon = ResourceIcon.GetIcon(location.IconPath, location.IconIndex); 21 | frm.Text = AppString.Dialog.DetailedEdit.Replace("%s", GuidInfo.GetText(GroupGuid)); 22 | frm.TopMost = AppConfig.TopMost; 23 | frm.AddList(list); 24 | list.GroupGuid = GroupGuid; 25 | list.UseUserDic = XmlDicHelper.DetailedEditGuidDic[GroupGuid]; 26 | list.LoadItems(); 27 | frm.ShowDialog(); 28 | } 29 | return false; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/DictionariesBox.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.Drawing; 6 | using System.IO; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace ContextMenuManager.Controls 11 | { 12 | sealed class DictionariesBox : TabControl 13 | { 14 | public DictionariesBox() 15 | { 16 | SuspendLayout(); 17 | Dock = DockStyle.Fill; 18 | Controls.AddRange(pages); 19 | ForeColor = MyMainForm.FormFore; 20 | BackColor = MyMainForm.FormBack; 21 | Font = SystemFonts.MenuFont; 22 | Font = new Font(Font.FontFamily, Font.Size + 1F); 23 | cms.Items.AddRange(items); 24 | for(int i = 0; i < 6; i++) 25 | { 26 | boxs[i] = new ReadOnlyRichTextBox { Parent = pages[i] }; 27 | if(i > 0) boxs[i].ContextMenuStrip = cms; 28 | } 29 | items[0].Click += (sender, e) => ExternalProgram.OpenNotepadWithText(GetInitialText()); 30 | items[2].Click += (sender, e) => SaveFile(); 31 | boxs[0].Controls.Add(btnOpenDir); 32 | btnOpenDir.Top = boxs[0].Height - btnOpenDir.Height; 33 | ToolTipBox.SetToolTip(btnOpenDir, AppString.Menu.FileLocation); 34 | btnOpenDir.MouseDown += (sender, e) => ExternalProgram.OpenDirectory(AppConfig.DicsDir); 35 | SelectedIndexChanged += (sender, e) => LoadText(); 36 | VisibleChanged += (sender, e) => this.SetEnabled(Visible); 37 | ResumeLayout(); 38 | } 39 | 40 | readonly TabPage[] pages = 41 | { 42 | new TabPage(AppString.Other.DictionaryDescription), 43 | new TabPage(AppString.SideBar.AppLanguage), 44 | new TabPage(AppString.Other.GuidInfosDictionary), 45 | new TabPage(AppString.SideBar.DetailedEdit), 46 | new TabPage(AppString.SideBar.EnhanceMenu), 47 | new TabPage(AppString.Other.UwpMode) 48 | }; 49 | readonly ReadOnlyRichTextBox[] boxs = new ReadOnlyRichTextBox[6]; 50 | readonly PictureButton btnOpenDir = new PictureButton(AppImage.Open) 51 | { 52 | Anchor = AnchorStyles.Left | AnchorStyles.Bottom, 53 | Left = 0 54 | }; 55 | readonly ContextMenuStrip cms = new ContextMenuStrip(); 56 | readonly ToolStripItem[] items = 57 | { 58 | new RToolStripMenuItem(AppString.Menu.Edit), 59 | new RToolStripSeparator(), 60 | new RToolStripMenuItem(AppString.Menu.Save) 61 | }; 62 | 63 | private void SaveFile() 64 | { 65 | using(SaveFileDialog dlg = new SaveFileDialog()) 66 | { 67 | string dirPath = AppConfig.UserDicsDir; 68 | switch(SelectedIndex) 69 | { 70 | case 1: 71 | dirPath = AppConfig.LangsDir; 72 | dlg.FileName = AppConfig.ZH_CNINI; 73 | break; 74 | case 2: 75 | dlg.FileName = AppConfig.GUIDINFOSDICINI; 76 | break; 77 | case 3: 78 | dlg.FileName = AppConfig.DETAILEDEDITDICXML; 79 | break; 80 | case 4: 81 | dlg.FileName = AppConfig.ENHANCEMENUSICXML; 82 | break; 83 | case 5: 84 | dlg.FileName = AppConfig.UWPMODEITEMSDICXML; 85 | break; 86 | } 87 | dlg.Filter = $"{dlg.FileName}|*{Path.GetExtension(dlg.FileName)}"; 88 | Directory.CreateDirectory(dirPath); 89 | dlg.InitialDirectory = dirPath; 90 | if(dlg.ShowDialog() == DialogResult.OK) 91 | { 92 | File.WriteAllText(dlg.FileName, GetInitialText(), Encoding.Unicode); 93 | } 94 | } 95 | } 96 | 97 | private string GetInitialText() 98 | { 99 | switch(SelectedIndex) 100 | { 101 | case 0: 102 | return AppString.Other.Dictionaries; 103 | case 1: 104 | return Properties.Resources.AppLanguageDic; 105 | case 2: 106 | return Properties.Resources.GuidInfosDic; 107 | case 3: 108 | return Properties.Resources.DetailedEditDic; 109 | case 4: 110 | return Properties.Resources.EnhanceMenusDic; 111 | case 5: 112 | return Properties.Resources.UwpModeItemsDic; 113 | default: 114 | return string.Empty; 115 | } 116 | } 117 | 118 | public void LoadText() 119 | { 120 | int index = SelectedIndex; 121 | if(boxs[index].Text.Length > 0) return; 122 | Action action = null; 123 | switch(index) 124 | { 125 | case 0: 126 | case 1: 127 | case 2: 128 | action = boxs[index].LoadIni; break; 129 | case 3: 130 | case 4: 131 | case 5: 132 | action = boxs[index].LoadXml; break; 133 | } 134 | BeginInvoke(action, new[] { GetInitialText() }); 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/EnhanceMenusDialog.cs: -------------------------------------------------------------------------------- 1 | using ContextMenuManager.Methods; 2 | using System; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | namespace ContextMenuManager.Controls 7 | { 8 | sealed class EnhanceMenusDialog : CommonDialog 9 | { 10 | public string ScenePath { get; set; } 11 | 12 | public override void Reset() { } 13 | 14 | protected override bool RunDialog(IntPtr hwndOwner) 15 | { 16 | using(SubItemsForm frm = new SubItemsForm()) 17 | using(EnhanceMenuList list = new EnhanceMenuList()) 18 | { 19 | frm.Text = AppString.SideBar.EnhanceMenu; 20 | frm.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); 21 | frm.TopMost = AppConfig.TopMost; 22 | frm.AddList(list); 23 | list.ScenePath = ScenePath; 24 | list.UseUserDic = XmlDicHelper.EnhanceMenuPathDic[ScenePath]; 25 | list.LoadItems(); 26 | frm.ShowDialog(); 27 | } 28 | return false; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/ExplorerRestarter.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls 8 | { 9 | sealed class ExplorerRestarter : MyListItem 10 | { 11 | public ExplorerRestarter() 12 | { 13 | Visible = false; 14 | DoubleBuffered = false; 15 | Dock = DockStyle.Bottom; 16 | Image = AppImage.Explorer; 17 | Text = AppString.Other.RestartExplorer; 18 | ToolTipBox.SetToolTip(BtnRestart, AppString.Tip.RestartExplorer); 19 | AddCtr(BtnRestart); 20 | this.CanMoveForm(); 21 | ShowHandler += () => Visible = true; 22 | HideHandler += () => Visible = false; 23 | BtnRestart.MouseDown += (sender, e) => 24 | { 25 | ExternalProgram.RestartExplorer(); 26 | Visible = false; 27 | }; 28 | } 29 | 30 | public new bool Visible 31 | { 32 | get => base.Visible; 33 | set 34 | { 35 | bool flag = base.Visible != value && Parent != null; 36 | base.Visible = value; 37 | if(flag) Parent.Height += value ? Height : -Height; 38 | } 39 | } 40 | 41 | private readonly PictureButton BtnRestart = new PictureButton(AppImage.RestartExplorer); 42 | 43 | private static Action ShowHandler; 44 | private static Action HideHandler; 45 | 46 | public static new void Show() => ShowHandler?.Invoke(); 47 | public static new void Hide() => HideHandler?.Invoke(); 48 | } 49 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/FileExtensionDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace ContextMenuManager.Controls 8 | { 9 | sealed class FileExtensionDialog : SelectDialog 10 | { 11 | public string Extension 12 | { 13 | get => Selected.Trim(); 14 | set => Selected = value?.Trim(); 15 | } 16 | 17 | public FileExtensionDialog() 18 | { 19 | CanEdit = true; 20 | Title = AppString.Dialog.SelectExtension; 21 | Items = FileExtensionItems.ToArray(); 22 | } 23 | 24 | public static List FileExtensionItems 25 | { 26 | get 27 | { 28 | List items = new List(); 29 | using (var key = RegistryEx.GetRegistryKey(FileExtension.FILEEXTSPATH)) 30 | { 31 | if (key != null) 32 | { 33 | foreach (string keyName in key.GetSubKeyNames()) 34 | { 35 | if (keyName.StartsWith(".")) items.Add(keyName.Substring(1)); 36 | } 37 | } 38 | } 39 | return items; 40 | } 41 | } 42 | 43 | protected override bool RunDialog(IntPtr hwndOwner) 44 | { 45 | bool flag = base.RunDialog(hwndOwner); 46 | if(flag) 47 | { 48 | string extension = ObjectPath.RemoveIllegalChars(Extension); 49 | int index = extension.LastIndexOf('.'); 50 | if(index >= 0) Extension = extension.Substring(index); 51 | else Extension = $".{extension}"; 52 | } 53 | return flag; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ContextMenuManager/Controls/FoldSubItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Controls.Interfaces; 4 | using ContextMenuManager.Methods; 5 | using System; 6 | using System.Drawing; 7 | using System.IO; 8 | using System.Windows.Forms; 9 | using static ContextMenuManager.Methods.ObjectPath; 10 | 11 | namespace ContextMenuManager.Controls 12 | { 13 | class FoldSubItem : MyListItem 14 | { 15 | public FoldGroupItem FoldGroupItem { get; set; } 16 | 17 | public void Indent() 18 | { 19 | int w = 40.DpiZoom(); 20 | Controls["Image"].Left += w; 21 | Controls["Text"].Left += w; 22 | } 23 | } 24 | 25 | class FoldGroupItem : MyListItem, IBtnShowMenuItem 26 | { 27 | private bool isFold; 28 | public bool IsFold 29 | { 30 | get => isFold; 31 | set 32 | { 33 | if(isFold == value) return; 34 | isFold = value; 35 | FoldMe(value); 36 | } 37 | } 38 | 39 | public string GroupPath { get; set; } 40 | public PathType PathType { get; set; } 41 | 42 | public MenuButton BtnShowMenu { get; set; } 43 | readonly PictureButton btnFold; 44 | readonly PictureButton btnOpenPath; 45 | readonly RToolStripMenuItem tsiFoldAll = new RToolStripMenuItem(AppString.Menu.FoldAll); 46 | readonly RToolStripMenuItem tsiUnfoldAll = new RToolStripMenuItem(AppString.Menu.UnfoldAll); 47 | 48 | public FoldGroupItem(string groupPath, PathType pathType) 49 | { 50 | btnFold = new PictureButton(AppImage.Up); 51 | BtnShowMenu = new MenuButton(this); 52 | btnOpenPath = new PictureButton(AppImage.Open); 53 | 54 | if(pathType == PathType.File || pathType == PathType.Directory) 55 | { 56 | groupPath = Environment.ExpandEnvironmentVariables(groupPath); 57 | } 58 | string tip = null; 59 | Action openPath = null; 60 | switch(pathType) 61 | { 62 | case PathType.File: 63 | tip = AppString.Menu.FileLocation; 64 | Text = Path.GetFileNameWithoutExtension(groupPath); 65 | Image = ResourceIcon.GetExtensionIcon(groupPath).ToBitmap(); 66 | openPath = () => ExternalProgram.JumpExplorer(groupPath, AppConfig.OpenMoreExplorer); 67 | break; 68 | case PathType.Directory: 69 | tip = AppString.Menu.FileLocation; 70 | Text = Path.GetFileNameWithoutExtension(groupPath); 71 | Image = ResourceIcon.GetFolderIcon(groupPath).ToBitmap(); 72 | openPath = () => ExternalProgram.OpenDirectory(groupPath); 73 | break; 74 | case PathType.Registry: 75 | tip = AppString.Menu.RegistryLocation; 76 | openPath = () => ExternalProgram.JumpRegEdit(groupPath, null, AppConfig.OpenMoreRegedit); 77 | break; 78 | } 79 | PathType = pathType; 80 | GroupPath = groupPath; 81 | Font = new Font(Font, FontStyle.Bold); 82 | AddCtrs(new[] { btnFold, btnOpenPath }); 83 | ContextMenuStrip.Items.AddRange(new[] { tsiFoldAll, tsiUnfoldAll }); 84 | MouseDown += (sender, e) => 85 | { 86 | if(e.Button == MouseButtons.Left) Fold(); 87 | }; 88 | btnFold.MouseDown += (sender, e) => 89 | { 90 | Fold(); 91 | btnFold.Image = btnFold.BaseImage; 92 | }; 93 | tsiFoldAll.Click += (sender, e) => FoldAll(true); 94 | tsiUnfoldAll.Click += (sender, e) => FoldAll(false); 95 | btnOpenPath.MouseDown += (sender, e) => openPath.Invoke(); 96 | ToolTipBox.SetToolTip(btnOpenPath, tip); 97 | } 98 | 99 | public void SetVisibleWithSubItemCount() 100 | { 101 | foreach(Control ctr in Parent.Controls) 102 | { 103 | if(ctr is FoldSubItem item && item.FoldGroupItem == this) 104 | { 105 | Visible = true; 106 | return; 107 | } 108 | } 109 | Visible = false; 110 | } 111 | 112 | private void Fold() 113 | { 114 | Parent.SuspendLayout(); 115 | IsFold = !IsFold; 116 | Parent.ResumeLayout(); 117 | } 118 | 119 | private void FoldMe(bool isFold) 120 | { 121 | btnFold.BaseImage = isFold ? AppImage.Down : AppImage.Up; 122 | foreach(Control ctr in Parent?.Controls) 123 | { 124 | if(ctr is FoldSubItem item && item.FoldGroupItem == this) ctr.Visible = !isFold; 125 | } 126 | } 127 | 128 | private void FoldAll(bool isFold) 129 | { 130 | Parent.SuspendLayout(); 131 | foreach(Control ctr in Parent.Controls) 132 | { 133 | if(ctr is FoldGroupItem groupItem) groupItem.IsFold = isFold; 134 | } 135 | Parent.ResumeLayout(); 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/GuidBlockedItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Controls.Interfaces; 4 | using ContextMenuManager.Methods; 5 | using System; 6 | using System.Linq; 7 | using System.Windows.Forms; 8 | 9 | namespace ContextMenuManager.Controls 10 | { 11 | class GuidBlockedItem : MyListItem, IBtnShowMenuItem, ITsiWebSearchItem, ITsiFilePathItem, ITsiGuidItem, ITsiRegPathItem 12 | { 13 | public GuidBlockedItem(string value) 14 | { 15 | InitializeComponents(); 16 | Value = value; 17 | if(GuidEx.TryParse(value, out Guid guid)) 18 | { 19 | Guid = guid; 20 | Image = GuidInfo.GetImage(guid); 21 | ItemFilePath = GuidInfo.GetFilePath(Guid); 22 | } 23 | else 24 | { 25 | Guid = Guid.Empty; 26 | Image = AppImage.SystemFile; 27 | } 28 | Text = ItemText; 29 | } 30 | 31 | public string Value { get; set; } 32 | public Guid Guid { get; set; } 33 | public string SearchText => Value; 34 | public string ValueName => Value; 35 | public string RegPath 36 | { 37 | get 38 | { 39 | foreach(string path in GuidBlockedList.BlockedPaths) 40 | { 41 | using(var key = RegistryEx.GetRegistryKey(path)) 42 | { 43 | if(key == null) continue; 44 | if(key.GetValueNames().Contains(Value, StringComparer.OrdinalIgnoreCase)) return path; 45 | } 46 | } 47 | return null; 48 | } 49 | } 50 | 51 | public string ItemText 52 | { 53 | get 54 | { 55 | string text; 56 | if(GuidEx.TryParse(Value, out Guid guid)) text = GuidInfo.GetText(guid); 57 | else text = AppString.Message.MalformedGuid; 58 | text += "\n" + Value; 59 | return text; 60 | } 61 | } 62 | 63 | public string ItemFilePath { get; set; } 64 | public MenuButton BtnShowMenu { get; set; } 65 | public DetailedEditButton BtnDetailedEdit { get; set; } 66 | public WebSearchMenuItem TsiSearch { get; set; } 67 | public FileLocationMenuItem TsiFileLocation { get; set; } 68 | public FilePropertiesMenuItem TsiFileProperties { get; set; } 69 | public HandleGuidMenuItem TsiHandleGuid { get; set; } 70 | public RegLocationMenuItem TsiRegLocation { get; set; } 71 | 72 | readonly RToolStripMenuItem TsiDetails = new RToolStripMenuItem(AppString.Menu.Details); 73 | readonly RToolStripMenuItem TsiDelete = new RToolStripMenuItem(AppString.Menu.Delete); 74 | 75 | private void InitializeComponents() 76 | { 77 | BtnShowMenu = new MenuButton(this); 78 | BtnDetailedEdit = new DetailedEditButton(this); 79 | TsiSearch = new WebSearchMenuItem(this); 80 | TsiFileProperties = new FilePropertiesMenuItem(this); 81 | TsiFileLocation = new FileLocationMenuItem(this); 82 | TsiRegLocation = new RegLocationMenuItem(this); 83 | TsiHandleGuid = new HandleGuidMenuItem(this); 84 | 85 | ContextMenuStrip.Items.AddRange(new ToolStripItem[] {TsiHandleGuid, 86 | new RToolStripSeparator(), TsiDetails, new RToolStripSeparator(), TsiDelete }); 87 | TsiDetails.DropDownItems.AddRange(new ToolStripItem[] { TsiSearch, 88 | new RToolStripSeparator(), TsiFileProperties, TsiFileLocation, TsiRegLocation}); 89 | 90 | TsiDelete.Click += (sender, e) => DeleteMe(); 91 | } 92 | 93 | public void DeleteMe() 94 | { 95 | if(AppMessageBox.Show(AppString.Message.ConfirmDelete, MessageBoxButtons.YesNo) != DialogResult.Yes) return; 96 | Array.ForEach(GuidBlockedList.BlockedPaths, path => RegistryEx.DeleteValue(path, Value)); 97 | if(!Guid.Equals(Guid.Empty)) ExplorerRestarter.Show(); 98 | int index = Parent.Controls.GetChildIndex(this); 99 | index -= (index < Parent.Controls.Count - 1) ? 0 : 1; 100 | Parent.Controls[index].Focus(); 101 | Dispose(); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/GuidBlockedList.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using Microsoft.Win32; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Windows.Forms; 9 | 10 | namespace ContextMenuManager.Controls 11 | { 12 | sealed class GuidBlockedList : MyList // 其他规则 GUID锁 13 | { 14 | public const string HKLMBLOCKED = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked"; 15 | public const string HKCUBLOCKED = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Blocked"; 16 | public static readonly string[] BlockedPaths = { HKLMBLOCKED, HKCUBLOCKED }; 17 | 18 | public void LoadItems() 19 | { 20 | AddNewItem(); 21 | LoadBlockedItems(); 22 | } 23 | 24 | private void LoadBlockedItems() 25 | { 26 | List values = new List(); 27 | foreach(string path in BlockedPaths) 28 | { 29 | using(RegistryKey key = RegistryEx.GetRegistryKey(path)) 30 | { 31 | if(key == null) continue; 32 | foreach(string value in key.GetValueNames()) 33 | { 34 | if(values.Contains(value, StringComparer.OrdinalIgnoreCase)) continue; 35 | AddItem(new GuidBlockedItem(value)); 36 | values.Add(value); 37 | } 38 | } 39 | } 40 | } 41 | 42 | private void AddNewItem() 43 | { 44 | NewItem newItem = new NewItem(AppString.Other.AddGuidBlockedItem); 45 | AddItem(newItem); 46 | newItem.AddNewItem += () => 47 | { 48 | using(InputDialog dlg = new InputDialog { Title = AppString.Dialog.InputGuid }) 49 | { 50 | if(GuidEx.TryParse(Clipboard.GetText(), out Guid guid)) dlg.Text = guid.ToString(); 51 | if(dlg.ShowDialog() != DialogResult.OK) return; 52 | if(GuidEx.TryParse(dlg.Text, out guid)) 53 | { 54 | string value = guid.ToString("B"); 55 | Array.ForEach(BlockedPaths, path => Registry.SetValue(path, value, "")); 56 | for(int i = 1; i < Controls.Count; i++) 57 | { 58 | if(((GuidBlockedItem)Controls[i]).Guid.Equals(guid)) 59 | { 60 | AppMessageBox.Show(AppString.Message.HasBeenAdded); 61 | return; 62 | } 63 | } 64 | InsertItem(new GuidBlockedItem(value), 1); 65 | ExplorerRestarter.Show(); 66 | } 67 | else AppMessageBox.Show(AppString.Message.MalformedGuid); 68 | } 69 | }; 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/IEItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Controls.Interfaces; 4 | using ContextMenuManager.Methods; 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Drawing; 8 | using System.Windows.Forms; 9 | 10 | namespace ContextMenuManager.Controls 11 | { 12 | sealed class IEItem : MyListItem, ITsiRegPathItem, ITsiFilePathItem, ITsiRegDeleteItem, ITsiCommandItem, 13 | ITsiWebSearchItem, ITsiTextItem, ITsiRegExportItem, IBtnShowMenuItem, IChkVisibleItem 14 | { 15 | public static readonly string[] MeParts = { "MenuExt", "-MenuExt" }; 16 | 17 | public IEItem(string regPath) 18 | { 19 | InitializeComponents(); 20 | RegPath = regPath; 21 | } 22 | 23 | private string regPath; 24 | public string RegPath 25 | { 26 | get => regPath; 27 | set 28 | { 29 | regPath = value; 30 | Text = ItemText; 31 | Image = ItemImage; 32 | } 33 | } 34 | public string ValueName => null; 35 | private string KeyName => RegistryEx.GetKeyName(RegPath); 36 | private string BackupPath => $@"{IEList.IEPath}\{(ItemVisible ? MeParts[1] : MeParts[0])}\{KeyName}"; 37 | private string MeKeyName => RegistryEx.GetKeyName(RegistryEx.GetParentPath(RegPath)); 38 | 39 | public string ItemText 40 | { 41 | get => RegistryEx.GetKeyName(RegPath); 42 | set 43 | { 44 | string newPath = $@"{RegistryEx.GetParentPath(RegPath)}\{value.Replace("\\", "")}"; 45 | string defaultValue = Registry.GetValue(newPath, "", null)?.ToString(); 46 | if(!defaultValue.IsNullOrWhiteSpace()) 47 | { 48 | AppMessageBox.Show(AppString.Message.HasBeenAdded); 49 | } 50 | else 51 | { 52 | RegistryEx.MoveTo(RegPath, newPath); 53 | RegPath = newPath; 54 | } 55 | } 56 | } 57 | 58 | public bool ItemVisible 59 | { 60 | get => MeKeyName.Equals(MeParts[0], StringComparison.OrdinalIgnoreCase); 61 | set 62 | { 63 | RegistryEx.MoveTo(RegPath, BackupPath); 64 | RegPath = BackupPath; 65 | } 66 | } 67 | 68 | public string ItemCommand 69 | { 70 | get => Registry.GetValue(RegPath, "", null)?.ToString(); 71 | set 72 | { 73 | Registry.SetValue(RegPath, "", value); 74 | Image = ItemImage; 75 | } 76 | } 77 | 78 | public string SearchText => $@"{AppString.SideBar.IEMenu} {Text}"; 79 | public string ItemFilePath => ObjectPath.ExtractFilePath(ItemCommand); 80 | private Icon ItemIcon => ResourceIcon.GetIcon(ItemFilePath) ?? ResourceIcon.GetExtensionIcon(ItemFilePath); 81 | private Image ItemImage => ItemIcon?.ToBitmap() ?? AppImage.NotFound; 82 | 83 | public MenuButton BtnShowMenu { get; set; } 84 | public VisibleCheckBox ChkVisible { get; set; } 85 | public WebSearchMenuItem TsiSearch { get; set; } 86 | public ChangeTextMenuItem TsiChangeText { get; set; } 87 | public ChangeCommandMenuItem TsiChangeCommand { get; set; } 88 | public FileLocationMenuItem TsiFileLocation { get; set; } 89 | public FilePropertiesMenuItem TsiFileProperties { get; set; } 90 | public RegLocationMenuItem TsiRegLocation { get; set; } 91 | public RegExportMenuItem TsiRegExport { get; set; } 92 | public DeleteMeMenuItem TsiDeleteMe { get; set; } 93 | readonly RToolStripMenuItem TsiDetails = new RToolStripMenuItem(AppString.Menu.Details); 94 | 95 | private void InitializeComponents() 96 | { 97 | BtnShowMenu = new MenuButton(this); 98 | ChkVisible = new VisibleCheckBox(this); 99 | TsiChangeText = new ChangeTextMenuItem(this); 100 | TsiChangeCommand = new ChangeCommandMenuItem(this); 101 | TsiSearch = new WebSearchMenuItem(this); 102 | TsiFileLocation = new FileLocationMenuItem(this); 103 | TsiFileProperties = new FilePropertiesMenuItem(this); 104 | TsiRegLocation = new RegLocationMenuItem(this); 105 | TsiRegExport = new RegExportMenuItem(this); 106 | TsiDeleteMe = new DeleteMeMenuItem(this); 107 | 108 | ContextMenuStrip.Items.AddRange(new ToolStripItem[] { TsiChangeText, 109 | new RToolStripSeparator(), TsiDetails, new RToolStripSeparator(), TsiDeleteMe }); 110 | 111 | TsiDetails.DropDownItems.AddRange(new ToolStripItem[] { TsiSearch, new RToolStripSeparator(), 112 | TsiChangeCommand, TsiFileProperties, TsiFileLocation, TsiRegLocation, TsiRegExport}); 113 | } 114 | 115 | public void DeleteMe() 116 | { 117 | RegistryEx.DeleteKeyTree(RegPath); 118 | RegistryEx.DeleteKeyTree(BackupPath); 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/IEList.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using Microsoft.Win32; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Windows.Forms; 8 | 9 | namespace ContextMenuManager.Controls 10 | { 11 | sealed class IEList : MyList // 其他规则 IE浏览器 12 | { 13 | public const string IEPath = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer"; 14 | 15 | public void LoadItems() 16 | { 17 | AddNewItem(); 18 | LoadIEItems(); 19 | } 20 | 21 | private void LoadIEItems() 22 | { 23 | List names = new List(); 24 | using(RegistryKey ieKey = RegistryEx.GetRegistryKey(IEPath)) 25 | { 26 | if(ieKey == null) return; 27 | foreach(string part in IEItem.MeParts) 28 | { 29 | using(RegistryKey meKey = ieKey.OpenSubKey(part)) 30 | { 31 | if(meKey == null) continue; 32 | foreach(string keyName in meKey.GetSubKeyNames()) 33 | { 34 | if(names.Contains(keyName, StringComparer.OrdinalIgnoreCase)) continue; 35 | using(RegistryKey key = meKey.OpenSubKey(keyName)) 36 | { 37 | if(!string.IsNullOrEmpty(key.GetValue("")?.ToString())) 38 | { 39 | AddItem(new IEItem(key.Name)); 40 | names.Add(keyName); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | 49 | private void AddNewItem() 50 | { 51 | NewItem newItem = new NewItem(); 52 | AddItem(newItem); 53 | newItem.AddNewItem += () => 54 | { 55 | using(NewIEDialog dlg = new NewIEDialog()) 56 | { 57 | if(dlg.ShowDialog() != DialogResult.OK) return; 58 | InsertItem(new IEItem(dlg.RegPath), 1); 59 | } 60 | }; 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/IBtnDeleteItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using ContextMenuManager.Methods; 3 | using System.Windows.Forms; 4 | 5 | namespace ContextMenuManager.Controls.Interfaces 6 | { 7 | interface IBtnDeleteItem 8 | { 9 | DeleteButton BtnDelete { get; set; } 10 | void DeleteMe(); 11 | } 12 | 13 | sealed class DeleteButton : PictureButton 14 | { 15 | public DeleteButton(IBtnDeleteItem item) : base(AppImage.Delete) 16 | { 17 | MyListItem listItem = (MyListItem)item; 18 | listItem.AddCtr(this); 19 | MouseDown += (sender, e) => 20 | { 21 | if(AppMessageBox.Show(AppString.Message.ConfirmDelete, MessageBoxButtons.YesNo) == DialogResult.Yes) item.DeleteMe(); 22 | }; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/IBtnMoveUpDownItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using ContextMenuManager.Methods; 3 | 4 | namespace ContextMenuManager.Controls.Interfaces 5 | { 6 | interface IBtnMoveUpDownItem 7 | { 8 | MoveButton BtnMoveUp { get; set; } 9 | MoveButton BtnMoveDown { get; set; } 10 | } 11 | 12 | sealed class MoveButton : PictureButton 13 | { 14 | public MoveButton(IBtnMoveUpDownItem item, bool isUp) : base(isUp ? AppImage.Up : AppImage.Down) 15 | { 16 | ((MyListItem)item).AddCtr(this); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/IBtnShowMenuItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using ContextMenuManager.Methods; 3 | using System.Windows.Forms; 4 | 5 | namespace ContextMenuManager.Controls.Interfaces 6 | { 7 | interface IBtnShowMenuItem 8 | { 9 | ContextMenuStrip ContextMenuStrip { get; set; } 10 | MenuButton BtnShowMenu { get; set; } 11 | } 12 | 13 | sealed class MenuButton : PictureButton 14 | { 15 | public MenuButton(IBtnShowMenuItem item) : base(AppImage.Setting) 16 | { 17 | item.ContextMenuStrip = new ContextMenuStrip(); 18 | ((MyListItem)item).AddCtr(this); 19 | bool isShow = false; 20 | MouseDown += (sender, e) => 21 | { 22 | if(!isShow) item.ContextMenuStrip.Show(this, 0, Height); 23 | else item.ContextMenuStrip.Close(); 24 | isShow = !isShow; 25 | }; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/IChkVisibleItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using ContextMenuManager.Methods; 3 | 4 | namespace ContextMenuManager.Controls.Interfaces 5 | { 6 | interface IChkVisibleItem 7 | { 8 | bool ItemVisible { get; set; } 9 | VisibleCheckBox ChkVisible { get; set; } 10 | } 11 | 12 | sealed class VisibleCheckBox : MyCheckBox 13 | { 14 | public VisibleCheckBox(IChkVisibleItem item) 15 | { 16 | MyListItem listItem = (MyListItem)item; 17 | listItem.AddCtr(this); 18 | CheckChanged += () => item.ItemVisible = Checked; 19 | listItem.ParentChanged += (sender, e) => 20 | { 21 | if(listItem.IsDisposed) return; 22 | if(listItem.Parent == null) return; 23 | Checked = item.ItemVisible; 24 | if(listItem is FoldSubItem subItem && subItem.FoldGroupItem != null) return; 25 | if(listItem.FindForm() is ShellStoreDialog.ShellStoreForm) return; 26 | if(AppConfig.HideDisabledItems) listItem.Visible = Checked; 27 | }; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/IProtectOpenItem.cs: -------------------------------------------------------------------------------- 1 | namespace ContextMenuManager.Controls.Interfaces 2 | { 3 | interface IProtectOpenItem 4 | { 5 | bool ItemVisible { get; set; } 6 | bool TryProtectOpenItem(); 7 | } 8 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiAdministratorItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | 6 | namespace ContextMenuManager.Controls.Interfaces 7 | { 8 | interface ITsiAdministratorItem 9 | { 10 | ContextMenuStrip ContextMenuStrip { get; set; } 11 | RunAsAdministratorItem TsiAdministrator { get; set; } 12 | ShellLink ShellLink { get; } 13 | } 14 | 15 | sealed class RunAsAdministratorItem : RToolStripMenuItem 16 | { 17 | public RunAsAdministratorItem(ITsiAdministratorItem item) : base(AppString.Menu.RunAsAdministrator) 18 | { 19 | item.ContextMenuStrip.Opening += (sender, e) => 20 | { 21 | if(item.ShellLink == null) 22 | { 23 | Enabled = false; 24 | return; 25 | } 26 | string filePath = item.ShellLink.TargetPath; 27 | string extension = Path.GetExtension(filePath)?.ToLower(); 28 | switch(extension) 29 | { 30 | case ".exe": 31 | case ".bat": 32 | case ".cmd": 33 | Enabled = true; 34 | break; 35 | default: 36 | Enabled = false; 37 | break; 38 | } 39 | Checked = item.ShellLink.RunAsAdministrator; 40 | }; 41 | Click += (sender, e) => 42 | { 43 | item.ShellLink.RunAsAdministrator = !Checked; 44 | item.ShellLink.Save(); 45 | if(item is WinXItem) ExplorerRestarter.Show(); 46 | }; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiCommandItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls.Interfaces 8 | { 9 | interface ITsiCommandItem 10 | { 11 | string ItemCommand { get; set; } 12 | ChangeCommandMenuItem TsiChangeCommand { get; set; } 13 | } 14 | 15 | sealed class ChangeCommandMenuItem : RToolStripMenuItem 16 | { 17 | public bool CommandCanBeEmpty { get; set; } 18 | 19 | public ChangeCommandMenuItem(ITsiCommandItem item) : base(AppString.Menu.ChangeCommand) 20 | { 21 | Click += (sender, e) => 22 | { 23 | string command = ChangeCommand(item.ItemCommand); 24 | if(command != null) item.ItemCommand = command; 25 | }; 26 | } 27 | 28 | private string ChangeCommand(string command) 29 | { 30 | using(InputDialog dlg = new InputDialog()) 31 | { 32 | dlg.Text = command; 33 | dlg.Title = AppString.Menu.ChangeCommand; 34 | dlg.Size = new Size(530, 260).DpiZoom(); 35 | if(dlg.ShowDialog() != DialogResult.OK) return null; 36 | if(!CommandCanBeEmpty && string.IsNullOrEmpty(dlg.Text)) 37 | { 38 | AppMessageBox.Show(AppString.Message.CommandCannotBeEmpty); 39 | return ChangeCommand(command); 40 | } 41 | else return dlg.Text; 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiDeleteItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.IO; 6 | using System.Windows.Forms; 7 | 8 | namespace ContextMenuManager.Controls.Interfaces 9 | { 10 | interface ITsiDeleteItem 11 | { 12 | DeleteMeMenuItem TsiDeleteMe { get; set; } 13 | void DeleteMe(); 14 | } 15 | 16 | interface ITsiRegDeleteItem : ITsiDeleteItem 17 | { 18 | string Text { get; } 19 | string RegPath { get; } 20 | } 21 | 22 | sealed class DeleteMeMenuItem : RToolStripMenuItem 23 | { 24 | public DeleteMeMenuItem(ITsiDeleteItem item) : base(item is RestoreItem ? AppString.Menu.DeleteBackup : AppString.Menu.Delete) 25 | { 26 | Click += (sender, e) => 27 | { 28 | if (item is ITsiRegDeleteItem regItem && AppConfig.AutoBackup) 29 | { 30 | if (AppMessageBox.Show(AppString.Message.DeleteButCanRestore, MessageBoxButtons.YesNo) != DialogResult.Yes) 31 | { 32 | return; 33 | } 34 | string date = DateTime.Today.ToString("yyyy-MM-dd"); 35 | string time = DateTime.Now.ToString("HH-mm-ss"); 36 | string filePath = $@"{AppConfig.RegBackupDir}\{date}\{regItem.Text} - {time}.reg"; 37 | Directory.CreateDirectory(Path.GetDirectoryName(filePath)); 38 | ExternalProgram.ExportRegistry(regItem.RegPath, filePath); 39 | } 40 | else if (AppMessageBox.Show(item is RestoreItem ? AppString.Message.ConfirmDeleteBackupPermanently : AppString.Message.ConfirmDeletePermanently, 41 | MessageBoxButtons.YesNo) != DialogResult.Yes) 42 | { 43 | return; 44 | } 45 | MyListItem listItem = (MyListItem)item; 46 | MyList list = (MyList)listItem.Parent; 47 | int index = list.GetItemIndex(listItem); 48 | try 49 | { 50 | item.DeleteMe(); 51 | } 52 | catch 53 | { 54 | AppMessageBox.Show(AppString.Message.AuthorityProtection); 55 | return; 56 | } 57 | list.Controls.Remove(listItem); 58 | list.Controls[index < list.Controls.Count ? index : (list.Controls.Count - 1)].Focus(); 59 | listItem.Dispose(); 60 | }; 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiFilePathItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | 6 | namespace ContextMenuManager.Controls.Interfaces 7 | { 8 | interface ITsiFilePathItem 9 | { 10 | string ItemFilePath { get; } 11 | ContextMenuStrip ContextMenuStrip { get; set; } 12 | FileLocationMenuItem TsiFileLocation { get; set; } 13 | FilePropertiesMenuItem TsiFileProperties { get; set; } 14 | } 15 | 16 | sealed class FileLocationMenuItem : RToolStripMenuItem 17 | { 18 | public FileLocationMenuItem(ITsiFilePathItem item) : base(AppString.Menu.FileLocation) 19 | { 20 | item.ContextMenuStrip.Opening += (sender, e) => 21 | { 22 | Visible = item.ItemFilePath != null; 23 | }; 24 | Click += (sender, e) => ExternalProgram.JumpExplorer(item.ItemFilePath, AppConfig.OpenMoreExplorer); 25 | } 26 | } 27 | 28 | sealed class FilePropertiesMenuItem : RToolStripMenuItem 29 | { 30 | public FilePropertiesMenuItem(ITsiFilePathItem item) : base(AppString.Menu.FileProperties) 31 | { 32 | item.ContextMenuStrip.Opening += (sender, e) => 33 | { 34 | string path = item.ItemFilePath; 35 | Visible = Directory.Exists(path) || File.Exists(path); 36 | }; 37 | Click += (sender, e) => ExternalProgram.ShowPropertiesDialog(item.ItemFilePath); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiIconItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls.Interfaces 8 | { 9 | interface ITsiIconItem 10 | { 11 | ChangeIconMenuItem TsiChangeIcon { get; set; } 12 | string IconLocation { get; set; } 13 | string IconPath { get; set; } 14 | int IconIndex { get; set; } 15 | Image Image { get; set; } 16 | Icon ItemIcon { get; } 17 | } 18 | 19 | sealed class ChangeIconMenuItem : RToolStripMenuItem 20 | { 21 | public ChangeIconMenuItem(ITsiIconItem item) : base(AppString.Menu.ChangeIcon) 22 | { 23 | Click += (sender, e) => 24 | { 25 | using(IconDialog dlg = new IconDialog()) 26 | { 27 | dlg.IconPath = item.IconPath; 28 | dlg.IconIndex = item.IconIndex; 29 | if(dlg.ShowDialog() != DialogResult.OK) return; 30 | using(Icon icon = ResourceIcon.GetIcon(dlg.IconPath, dlg.IconIndex)) 31 | { 32 | Image image = icon?.ToBitmap(); 33 | if(image == null) return; 34 | item.Image = image; 35 | item.IconPath = dlg.IconPath; 36 | item.IconIndex = dlg.IconIndex; 37 | item.IconLocation = $"{dlg.IconPath},{dlg.IconIndex}"; 38 | } 39 | } 40 | }; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiRegExportItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System; 4 | using System.IO; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls.Interfaces 8 | { 9 | interface ITsiRegExportItem 10 | { 11 | string Text { get; set; } 12 | string RegPath { get; } 13 | ContextMenuStrip ContextMenuStrip { get; set; } 14 | RegExportMenuItem TsiRegExport { get; set; } 15 | } 16 | 17 | sealed class RegExportMenuItem : RToolStripMenuItem 18 | { 19 | public RegExportMenuItem(ITsiRegExportItem item) : base(AppString.Menu.ExportRegistry) 20 | { 21 | item.ContextMenuStrip.Opening += (sender, e) => 22 | { 23 | using(var key = RegistryEx.GetRegistryKey(item.RegPath)) 24 | Visible = key != null; 25 | }; 26 | Click += (sender, e) => 27 | { 28 | using(SaveFileDialog dlg = new SaveFileDialog()) 29 | { 30 | string date = DateTime.Today.ToString("yyyy-MM-dd"); 31 | string time = DateTime.Now.ToString("HH-mm-ss"); 32 | string filePath = $@"{AppConfig.RegBackupDir}\{date}\{item.Text} - {time}.reg"; 33 | string dirPath = Path.GetDirectoryName(filePath); 34 | string fileName = Path.GetFileName(filePath); 35 | Directory.CreateDirectory(dirPath); 36 | dlg.FileName = fileName; 37 | dlg.InitialDirectory = dirPath; 38 | dlg.Filter = $"{AppString.Dialog.RegistryFile}|*.reg"; 39 | if(dlg.ShowDialog() == DialogResult.OK) 40 | { 41 | ExternalProgram.ExportRegistry(item.RegPath, dlg.FileName); 42 | } 43 | if(Directory.GetFileSystemEntries(dirPath).Length == 0) 44 | { 45 | Directory.Delete(dirPath); 46 | } 47 | } 48 | }; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiRegPathItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System.Windows.Forms; 4 | 5 | namespace ContextMenuManager.Controls.Interfaces 6 | { 7 | interface ITsiRegPathItem 8 | { 9 | string RegPath { get; } 10 | string ValueName { get; } 11 | ContextMenuStrip ContextMenuStrip { get; set; } 12 | RegLocationMenuItem TsiRegLocation { get; set; } 13 | } 14 | 15 | sealed class RegLocationMenuItem : RToolStripMenuItem 16 | { 17 | public RegLocationMenuItem(ITsiRegPathItem item) : base(AppString.Menu.RegistryLocation) 18 | { 19 | Click += (sender, e) => ExternalProgram.JumpRegEdit(item.RegPath, item.ValueName, AppConfig.OpenMoreRegedit); 20 | item.ContextMenuStrip.Opening += (sender, e) => 21 | { 22 | using(var key = RegistryEx.GetRegistryKey(item.RegPath)) 23 | Visible = key != null; 24 | }; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiRestoreItem.cs: -------------------------------------------------------------------------------- 1 | using ContextMenuManager.Methods; 2 | using System.Windows.Forms; 3 | 4 | namespace ContextMenuManager.Controls.Interfaces 5 | { 6 | interface ITsiRestoreItem 7 | { 8 | DeleteMeMenuItem TsiDeleteMe { get; set; } 9 | void RestoreMe(); 10 | } 11 | 12 | sealed class RestoreMeMenuItem : RToolStripMenuItem 13 | { 14 | public RestoreMeMenuItem(ITsiRestoreItem item) : base(AppString.Menu.RestoreBackup) 15 | { 16 | Click += (sender, e) => 17 | { 18 | item.RestoreMe(); 19 | }; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiShortcutCommandItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | 8 | namespace ContextMenuManager.Controls.Interfaces 9 | { 10 | interface ITsiShortcutCommandItem 11 | { 12 | ShellLink ShellLink { get; } 13 | ShortcutCommandMenuItem TsiChangeCommand { get; set; } 14 | ContextMenuStrip ContextMenuStrip { get; set; } 15 | } 16 | 17 | sealed class ShortcutCommandMenuItem : RToolStripMenuItem 18 | { 19 | public ShortcutCommandMenuItem(ITsiShortcutCommandItem item) : base(AppString.Menu.ChangeCommand) 20 | { 21 | item.ContextMenuStrip.Opening += (sender, e) => 22 | { 23 | Visible = !string.IsNullOrEmpty(item.ShellLink?.TargetPath); 24 | }; 25 | } 26 | 27 | public bool ChangeCommand(ShellLink shellLink) 28 | { 29 | using(CommandDialog dlg = new CommandDialog()) 30 | { 31 | dlg.Command = shellLink.TargetPath; 32 | dlg.Arguments = shellLink.Arguments; 33 | if(dlg.ShowDialog() != DialogResult.OK) return false; 34 | shellLink.TargetPath = dlg.Command; 35 | shellLink.Arguments = dlg.Arguments; 36 | shellLink.Save(); 37 | return true; 38 | } 39 | } 40 | 41 | sealed class CommandDialog : CommonDialog 42 | { 43 | public string Command { get; set; } 44 | public string Arguments { get; set; } 45 | 46 | public override void Reset() { } 47 | 48 | protected override bool RunDialog(IntPtr hwndOwner) 49 | { 50 | using(CommandForm frm = new CommandForm()) 51 | { 52 | frm.Command = Command; 53 | frm.Arguments = Arguments; 54 | frm.TopMost = AppConfig.TopMost; 55 | bool flag = frm.ShowDialog() == DialogResult.OK; 56 | if(flag) 57 | { 58 | Command = frm.Command; 59 | Arguments = frm.Arguments; 60 | } 61 | return flag; 62 | } 63 | } 64 | 65 | sealed class CommandForm : ResizeLimitedForm 66 | { 67 | public CommandForm() 68 | { 69 | AcceptButton = btnOK; 70 | CancelButton = btnCancel; 71 | VerticalResizable = false; 72 | Font = SystemFonts.MessageBoxFont; 73 | Text = AppString.Menu.ChangeCommand; 74 | SizeGripStyle = SizeGripStyle.Hide; 75 | StartPosition = FormStartPosition.CenterParent; 76 | MaximizeBox = MinimizeBox = ShowIcon = ShowInTaskbar = false; 77 | InitializeComponents(); 78 | } 79 | 80 | public string Command 81 | { 82 | get => txtCommand.Text; 83 | set => txtCommand.Text = value; 84 | } 85 | 86 | public string Arguments 87 | { 88 | get => txtArguments.Text; 89 | set => txtArguments.Text = value; 90 | } 91 | 92 | readonly Label lblCommand = new Label 93 | { 94 | Text = AppString.Dialog.ItemCommand, 95 | AutoSize = true 96 | }; 97 | readonly Label lblArguments = new Label 98 | { 99 | Text = AppString.Dialog.CommandArguments, 100 | AutoSize = true 101 | }; 102 | readonly TextBox txtCommand = new TextBox(); 103 | readonly TextBox txtArguments = new TextBox(); 104 | readonly Button btnOK = new Button 105 | { 106 | DialogResult = DialogResult.OK, 107 | Text = ResourceString.OK, 108 | AutoSize = true 109 | }; 110 | readonly Button btnCancel = new Button 111 | { 112 | DialogResult = DialogResult.Cancel, 113 | Text = ResourceString.Cancel, 114 | AutoSize = true 115 | }; 116 | 117 | private void InitializeComponents() 118 | { 119 | Controls.AddRange(new Control[] { lblCommand, lblArguments, txtCommand, txtArguments, btnOK, btnCancel }); 120 | int a = 20.DpiZoom(); 121 | lblArguments.Left = lblCommand.Left = lblCommand.Top = txtCommand.Top = a; 122 | lblArguments.Top = txtArguments.Top = txtCommand.Bottom + a; 123 | btnOK.Top = btnCancel.Top = txtArguments.Bottom + a; 124 | int b = Math.Max(lblCommand.Width, lblArguments.Width) + 3 * a; 125 | ClientSize = new Size(250.DpiZoom() + b, btnOK.Bottom + a); 126 | btnOK.Anchor = btnCancel.Anchor = AnchorStyles.Right | AnchorStyles.Top; 127 | btnCancel.Left = ClientSize.Width - btnCancel.Width - a; 128 | btnOK.Left = btnCancel.Left - btnOK.Width - a; 129 | Resize += (sender, e) => 130 | { 131 | txtArguments.Width = txtCommand.Width = ClientSize.Width - b; 132 | txtArguments.Left = txtCommand.Left = btnCancel.Right - txtCommand.Width; 133 | }; 134 | OnResize(null); 135 | MinimumSize = Size; 136 | } 137 | } 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiTextItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System.Windows.Forms; 5 | 6 | namespace ContextMenuManager.Controls.Interfaces 7 | { 8 | interface ITsiTextItem 9 | { 10 | string Text { get; set; } 11 | string ItemText { get; set; } 12 | ChangeTextMenuItem TsiChangeText { get; set; } 13 | } 14 | 15 | sealed class ChangeTextMenuItem : RToolStripMenuItem 16 | { 17 | public ChangeTextMenuItem(ITsiTextItem item) : base(AppString.Menu.ChangeText) 18 | { 19 | Click += (sender, e) => 20 | { 21 | string name = ChangeText(item.Text); 22 | if(name != null) item.ItemText = name; 23 | }; 24 | } 25 | 26 | private string ChangeText(string text) 27 | { 28 | using(InputDialog dlg = new InputDialog { Text = text, Title = AppString.Menu.ChangeText }) 29 | { 30 | if(dlg.ShowDialog() != DialogResult.OK) return null; 31 | if(dlg.Text.Length == 0) 32 | { 33 | AppMessageBox.Show(AppString.Message.TextCannotBeEmpty); 34 | return ChangeText(text); 35 | } 36 | else if(ResourceString.GetDirectString(dlg.Text).Length == 0) 37 | { 38 | AppMessageBox.Show(AppString.Message.StringParsingFailed); 39 | return ChangeText(text); 40 | } 41 | else return dlg.Text; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ContextMenuManager/Controls/Interfaces/ITsiWebSearchItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System.Windows.Forms; 4 | 5 | namespace ContextMenuManager.Controls.Interfaces 6 | { 7 | interface ITsiWebSearchItem 8 | { 9 | string SearchText { get; } 10 | WebSearchMenuItem TsiSearch { get; set; } 11 | } 12 | 13 | sealed class WebSearchMenuItem : RToolStripMenuItem 14 | { 15 | public WebSearchMenuItem(ITsiWebSearchItem item) : base(AppString.Menu.WebSearch) 16 | { 17 | Click += (sender, e) => 18 | { 19 | string url = AppConfig.EngineUrl.Replace("%s", item.SearchText); 20 | ExternalProgram.OpenWebUrl(url); 21 | }; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/NewIEDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System; 4 | using System.IO; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls 8 | { 9 | sealed class NewIEDialog : CommonDialog 10 | { 11 | public string RegPath { get; private set; } 12 | public override void Reset() { } 13 | 14 | protected override bool RunDialog(IntPtr hwndOwner) 15 | { 16 | using(NewIEForm frm = new NewIEForm()) 17 | { 18 | frm.TopMost = AppConfig.TopMost; 19 | bool flag = frm.ShowDialog() == DialogResult.OK; 20 | if(flag) RegPath = frm.RegPath; 21 | return flag; 22 | } 23 | } 24 | 25 | sealed class NewIEForm : NewItemForm 26 | { 27 | public string RegPath { get; set; } 28 | 29 | protected override void InitializeComponents() 30 | { 31 | base.InitializeComponents(); 32 | btnOK.Click += (sender, e) => 33 | { 34 | if(ItemText.IsNullOrWhiteSpace()) 35 | { 36 | AppMessageBox.Show(AppString.Message.TextCannotBeEmpty); 37 | return; 38 | } 39 | if(ItemCommand.IsNullOrWhiteSpace()) 40 | { 41 | AppMessageBox.Show(AppString.Message.CommandCannotBeEmpty); 42 | return; 43 | } 44 | AddNewItem(); 45 | DialogResult = DialogResult.OK; 46 | }; 47 | 48 | btnBrowse.Click += (sender, e) => 49 | { 50 | using(OpenFileDialog dlg = new OpenFileDialog()) 51 | { 52 | if(dlg.ShowDialog() != DialogResult.OK) return; 53 | ItemFilePath = dlg.FileName; 54 | ItemText = Path.GetFileNameWithoutExtension(dlg.FileName); 55 | } 56 | }; 57 | } 58 | 59 | private void AddNewItem() 60 | { 61 | RegPath = $@"{IEList.IEPath}\{IEItem.MeParts[0]}\{ItemText.Replace("\\", "")}"; 62 | Microsoft.Win32.Registry.SetValue(RegPath, "", ItemCommand); 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/NewItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | 6 | namespace ContextMenuManager.Controls 7 | { 8 | class NewItem : MyListItem 9 | { 10 | public NewItem() : this(AppString.Other.NewItem) { } 11 | 12 | public NewItem(string text) 13 | { 14 | Text = text; 15 | Image = AppImage.NewItem; 16 | AddCtr(BtnAddNewItem); 17 | ToolTipBox.SetToolTip(BtnAddNewItem, text); 18 | BtnAddNewItem.MouseDown += (sender, e) => AddNewItem?.Invoke(); 19 | MouseDoubleClick += (sender, e) => AddNewItem?.Invoke(); 20 | 21 | } 22 | public Action AddNewItem; 23 | readonly PictureButton BtnAddNewItem = new PictureButton(AppImage.AddNewItem); 24 | } 25 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/NewItemForm.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | 8 | namespace ContextMenuManager.Controls 9 | { 10 | class NewItemForm : ResizeLimitedForm 11 | { 12 | public NewItemForm() 13 | { 14 | AcceptButton = btnOK; 15 | CancelButton = btnCancel; 16 | Text = AppString.Other.NewItem; 17 | Font = SystemFonts.MenuFont; 18 | MaximizeBox = MinimizeBox = false; 19 | ShowIcon = ShowInTaskbar = false; 20 | StartPosition = FormStartPosition.CenterParent; 21 | SizeGripStyle = SizeGripStyle.Hide; 22 | VerticalResizable = false; 23 | InitializeComponents(); 24 | } 25 | 26 | public string ItemText { get => txtText.Text; set => txtText.Text = value; } 27 | public string ItemFilePath { get => txtFilePath.Text; set => txtFilePath.Text = value; } 28 | public string Arguments { get => txtArguments.Text; set => txtArguments.Text = value; } 29 | public string ItemCommand 30 | { 31 | get 32 | { 33 | string filePath = ItemFilePath; 34 | string arguments = Arguments; 35 | if(arguments.IsNullOrWhiteSpace()) return filePath; 36 | if(filePath.IsNullOrWhiteSpace()) return arguments; 37 | if(filePath.Contains(" ")) filePath = $"\"{filePath}\""; 38 | if(!arguments.Contains("\"")) arguments = $"\"{arguments}\""; 39 | return $"{filePath} {arguments}"; 40 | } 41 | } 42 | 43 | protected readonly Label lblText = new Label 44 | { 45 | Text = AppString.Dialog.ItemText, 46 | AutoSize = true 47 | }; 48 | protected readonly Label lblCommand = new Label 49 | { 50 | Text = AppString.Dialog.ItemCommand, 51 | AutoSize = true 52 | }; 53 | protected readonly Label lblArguments = new Label 54 | { 55 | Text = AppString.Dialog.CommandArguments, 56 | AutoSize = true 57 | }; 58 | protected readonly TextBox txtText = new TextBox(); 59 | protected readonly TextBox txtFilePath = new TextBox(); 60 | protected readonly TextBox txtArguments = new TextBox(); 61 | protected readonly Button btnBrowse = new Button 62 | { 63 | Text = AppString.Dialog.Browse, 64 | AutoSize = true 65 | }; 66 | protected readonly Button btnOK = new Button 67 | { 68 | Text = ResourceString.OK, 69 | AutoSize = true 70 | }; 71 | protected readonly Button btnCancel = new Button 72 | { 73 | DialogResult = DialogResult.Cancel, 74 | Text = ResourceString.Cancel, 75 | AutoSize = true 76 | }; 77 | 78 | protected virtual void InitializeComponents() 79 | { 80 | Controls.AddRange(new Control[] { lblText, lblCommand, lblArguments, 81 | txtText, txtFilePath, txtArguments, btnBrowse, btnOK, btnCancel }); 82 | int a = 20.DpiZoom(); 83 | btnBrowse.Anchor = btnOK.Anchor = btnCancel.Anchor = AnchorStyles.Right | AnchorStyles.Top; 84 | txtText.Top = lblText.Top = lblText.Left = lblCommand.Left = lblArguments.Left = a; 85 | btnBrowse.Top = txtFilePath.Top = lblCommand.Top = txtText.Bottom + a; 86 | lblArguments.Top = txtArguments.Top = txtFilePath.Bottom + a; 87 | btnOK.Top = btnCancel.Top = txtArguments.Bottom + a; 88 | btnCancel.Left = btnBrowse.Left = ClientSize.Width - btnCancel.Width - a; 89 | btnOK.Left = btnCancel.Left - btnOK.Width - a; 90 | int b = Math.Max(Math.Max(lblText.Width, lblCommand.Width), lblArguments.Width) + btnBrowse.Width + 4 * a; 91 | ClientSize = new Size(320.DpiZoom() + b, btnOK.Bottom + a); 92 | MinimumSize = Size; 93 | Resize += (sender, e) => 94 | { 95 | txtText.Width = txtFilePath.Width = txtArguments.Width = ClientSize.Width - b; 96 | txtText.Left = txtFilePath.Left = txtArguments.Left = btnBrowse.Left - txtFilePath.Width - a; 97 | }; 98 | OnResize(null); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/NewLnkFileDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System; 4 | using System.IO; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls 8 | { 9 | sealed class NewLnkFileDialog : CommonDialog 10 | { 11 | public string ItemText { get; set; } 12 | public string ItemFilePath { get; set; } 13 | public string Arguments { get; set; } 14 | public string FileFilter { get; set; } 15 | public override void Reset() { } 16 | 17 | protected override bool RunDialog(IntPtr hwndOwner) 18 | { 19 | using(NewLnkForm frm = new NewLnkForm()) 20 | { 21 | frm.FileFilter = FileFilter; 22 | frm.TopMost = AppConfig.TopMost; 23 | bool flag = frm.ShowDialog() == DialogResult.OK; 24 | if(flag) 25 | { 26 | ItemText = frm.ItemText; 27 | ItemFilePath = frm.ItemFilePath; 28 | Arguments = frm.Arguments; 29 | } 30 | return flag; 31 | } 32 | } 33 | 34 | sealed class NewLnkForm : NewItemForm 35 | { 36 | public string FileFilter { get; set; } 37 | 38 | readonly RadioButton rdoFile = new RadioButton 39 | { 40 | Text = AppString.SideBar.File, 41 | AutoSize = true, 42 | Checked = true 43 | }; 44 | readonly RadioButton rdoFolder = new RadioButton 45 | { 46 | Text = AppString.SideBar.Folder, 47 | AutoSize = true 48 | }; 49 | 50 | protected override void InitializeComponents() 51 | { 52 | base.InitializeComponents(); 53 | Controls.AddRange(new Control[] { rdoFile, rdoFolder }); 54 | rdoFile.Top = rdoFolder.Top = btnOK.Top + (btnOK.Height - rdoFile.Height) / 2; 55 | rdoFile.Left = lblCommand.Left; 56 | rdoFolder.Left = rdoFile.Right + 20.DpiZoom(); 57 | 58 | btnBrowse.Click += (sender, e) => 59 | { 60 | if(rdoFile.Checked) BrowseFile(); 61 | else BrowseFolder(); 62 | }; 63 | 64 | btnOK.Click += (sender, e) => 65 | { 66 | if(ItemText.IsNullOrWhiteSpace()) 67 | { 68 | AppMessageBox.Show(AppString.Message.TextCannotBeEmpty); 69 | } 70 | else if(ItemFilePath.IsNullOrWhiteSpace()) 71 | { 72 | AppMessageBox.Show(AppString.Message.CommandCannotBeEmpty); 73 | } 74 | else if(rdoFile.Checked && !ObjectPath.GetFullFilePath(ItemFilePath, out _)) 75 | { 76 | AppMessageBox.Show(AppString.Message.FileNotExists); 77 | } 78 | else if(rdoFolder.Checked && !Directory.Exists(ItemFilePath)) 79 | { 80 | AppMessageBox.Show(AppString.Message.FolderNotExists); 81 | } 82 | else DialogResult = DialogResult.OK; 83 | }; 84 | 85 | txtFilePath.TextChanged += (sender, e) => 86 | { 87 | if(Path.GetExtension(ItemFilePath).ToLower() == ".lnk") 88 | { 89 | using(ShellLink shortcut = new ShellLink(ItemFilePath)) 90 | { 91 | if(File.Exists(shortcut.TargetPath)) 92 | { 93 | ItemFilePath = shortcut.TargetPath; 94 | } 95 | } 96 | } 97 | }; 98 | } 99 | 100 | private void BrowseFile() 101 | { 102 | using(OpenFileDialog dlg = new OpenFileDialog()) 103 | { 104 | dlg.Filter = FileFilter; 105 | //取消获取lnk目标路径,可选中UWP快捷方式 106 | dlg.DereferenceLinks = false; 107 | if(dlg.ShowDialog() == DialogResult.OK) 108 | { 109 | ItemFilePath = dlg.FileName; 110 | string extension = Path.GetExtension(dlg.FileName).ToLower(); 111 | if(extension == ".lnk") 112 | { 113 | using(ShellLink shortcut = new ShellLink(dlg.FileName)) 114 | { 115 | if(File.Exists(shortcut.TargetPath)) 116 | { 117 | ItemFilePath = shortcut.TargetPath; 118 | Arguments = shortcut.Arguments; 119 | } 120 | } 121 | } 122 | ItemText = Path.GetFileNameWithoutExtension(dlg.FileName); 123 | } 124 | } 125 | } 126 | 127 | private void BrowseFolder() 128 | { 129 | using(FolderBrowserDialog dlg = new FolderBrowserDialog()) 130 | { 131 | if(Directory.Exists(ItemFilePath)) dlg.SelectedPath = ItemFilePath; 132 | else dlg.SelectedPath = Application.StartupPath; 133 | if(dlg.ShowDialog() == DialogResult.OK) 134 | { 135 | ItemFilePath = dlg.SelectedPath; 136 | ItemText = Path.GetFileNameWithoutExtension(dlg.SelectedPath); 137 | } 138 | } 139 | } 140 | } 141 | } 142 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/NewOpenWithDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using ContextMenuManager.Methods; 3 | using System; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Windows.Forms; 7 | 8 | namespace ContextMenuManager.Controls 9 | { 10 | sealed class NewOpenWithDialog : CommonDialog 11 | { 12 | public string RegPath { get; private set; } 13 | public override void Reset() { } 14 | 15 | protected override bool RunDialog(IntPtr hwndOwner) 16 | { 17 | using(NewOpenWithForm frm = new NewOpenWithForm()) 18 | { 19 | frm.TopMost = AppConfig.TopMost; 20 | bool flag = frm.ShowDialog() == DialogResult.OK; 21 | if(flag) RegPath = frm.RegPath; 22 | return flag; 23 | } 24 | } 25 | 26 | sealed class NewOpenWithForm : NewItemForm 27 | { 28 | public string RegPath { get; private set; } 29 | 30 | private string FilePath; 31 | private string FileName => Path.GetFileName(FilePath); 32 | private string AppRegPath => $@"{RegistryEx.CLASSES_ROOT}\Applications\{FileName}"; 33 | private string CommandPath => $@"{AppRegPath}\shell\open\command"; 34 | 35 | protected override void InitializeComponents() 36 | { 37 | base.InitializeComponents(); 38 | btnBrowse.Click += (sender, e) => BrowseFile(); 39 | btnOK.Click += (sender, e) => 40 | { 41 | if(string.IsNullOrEmpty(ItemText)) 42 | { 43 | AppMessageBox.Show(AppString.Message.TextCannotBeEmpty); 44 | return; 45 | } 46 | if(ItemCommand.IsNullOrWhiteSpace()) 47 | { 48 | AppMessageBox.Show(AppString.Message.CommandCannotBeEmpty); 49 | return; 50 | } 51 | FilePath = ObjectPath.ExtractFilePath(base.ItemFilePath); 52 | using(var key = RegistryEx.GetRegistryKey(CommandPath)) 53 | { 54 | string path = ObjectPath.ExtractFilePath(key?.GetValue("")?.ToString()); 55 | string name = Path.GetFileName(path); 56 | if(FilePath != null && FilePath.Equals(path, StringComparison.OrdinalIgnoreCase)) 57 | { 58 | AppMessageBox.Show(AppString.Message.HasBeenAdded); 59 | return; 60 | } 61 | if(FileName == null || FileName.Equals(name, StringComparison.OrdinalIgnoreCase)) 62 | { 63 | AppMessageBox.Show(AppString.Message.UnsupportedFilename); 64 | return; 65 | } 66 | } 67 | AddNewItem(); 68 | DialogResult = DialogResult.OK; 69 | }; 70 | } 71 | 72 | private void BrowseFile() 73 | { 74 | using(OpenFileDialog dlg = new OpenFileDialog()) 75 | { 76 | dlg.Filter = $"{AppString.Dialog.Program}|*.exe"; 77 | if(dlg.ShowDialog() == DialogResult.OK) 78 | { 79 | base.ItemFilePath = dlg.FileName; 80 | Arguments = "\"%1\""; 81 | ItemText = FileVersionInfo.GetVersionInfo(dlg.FileName).FileDescription; 82 | } 83 | } 84 | } 85 | 86 | private void AddNewItem() 87 | { 88 | using(var key = RegistryEx.GetRegistryKey(AppRegPath, true, true)) 89 | { 90 | key.SetValue("FriendlyAppName", ItemText); 91 | } 92 | using(var cmdKey = RegistryEx.GetRegistryKey(CommandPath, true, true)) 93 | { 94 | cmdKey.SetValue("", ItemCommand); 95 | RegPath = cmdKey.Name; 96 | } 97 | } 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/OpenWithItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Controls.Interfaces; 4 | using ContextMenuManager.Methods; 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Diagnostics; 8 | using System.Drawing; 9 | using System.IO; 10 | using System.Windows.Forms; 11 | 12 | namespace ContextMenuManager.Controls 13 | { 14 | sealed class OpenWithItem : MyListItem, IChkVisibleItem, IBtnShowMenuItem, ITsiTextItem, 15 | ITsiCommandItem, ITsiWebSearchItem, ITsiFilePathItem, ITsiRegPathItem, ITsiRegDeleteItem, ITsiRegExportItem 16 | { 17 | 18 | public OpenWithItem(string regPath) 19 | { 20 | InitializeComponents(); 21 | RegPath = regPath; 22 | } 23 | 24 | private string regPath; 25 | public string RegPath 26 | { 27 | get => regPath; 28 | set 29 | { 30 | regPath = value; 31 | ItemFilePath = ObjectPath.ExtractFilePath(ItemCommand); 32 | Text = ItemText; 33 | Image = ItemIcon.ToBitmap(); 34 | } 35 | } 36 | public string ValueName => null; 37 | private string ShellPath => RegistryEx.GetParentPath(RegPath); 38 | private string AppPath => RegistryEx.GetParentPath(RegistryEx.GetParentPath(ShellPath)); 39 | private bool NameEquals => RegistryEx.GetKeyName(AppPath).Equals(Path.GetFileName(ItemFilePath), StringComparison.OrdinalIgnoreCase); 40 | private Icon ItemIcon => Icon.ExtractAssociatedIcon(ItemFilePath); 41 | 42 | public string ItemText 43 | { 44 | get 45 | { 46 | string name = null; 47 | if(NameEquals) 48 | { 49 | name = Registry.GetValue(AppPath, "FriendlyAppName", null)?.ToString(); 50 | name = ResourceString.GetDirectString(name); 51 | } 52 | if(string.IsNullOrEmpty(name)) name = FileVersionInfo.GetVersionInfo(ItemFilePath).FileDescription; 53 | if(string.IsNullOrEmpty(name)) name = Path.GetFileName(ItemFilePath); 54 | return name; 55 | } 56 | set 57 | { 58 | Registry.SetValue(AppPath, "FriendlyAppName", value); 59 | Text = ResourceString.GetDirectString(value); 60 | } 61 | } 62 | 63 | public string ItemCommand 64 | { 65 | get => Registry.GetValue(RegPath, "", null)?.ToString(); 66 | set 67 | { 68 | if(ObjectPath.ExtractFilePath(value) != ItemFilePath) 69 | { 70 | AppMessageBox.Show(AppString.Message.CannotChangePath); 71 | } 72 | else Registry.SetValue(RegPath, "", value); 73 | } 74 | } 75 | 76 | public bool ItemVisible 77 | { 78 | get => Registry.GetValue(AppPath, "NoOpenWith", null) == null; 79 | set 80 | { 81 | if(value) RegistryEx.DeleteValue(AppPath, "NoOpenWith"); 82 | else Registry.SetValue(AppPath, "NoOpenWith", ""); 83 | } 84 | } 85 | 86 | public string SearchText => $"{AppString.SideBar.OpenWith} {Text}"; 87 | public string ItemFilePath { get; private set; } 88 | public string ItemFileName => Path.GetFileName(ItemFilePath); 89 | 90 | public VisibleCheckBox ChkVisible { get; set; } 91 | public MenuButton BtnShowMenu { get; set; } 92 | public ChangeTextMenuItem TsiChangeText { get; set; } 93 | public ChangeCommandMenuItem TsiChangeCommand { get; set; } 94 | public WebSearchMenuItem TsiSearch { get; set; } 95 | public FilePropertiesMenuItem TsiFileProperties { get; set; } 96 | public FileLocationMenuItem TsiFileLocation { get; set; } 97 | public RegLocationMenuItem TsiRegLocation { get; set; } 98 | public DeleteMeMenuItem TsiDeleteMe { get; set; } 99 | public RegExportMenuItem TsiRegExport { get; set; } 100 | 101 | readonly RToolStripMenuItem TsiDetails = new RToolStripMenuItem(AppString.Menu.Details); 102 | 103 | private void InitializeComponents() 104 | { 105 | BtnShowMenu = new MenuButton(this); 106 | ChkVisible = new VisibleCheckBox(this); 107 | TsiChangeText = new ChangeTextMenuItem(this); 108 | TsiChangeCommand = new ChangeCommandMenuItem(this); 109 | TsiSearch = new WebSearchMenuItem(this); 110 | TsiFileProperties = new FilePropertiesMenuItem(this); 111 | TsiFileLocation = new FileLocationMenuItem(this); 112 | TsiRegLocation = new RegLocationMenuItem(this); 113 | TsiRegExport = new RegExportMenuItem(this); 114 | TsiDeleteMe = new DeleteMeMenuItem(this); 115 | 116 | ContextMenuStrip.Items.AddRange(new ToolStripItem[] { TsiChangeText, 117 | new RToolStripSeparator(), TsiDetails, new RToolStripSeparator(), TsiDeleteMe }); 118 | 119 | TsiDetails.DropDownItems.AddRange(new ToolStripItem[] { TsiSearch, new RToolStripSeparator(), 120 | TsiChangeCommand, TsiFileProperties, TsiFileLocation, TsiRegLocation, TsiRegExport }); 121 | 122 | ContextMenuStrip.Opening += (sender, e) => TsiChangeText.Enabled = NameEquals; 123 | } 124 | 125 | public void DeleteMe() 126 | { 127 | RegistryEx.DeleteKeyTree(RegPath); 128 | using(RegistryKey key = RegistryEx.GetRegistryKey(ShellPath)) 129 | { 130 | if(key.GetSubKeyNames().Length == 0) RegistryEx.DeleteKeyTree(AppPath); 131 | } 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/OpenWithList.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using Microsoft.Win32; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Windows.Forms; 9 | 10 | namespace ContextMenuManager.Controls 11 | { 12 | sealed class OpenWithList : MyList // 主页 打开方式 13 | { 14 | public void LoadItems() 15 | { 16 | LoadOpenWithItems(); 17 | SortItemByText(); 18 | AddNewItem(); 19 | //Win8及以上版本系统才有在应用商店中查找应用 20 | if (WinOsVersion.Current >= WinOsVersion.Win8) 21 | { 22 | VisibleRegRuleItem storeItem = new VisibleRegRuleItem(VisibleRegRuleItem.UseStoreOpenWith); 23 | InsertItem(storeItem, 1); 24 | } 25 | } 26 | 27 | private void LoadOpenWithItems() 28 | { 29 | using(RegistryKey root = Registry.ClassesRoot) 30 | using(RegistryKey appKey = root.OpenSubKey("Applications")) 31 | { 32 | foreach(string appName in appKey.GetSubKeyNames()) 33 | { 34 | if(!appName.Contains('.')) continue;//需要为有扩展名的文件名 35 | using(RegistryKey shellKey = appKey.OpenSubKey($@"{appName}\shell")) 36 | { 37 | if(shellKey == null) continue; 38 | 39 | List names = shellKey.GetSubKeyNames().ToList(); 40 | if(names.Contains("open", StringComparer.OrdinalIgnoreCase)) names.Insert(0, "open"); 41 | 42 | string keyName = names.Find(name => 43 | { 44 | using(RegistryKey cmdKey = shellKey.OpenSubKey(name)) 45 | return cmdKey.GetValue("NeverDefault") == null; 46 | }); 47 | if(keyName == null) continue; 48 | 49 | using(RegistryKey commandKey = shellKey.OpenSubKey($@"{keyName}\command")) 50 | { 51 | string command = commandKey?.GetValue("")?.ToString(); 52 | if(ObjectPath.ExtractFilePath(command) != null) 53 | { 54 | OpenWithItem item = new OpenWithItem(commandKey.Name); 55 | AddItem(item); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } 62 | 63 | private void AddNewItem() 64 | { 65 | NewItem newItem = new NewItem(); 66 | InsertItem(newItem, 0); 67 | newItem.AddNewItem += () => 68 | { 69 | using(NewOpenWithDialog dlg = new NewOpenWithDialog()) 70 | { 71 | if(dlg.ShowDialog() == DialogResult.OK) 72 | InsertItem(new OpenWithItem(dlg.RegPath), 2); 73 | } 74 | }; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/RForm.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System.Drawing; 3 | using System.Runtime.InteropServices; 4 | using System; 5 | using System.Windows.Forms; 6 | 7 | namespace BluePointLilac.Controls 8 | { 9 | /// 10 | /// Edited from: https://github.com/seerge/g-helper 11 | /// 12 | public class RForm : Form 13 | { 14 | protected override void OnLoad(EventArgs e) 15 | { 16 | StartPosition = FormStartPosition.CenterScreen; 17 | base.OnLoad(e); 18 | } 19 | 20 | public static Color ButtonMain => MyMainForm.ButtonMain; 21 | public static Color ButtonSecond => MyMainForm.ButtonSecond; 22 | 23 | public static Color FormBack => MyMainForm.FormBack; 24 | public static Color FormFore => MyMainForm.FormFore; 25 | public static Color FormBorder => MyMainForm.FormBorder; 26 | 27 | [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")] 28 | public static extern bool CheckSystemDarkModeStatus(); 29 | 30 | [DllImport("DwmApi")] //System.Runtime.InteropServices 31 | private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, int[] attrValue, int attrSize); 32 | 33 | public bool darkTheme = false; 34 | protected override CreateParams CreateParams 35 | { 36 | get 37 | { 38 | var parms = base.CreateParams; 39 | parms.Style &= ~0x02000000; // Turn off WS_CLIPCHILDREN 40 | parms.ClassStyle &= ~0x00020000; 41 | return parms; 42 | } 43 | } 44 | 45 | private static bool IsDarkTheme() 46 | { 47 | using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize")) 48 | { 49 | var registryValueObject = key?.GetValue("AppsUseLightTheme"); 50 | 51 | if (registryValueObject == null) return false; 52 | return (int)registryValueObject <= 0; 53 | } 54 | } 55 | 56 | public bool InitTheme() 57 | { 58 | bool newDarkTheme = IsDarkTheme(); 59 | bool changed = darkTheme != newDarkTheme; 60 | darkTheme = newDarkTheme; 61 | 62 | if (changed) 63 | { 64 | DwmSetWindowAttribute(Handle, 20, new[] { darkTheme ? 1 : 0 }, 4); 65 | Adjust(); 66 | Invalidate(); 67 | } 68 | 69 | return changed; 70 | } 71 | 72 | protected void ApplyDarkModeToDataGridView(DataGridView dgv) 73 | { 74 | // Background color 75 | dgv.BackgroundColor = MyMainForm.FormBack; 76 | dgv.DefaultCellStyle.BackColor = MyMainForm.FormBack; 77 | dgv.DefaultCellStyle.ForeColor = MyMainForm.FormFore; 78 | 79 | // Grid color 80 | dgv.GridColor = Color.DimGray; 81 | 82 | // Header style 83 | dgv.ColumnHeadersDefaultCellStyle.BackColor = MyMainForm.FormBack; 84 | dgv.ColumnHeadersDefaultCellStyle.ForeColor = MyMainForm.FormFore; 85 | dgv.ColumnHeadersDefaultCellStyle.SelectionBackColor = MyMainForm.MainColor; 86 | dgv.ColumnHeadersDefaultCellStyle.SelectionForeColor = MyMainForm.FormFore; 87 | dgv.EnableHeadersVisualStyles = false; // Ensure custom header styles apply 88 | 89 | // Row styles 90 | dgv.RowsDefaultCellStyle.BackColor = MyMainForm.FormBack; 91 | dgv.RowsDefaultCellStyle.ForeColor = MyMainForm.FormFore; 92 | dgv.AlternatingRowsDefaultCellStyle.BackColor = MyMainForm.FormBack; 93 | 94 | // Selection color 95 | dgv.DefaultCellStyle.SelectionBackColor = MyMainForm.MainColor; 96 | dgv.DefaultCellStyle.SelectionForeColor = MyMainForm.FormFore; 97 | } 98 | 99 | private void Adjust() 100 | { 101 | BackColor = FormBack; 102 | ForeColor = FormFore; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /ContextMenuManager/Controls/RToolStripMenuItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using System; 3 | using System.Drawing; 4 | using System.Windows.Forms; 5 | 6 | namespace ContextMenuManager.Controls 7 | { 8 | internal class RToolStripMenuItem : ToolStripMenuItem 9 | { 10 | public RToolStripMenuItem() : base() 11 | { 12 | ForeColor = MyMainForm.FormFore; 13 | BackColor = MyMainForm.FormBack; 14 | } 15 | 16 | public RToolStripMenuItem(string text) : base(text) 17 | { 18 | ForeColor = MyMainForm.FormFore; 19 | BackColor = MyMainForm.FormBack; 20 | } 21 | 22 | public RToolStripMenuItem(string text, Image image) : base(text, image) 23 | { 24 | ForeColor = MyMainForm.FormFore; 25 | BackColor = MyMainForm.FormBack; 26 | } 27 | 28 | public RToolStripMenuItem(string text, Image image, EventHandler onClick) : base(text, image, onClick) 29 | { 30 | ForeColor = MyMainForm.FormFore; 31 | BackColor = MyMainForm.FormBack; 32 | } 33 | 34 | public RToolStripMenuItem(string text, Image image, EventHandler onClick, string name) : base(text, image, onClick, name) 35 | { 36 | ForeColor = MyMainForm.FormFore; 37 | BackColor = MyMainForm.FormBack; 38 | } 39 | } 40 | 41 | public class RToolStripSeparator : ToolStripSeparator 42 | { 43 | public RToolStripSeparator() : base() 44 | { 45 | ForeColor = MyMainForm.FormFore; 46 | BackColor = MyMainForm.FormBack; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ContextMenuManager/Controls/RestoreItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using ContextMenuManager.Controls.Interfaces; 3 | using ContextMenuManager.Methods; 4 | using System.IO; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls 8 | { 9 | interface ITsiRestoreFile 10 | { 11 | void RestoreItems(string restoreFile); 12 | } 13 | 14 | sealed class RestoreItem : MyListItem, IBtnShowMenuItem, ITsiFilePathItem, ITsiDeleteItem, ITsiRestoreItem 15 | { 16 | public RestoreItem(ITsiRestoreFile item, string filePath, string deviceName, string creatTime) 17 | { 18 | InitializeComponents(); 19 | restoreInterface = item; 20 | FilePath = filePath; 21 | Text = AppString.Other.RestoreItemText.Replace("%device", deviceName).Replace("%time", creatTime); 22 | Image = AppImage.BackupItem; 23 | } 24 | 25 | // 恢复函数接口对象 26 | private readonly ITsiRestoreFile restoreInterface; 27 | 28 | // 备份文件目录 29 | private string filePath; 30 | public string FilePath 31 | { 32 | get => filePath; 33 | set => filePath = value; 34 | } 35 | public string ItemFilePath { get { return filePath; } } 36 | 37 | public MenuButton BtnShowMenu { get; set; } 38 | public FilePropertiesMenuItem TsiFileProperties { get; set; } 39 | public FileLocationMenuItem TsiFileLocation { get; set; } 40 | public DeleteMeMenuItem TsiDeleteMe { get; set; } 41 | public RestoreMeMenuItem TsiRestoreMe { get; set; } 42 | 43 | readonly RToolStripMenuItem TsiDetails = new RToolStripMenuItem(AppString.Menu.Details); 44 | 45 | private void InitializeComponents() 46 | { 47 | BtnShowMenu = new MenuButton(this); 48 | TsiFileLocation = new FileLocationMenuItem(this); 49 | TsiFileProperties = new FilePropertiesMenuItem(this); 50 | TsiDeleteMe = new DeleteMeMenuItem(this); 51 | TsiRestoreMe = new RestoreMeMenuItem(this); 52 | 53 | // 设置菜单:详细信息;删除备份;恢复备份 54 | ContextMenuStrip.Items.AddRange(new ToolStripItem[] { TsiDetails, new RToolStripSeparator(), 55 | TsiRestoreMe, new RToolStripSeparator(), TsiDeleteMe }); 56 | 57 | // 详细信息 58 | TsiDetails.DropDownItems.AddRange(new ToolStripItem[] { TsiFileProperties, TsiFileLocation }); 59 | } 60 | 61 | public void DeleteMe() 62 | { 63 | File.Delete(filePath); 64 | } 65 | 66 | public void RestoreMe() 67 | { 68 | restoreInterface.RestoreItems(filePath); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/RestoreListDialog.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Drawing; 7 | using System.Windows.Forms; 8 | 9 | namespace ContextMenuManager.Controls 10 | { 11 | sealed class RestoreListDialog : CommonDialog 12 | { 13 | public List RestoreData { get; set; } 14 | 15 | public override void Reset() { } 16 | 17 | protected override bool RunDialog(IntPtr hwndOwner) 18 | { 19 | MainForm mainForm = (MainForm)Control.FromHandle(hwndOwner); 20 | if (mainForm != null) 21 | { 22 | using (RestoreListForm frm = new RestoreListForm()) 23 | { 24 | frm.ShowDonateList(RestoreData); 25 | frm.Left = mainForm.Left + (mainForm.Width + mainForm.SideBar.Width - frm.Width) / 2; 26 | frm.Top = mainForm.Top + 150.DpiZoom(); 27 | frm.TopMost = AppConfig.TopMost; 28 | frm.ShowDialog(); 29 | } 30 | } 31 | return true; 32 | } 33 | 34 | sealed class RestoreListForm : RForm 35 | { 36 | public RestoreListForm() 37 | { 38 | Font = SystemFonts.DialogFont; 39 | Text = AppString.Dialog.RestoreDetails; 40 | SizeGripStyle = SizeGripStyle.Hide; 41 | StartPosition = FormStartPosition.Manual; 42 | Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); 43 | MinimizeBox = MaximizeBox = ShowInTaskbar = false; 44 | ClientSize = new Size(520, 350).DpiZoom(); 45 | MinimumSize = Size; 46 | dgvRestore.ColumnHeadersDefaultCellStyle.Alignment 47 | = dgvRestore.RowsDefaultCellStyle.Alignment 48 | = DataGridViewContentAlignment.BottomCenter; 49 | Controls.AddRange(new Control[] { lblRestore, dgvRestore }); 50 | lblRestore.Resize += (sender, e) => OnResize(null); 51 | this.AddEscapeButton(); 52 | InitTheme(); 53 | ApplyDarkModeToDataGridView(dgvRestore); 54 | } 55 | 56 | readonly DataGridView dgvRestore = new DataGridView 57 | { 58 | ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize, 59 | AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells, 60 | SelectionMode = DataGridViewSelectionMode.FullRowSelect, 61 | BackgroundColor = SystemColors.Control, 62 | BorderStyle = BorderStyle.None, 63 | AllowUserToResizeRows = false, 64 | AllowUserToAddRows = false, 65 | RowHeadersVisible = false, 66 | MultiSelect = false, 67 | ReadOnly = true 68 | }; 69 | 70 | readonly Label lblRestore = new Label { 71 | Width = 480.DpiZoom() 72 | }; 73 | 74 | protected override void OnResize(EventArgs e) 75 | { 76 | base.OnResize(e); 77 | int a = 20.DpiZoom(); 78 | lblRestore.Location = new Point(a, a); 79 | lblRestore.Width = ClientSize.Width; 80 | dgvRestore.Location = new Point(a, lblRestore.Bottom + a); 81 | dgvRestore.Width = ClientSize.Width - 2 * a; 82 | dgvRestore.Height = ClientSize.Height - 3 * a - lblRestore.Height; 83 | } 84 | 85 | public void ShowDonateList(List restoreList) 86 | { 87 | string[] heads = new[] { AppString.Dialog.ItemLocation, AppString.Dialog.RestoredValue }; 88 | dgvRestore.ColumnCount = heads.Length; 89 | dgvRestore.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; 90 | int restoreCount = restoreList.Count; 91 | for (int n = 0; n < heads.Length; n++) 92 | { 93 | dgvRestore.Columns[n].HeaderText = heads[n]; 94 | } 95 | for (int n = 0; n < restoreCount; n++) 96 | { 97 | RestoreChangedItem item = restoreList[n]; 98 | Scenes scene = item.BackupScene; 99 | string sceneText = BackupHelper.BackupScenesText[(int)scene]; 100 | string[] values; 101 | string changedValue = item.ItemData; 102 | if (changedValue == false.ToString()) changedValue = AppString.Dialog.Disabled; 103 | if (changedValue == true.ToString()) changedValue = AppString.Dialog.Enabled; 104 | if (Array.IndexOf(BackupHelper.TypeBackupScenesText, sceneText) != -1) 105 | { 106 | values = new[] { AppString.ToolBar.Type + " -> " + sceneText + " -> " + item.KeyName, changedValue }; 107 | } 108 | else if (Array.IndexOf(BackupHelper.RuleBackupScenesText, sceneText) != -1) 109 | { 110 | values = new[] { AppString.ToolBar.Rule + " -> " + sceneText + " -> " + item.KeyName, changedValue }; 111 | } 112 | else 113 | { 114 | values = new[] { AppString.ToolBar.Home + " -> " + sceneText + " -> " + item.KeyName, changedValue }; 115 | } 116 | dgvRestore.Rows.Add(values); 117 | } 118 | lblRestore.Text = AppString.Message.RestoreSucceeded.Replace("%s", restoreCount.ToString()); ; 119 | } 120 | } 121 | } 122 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/SendToList.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.IO; 6 | using System.Windows.Forms; 7 | 8 | namespace ContextMenuManager.Controls 9 | { 10 | sealed class SendToList : MyList // 主页 发送到 11 | { 12 | public static readonly string SendToPath = Environment.ExpandEnvironmentVariables(@"%AppData%\Microsoft\Windows\SendTo"); 13 | public static readonly string DefaultSendToPath = Environment.ExpandEnvironmentVariables(@"%SystemDrive%\Users\Default\AppData\Roaming\Microsoft\Windows\SendTo"); 14 | 15 | public void LoadItems() 16 | { 17 | foreach(string path in Directory.GetFileSystemEntries(SendToPath)) 18 | { 19 | if(Path.GetFileName(path).ToLower() == "desktop.ini") continue; 20 | AddItem(new SendToItem(path)); 21 | } 22 | SortItemByText(); 23 | AddNewItem(); 24 | AddDirItem(); // 发送到右键菜单Ink文件的文件夹存放位置 25 | AddItem(new VisibleRegRuleItem(VisibleRegRuleItem.SendToDrive)); 26 | AddItem(new VisibleRegRuleItem(VisibleRegRuleItem.DeferBuildSendTo)); 27 | } 28 | 29 | private void AddNewItem() 30 | { 31 | NewItem newItem = new NewItem(); 32 | InsertItem(newItem, 0); 33 | newItem.AddNewItem += () => 34 | { 35 | using(NewLnkFileDialog dlg = new NewLnkFileDialog()) 36 | { 37 | dlg.FileFilter = $"{AppString.Dialog.Program}|*.exe;*.bat;*.cmd;*.vbs;*.vbe;*.js;*.jse;*.wsf"; 38 | if(dlg.ShowDialog() != DialogResult.OK) return; 39 | string lnkPath = $@"{SendToPath}\{ObjectPath.RemoveIllegalChars(dlg.ItemText)}.lnk"; 40 | lnkPath = ObjectPath.GetNewPathWithIndex(lnkPath, ObjectPath.PathType.File); 41 | using(ShellLink shellLink = new ShellLink(lnkPath)) 42 | { 43 | shellLink.TargetPath = dlg.ItemFilePath; 44 | shellLink.WorkingDirectory = Path.GetDirectoryName(dlg.ItemFilePath); 45 | shellLink.Arguments = dlg.Arguments; 46 | shellLink.Save(); 47 | } 48 | DesktopIni.SetLocalizedFileNames(lnkPath, dlg.ItemText); 49 | InsertItem(new SendToItem(lnkPath), 2); 50 | } 51 | }; 52 | } 53 | 54 | private void AddDirItem() 55 | { 56 | MyListItem item = new MyListItem 57 | { 58 | Text = Path.GetFileNameWithoutExtension(SendToPath), 59 | Image = ResourceIcon.GetFolderIcon(SendToPath).ToBitmap() 60 | }; 61 | PictureButton btnPath = new PictureButton(AppImage.Open); 62 | ToolTipBox.SetToolTip(btnPath, AppString.Menu.FileLocation); 63 | btnPath.MouseDown += (sender, e) => ExternalProgram.OpenDirectory(SendToPath); 64 | item.AddCtr(btnPath); 65 | InsertItem(item, 1); 66 | item.ContextMenuStrip = new ContextMenuStrip(); 67 | var tsiRestoreDefault = new RToolStripMenuItem(AppString.Menu.RestoreDefault); 68 | item.ContextMenuStrip.Items.Add(tsiRestoreDefault); 69 | tsiRestoreDefault.Enabled = Directory.Exists(DefaultSendToPath); 70 | tsiRestoreDefault.Click += (sender, e) => 71 | { 72 | if(AppMessageBox.Show(AppString.Message.RestoreDefault, MessageBoxButtons.OKCancel) == DialogResult.OK) 73 | { 74 | File.SetAttributes(SendToPath, FileAttributes.Normal); 75 | Directory.Delete(SendToPath, true); 76 | Directory.CreateDirectory(SendToPath); 77 | File.SetAttributes(SendToPath, File.GetAttributes(DefaultSendToPath)); 78 | foreach(string srcPath in Directory.GetFiles(DefaultSendToPath)) 79 | { 80 | string dstPath = $@"{SendToPath}\{Path.GetFileName(srcPath)}"; 81 | File.Copy(srcPath, dstPath); 82 | } 83 | ClearItems(); 84 | LoadItems(); 85 | } 86 | }; 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/SubItemsForm.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System.Drawing; 5 | using System.Windows.Forms; 6 | 7 | namespace ContextMenuManager.Controls 8 | { 9 | sealed class SubItemsForm : RForm 10 | { 11 | public SubItemsForm() 12 | { 13 | SuspendLayout(); 14 | StartPosition = FormStartPosition.CenterParent; 15 | ShowInTaskbar = MaximizeBox = MinimizeBox = false; 16 | MinimumSize = Size = new Size(646, 419).DpiZoom(); 17 | Controls.AddRange(new Control[] { listBox, statusBar }); 18 | statusBar.CanMoveForm(); 19 | this.AddEscapeButton(); 20 | ResumeLayout(); 21 | InitTheme(); 22 | } 23 | 24 | readonly MyListBox listBox = new MyListBox { Dock = DockStyle.Fill }; 25 | readonly MyStatusBar statusBar = new MyStatusBar(); 26 | 27 | public void AddList(MyList myList) 28 | { 29 | myList.Owner = listBox; 30 | myList.HoveredItemChanged += (sender, e) => 31 | { 32 | if(!AppConfig.ShowFilePath) return; 33 | MyListItem item = myList.HoveredItem; 34 | foreach(string prop in new[] { "ItemFilePath", "RegPath", "GroupPath" }) 35 | { 36 | string path = item.GetType().GetProperty(prop)?.GetValue(item, null)?.ToString(); 37 | if(!path.IsNullOrWhiteSpace()) { statusBar.Text = path; return; } 38 | } 39 | statusBar.Text = item.Text; 40 | }; 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/SwitchDicList.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.Drawing; 6 | using System.Windows.Forms; 7 | 8 | namespace ContextMenuManager.Controls 9 | { 10 | class SwitchDicList : MyList // 其他菜单 增强菜单 11 | { 12 | public bool UseUserDic { get; set; } 13 | 14 | public virtual void LoadItems() 15 | { 16 | AddSwitchItem(); 17 | } 18 | 19 | public void AddSwitchItem() 20 | { 21 | SwitchDicItem item = new SwitchDicItem { UseUserDic = UseUserDic }; 22 | item.UseDicChanged += () => 23 | { 24 | UseUserDic = item.UseUserDic; 25 | ClearItems(); 26 | LoadItems(); 27 | }; 28 | AddItem(item); 29 | } 30 | } 31 | 32 | sealed class SwitchDicItem : MyListItem 33 | { 34 | public SwitchDicItem() 35 | { 36 | Text = AppString.Other.SwitchDictionaries; 37 | AddCtr(cmbDic); 38 | cmbDic.AutosizeDropDownWidth(); 39 | cmbDic.Font = new Font(Font.FontFamily, Font.Size + 1F); 40 | cmbDic.Items.AddRange(new[] { AppString.Other.WebDictionaries, AppString.Other.UserDictionaries }); 41 | cmbDic.SelectionChangeCommitted += (sender, e) => 42 | { 43 | Focus(); 44 | UseUserDic = cmbDic.SelectedIndex == 1; 45 | }; 46 | } 47 | 48 | private bool? useUserDic = null; 49 | public bool UseUserDic 50 | { 51 | get => useUserDic == true; 52 | set 53 | { 54 | if(useUserDic == value) return; 55 | bool flag = useUserDic == null; 56 | useUserDic = value; 57 | Image = UseUserDic ? AppImage.User : AppImage.Web; 58 | cmbDic.SelectedIndex = value ? 1 : 0; 59 | if(!flag) UseDicChanged?.Invoke(); 60 | } 61 | } 62 | 63 | public Action UseDicChanged; 64 | 65 | readonly RComboBox cmbDic = new RComboBox 66 | { 67 | DropDownStyle = ComboBoxStyle.DropDownList, 68 | Width = 120.DpiZoom() 69 | }; 70 | } 71 | } -------------------------------------------------------------------------------- /ContextMenuManager/Controls/UwpModeItem.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Controls.Interfaces; 4 | using ContextMenuManager.Methods; 5 | using Microsoft.Win32; 6 | using System; 7 | using System.Windows.Forms; 8 | 9 | namespace ContextMenuManager.Controls 10 | { 11 | sealed class UwpModeItem : MyListItem, IChkVisibleItem, ITsiRegPathItem, ITsiFilePathItem, 12 | IBtnShowMenuItem, ITsiWebSearchItem, ITsiRegExportItem, ITsiRegDeleteItem, ITsiGuidItem 13 | { 14 | public UwpModeItem(string uwpName, Guid guid) 15 | { 16 | Guid = guid; 17 | UwpName = uwpName; 18 | InitializeComponents(); 19 | Visible = UwpHelper.GetPackageName(uwpName) != null; 20 | Image = GuidInfo.GetImage(guid); 21 | Text = ItemText; 22 | } 23 | 24 | public Guid Guid { get; set; } 25 | public string UwpName { get; set; } 26 | 27 | public bool ItemVisible // 是否显示于右键菜单中 28 | { 29 | get 30 | { 31 | foreach(string path in GuidBlockedList.BlockedPaths) 32 | { 33 | using(RegistryKey key = RegistryEx.GetRegistryKey(path)) 34 | { 35 | if(key == null) continue; 36 | if(key.GetValue(Guid.ToString("B")) != null) return false; 37 | } 38 | } 39 | return true; 40 | } 41 | set 42 | { 43 | foreach(string path in GuidBlockedList.BlockedPaths) 44 | { 45 | if(value) 46 | { 47 | RegistryEx.DeleteValue(path, Guid.ToString("B")); 48 | } 49 | else 50 | { 51 | Registry.SetValue(path, Guid.ToString("B"), ""); 52 | } 53 | } 54 | ExplorerRestarter.Show(); 55 | } 56 | } 57 | 58 | public string ItemText => GuidInfo.GetText(Guid); 59 | public string RegPath => UwpHelper.GetRegPath(UwpName, Guid); 60 | public string ItemFilePath => UwpHelper.GetFilePath(UwpName, Guid); 61 | 62 | public string SearchText => Text; 63 | public string ValueName => "DllPath"; 64 | public MenuButton BtnShowMenu { get; set; } 65 | public VisibleCheckBox ChkVisible { get; set; } 66 | public DetailedEditButton BtnDetailedEdit { get; set; } 67 | public RegLocationMenuItem TsiRegLocation { get; set; } 68 | public FileLocationMenuItem TsiFileLocation { get; set; } 69 | public FilePropertiesMenuItem TsiFileProperties { get; set; } 70 | public WebSearchMenuItem TsiSearch { get; set; } 71 | public DeleteMeMenuItem TsiDeleteMe { get; set; } 72 | public RegExportMenuItem TsiRegExport { get; set; } 73 | public HandleGuidMenuItem TsiHandleGuid { get; set; } 74 | 75 | readonly RToolStripMenuItem TsiDetails = new RToolStripMenuItem(AppString.Menu.Details); 76 | 77 | private void InitializeComponents() 78 | { 79 | BtnShowMenu = new MenuButton(this); 80 | ChkVisible = new VisibleCheckBox(this); 81 | BtnDetailedEdit = new DetailedEditButton(this); 82 | TsiSearch = new WebSearchMenuItem(this); 83 | TsiFileLocation = new FileLocationMenuItem(this); 84 | TsiFileProperties = new FilePropertiesMenuItem(this); 85 | TsiRegLocation = new RegLocationMenuItem(this); 86 | TsiDeleteMe = new DeleteMeMenuItem(this); 87 | TsiRegExport = new RegExportMenuItem(this); 88 | TsiHandleGuid = new HandleGuidMenuItem(this); 89 | 90 | ContextMenuStrip.Items.AddRange(new ToolStripItem[] { TsiHandleGuid, 91 | new RToolStripSeparator(), TsiDetails, new RToolStripSeparator(), TsiDeleteMe }); 92 | TsiDetails.DropDownItems.AddRange(new ToolStripItem[] { TsiSearch, new RToolStripSeparator(), 93 | TsiFileProperties, TsiFileLocation, TsiRegLocation, TsiRegExport }); 94 | } 95 | 96 | public void DeleteMe() 97 | { 98 | RegistryEx.DeleteKeyTree(RegPath); 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /ContextMenuManager/Methods/AppMessageBox.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System.Windows.Forms; 3 | 4 | namespace ContextMenuManager.Methods 5 | { 6 | public static class AppMessageBox 7 | { 8 | public static DialogResult Show(string text, MessageBoxButtons buttons = MessageBoxButtons.OK, 9 | MessageBoxIcon icon = MessageBoxIcon.Warning, string caption = null) 10 | { 11 | return MessageBoxEx.Show(text, caption ?? AppString.General.AppName, buttons, icon); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ContextMenuManager/Methods/DesktopIni.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using System.IO; 3 | 4 | namespace ContextMenuManager.Methods 5 | { 6 | static class DesktopIni 7 | { 8 | private const string LocalizedFileNames = "LocalizedFileNames"; 9 | 10 | public static string GetDesktopIniPath(string filePath) => $@"{Path.GetDirectoryName(filePath)}\desktop.ini"; 11 | 12 | public static void DeleteLocalizedFileNames(string filePath) 13 | { 14 | IniWriter writer = new IniWriter(GetDesktopIniPath(filePath)); 15 | string fileName = Path.GetFileName(filePath); 16 | writer.DeleteKey(LocalizedFileNames, fileName); 17 | } 18 | 19 | public static void SetLocalizedFileNames(string filePath, string name) 20 | { 21 | IniWriter writer = new IniWriter(GetDesktopIniPath(filePath)); 22 | string fileName = Path.GetFileName(filePath); 23 | writer.SetValue(LocalizedFileNames, fileName, name); 24 | } 25 | 26 | public static string GetLocalizedFileNames(string filePath, bool translate = false) 27 | { 28 | IniWriter writer = new IniWriter(GetDesktopIniPath(filePath)); 29 | string fileName = Path.GetFileName(filePath); 30 | string name = writer.GetValue(LocalizedFileNames, fileName); 31 | if(translate) name = ResourceString.GetDirectString(name); 32 | return name; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ContextMenuManager/Methods/UwpHelper.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Methods; 2 | using Microsoft.Win32; 3 | using System; 4 | using System.IO; 5 | 6 | namespace ContextMenuManager.Methods 7 | { 8 | static class UwpHelper 9 | { 10 | private const string PackageRegPath = @"HKEY_CLASSES_ROOT\PackagedCom\Package"; 11 | private const string PackagesRegPath = @"HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\PackageRepository\Packages"; 12 | 13 | public static string GetPackageName(string uwpName) 14 | { 15 | if(string.IsNullOrEmpty(uwpName)) return null; 16 | using(RegistryKey packageKey = RegistryEx.GetRegistryKey(PackageRegPath)) 17 | { 18 | if(packageKey == null) return null; 19 | foreach(string packageName in packageKey.GetSubKeyNames()) 20 | { 21 | if(packageName.StartsWith(uwpName, StringComparison.OrdinalIgnoreCase)) 22 | { 23 | return packageName; 24 | } 25 | } 26 | } 27 | return null; 28 | } 29 | 30 | public static string GetRegPath(string uwpName, Guid guid) 31 | { 32 | string packageName = GetPackageName(uwpName); 33 | if(packageName == null) return null; 34 | else return $@"{PackageRegPath}\{packageName}\Class\{guid:B}"; 35 | } 36 | 37 | public static string GetFilePath(string uwpName, Guid guid) 38 | { 39 | string regPath = GetRegPath(uwpName, guid); 40 | if(regPath == null) return null; 41 | string packageName = GetPackageName(uwpName); 42 | using(RegistryKey pKey = RegistryEx.GetRegistryKey($@"{PackagesRegPath}\{packageName}")) 43 | { 44 | if(pKey == null) return null; 45 | string dirPath = pKey.GetValue("Path")?.ToString(); 46 | string dllPath = Registry.GetValue(regPath, "DllPath", null)?.ToString(); 47 | string filePath = $@"{dirPath}\{dllPath}"; 48 | if(File.Exists(filePath)) return filePath; 49 | string[] names = pKey.GetSubKeyNames(); 50 | if(names.Length == 1) 51 | { 52 | filePath = "shell:AppsFolder\\" + names[0]; 53 | return filePath; 54 | } 55 | if(Directory.Exists(dirPath)) return dirPath; 56 | return null; 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ContextMenuManager/Program.cs: -------------------------------------------------------------------------------- 1 | using BluePointLilac.Controls; 2 | using BluePointLilac.Methods; 3 | using ContextMenuManager.Methods; 4 | using System; 5 | using System.IO; 6 | using System.Windows.Forms; 7 | 8 | namespace ContextMenuManager 9 | { 10 | //兼容.Net3.5和.Net4.0,兼容Vista - Win11 11 | static class Program 12 | { 13 | [STAThread] 14 | static void Main() 15 | { 16 | #if DEBUG 17 | if (AppConfig.EnableLog) 18 | { 19 | using (StreamWriter sw = new StreamWriter(AppConfig.DebugLogPath, true)) 20 | { 21 | sw.WriteLine($@"--------------------{DateTime.Now:yyyy-MM-dd HH:mm:ss}--------------------"); 22 | } 23 | } 24 | #endif 25 | MyMainForm.InitColors(); 26 | Application.EnableVisualStyles(); 27 | Application.SetCompatibleTextRenderingDefault(false); 28 | if(SingleInstance.IsRunning()) return; 29 | AppString.LoadStrings(); 30 | Updater.PeriodicUpdate(); 31 | XmlDicHelper.ReloadDics(); 32 | Application.Run(new MainForm()); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ContextMenuManager/Properties/App.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | true 23 | 24 | 25 | -------------------------------------------------------------------------------- /ContextMenuManager/Properties/AppIcon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/AppIcon.ico -------------------------------------------------------------------------------- /ContextMenuManager/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("右键菜单管理工具")] 5 | [assembly: AssemblyDescription("右键菜单管理工具")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("蓝点lilac Jack251970")] 8 | [assembly: AssemblyProduct("右键菜单管理工具")] 9 | [assembly: AssemblyCopyright("Copyright @ 2020-2025 蓝点lilac Jack251970")] 10 | [assembly: AssemblyTrademark("蓝点lilac Jack25197")] 11 | [assembly: AssemblyCulture("")] 12 | [assembly: ComVisible(false)] 13 | [assembly: Guid("35190ec1-2515-488d-a2e9-825d6ff67aa2")] 14 | [assembly: AssemblyVersion("3.4.0.1")] 15 | [assembly: AssemblyFileVersion("3.4.0.1")] -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/About.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/About.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Add.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/AddExisting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/AddExisting.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/AddSeparator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/AddSeparator.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/BackupItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/BackupItem.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/CheckUpdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/CheckUpdate.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/ContextMenuStyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/ContextMenuStyle.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Custom.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Delete.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Donate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Donate.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/DownLoad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/DownLoad.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Enhance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Enhance.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Home.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Jump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Jump.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/MicrosoftStore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/MicrosoftStore.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/NewFolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/NewFolder.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/NewItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/NewItem.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Open.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Refresh.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Select.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Setting.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Sort.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Star.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/SubItems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/SubItems.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Translate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Translate.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Type.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Up.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/User.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/User.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Images/Web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/Images/Web.png -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | return 0; 6 | } -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/ShellNew/0.rar -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.reg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/ShellNew/0.reg -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1} -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/ContextMenuManager/Properties/Resources/ShellNew/0.xlsx -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/ShellNew/0.zip: -------------------------------------------------------------------------------- 1 | PK -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Resources/Texts/UwpModeItemsDic.xml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ContextMenuManager.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.6.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ContextMenuManager/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Logo/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/Logo/Logo.png -------------------------------------------------------------------------------- /README-en.md: -------------------------------------------------------------------------------- 1 | **[简体中文](README.md)** | **English** 2 | 3 | # ContextMenuManager 4 | ![](Logo/Logo.png) 5 | ------ 6 | > 🖱️ A program to manage the Windows right-click context menu with support of Windows 7 - 11. 7 | 8 | ## 💕 Thanks 9 | * This project is based on [https://github.com/BluePointLilac/ContextMenuManager](https://github.com/BluePointLilac/ContextMenuManager), thanks to [蓝点lilac](https://github.com/BluePointLilac)! 10 | * Thanks to [蓝芸柒](https://github.com/LanYunSeven) for new icons! 11 | 12 | ## 🚀 Download 13 | * [Latest Version][Latest]
14 | [Github Releases][GitHub Releases]
15 | [Gitee Releases][Gitee Releases]
16 | * Note: Download the zip file (recommended) or the exe file in the Assets list 17 | * About .NET versions: This application is based on the the .Net 4.8, and it is compatible with Windows 7, 8, 8.1, 10, 11.
18 | Win8, 8.1, 10, 11 come with .NET 4.8. Vista and Win7 does not come with .NET 4.8.
You may need to install the appropriate [.NET Framework Runtime Library][.NET Framework Runtime Library]. 19 | 20 | ## ⭐ Features 21 | * Enable and disable context menu options for files, folders, submenus (e.g. open, send to), Internet Explorer, and Win+X, etc., and backup and restore right-click menus 22 | * Modify menu names and icons 23 | * Delete context menu entries 24 | * Navigate menus in the registry or File Explorer 25 | * Add custom menu items and commands 26 | 27 | ## 🖥️ Compatibility 28 | * Windows 7, 8, 8.1, 10, 11 29 | * 32 and 64 bit operating systems 30 | * Support for display scaling, optimal at 150% DPI 31 | * Localization support: contributions are welcome 32 | 33 | ## 🖼️ Screenshots 34 | 35 | 36 | 37 | Screenshots 38 | 39 | 40 | ## 🔣 Resources 41 | 42 | 43 | 44 | Resources 45 | 46 | 47 | ## 🪧 Notices 48 | * The program needs to read, write and delete a lot of registry entries and files, these behaviours are sensitive and may be mistakenly reported as viruses by Windows Defender, etc. If this happens, please add it to the whitelist by yourself. 49 | 50 | * Some special menu items (Shell extensions, file encryption, etc.) may not be displayed in the context menu, but will still show as enabled within the program; this is normal. 51 | 52 | * Different context menu manager programs may use different methods for disabling menu options. Using multiple managers at the same time is not recommended. 53 | 54 | * While other programs may use destructive methods, this program utilizes the registry keys provided by the system to hide menu items when possible. 55 | 56 | * If you have used other context menu managers in the past, use that program to restore the menu items before using this one in order to avoid any potential issues. 57 | 58 | * This program is not designed to perform clean uninstalls; however, it can help you find the registry and file locations of menu items so that they can be modified. If you are not familiar with such operations, it is recommended you use the enable/disable functions only. 59 | 60 | ## 🏆 Contributors 61 | Thanks to our amazing contributors! 62 | 63 | [![ContextMenuManager Contributors](https://contrib.rocks/image?repo=Jack251970/ContextMenuManager)](https://github.com/Jack251970/ContextMenuManager/graphs/contributors) 64 | 65 | Made with [contrib.rocks](https://contrib.rocks). 66 | 67 | [Latest]: https://github.com/Jack251970/ContextMenuManager/releases/latest 68 | [GitHub Releases]: https://github.com/Jack251970/ContextMenuManager/releases 69 | [Gitee Releases]: https://gitee.com/Jack251970/ContextMenuManager/releases 70 | [.NET Framework Runtime Library]: https://dotnet.microsoft.com/download/dotnet-framework 71 | 72 | ## ❤️ Thank You 73 | 74 | If you are enjoying this plugin, then please support my work and enthusiasm by buying me a coffee on 75 | [https://ko-fi/jackye](https://ko-fi.com/jackye). 76 | 77 | [](https://ko-fi.com/jackye) 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **简体中文** | **[English](README-en.md)** 2 | 3 | # ContextMenuManager 4 | ![](Logo/Logo.png) 5 | ------ 6 | > 🖱️ 一个纯粹的Windows右键菜单管理程序,支持 Windows 7 ~ 11。 7 | 8 | ## 💕 特别感谢 9 | * 本项目基于 [https://github.com/BluePointLilac/ContextMenuManager](https://github.com/BluePointLilac/ContextMenuManager) 进行开发,感谢作者 [蓝点lilac](https://github.com/BluePointLilac)! 10 | * 感谢由 [蓝芸柒](https://github.com/LanYunSeven) 制作的的新图标! 11 | 12 | ## 🚀 程序下载 13 | * [最新版本][Latest]
14 | [GitHub Releases][GitHub Releases]
15 | [Gitee Releases][Gitee Releases]
16 | * 下载说明:在Assets文件列表里面下载zip(建议)或者直接下载exe 17 | * .NET版本说明:程序基于.NET4.8,适用于Win11、10、8.1、8、7
18 | Win8、8.1、10、11自带.NET4.8,win7不自带.NET4.8
19 | 自带.NET可直接运行程序,不自带则需要安装对应版本的[.NET Framework运行库] 20 | 21 | ## ⭐ 主要功能 22 | * 启用或禁用文件、文件夹、新建、发送到、打开方式、自定义文件格式、IE浏览器、WinX等右键菜单项目并对右键菜单进行备份和恢复 23 | * 对上述场景右键菜单项目进行修改名称、修改图标、导航注册表位置、导航文件位置、永久删除等操作 24 | * 对上述场景右键菜单自定义添加项目,自定义菜单命令 25 | 26 | ## 🖥️ 兼容性 27 | * 适用于 Windows 7、8、8.1、10、11 28 | * 适用于 64位、32位 的系统 29 | * 适用于高分屏,最佳显示缩放比为150% 30 | * 程序支持国际化多语言显示,欢迎为此程序制作语言字典 31 | 32 | ## 🖼️ 运行截图 33 | 34 | 35 | 36 | 运行截图 37 | 38 | 39 | ## 🔣 资源引用 40 | 41 | 42 | 43 | 资源引用 44 | 45 | 46 | ## 🪧 温馨提示 47 | * 程序需要对大量的注册表项和文件进行读写删改操作,这些行为比较敏感,可能会被 Windows Defender 等误报为病毒,如发生此情况请自行添加进白名单。 48 | 49 | * 一些特殊菜单项(Shell 扩展、加密文件等)可能会受到其他因素影响导致不会直接显示在右键菜单中,但是按照程序使用的通用规则在此程序中仍会显示为启用,这是正常的现象。 50 | 51 | * 每个右键管理程序禁用菜单方法可能不同,建议不要同时使用多个右键菜单管理程序。 52 | 53 | * 大部分程序使用简单暴力的备份删除法,此程序尽可能使用了系统提供的键值进行隐藏以便于之后的恢复。 54 | 55 | * 通过其他程序禁用的菜单项目。请先使用对应程序还原,不然可能无法在此程序中看到它。 56 | 57 | * 此程序不用于清理未卸载干净的程序,但是可以帮助你快速定位菜单项相关注册表位置和文件位置,你可以根据相关内容进行你的操作。如果你是一个电脑小白,建议只使用启用/禁用功能。 58 | 59 | ## 🏆 贡献者 60 | 感谢我们的贡献者们! 61 | 62 | [![ContextMenuManager Contributors](https://contrib.rocks/image?repo=Jack251970/ContextMenuManager)](https://github.com/Jack251970/ContextMenuManager/graphs/contributors) 63 | 64 | 由 [contrib.rocks](https://contrib.rocks) 生成。 65 | 66 | [Latest]: https://github.com/Jack251970/ContextMenuManager/releases/latest 67 | [GitHub Releases]: https://github.com/Jack251970/ContextMenuManager/releases 68 | [Gitee Releases]: https://gitee.com/Jack251970/ContextMenuManager/releases 69 | [.NET Framework运行库]: https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net48 70 | 71 | ## ❤️ 感谢 72 | 73 | 要是你觉得这插件好用,就请我喝杯咖啡支持一下吧! 74 | 75 | [](https://ko-fi.com/jackye) 76 | -------------------------------------------------------------------------------- /Screenshot/AppImage-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/Screenshot/AppImage-dark.png -------------------------------------------------------------------------------- /Screenshot/AppImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/Screenshot/AppImage.png -------------------------------------------------------------------------------- /Screenshot/Screenshot-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/Screenshot/Screenshot-dark.png -------------------------------------------------------------------------------- /Screenshot/Screenshot-en-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/Screenshot/Screenshot-en-dark.png -------------------------------------------------------------------------------- /Screenshot/Screenshot-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/Screenshot/Screenshot-en.png -------------------------------------------------------------------------------- /Screenshot/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/Screenshot/Screenshot.png -------------------------------------------------------------------------------- /languages/pt-BR.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/languages/pt-BR.ini -------------------------------------------------------------------------------- /languages/ru-RU.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jack251970/ContextMenuManager/05f79d92f396125909e114754a126b086a0945ca/languages/ru-RU.ini --------------------------------------------------------------------------------