├── .gitattributes ├── .gitignore ├── ChangeFolderIcon ├── MainWindow.xaml.cs ├── Assets │ ├── icon │ │ ├── default.ico │ │ ├── app_icon.ico │ │ └── microsoft_windows_11.png │ ├── Images │ │ ├── 1_en-us.png │ │ └── 1_zh-cn.png │ └── VisualAssets │ │ ├── BadgeLogo.scale-100.png │ │ ├── BadgeLogo.scale-125.png │ │ ├── BadgeLogo.scale-150.png │ │ ├── BadgeLogo.scale-200.png │ │ ├── BadgeLogo.scale-400.png │ │ ├── LargeTile.scale-100.png │ │ ├── LargeTile.scale-125.png │ │ ├── LargeTile.scale-150.png │ │ ├── LargeTile.scale-200.png │ │ ├── LargeTile.scale-400.png │ │ ├── SmallTile.scale-100.png │ │ ├── SmallTile.scale-125.png │ │ ├── SmallTile.scale-150.png │ │ ├── SmallTile.scale-200.png │ │ ├── SmallTile.scale-400.png │ │ ├── StoreLogo.scale-100.png │ │ ├── StoreLogo.scale-125.png │ │ ├── StoreLogo.scale-150.png │ │ ├── StoreLogo.scale-200.png │ │ ├── StoreLogo.scale-400.png │ │ ├── SplashScreen.scale-100.png │ │ ├── SplashScreen.scale-125.png │ │ ├── SplashScreen.scale-150.png │ │ ├── SplashScreen.scale-200.png │ │ ├── SplashScreen.scale-400.png │ │ ├── Square44x44Logo.scale-100.png │ │ ├── Square44x44Logo.scale-125.png │ │ ├── Square44x44Logo.scale-150.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.scale-400.png │ │ ├── Wide310x150Logo.scale-100.png │ │ ├── Wide310x150Logo.scale-125.png │ │ ├── Wide310x150Logo.scale-150.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Wide310x150Logo.scale-400.png │ │ ├── Square150x150Logo.scale-100.png │ │ ├── Square150x150Logo.scale-125.png │ │ ├── Square150x150Logo.scale-150.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-400.png │ │ ├── Square44x44Logo.targetsize-16.png │ │ ├── Square44x44Logo.targetsize-24.png │ │ ├── Square44x44Logo.targetsize-32.png │ │ ├── Square44x44Logo.targetsize-48.png │ │ ├── Square44x44Logo.targetsize-256.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png │ │ └── Square44x44Logo.altform-lightunplated_targetsize-256.png ├── UserControls │ ├── IconControl.xaml.cs │ ├── WindowControl │ │ ├── CustomTitleBar.xaml.cs │ │ └── CustomTitleBar.xaml │ └── IconControl.xaml ├── Properties │ ├── launchSettings.json │ └── PublishProfiles │ │ ├── win-arm64.pubxml.user │ │ ├── win-x86.pubxml.user │ │ ├── win-x64.pubxml.user │ │ ├── win-x86.pubxml │ │ ├── win-x64.pubxml │ │ └── win-arm64.pubxml ├── Utils │ ├── Services │ │ ├── LanguageService.cs │ │ ├── SettingsService.cs │ │ ├── IconPackService.cs │ │ ├── FolderNavigationService.cs │ │ └── ElevationService.cs │ ├── Events │ │ └── IconChangedEventArgs.cs │ └── WindowsAPI │ │ ├── DpiHelper.cs │ │ └── IconManager.cs ├── App.xaml ├── Models │ └── IconInfo.cs ├── app.manifest ├── Program.cs ├── App.xaml.cs ├── Package.appxmanifest ├── ChangeFolderIcon.csproj.user ├── ChangeFolderIcon.csproj ├── MainWindow.xaml ├── Pages │ ├── SettingsPage.xaml.cs │ ├── IconsPage.xaml │ ├── IconsPage.xaml.cs │ └── SettingsPage.xaml └── Strings │ ├── en-US │ └── Resources.resw │ └── zh-CN │ └── Resources.resw ├── ElevatedWorker ├── ElevatedWorker.csproj ├── Properties │ └── PublishProfiles │ │ ├── FolderProfile.pubxml.user │ │ └── FolderProfile.pubxml ├── ElevatedWorker.csproj.user ├── Program.cs └── WindowsAPI │ └── IconManager.cs ├── README.md ├── README-EN-US.md ├── ChangeFolderIcon.iss └── ChangeFolderIcon.sln /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | /Output 3 | /ChangeFolderIcon/bin 4 | /ChangeFolderIcon/obj 5 | /ElevatedWorker/bin 6 | /ElevatedWorker/obj 7 | -------------------------------------------------------------------------------- /ChangeFolderIcon/MainWindow.xaml.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/MainWindow.xaml.cs -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/icon/default.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/icon/default.ico -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/Images/1_en-us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/Images/1_en-us.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/Images/1_zh-cn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/Images/1_zh-cn.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/icon/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/icon/app_icon.ico -------------------------------------------------------------------------------- /ChangeFolderIcon/UserControls/IconControl.xaml.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/UserControls/IconControl.xaml.cs -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/icon/microsoft_windows_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/icon/microsoft_windows_11.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/BadgeLogo.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/LargeTile.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SmallTile.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/UserControls/WindowControl/CustomTitleBar.xaml.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/UserControls/WindowControl/CustomTitleBar.xaml.cs -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-24.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-16.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-24.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-32.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-48.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YILING0013/ChangeFolderIcon/HEAD/ChangeFolderIcon/Assets/VisualAssets/Square44x44Logo.altform-lightunplated_targetsize-256.png -------------------------------------------------------------------------------- /ChangeFolderIcon/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "ChangeFolderIcon (Package)": { 4 | "commandName": "MsixPackage" 5 | }, 6 | "ChangeFolderIcon (Unpackaged)": { 7 | "commandName": "Project" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /ChangeFolderIcon/Properties/PublishProfiles/win-arm64.pubxml.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | True|2025-08-08T16:31:07.2891900Z||; 4 | 5 | 6 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Properties/PublishProfiles/win-x86.pubxml.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | True|2025-08-08T16:29:37.2645296Z||; 4 | 5 | 6 | -------------------------------------------------------------------------------- /ElevatedWorker/ElevatedWorker.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ElevatedWorker/Properties/PublishProfiles/FolderProfile.pubxml.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | True|2025-08-11T16:14:40.8837494Z||;True|2025-08-11T23:53:22.2925264+08:00||; 6 | 7 | 8 | -------------------------------------------------------------------------------- /ElevatedWorker/ElevatedWorker.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <_LastSelectedProfileId>E:\Visual_Studio_project\ChangeFolderIcon\ElevatedWorker\Properties\PublishProfiles\FolderProfile.pubxml 5 | 6 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Properties/PublishProfiles/win-x64.pubxml.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | True|2025-08-08T16:11:05.3022052Z||;True|2025-08-09T00:03:30.3577429+08:00||;True|2025-08-09T00:01:19.9752697+08:00||;True|2025-08-08T22:01:42.3759655+08:00||;False|2025-08-08T22:00:35.2751804+08:00||; 4 | 5 | 6 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Utils/Services/LanguageService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.Windows.Globalization; 7 | 8 | namespace ChangeFolderIcon.Utils.Services 9 | { 10 | public static class LanguageService 11 | { 12 | public static void SetLanguage(string language) 13 | { 14 | ApplicationLanguages.PrimaryLanguageOverride = language; 15 | // 重置资源加载器,以便更改生效。要重启应用 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Utils/Events/IconChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ChangeFolderIcon.Utils.Events 4 | { 5 | /// 6 | /// IconsPage 在图标被应用 / 清除后抛出的事件参数。 7 | /// IconPath == null 表示已清除图标。 8 | /// 9 | public sealed class IconChangedEventArgs : EventArgs 10 | { 11 | public string FolderPath { get; } 12 | public string? IconPath { get; } 13 | 14 | public IconChangedEventArgs(string folderPath, string? iconPath) 15 | { 16 | FolderPath = folderPath; 17 | IconPath = iconPath; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ElevatedWorker/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | x86 7 | bin\Release\Publish 8 | FileSystem 9 | <_TargetId>Folder 10 | net8.0 11 | win-x86 12 | true 13 | true 14 | false 15 | false 16 | 17 | -------------------------------------------------------------------------------- /ChangeFolderIcon/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Properties/PublishProfiles/win-x86.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | FileSystem 8 | x86 9 | win-x86 10 | bin\\\unpackage\publish\x86 11 | true 12 | false 13 | Release 14 | net8.0-windows10.0.22621.0 15 | true 16 | true 17 | 18 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Properties/PublishProfiles/win-x64.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | FileSystem 8 | x64 9 | win-x64 10 | bin\\\unpackage\publish\win-x64 11 | true 12 | false 13 | Release 14 | net8.0-windows10.0.22621.0 15 | false 16 | false 17 | 18 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Properties/PublishProfiles/win-arm64.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | FileSystem 8 | ARM64 9 | win-arm64 10 | bin\\\unpackage\publish\arm64 11 | true 12 | false 13 | Release 14 | net8.0-windows10.0.22621.0 15 | true 16 | true 17 | 18 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Models/IconInfo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml.Media.Imaging; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ChangeFolderIcon.Models 9 | { 10 | public class IconInfo 11 | { 12 | public string Name { get; set; } = ""; 13 | public string FullPath { get; set; } = ""; 14 | public BitmapImage IconSource { get; set; } = new BitmapImage(); 15 | 16 | public static IconInfo FromPath(string path) 17 | { 18 | return new IconInfo 19 | { 20 | Name = System.IO.Path.GetFileNameWithoutExtension(path), 21 | FullPath = path, 22 | IconSource = new BitmapImage(new Uri(path)) 23 | }; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ChangeFolderIcon/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | PerMonitorV2 17 | 18 | 19 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Utils/WindowsAPI/DpiHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ChangeFolderIcon.Utils.WindowsAPI 10 | { 11 | public class DpiHelper 12 | { 13 | // Win32 API for DPI 14 | [DllImport("user32.dll", SetLastError = true)] 15 | static extern uint GetDpiForWindow(nint hWnd); 16 | 17 | [DllImport("user32.dll", SetLastError = true)] 18 | static extern int GetSystemMetricsForDpi(int nIndex, uint dpi); 19 | 20 | // Constants for system metrics 21 | private const int SM_CXCAPTION = 4; 22 | private const int SM_CYCAPTION = 4; 23 | 24 | /// 25 | /// 获取当前窗口的DPI缩放比例 26 | /// 27 | public static double GetScaleAdjustment(Window window) 28 | { 29 | var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window); 30 | var dpi = GetDpiForWindow(hWnd); 31 | return (double)dpi / 96; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Program.cs: -------------------------------------------------------------------------------- 1 | using ChangeFolderIcon.Utils.Services; 2 | using Microsoft.UI.Dispatching; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | using Microsoft.Windows.Globalization; 11 | 12 | namespace ChangeFolderIcon 13 | { 14 | public static class Program 15 | { 16 | [STAThread] 17 | static void Main(string[] args) 18 | { 19 | WinRT.ComWrappersSupport.InitializeComWrappers(); 20 | 21 | var settingsService = new SettingsService(); 22 | var lang = settingsService.Settings.Language; 23 | 24 | if (!string.IsNullOrWhiteSpace(lang)) 25 | { 26 | ApplicationLanguages.PrimaryLanguageOverride = lang; // ← Microsoft.Windows.* 27 | } 28 | 29 | Microsoft.UI.Xaml.Application.Start(p => 30 | { 31 | var context = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread()); 32 | SynchronizationContext.SetSynchronizationContext(context); 33 | new App(); 34 | }); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ChangeFolderIcon 文件夹图标修改程序 2 | 3 | [ChangeFolderIcon](https://github.com/YILING0013/ChangeFolderIcon)是基于WinUI3以及Windows API开发的一款对Windows文件夹图标快速修改程序,支持拖入文件夹快速应用图标样式,以及创建文件夹层级目录,快捷变更每一层文件夹的图标样式。 4 | 5 | [English Version](README-EN-US.md) 6 | 7 | --- 8 | 9 | ### 预览图: 10 | 11 | ![](./ChangeFolderIcon/Assets/Images/1_zh-cn.png) 12 | 13 | ## 从源码构建 14 | 15 | #### 开发环境要求 16 | 17 | * **Visual Studio 2022** (17.0 或更高版本) 18 | * **.NET 桌面开发** 工作负载 19 | * **Windows 应用 SDK** 开发工具 20 | 21 | #### 构建步骤 22 | 23 | - [ ] 安装**Visual Studio 2022**,安装 .Net桌面开发以及WinUI 应用程序开发 24 | - [ ] 克隆项目到本地:`get clone https://github.com/YILING0013/ChangeFolderIcon.git` 25 | - [ ] 打开`ChangeFolderIcon`文件夹内的`ChangeFolderIcon.sln` 26 | - [ ] 在` Visual Studio` 中右键解决方案 → 还原 `NuGet` 包 27 | - [ ] 按 `Ctrl+Shift+B` 或菜单栏 **生成** → **生成解决方案** 28 | - [ ] 右键 `ElevatedWorker` 项目->发布,点击发布按钮 29 | - [ ] 选择 `ChangeFolderIcon` 项目,按 `F5` 启动调试,或 `Ctrl+F5` 无调试启动 30 | 31 | ### 注意事项 32 | - 确保您的系统为 Windows 10 或更高版本。 33 | - 初次运行请点击设置页,等待图标资源加载完成后点击检查更新。 34 | - 如果无法正常拉取图标资源,请检查网络连接或手动下载图标资源包,并在设置页中选择本地图标资源包。 35 | - 切换语言请在设置页中选择语言后重启程序。 36 | 37 | ## 许可证 38 | 39 | 本项目开源许可采用 [GPL-3.0 license](LICENSE)。 40 | 41 | --- 42 | 43 | ### 致谢 44 | 45 | 本项目部分图标资源来源于 [Folder-Ico](https://github.com/icon11-community/Folder-Ico),特此感谢该项目的贡献者。 46 | 47 | --- 48 | 49 | ⭐ 如果这个项目对您有帮助,请给我一个 Star!🚀 50 | -------------------------------------------------------------------------------- /ElevatedWorker/Program.cs: -------------------------------------------------------------------------------- 1 | using ElevatedWorker.WindowsAPI; 2 | using System; 3 | using System.IO; 4 | 5 | namespace ElevatedWorker 6 | { 7 | class Program 8 | { 9 | // 入口点 10 | static void Main(string[] args) 11 | { 12 | // 设计命令行参数: 13 | // args[0]: 命令 ("set" 或 "clear") 14 | // args[1]: 目标文件夹路径 15 | // args[2]: 图标文件路径 (仅 "set" 命令需要) 16 | if (args.Length < 2) 17 | { 18 | // 参数不足,直接退出 19 | return; 20 | } 21 | 22 | string command = args[0].ToLower(); 23 | string folderPath = args[1]; 24 | 25 | try 26 | { 27 | switch (command) 28 | { 29 | case "set": 30 | if (args.Length < 3) return; // "set" 命令需要3个参数 31 | string iconPath = args[2]; 32 | IconManager.SetFolderIcon(folderPath, iconPath); 33 | break; 34 | 35 | case "clear": 36 | IconManager.ClearFolderIcon(folderPath); 37 | break; 38 | } 39 | } 40 | catch (Exception ex) 41 | { 42 | string logPath = Path.Combine(Path.GetTempPath(), "ChangeFolderIcon_ElevatedWorker_Error.log"); 43 | File.WriteAllText(logPath, $"Command: {command}\nFolder: {folderPath}\nError: {ex}"); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /README-EN-US.md: -------------------------------------------------------------------------------- 1 | # ChangeFolderIcon - Folder Icon Customization Tool 2 | 3 | [ChangeFolderIcon](https://github.com/YILING0013/ChangeFolderIcon) is a Windows folder icon customization tool developed using **WinUI3** and **Windows API**. It allows quick icon modification via drag-and-drop, supports batch icon updates for nested folders, and provides predefined icon styles for easy application. 4 | 5 | [中文版本](README.md) 6 | 7 | --- 8 | 9 | ### Preview: 10 | 11 | ![](./ChangeFolderIcon/Assets/Images/1_en-us.png) 12 | 13 | ## Build from Source 14 | 15 | #### Development Requirements 16 | 17 | * **Visual Studio 2022** (Version 17.0 or later) 18 | * **.NET Desktop Development** workload 19 | * **Windows App SDK** development tools 20 | 21 | #### Build Steps 22 | 23 | - [ ] Install **Visual Studio 2022** with **.NET Desktop Development** and **WinUI App Development** workloads. 24 | - [ ] Clone the repository: `git clone https://github.com/YILING0013/ChangeFolderIcon.git` 25 | - [ ] Open `ChangeFolderIcon.sln` inside the `ChangeFolderIcon` folder. 26 | - [ ] In **Visual Studio**, right-click the solution → **Restore NuGet Packages**. 27 | - [ ] Press `Ctrl+Shift+B` or go to **Build** → **Build Solution**. 28 | - [ ] right-click `ElevatedWorker` project → **Publish**. Click the **Publish** button. 29 | - [ ] Select `ChangeFolderIcon` project, press `F5` to start debugging, or `Ctrl+F5` to start without debugging. 30 | 31 | ### Notes 32 | - Requires **Windows 10 or later**. 33 | - On first launch, go to **Settings** and wait for icon resources to load, then check for updates. 34 | - if you encounter issues fetching icon resources, check your network connection or manually download the icon resource package and select it in the settings page. 35 | - To change the language, select a language in **Settings** and restart the app. 36 | 37 | ## License 38 | 39 | This project is open-source under the [GPL-3.0 license](LICENSE). 40 | 41 | --- 42 | ### Acknowledgments 43 | 44 | Special thanks to the contributors of [Folder-Ico](https://github.com/icon11-community/Folder-Ico) for providing some of the icon resources used in this project. 45 | 46 | --- 47 | 48 | ⭐ If you find this project useful, please give it a **Star**! 🚀 49 | -------------------------------------------------------------------------------- /ChangeFolderIcon.iss: -------------------------------------------------------------------------------- 1 | ; -- Inno Setup Script -- 2 | [Setup] 3 | ; 定义应用程序的基本信息 4 | AppName=ChangeFolderIcon APP 5 | AppVersion=1.0.4 6 | AppPublisher=IDLE_CLOUD 7 | AppPublisherURL=https://github.com/YILING0013 8 | ; 安装路径, {commonpf} 表示 Program Files/Program Files (x86) 文件夹 9 | DefaultDirName={autopf}\ChangeFolderIcon 10 | ; 开始菜单组名称 11 | DefaultGroupName=ChangeFolderIcon 12 | ; 输出的安装包名称 13 | OutputBaseFilename=ChangeFolderIcon_Setup 14 | ; 使用 lzma 压缩算法 15 | Compression=lzma 16 | ; 使用固体压缩 17 | SolidCompression=yes 18 | ; 不创建程序组 19 | DisableProgramGroupPage=yes 20 | ; 设置安装程序的图标 21 | SetupIconFile=E:\Visual_Studio_project\ChangeFolderIcon\ChangeFolderIcon\Assets\icon\app_icon.ico 22 | ; 使用现代风格向导 23 | WizardStyle=modern 24 | 25 | ; 卸载设置 26 | UninstallDisplayIcon={app}\app_icon.ico 27 | UninstallDisplayName=卸载 ChangeFolderIcon 28 | 29 | [Tasks] 30 | ; 自动处理桌面图标的创建 31 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkablealone 32 | Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 33 | 34 | 35 | [Files] 36 | #define SourcePath "E:\Visual_Studio_project\ChangeFolderIcon\ChangeFolderIcon\bin\unpackage\publish\arm64" 37 | ; 将应用程序的文件添加到安装程序中 38 | Source: "{#SourcePath}\ChangeFolderIcon.exe"; DestDir: "{app}"; Flags: ignoreversion 39 | Source: "{#SourcePath}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 40 | ; 将图标文件添加到安装程序中 41 | Source: "E:\Visual_Studio_project\ChangeFolderIcon\ChangeFolderIcon\Assets\icon\app_icon.ico"; DestDir: "{app}"; Flags: ignoreversion 42 | 43 | [Icons] 44 | ; 创建桌面和开始菜单快捷方式,并设置快捷方式图标 45 | Name: "{group}\ChangeFolderIcon"; Filename: "{app}\ChangeFolderIcon.exe"; IconFilename: "{app}\app_icon.ico" 46 | Name: "{commondesktop}\ChangeFolderIcon"; Filename: "{app}\ChangeFolderIcon.exe"; Tasks: desktopicon; IconFilename: "{app}\app_icon.ico" 47 | Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\ChangeFolderIcon"; Filename: "{app}\ChangeFolderIcon.exe"; Tasks: quicklaunchicon; IconFilename: "{app}\app_icon.ico" 48 | 49 | [Run] 50 | ; 安装后自动运行应用程序 51 | Filename: "{app}\ChangeFolderIcon.exe"; Description: "{cm:LaunchProgram,ChangeFolderIcon}"; Flags: nowait postinstall skipifsilent unchecked 52 | -------------------------------------------------------------------------------- /ChangeFolderIcon/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using ChangeFolderIcon.Utils.Services; 2 | using Microsoft.UI.Xaml; 3 | using Microsoft.UI.Xaml.Controls; 4 | using Microsoft.UI.Xaml.Controls.Primitives; 5 | using Microsoft.UI.Xaml.Data; 6 | using Microsoft.UI.Xaml.Input; 7 | using Microsoft.UI.Xaml.Media; 8 | using Microsoft.UI.Xaml.Navigation; 9 | using Microsoft.UI.Xaml.Shapes; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.IO; 13 | using System.Linq; 14 | using System.Runtime.InteropServices.WindowsRuntime; 15 | using Windows.ApplicationModel; 16 | using Windows.ApplicationModel.Activation; 17 | using Windows.Foundation; 18 | using Windows.Foundation.Collections; 19 | 20 | // To learn more about WinUI, the WinUI project structure, 21 | // and more about our project templates, see: http://aka.ms/winui-project-info. 22 | 23 | namespace ChangeFolderIcon 24 | { 25 | public partial class App : Application 26 | { 27 | public static Window? window; 28 | public static SettingsService? SettingsService { get; private set; } 29 | public static IconPackService? IconPackService { get; private set; } 30 | 31 | public App() 32 | { 33 | InitializeComponent(); 34 | SettingsService = new SettingsService(); 35 | IconPackService = new IconPackService(SettingsService.Settings.IconPackRepo, SettingsService.Settings.IconRepoLocalPath); 36 | } 37 | 38 | protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) 39 | { 40 | window = new MainWindow(); 41 | 42 | ApplyThemeAndBackdropSetting(); 43 | _ = IconPackService?.UpdateIconPackAsync(); 44 | window.Activate(); 45 | } 46 | 47 | private void ApplyThemeAndBackdropSetting() 48 | { 49 | if (window is MainWindow mainWindow && SettingsService != null) 50 | { 51 | SettingsService.ApplyTheme(mainWindow, SettingsService.Settings.Theme); 52 | SettingsService.ApplyBackdrop(mainWindow, SettingsService.Settings.Backdrop); 53 | } 54 | else 55 | { 56 | throw new InvalidOperationException("Window or SettingsService is not initialized."); 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | ChangeFolderIcon 19 | xieli 20 | Assets\VisualAssets\StoreLogo.png 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 36 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /ChangeFolderIcon/ChangeFolderIcon.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 5 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 6 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 7 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 8 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 9 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 10 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 11 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 12 | E:\Visual_Studio_project\ChangeFolderIcon\Assets\icon\microsoft_windows_11.png 13 | ChangeFolderIcon (Unpackaged) 14 | <_LastSelectedProfileId>E:\Visual_Studio_project\ChangeFolderIcon\Properties\PublishProfiles\win-arm64.pubxml 15 | 16 | 17 | ProjectDebugger 18 | 19 | 20 | ProjectDebugger 21 | 22 | 23 | 24 | Designer 25 | 26 | 27 | Designer 28 | 29 | 30 | Designer 31 | 32 | 33 | Designer 34 | 35 | 36 | Designer 37 | 38 | 39 | Designer 40 | 41 | 42 | Designer 43 | 44 | 45 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Utils/Services/SettingsService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text.Json; 4 | using System.Text.Json.Serialization; 5 | using Microsoft.UI.Xaml; 6 | 7 | namespace ChangeFolderIcon.Utils.Services 8 | { 9 | public class AppSettings 10 | { 11 | public string Language { get; set; } = "en-US"; 12 | public string Theme { get; set; } = "Default"; // "Light", "Dark", "Default" 13 | public string Backdrop { get; set; } = "Mica"; // "Mica", "Acrylic", "Transparent" 14 | 15 | // 克隆仓库的目标路径 16 | public string IconRepoLocalPath { get; set; } = Path.Combine(AppContext.BaseDirectory, "Assets", "Folder11-ico"); 17 | 18 | // 图标文件所在的真实路径 (由仓库路径和ico子目录构成) 19 | [JsonIgnore] // 此属性不需要保存到json,因为它可以被推导出来 20 | public string IconPackPath => Path.Combine(IconRepoLocalPath, "ico"); 21 | 22 | public string IconPackRepo { get; set; } = "https://github.com/icon11-community/Folder11-ico.git"; 23 | } 24 | 25 | public class SettingsService 26 | { 27 | private const string ConfigFileName = "settings.json"; 28 | private static readonly string ConfigFilePath = Path.Combine(AppContext.BaseDirectory, ConfigFileName); 29 | 30 | public AppSettings Settings { get; private set; } 31 | 32 | public SettingsService() 33 | { 34 | Settings = LoadSettings(); 35 | } 36 | 37 | // 从文件加载配置 38 | private AppSettings LoadSettings() 39 | { 40 | try 41 | { 42 | if (File.Exists(ConfigFilePath)) 43 | { 44 | var json = File.ReadAllText(ConfigFilePath); 45 | return JsonSerializer.Deserialize(json) ?? new AppSettings(); 46 | } 47 | } 48 | catch (Exception) 49 | { 50 | // 如果加载失败,返回默认配置 51 | } 52 | return new AppSettings(); 53 | } 54 | 55 | // 保存配置到文件 56 | public void SaveSettings() 57 | { 58 | try 59 | { 60 | var options = new JsonSerializerOptions { WriteIndented = true }; 61 | var json = JsonSerializer.Serialize(Settings, options); 62 | File.WriteAllText(ConfigFilePath, json); 63 | } 64 | catch (Exception) 65 | { 66 | // 处理保存失败的异常 67 | } 68 | } 69 | 70 | // 应用主题设置 71 | public static void ApplyTheme(Window window, string theme) 72 | { 73 | if (window.Content is FrameworkElement rootElement) 74 | { 75 | switch (theme.ToLower()) 76 | { 77 | case "light": 78 | rootElement.RequestedTheme = ElementTheme.Light; 79 | break; 80 | case "dark": 81 | rootElement.RequestedTheme = ElementTheme.Dark; 82 | break; 83 | default: 84 | rootElement.RequestedTheme = ElementTheme.Default; 85 | break; 86 | } 87 | } 88 | } 89 | 90 | // 应用背景材质设置 91 | public static void ApplyBackdrop(MainWindow window, string backdrop) 92 | { 93 | window.SetBackdrop(backdrop); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Utils/Services/IconPackService.cs: -------------------------------------------------------------------------------- 1 | using LibGit2Sharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace ChangeFolderIcon.Utils.Services 10 | { 11 | public class IconPackService 12 | { 13 | private readonly string? _repoUrl; 14 | private readonly string? _localPath; 15 | public event Action? StatusUpdated; 16 | 17 | // 新增: 公共属性,用于暴露本地路径 18 | public string? IconPackDirectory => _localPath; 19 | 20 | public IconPackService(string repoUrl, string localPath) 21 | { 22 | _repoUrl = repoUrl; 23 | _localPath = localPath; // 直接使用传入的专用路径 24 | } 25 | 26 | public async Task UpdateIconPackAsync() 27 | { 28 | return await Task.Run(() => 29 | { 30 | try 31 | { 32 | if (string.IsNullOrEmpty(_localPath) || string.IsNullOrEmpty(_repoUrl)) 33 | { 34 | StatusUpdated?.Invoke("Repository URL or local path is not configured."); 35 | return false; 36 | } 37 | 38 | // 如果目标目录存在但不是一个有效的Git仓库,则先清理 39 | if (Directory.Exists(_localPath) && !Repository.IsValid(_localPath)) 40 | { 41 | StatusUpdated?.Invoke("Invalid repository found. Cleaning up..."); 42 | Directory.Delete(_localPath, true); 43 | } 44 | 45 | // 如果仓库目录不存在,则克隆 46 | if (!Repository.IsValid(_localPath)) 47 | { 48 | StatusUpdated?.Invoke("Cloning icon repository..."); 49 | Repository.Clone(_repoUrl, _localPath, new CloneOptions()); 50 | StatusUpdated?.Invoke("Clone successful."); 51 | return true; 52 | } 53 | 54 | // 如果目录存在且是有效仓库,则拉取更新 55 | using (var repo = new Repository(_localPath)) 56 | { 57 | StatusUpdated?.Invoke("Fetching updates..."); 58 | var remote = repo.Network.Remotes["origin"]; 59 | var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification); 60 | Commands.Fetch(repo, remote.Name, refSpecs, new FetchOptions(), ""); 61 | StatusUpdated?.Invoke("Fetch complete. Merging changes..."); 62 | 63 | var result = repo.MergeFetchedRefs(new Signature("user", "user@example.com", DateTimeOffset.Now), new MergeOptions()); 64 | 65 | if (result.Status == MergeStatus.UpToDate) 66 | { 67 | StatusUpdated?.Invoke("Icon pack is up to date."); 68 | } 69 | else 70 | { 71 | StatusUpdated?.Invoke("Icon pack updated successfully."); 72 | } 73 | return true; 74 | } 75 | } 76 | catch (Exception ex) 77 | { 78 | StatusUpdated?.Invoke($"Error updating icon pack: {ex.Message}"); 79 | return false; 80 | } 81 | }); 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /ChangeFolderIcon.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.14.36301.6 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChangeFolderIcon", "ChangeFolderIcon\ChangeFolderIcon.csproj", "{B0047555-34AA-4500-92EF-418C66078372}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {E8459169-620E-4EFC-AA5F-03319FC275C3} = {E8459169-620E-4EFC-AA5F-03319FC275C3} 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElevatedWorker", "ElevatedWorker\ElevatedWorker.csproj", "{E8459169-620E-4EFC-AA5F-03319FC275C3}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|ARM64 = Debug|ARM64 16 | Debug|x64 = Debug|x64 17 | Debug|x86 = Debug|x86 18 | Release|ARM64 = Release|ARM64 19 | Release|x64 = Release|x64 20 | Release|x86 = Release|x86 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|x64.ActiveCfg = Debug|x64 27 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|x64.Build.0 = Debug|x64 28 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|x64.Deploy.0 = Debug|x64 29 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|x86.ActiveCfg = Debug|x86 30 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|x86.Build.0 = Debug|x86 31 | {B0047555-34AA-4500-92EF-418C66078372}.Debug|x86.Deploy.0 = Debug|x86 32 | {B0047555-34AA-4500-92EF-418C66078372}.Release|ARM64.ActiveCfg = Release|ARM64 33 | {B0047555-34AA-4500-92EF-418C66078372}.Release|ARM64.Build.0 = Release|ARM64 34 | {B0047555-34AA-4500-92EF-418C66078372}.Release|ARM64.Deploy.0 = Release|ARM64 35 | {B0047555-34AA-4500-92EF-418C66078372}.Release|x64.ActiveCfg = Release|x64 36 | {B0047555-34AA-4500-92EF-418C66078372}.Release|x64.Build.0 = Release|x64 37 | {B0047555-34AA-4500-92EF-418C66078372}.Release|x64.Deploy.0 = Release|x64 38 | {B0047555-34AA-4500-92EF-418C66078372}.Release|x86.ActiveCfg = Release|x86 39 | {B0047555-34AA-4500-92EF-418C66078372}.Release|x86.Build.0 = Release|x86 40 | {B0047555-34AA-4500-92EF-418C66078372}.Release|x86.Deploy.0 = Release|x86 41 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Debug|ARM64.ActiveCfg = Debug|Any CPU 42 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Debug|ARM64.Build.0 = Debug|Any CPU 43 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Debug|x64.ActiveCfg = Debug|Any CPU 44 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Debug|x64.Build.0 = Debug|Any CPU 45 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Debug|x86.ActiveCfg = Debug|Any CPU 46 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Debug|x86.Build.0 = Debug|Any CPU 47 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Release|ARM64.ActiveCfg = Release|Any CPU 48 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Release|ARM64.Build.0 = Release|Any CPU 49 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Release|x64.ActiveCfg = Release|Any CPU 50 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Release|x64.Build.0 = Release|Any CPU 51 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Release|x86.ActiveCfg = Release|Any CPU 52 | {E8459169-620E-4EFC-AA5F-03319FC275C3}.Release|x86.Build.0 = Release|Any CPU 53 | EndGlobalSection 54 | GlobalSection(SolutionProperties) = preSolution 55 | HideSolutionNode = FALSE 56 | EndGlobalSection 57 | GlobalSection(ExtensibilityGlobals) = postSolution 58 | SolutionGuid = {FCF87F20-CE28-4D70-8A3F-CFA0413219D3} 59 | EndGlobalSection 60 | EndGlobal 61 | -------------------------------------------------------------------------------- /ChangeFolderIcon/ChangeFolderIcon.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | WinExe 4 | None 5 | true 6 | net8.0-windows10.0.22621.0 7 | 10.0.17763.0 8 | ChangeFolderIcon 9 | app.manifest 10 | x86;x64;ARM64 11 | win-x86;win-x64;win-arm64 12 | win-$(Platform).pubxml 13 | true 14 | true 15 | enable 16 | DISABLE_XAML_GENERATED_MAIN;$(DefineConstants) 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 35 | 36 | 37 | 38 | 39 | 40 | PreserveNewest 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | MSBuild:Compile 52 | 53 | 54 | 55 | 56 | MSBuild:Compile 57 | 58 | 59 | 60 | 61 | MSBuild:Compile 62 | 63 | 64 | 65 | 66 | MSBuild:Compile 67 | 68 | 69 | 70 | 71 | MSBuild:Compile 72 | 73 | 74 | 75 | 80 | 81 | true 82 | 83 | 84 | 85 | 86 | False 87 | True 88 | False 89 | True 90 | en-us 91 | Assets\icon\app_icon.ico 92 | 93 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Utils/Services/FolderNavigationService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ChangeFolderIcon.Utils.Services 9 | { 10 | /// 11 | /// 提供加载文件夹结构相关的功能。 12 | /// 13 | public class FolderNavigationService 14 | { 15 | /// 16 | /// 递归地使用 System.IO 构建子文件夹的数据模型树。 17 | /// 18 | /// 父文件夹的路径。 19 | /// 子文件夹节点列表。 20 | public List BuildChildNodes(string path) 21 | { 22 | var children = new List(); 23 | try 24 | { 25 | foreach (var dirPath in Directory.EnumerateDirectories(path)) 26 | { 27 | var childNode = new FolderNode 28 | { 29 | Name = Path.GetFileName(dirPath), 30 | Path = dirPath, 31 | // 从 desktop.ini 获取图标路径 32 | IconPath = GetIconPathFromDesktopIni(dirPath), 33 | // 递归为子文件夹构建它们的子节点 34 | SubFolders = BuildChildNodes(dirPath) 35 | }; 36 | children.Add(childNode); 37 | } 38 | } 39 | catch (UnauthorizedAccessException) 40 | { 41 | // 忽略无权访问的文件夹,避免程序崩溃 42 | } 43 | catch (IOException) 44 | { 45 | // 忽略其他可能的IO错误 46 | } 47 | return children; 48 | } 49 | 50 | /// 51 | /// 尝试从文件夹的 desktop.ini 文件中读取图标路径。 52 | /// 53 | /// 文件夹的完整路径。 54 | /// 图标文件的路径,如果不存在或解析失败则返回 null。 55 | private string? GetIconPathFromDesktopIni(string folderPath) 56 | { 57 | var iniPath = Path.Combine(folderPath, "desktop.ini"); 58 | if (!File.Exists(iniPath)) return null; 59 | 60 | try 61 | { 62 | var lines = File.ReadAllLines(iniPath); 63 | var iconResourceLine = lines.FirstOrDefault(line => line.Trim().StartsWith("IconResource=", StringComparison.OrdinalIgnoreCase)); 64 | 65 | if (iconResourceLine != null) 66 | { 67 | // 提取等号后面的路径部分 68 | var pathPart = iconResourceLine.Split('=')[1].Trim(); 69 | 70 | // 移除图标索引 (例如 ",0") 71 | int commaIndex = pathPart.LastIndexOf(','); 72 | if (commaIndex != -1) 73 | { 74 | if (int.TryParse(pathPart.Substring(commaIndex + 1), out _)) 75 | { 76 | pathPart = pathPart.Substring(0, commaIndex); 77 | } 78 | } 79 | 80 | // 展开路径中的环境变量 (例如 %SystemRoot%) 81 | var expandedPath = Environment.ExpandEnvironmentVariables(pathPart); 82 | 83 | // 如果路径不是绝对路径,则视为相对于当前文件夹 84 | if (!Path.IsPathRooted(expandedPath)) 85 | { 86 | expandedPath = Path.GetFullPath(Path.Combine(folderPath, expandedPath)); 87 | } 88 | 89 | // 只有当路径指向一个实际存在的文件时才返回它 90 | if (File.Exists(expandedPath)) 91 | { 92 | return expandedPath; 93 | } 94 | } 95 | } 96 | catch (Exception) 97 | { 98 | // 忽略解析过程中的任何错误,并返回null 99 | } 100 | 101 | return null; 102 | } 103 | 104 | 105 | public class FolderNode 106 | { 107 | public string? Name { get; set; } 108 | public string? Path { get; set; } 109 | /// 110 | /// 文件夹自定义图标的路径 (如果有)。 111 | /// 112 | public string? IconPath { get; set; } 113 | public List SubFolders { get; set; } = new List(); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /ChangeFolderIcon/UserControls/WindowControl/CustomTitleBar.xaml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Utils/Services/ElevationService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | 6 | namespace ChangeFolderIcon.Utils.Services 7 | { 8 | public static class ElevationService 9 | { 10 | /// 11 | /// 检查写入指定路径是否需要管理员权限。 12 | /// 13 | /// 要检查的文件夹路径。 14 | /// 如果需要提权则返回 true,否则返回 false。 15 | public static bool NeedsElevation(string folderPath) 16 | { 17 | try 18 | { 19 | // 检查一些已知的受保护系统文件夹 20 | string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); 21 | string programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); 22 | string windows = Environment.GetFolderPath(Environment.SpecialFolder.Windows); 23 | 24 | if (!string.IsNullOrEmpty(programFiles) && folderPath.StartsWith(programFiles, StringComparison.OrdinalIgnoreCase)) return true; 25 | if (!string.IsNullOrEmpty(programFilesX86) && folderPath.StartsWith(programFilesX86, StringComparison.OrdinalIgnoreCase)) return true; 26 | if (!string.IsNullOrEmpty(windows) && folderPath.StartsWith(windows, StringComparison.OrdinalIgnoreCase)) return true; 27 | 28 | // 尝试创建一个临时文件来直接测试写权限 29 | string testFile = Path.Combine(folderPath, Guid.NewGuid().ToString("N") + ".tmp"); 30 | File.WriteAllText(testFile, "test"); 31 | File.Delete(testFile); 32 | return false; // 成功写入并删除,说明有权限 33 | } 34 | catch (UnauthorizedAccessException) 35 | { 36 | return true; // 捕获到“无权限”异常,说明需要提权 37 | } 38 | catch 39 | { 40 | // 其他异常,为安全起见,也认为需要提权 41 | return true; 42 | } 43 | } 44 | 45 | /// 46 | /// 以管理员权限运行辅助工具。 47 | /// 48 | /// 传递给 ElevatedWorker.exe 的命令行参数。 49 | /// 操作成功完成返回 true,用户取消UAC或发生错误则返回 false。 50 | private static Task RunWorkerAsync(string arguments) 51 | { 52 | var tcs = new TaskCompletionSource(); 53 | 54 | // 获取 ElevatedWorker.exe 的路径,假设它和主程序在同一目录下 55 | string workerPath = Path.Combine(AppContext.BaseDirectory, "ElevatedWorker.exe"); 56 | 57 | if (!File.Exists(workerPath)) 58 | { 59 | // 如果找不到辅助工具,直接返回失败 60 | tcs.SetResult(false); 61 | return tcs.Task; 62 | } 63 | 64 | try 65 | { 66 | var process = new Process 67 | { 68 | StartInfo = 69 | { 70 | FileName = workerPath, 71 | Arguments = arguments, 72 | // Verb = "runas" 是触发 UAC 提权的关键 73 | Verb = "runas", 74 | UseShellExecute = true, 75 | // 隐藏控制台窗口 76 | WindowStyle = ProcessWindowStyle.Hidden, 77 | CreateNoWindow = true 78 | }, 79 | EnableRaisingEvents = true 80 | }; 81 | 82 | process.Exited += (sender, args) => 83 | { 84 | // 进程退出后,根据退出代码判断是否成功 85 | tcs.SetResult(process.ExitCode == 0); 86 | process.Dispose(); 87 | }; 88 | 89 | process.Start(); 90 | } 91 | catch (Exception) 92 | { 93 | // 如果用户在UAC提示框中点击“否”,会抛出异常 94 | tcs.SetResult(false); 95 | } 96 | 97 | return tcs.Task; 98 | } 99 | 100 | /// 101 | /// 提权设置文件夹图标。 102 | /// 103 | public static Task SetFolderIconElevatedAsync(string folderPath, string iconPath) 104 | { 105 | // 将路径用引号包裹,以正确处理带空格的路径 106 | string arguments = $"set \"{folderPath}\" \"{iconPath}\""; 107 | return RunWorkerAsync(arguments); 108 | } 109 | 110 | /// 111 | /// 提权清除文件夹图标。 112 | /// 113 | public static Task ClearFolderIconElevatedAsync(string folderPath) 114 | { 115 | string arguments = $"clear \"{folderPath}\""; 116 | return RunWorkerAsync(arguments); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /ChangeFolderIcon/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 56 | 57 | 58 | 96 | 97 | 98 | 99 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /ChangeFolderIcon/UserControls/IconControl.xaml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 93 | 96 | 97 | 98 | 99 | 106 | 107 | 108 | 109 | 113 | 118 | 119 | 120 | 121 | 127 | 130 | 133 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /ChangeFolderIcon/Pages/SettingsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using ChangeFolderIcon.Utils.Services; 2 | using Microsoft.UI.Xaml; 3 | using Microsoft.UI.Xaml.Controls; 4 | using Microsoft.UI.Xaml.Navigation; 5 | using Microsoft.Windows.ApplicationModel.Resources; 6 | using System; 7 | using System.IO; 8 | using System.Linq; 9 | 10 | namespace ChangeFolderIcon.Pages 11 | { 12 | public sealed partial class SettingsPage : Page 13 | { 14 | private readonly SettingsService? _settingsService; 15 | private readonly IconPackService? _iconPackService; 16 | private bool _isInitializing = true; 17 | private readonly ResourceLoader resourceLoader = new(); 18 | 19 | // 当图标包路径改变时触发的事件 20 | public event EventHandler? IconPackPathChanged; 21 | 22 | public SettingsPage() 23 | { 24 | this.InitializeComponent(); 25 | _settingsService = App.SettingsService; 26 | _iconPackService = App.IconPackService; 27 | 28 | if (_iconPackService != null) 29 | { 30 | _iconPackService.StatusUpdated += OnIconPackStatusUpdated; 31 | } 32 | 33 | LoadSettings(); 34 | _isInitializing = false; 35 | } 36 | 37 | private void LoadSettings() 38 | { 39 | // Language 40 | var currentLang = _settingsService?.Settings.Language; 41 | LanguageComboBox.SelectedItem = LanguageComboBox.Items 42 | .Cast() 43 | .FirstOrDefault(item => (string)item.Tag == currentLang) ?? LanguageComboBox.Items[0]; 44 | 45 | // Theme 46 | var currentTheme = _settingsService?.Settings.Theme; 47 | ThemeComboBox.SelectedItem = ThemeComboBox.Items 48 | .Cast() 49 | .FirstOrDefault(item => (string)item.Tag == currentTheme) ?? ThemeComboBox.Items[2]; 50 | 51 | // Backdrop 52 | var currentBackdrop = _settingsService?.Settings.Backdrop; 53 | BackdropComboBox.SelectedItem = BackdropComboBox.Items 54 | .Cast() 55 | .FirstOrDefault(item => (string)item.Tag == currentBackdrop) ?? BackdropComboBox.Items[0]; 56 | 57 | // Icon Pack Path 58 | UpdateIconPackPathDisplay(); 59 | } 60 | 61 | private void UpdateIconPackPathDisplay() 62 | { 63 | if (_settingsService != null) 64 | { 65 | // 显示当前设置的ico文件夹路径 66 | string path = _settingsService.Settings.IconPackPath ?? resourceLoader.GetString("NotSet"); 67 | string displayPath = _settingsService.Settings.IconRepoLocalPath ?? resourceLoader.GetString("NotSet"); 68 | IconPackPathTextBlock.Text = $"{resourceLoader.GetString("CurrentPath")}: {displayPath}"; 69 | } 70 | } 71 | 72 | private void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 73 | { 74 | if (_isInitializing) return; 75 | 76 | var selectedTag = ((ComboBoxItem)LanguageComboBox.SelectedItem)?.Tag as string; 77 | if (selectedTag != null && _settingsService != null) 78 | { 79 | // Check if language actually changed 80 | if (_settingsService.Settings.Language != selectedTag) 81 | { 82 | _settingsService.Settings.Language = selectedTag; 83 | _settingsService.SaveSettings(); 84 | LanguageService.SetLanguage(selectedTag); 85 | 86 | // Show restart info bar 87 | LanguageRestartInfoBar.IsOpen = true; 88 | } 89 | } 90 | } 91 | 92 | private void ThemeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 93 | { 94 | if (_isInitializing) return; 95 | 96 | var selectedTag = ((ComboBoxItem)ThemeComboBox.SelectedItem)?.Tag as string; 97 | if (selectedTag != null && _settingsService != null) 98 | { 99 | _settingsService.Settings.Theme = selectedTag; 100 | _settingsService.SaveSettings(); 101 | 102 | if (App.window != null) 103 | { 104 | SettingsService.ApplyTheme(App.window, selectedTag); 105 | } 106 | } 107 | } 108 | 109 | private void BackdropComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 110 | { 111 | if (_isInitializing) return; 112 | 113 | var selectedTag = ((ComboBoxItem)BackdropComboBox.SelectedItem)?.Tag as string; 114 | if (selectedTag != null && _settingsService != null) 115 | { 116 | if (App.window is MainWindow mainWindow) 117 | { 118 | _settingsService.Settings.Backdrop = selectedTag; 119 | _settingsService.SaveSettings(); 120 | SettingsService.ApplyBackdrop(mainWindow, selectedTag); 121 | } 122 | } 123 | } 124 | 125 | private async void UpdateIconsButton_Click(object sender, RoutedEventArgs e) 126 | { 127 | if (_iconPackService == null || _settingsService == null) return; 128 | 129 | UpdateIconsButton.IsEnabled = false; 130 | UpdateProgressRing.Visibility = Visibility.Visible; 131 | IconPackStatusTextBlock.Text = ""; 132 | 133 | try 134 | { 135 | bool success = await _iconPackService.UpdateIconPackAsync(); 136 | if (success && _iconPackService.IconPackDirectory != null) 137 | { 138 | _settingsService.Settings.IconRepoLocalPath = _iconPackService.IconPackDirectory; 139 | _settingsService.SaveSettings(); 140 | UpdateIconPackPathDisplay(); 141 | IconPackPathChanged?.Invoke(this, EventArgs.Empty); 142 | } 143 | } 144 | catch (Exception ex) 145 | { 146 | IconPackStatusTextBlock.Text = $"Error: {ex.Message}"; 147 | } 148 | finally 149 | { 150 | UpdateIconsButton.IsEnabled = true; 151 | UpdateProgressRing.Visibility = Visibility.Collapsed; 152 | } 153 | } 154 | 155 | private async void SelectIconsFolderButton_Click(object sender, RoutedEventArgs e) 156 | { 157 | var picker = new Windows.Storage.Pickers.FolderPicker 158 | { 159 | SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop 160 | }; 161 | picker.FileTypeFilter.Add("*"); 162 | var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.window); 163 | WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd); 164 | 165 | var folder = await picker.PickSingleFolderAsync(); 166 | if (folder != null && _settingsService != null) 167 | { 168 | _settingsService.Settings.IconRepoLocalPath = folder.Path; 169 | _settingsService.SaveSettings(); 170 | UpdateIconPackPathDisplay(); 171 | // 触发事件通知MainWindow刷新IconsPage 172 | IconPackPathChanged?.Invoke(this, EventArgs.Empty); 173 | } 174 | } 175 | 176 | private void OnIconPackStatusUpdated(string status) 177 | { 178 | DispatcherQueue.TryEnqueue(() => 179 | { 180 | IconPackStatusTextBlock.Text = status; 181 | }); 182 | } 183 | 184 | protected override void OnNavigatedFrom(NavigationEventArgs e) 185 | { 186 | base.OnNavigatedFrom(e); 187 | 188 | // Unsubscribe from events 189 | if (_iconPackService != null) 190 | { 191 | _iconPackService.StatusUpdated -= OnIconPackStatusUpdated; 192 | } 193 | } 194 | } 195 | } -------------------------------------------------------------------------------- /ChangeFolderIcon/Pages/IconsPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 70 | 71 | 72 | 73 | 74 | 78 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 96 | 97 | 98 | 99 | 100 | 101 | 105 | 106 | 107 | 111 | 117 |