├── DeskFrame
├── ico.png
├── Icon
│ ├── Ico.ico
│ ├── ico.png
│ └── support_me_on_kofi_badge_dark.png
├── Shaders
│ ├── GrayscaleEffect.ps
│ └── GrayscaleEffect.cs
├── AssemblyInfo.cs
├── Converters
│ ├── IconSizeToHeightWidthConverter.cs
│ ├── BooleanToBorderThicknessConverter.cs
│ ├── OffsetConverter.cs
│ ├── BooleanFrameTypeToSymbolConverter.cs
│ ├── ShowDisplayNameToItemWidthConverter.cs
│ ├── BooleanToVisibilityConverter.cs
│ └── TitleTextAlignmentToMarginConverter.cs
├── App.xaml
├── App.xaml.cs
├── MainWindow.xaml
├── DeskFrame.csproj
├── Core
│ └── FileItem.cs
├── SettingsWindow.xaml.cs
├── SettingsWindow.xaml
├── ColorPicker
│ ├── ColorPicker.xaml
│ └── ColorPicker.xaml.cs
├── Util
│ ├── RegistryHelper.cs
│ ├── Updater.cs
│ └── Interop.cs
├── MainWindow.xaml.cs
└── Properties
│ ├── Lang.zh-CN.resx
│ ├── Lang.ko-KR.resx
│ ├── Lang.pl-PL.resx
│ ├── Lang.es-ES.resx
│ └── Lang.resx
├── .github
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── DeskFrame.sln
├── LICENSE.txt
├── .gitattributes
├── README.md
└── .gitignore
/DeskFrame/ico.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PinchToDebug/DeskFrame/HEAD/DeskFrame/ico.png
--------------------------------------------------------------------------------
/DeskFrame/Icon/Ico.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PinchToDebug/DeskFrame/HEAD/DeskFrame/Icon/Ico.ico
--------------------------------------------------------------------------------
/DeskFrame/Icon/ico.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PinchToDebug/DeskFrame/HEAD/DeskFrame/Icon/ico.png
--------------------------------------------------------------------------------
/DeskFrame/Shaders/GrayscaleEffect.ps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PinchToDebug/DeskFrame/HEAD/DeskFrame/Shaders/GrayscaleEffect.ps
--------------------------------------------------------------------------------
/DeskFrame/Icon/support_me_on_kofi_badge_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PinchToDebug/DeskFrame/HEAD/DeskFrame/Icon/support_me_on_kofi_badge_dark.png
--------------------------------------------------------------------------------
/DeskFrame/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/DeskFrame/Converters/IconSizeToHeightWidthConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows.Data;
3 |
4 | namespace DeskFrame
5 | {
6 | public class IconSizeToHeightWidthConverter : IValueConverter
7 | {
8 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
9 | {
10 | if (value is int iconSize)
11 | {
12 | return iconSize;
13 | }
14 | return 32;
15 | }
16 |
17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
18 | {
19 | throw new NotImplementedException();
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[Feature request] - "
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/DeskFrame/App.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/DeskFrame/Converters/BooleanToBorderThicknessConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows;
3 | using System.Windows.Data;
4 |
5 | namespace DeskFrame
6 | {
7 | public class BooleanToBorderThicknessConverter : IValueConverter
8 | {
9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
10 | {
11 | if (value is bool enabled)
12 | {
13 | return enabled ? new Thickness(1.3) : new Thickness(0);
14 | }
15 | return new Thickness(0);
16 | }
17 |
18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
19 | {
20 | throw new NotImplementedException();
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/DeskFrame/Converters/OffsetConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows.Data;
3 |
4 | namespace DeskFrame
5 | {
6 | public class OffsetConverter : IValueConverter
7 | {
8 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
9 | {
10 | if (value is double input)
11 | {
12 | if (input <= 110)
13 | {
14 | return input - 100;
15 | }
16 | return 10;
17 | }
18 | return 80;
19 | }
20 |
21 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
22 | {
23 | throw new NotImplementedException();
24 | }
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/DeskFrame/Converters/BooleanFrameTypeToSymbolConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 | using Wpf.Ui.Controls;
5 |
6 | namespace DeskFrame
7 | {
8 | public class BooleanFrameTypeToSymbolConverter : IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | if (value is bool isShortcutsOnly)
13 | {
14 | return isShortcutsOnly ? SymbolRegular.Document16 : SymbolRegular.Folder16;
15 | }
16 | return SymbolRegular.Folder16;
17 | }
18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
19 | {
20 | throw new NotImplementedException();
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/DeskFrame/Converters/ShowDisplayNameToItemWidthConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows.Data;
3 |
4 | namespace DeskFrame
5 | {
6 | public class ShowDisplayNameToItemWidthConverter : IMultiValueConverter
7 | {
8 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
9 | {
10 | bool showDisplayName = values[0] is bool b && b;
11 | double.TryParse(values[1]?.ToString(), out double iconSize);
12 | if (iconSize <= 64 && showDisplayName)
13 | {
14 | return showDisplayName ? 85 : iconSize + 10;
15 | }
16 | return iconSize + 20;
17 | }
18 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) =>
19 | throw new NotImplementedException();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DeskFrame/Converters/BooleanToVisibilityConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 | using System.Windows;
5 |
6 | namespace DeskFrame
7 | {
8 | public class BooleanToVisibilityConverter : IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | if (value is bool boolValue)
13 | {
14 | return boolValue ? Visibility.Visible : Visibility.Collapsed;
15 | }
16 | return Visibility.Collapsed;
17 | }
18 |
19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
20 | {
21 | if (value is Visibility visibility)
22 | {
23 | return visibility == Visibility.Visible;
24 | }
25 | return false;
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG] - "
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 | **or include a video**
20 |
21 | **Expected behavior**
22 | A clear and concise description of what you expected to happen.
23 |
24 | **Screenshots / Screenrecording**
25 | If applicable, add screenshots or a screenrecording to help explain your problem.
26 |
27 | **Desktop (please complete the following information):**
28 | - OS Version [e.g. 22H2]
29 | - OS Build [e.g. 22000.1]
30 |
31 | **Additional context**
32 | Details about your setup here such as number of monitors, scaling settings, whether you're using any other software that changes the look of windows, or how it functions.
33 |
--------------------------------------------------------------------------------
/DeskFrame.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.12.35527.113
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeskFrame", "DeskFrame\DeskFrame.csproj", "{6EC5031A-C61D-41A0-B262-A927C1093F21}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {6EC5031A-C61D-41A0-B262-A927C1093F21}.Debug|Any CPU.ActiveCfg = Debug|x64
15 | {6EC5031A-C61D-41A0-B262-A927C1093F21}.Debug|Any CPU.Build.0 = Debug|x64
16 | {6EC5031A-C61D-41A0-B262-A927C1093F21}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {6EC5031A-C61D-41A0-B262-A927C1093F21}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 PinchToDebug
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/DeskFrame/Shaders/GrayscaleEffect.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Media.Effects;
3 |
4 | namespace DeskFrame.Shaders
5 | {
6 | public class GrayscaleEffect : ShaderEffect
7 | {
8 | public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(GrayscaleEffect), 0);
9 | public static readonly DependencyProperty StrengthProperty = DependencyProperty.Register("Strength", typeof(double), typeof(GrayscaleEffect), new UIPropertyMetadata(((double)(0D)), PixelShaderConstantCallback(0)));
10 | public GrayscaleEffect()
11 | {
12 | PixelShader pixelShader = new PixelShader();
13 | pixelShader.UriSource = new Uri("/DeskFrame;component/Shaders/GrayscaleEffect.ps", UriKind.Relative);
14 | this.PixelShader = pixelShader;
15 |
16 | this.UpdateShaderValue(InputProperty);
17 | this.UpdateShaderValue(StrengthProperty);
18 | }
19 | public Brush Input
20 | {
21 | get
22 | {
23 | return ((Brush)(this.GetValue(InputProperty)));
24 | }
25 | set
26 | {
27 | this.SetValue(InputProperty, value);
28 | }
29 | }
30 | public double Strength
31 | {
32 | get
33 | {
34 | return ((double)(this.GetValue(StrengthProperty)));
35 | }
36 | set
37 | {
38 | this.SetValue(StrengthProperty, value);
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/DeskFrame/Converters/TitleTextAlignmentToMarginConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using System.Windows.Data;
3 | using System.Windows;
4 | using HorizontalAlignment = System.Windows.HorizontalAlignment;
5 | using System.Diagnostics;
6 |
7 | namespace DeskFrame
8 | {
9 | public class TitleTextAlignmentToMarginConverter : IMultiValueConverter
10 | {
11 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
12 | {
13 | if (values.Length >= 3 &&
14 | values[0] is System.Windows.HorizontalAlignment alignment &&
15 | values[1] is Visibility vis1 &&
16 | values[2] is Visibility vis2)
17 | {
18 | int visibleCount = 0;
19 | int margin = 0;
20 | switch (alignment)
21 | {
22 | case HorizontalAlignment.Left:
23 | return new Thickness(10,0,0,0);
24 | case HorizontalAlignment.Right:
25 | if (vis1 == Visibility.Visible) visibleCount++;
26 | if (vis2 == Visibility.Visible) visibleCount++;
27 | margin = visibleCount switch
28 | {
29 | 1 => 60,
30 | 2 => 90,
31 | _ => 30
32 | };
33 | return new Thickness(0, 0, margin, 0);
34 | case HorizontalAlignment.Center:
35 | return new Thickness(0, 0, 0, 0);
36 | default:
37 | return new Thickness(0);
38 | }
39 | }
40 |
41 | return new Thickness(0);
42 | }
43 |
44 |
45 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
46 | {
47 | throw new NotImplementedException();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/DeskFrame/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using DeskFrame.Properties;
2 | using Microsoft.Toolkit.Uwp.Notifications;
3 | using Microsoft.Win32;
4 | using System.Diagnostics;
5 | using System.Windows;
6 | using System.Windows.Threading;
7 | using Application = System.Windows.Application;
8 |
9 | namespace DeskFrame
10 | {
11 | ///
12 | /// Interaction logic for App.xaml
13 | ///
14 | public partial class App : Application
15 | {
16 | private DispatcherTimer updateTimer;
17 | public RegistryHelper reg = new RegistryHelper("DeskFrame");
18 | protected override void OnStartup(StartupEventArgs e)
19 | {
20 | #if !DEBUG
21 | if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
22 | {
23 |
24 | var dialog = new Wpf.Ui.Controls.MessageBox
25 | {
26 | Title = "DeskFrame",
27 | Content = Lang.DeskFrame_AlreadyRunning,
28 | };
29 |
30 | var result = dialog.ShowDialogAsync();
31 |
32 | if (result.Result == Wpf.Ui.Controls.MessageBoxResult.None)
33 | {
34 | Application.Current.Shutdown();
35 | }
36 | }
37 | #endif
38 | PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Critical;
39 | base.OnStartup(e);
40 | ToastNotificationManagerCompat.OnActivated += ToastActivatedHandler;
41 | StartUpdateCheckTimer();
42 | }
43 | private void ToastActivatedHandler(ToastNotificationActivatedEventArgsCompat toastArgs)
44 | {
45 | var args = ToastArguments.Parse(toastArgs.Argument);
46 | Current.Dispatcher.Invoke(async () =>
47 | {
48 | if (args.Contains("action") && args["action"] == "install_update")
49 | {
50 | await Updater.InstallUpdate();
51 | }
52 |
53 | });
54 | }
55 | private void StartUpdateCheckTimer()
56 | {
57 | updateTimer = new DispatcherTimer
58 | {
59 | Interval = TimeSpan.FromHours(6)
60 | };
61 | updateTimer.Tick += async (_, _) =>
62 | {
63 | if (reg.KeyExistsRoot("AutoUpdate") && (bool)reg.ReadKeyValueRoot("AutoUpdate"))
64 | {
65 | await Updater.CheckUpdateAsync("https://api.github.com/repos/PinchToDebug/DeskFrame/releases/latest",true);
66 | }
67 | };
68 | updateTimer.Start();
69 | }
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/DeskFrame/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
29 |
30 |
31 |
32 |
34 |
35 |
36 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/DeskFrame/DeskFrame.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net8.0-windows10.0.19041.0
6 | enable
7 | enable
8 | true
9 | True
10 | 1.37.0
11 | 1.37.0
12 | ico.png
13 | Icon\ico.ico
14 | AnyCPU;x64
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | tlbimp
27 | 0
28 | 1
29 | 50a7e9b0-70ef-11d1-b75a-00a0c90564fe
30 | 0
31 | false
32 | true
33 |
34 |
35 | tlbimp
36 | 0
37 | 1
38 | f935dc20-1cf0-11d0-adb9-00c04fd58a0b
39 | 0
40 | false
41 | true
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | VirtualDesktop\VirtualDesktop.dll
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | True
76 | True
77 | Lang.resx
78 |
79 |
80 | MSBuild:Compile
81 |
82 |
83 |
84 |
85 |
86 | PublicResXFileCodeGenerator
87 | Lang.Designer.cs
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/DeskFrame/Core/FileItem.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Windows.Media.Imaging;
3 | using System.Windows.Media;
4 | using System.Windows;
5 | using Brushes = System.Windows.Media.Brushes;
6 | using Brush = System.Windows.Media.Brush;
7 | using Color = System.Windows.Media.Color;
8 |
9 | namespace DeskFrame.Core
10 | {
11 | public class FileItem : INotifyPropertyChanged
12 | {
13 | public event PropertyChangedEventHandler? PropertyChanged;
14 |
15 | private bool _isMoveBarVisible;
16 | private bool _isSelected;
17 | public bool IsFolder { get; set; }
18 | private Brush _background = Brushes.Transparent;
19 | private int _maxHeight = 40;
20 | private TextTrimming _textTrimming = TextTrimming.CharacterEllipsis;
21 | private string? _displayName;
22 | public string? Name { get; set; }
23 | public string? FullPath { get; set; }
24 | public BitmapSource? Thumbnail { get; set; }
25 | public DateTime DateModified { get; set; }
26 | public DateTime DateCreated { get; set; }
27 | public string? FileType { get; set; }
28 | public long ItemSize { get; set; }
29 | public string DisplaySize { get; set; }
30 |
31 | public bool IsMoveBarVisible
32 | {
33 | get => _isMoveBarVisible;
34 | set
35 | {
36 | if (_isMoveBarVisible != value)
37 | {
38 | _isMoveBarVisible = value;
39 | OnPropertyChanged(nameof(IsMoveBarVisible));
40 | }
41 | }
42 | }
43 | public string DisplayName
44 | {
45 | get => Name;
46 |
47 | private set
48 | {
49 | _displayName = value;
50 | OnPropertyChanged(nameof(DisplayName));
51 | }
52 | }
53 |
54 | public bool IsSelected
55 | {
56 | get => _isSelected;
57 | set
58 | {
59 | if (_isSelected != value)
60 | {
61 | _isSelected = value;
62 | Background = _isSelected ? new SolidColorBrush(Color.FromArgb(50, 255, 255, 255)) : Brushes.Transparent;
63 |
64 | // int.MaxValue for full height, 70 for 4 lines
65 | // MaxHeight = _isSelected ? 70 : 40;
66 | //MaxHeight = _isSelected ? 40 : 40;
67 | TextTrimming = _isSelected ? TextTrimming.CharacterEllipsis : TextTrimming.CharacterEllipsis;
68 |
69 | OnPropertyChanged(nameof(IsSelected));
70 | OnPropertyChanged(nameof(Background));
71 | OnPropertyChanged(nameof(MaxHeight));
72 | OnPropertyChanged(nameof(TextTrimming));
73 | OnPropertyChanged(nameof(DisplayName));
74 | }
75 | }
76 | }
77 |
78 | public Brush Background
79 | {
80 | get => _background;
81 | set
82 | {
83 | _background = value;
84 | OnPropertyChanged(nameof(Background));
85 | }
86 | }
87 |
88 | public int MaxHeight
89 | {
90 | get => _maxHeight;
91 | private set
92 | {
93 | _maxHeight = value;
94 | OnPropertyChanged(nameof(MaxHeight));
95 | }
96 | }
97 |
98 | public TextTrimming TextTrimming
99 | {
100 | get => _textTrimming;
101 | private set
102 | {
103 | _textTrimming = value;
104 | OnPropertyChanged(nameof(TextTrimming));
105 | }
106 | }
107 |
108 | protected void OnPropertyChanged(string propertyName)
109 | {
110 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 | # DeskFrame
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | A highly customizable, open-source tool for desktop organization.
Fast, lightweight, and always at hand.
16 |
17 |
18 | [](https://ko-fi.com/J3J61PAH6H)
19 | ## ✨ Features
20 |
21 | - Instant search *(just type when the cursor is over the frame)*
22 | - Fully customizable colors
23 | - Background colors with transparency
24 | - Toggle hidden files and file extensions
25 | - Rearrange items with `ALT` + drag
26 | - Sticky + lockable frames (hold `ALT` to stick with gap)
27 | - Open/close frame toggle
28 | - `CTRL`+`SCROLL` resize icons
29 | - Lightweight and fast (~75MB RAM usage)
30 | - Sorting options (by name, date, type, etc.)
31 | - First row for last accessed items
32 | - Regex search and item filtering
33 | - Option to display per virtual desktop
34 | - Double click on desktop to hide frames
35 | - Grayscale
36 | - Supported languages: English, Spanish, Mandarin, Polish, Korean
37 |
38 | ...and more!
39 |
40 | ## 🖼️ Screenshot
41 |
42 |
52 |
53 | ## 🚀 Quick Start
54 |
55 | 1. [Download the latest release](https://github.com/PinchToDebug/DeskFrame/releases/latest/download/DeskFrame.exe)
56 | 2. Run the executable.
57 | 3. Drag a folder into the frame.
58 |
59 | ## ⌨️ Tips
60 |
61 | - Type while focused to search.
62 | - Scroll content with the mouse wheel.
63 | - Right-click the title bar for options and customization.
64 |
65 | ## 🤝 Contributing
66 |
67 | Contributions are welcome! Open an [issue](https://github.com/PinchToDebug/DeskFrame/issues) or submit a [pull request](https://github.com/PinchToDebug/DeskFrame/pulls).
68 |
69 | ## 📝 Important
70 |
71 | The project is under development and may contain bugs.
72 |
73 | ## 📜 License
74 |
75 | This project is licensed under the MIT License.
76 |
77 | ## 🌟 Credits
78 |
79 | - [WPF UI](https://github.com/lepoco/wpfui) - [MIT License](https://github.com/lepoco/wpfui/blob/main/LICENSE)
80 | - [WindowsCommunityToolkit](https://github.com/CommunityToolkit/WindowsCommunityToolkit) - [MIT License](https://github.com/CommunityToolkit/WindowsCommunityToolkit?tab=License-1-ov-file#License-1-ov-file)
81 | - [SVG.NET](https://github.com/svg-net/SVG) - [MS-PL License](https://github.com/svg-net/SVG?tab=MS-PL-1-ov-file#readme)
82 | - [VirtualDesktop](https://github.com/Slion/VirtualDesktop) - [MIT License](https://github.com/Slion/VirtualDesktop/blob/main/LICENSE)
83 | - [H.Hooks](https://github.com/HavenDV/H.Hooks) - [MIT License](https://github.com/HavenDV/H.Hooks?tab=MIT-1-ov-file#readme)
84 | - [Vanara](https://github.com/dahall/Vanara) - [MIT License](https://github.com/dahall/Vanara?tab=MIT-1-ov-file#readme)
85 | - [Microsoft.WindowsAPICodePack.Shell](https://github.com/contre/Windows-API-Code-Pack-1.1) - [Custom License](https://github.com/contre/Windows-API-Code-Pack-1.1?tab=License-1-ov-file)
86 |
--------------------------------------------------------------------------------
/DeskFrame/SettingsWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using Wpf.Ui.Controls;
3 | using System.Windows;
4 | using System.Windows.Media.Imaging;
5 | using Microsoft.Win32;
6 | namespace DeskFrame
7 | {
8 | public partial class SettingsWindow : FluentWindow
9 | {
10 | InstanceController _controller;
11 | DeskFrameWindow _dWindows;
12 | Instance _instance;
13 | MainWindow _window;
14 | public SettingsWindow(InstanceController controller, MainWindow window)
15 | {
16 | InitializeComponent();
17 | this.LocationChanged += Window_LocationChanged;
18 | this.MinHeight = 0;
19 | this.MinWidth = 200;
20 | _window = window;
21 | _controller = controller;
22 | // if (_controller.reg.KeyExistsRoot("blurBackground")) blurToggle.IsChecked = (bool)_controller.reg.ReadKeyValueRoot("blurBackground");
23 | if (_controller.reg.KeyExistsRoot("AutoUpdate")) AutoUpdateToggleSwitch.IsChecked = (bool)_controller.reg.ReadKeyValueRoot("AutoUpdate");
24 | if (_controller.reg.KeyExistsRoot("DoubleClickToHide")) DoubleClickToHideSwitch.IsChecked = (bool)_controller.reg.ReadKeyValueRoot("DoubleClickToHide");
25 | }
26 |
27 | private void blurToggle_CheckChanged(object sender, System.Windows.RoutedEventArgs e)
28 | {
29 | // _controller.reg.WriteToRegistryRoot("blurBackground", blurToggle.IsChecked!);
30 | // _controller.ChangeBlur((bool)blurToggle.IsChecked!);
31 | }
32 |
33 | private void ExportSettingsButton_Click(object sender, RoutedEventArgs e)
34 | {
35 | ExportRegistryKey(_controller.reg.regKeyName);
36 | }
37 |
38 | void ExportRegistryKey(string regKeyName)
39 | {
40 | var saveDialog = new Microsoft.Win32.SaveFileDialog
41 | {
42 | Filter = "Registry Files (*.reg)|*.reg",
43 | Title = "Export Registry Key",
44 | FileName = $"DeskFrame_settings_{DateTime.Now.ToString("yyyy-MM-dd_hhmm")}"
45 | };
46 | if (saveDialog.ShowDialog() == true)
47 | {
48 | string fullKeyPath = $@"HKCU\SOFTWARE\{regKeyName}";
49 | string arguments = $"export \"{fullKeyPath}\" \"{saveDialog.FileName}\" /y";
50 |
51 | var process = new Process
52 | {
53 | StartInfo = new ProcessStartInfo
54 | {
55 | FileName = "reg.exe",
56 | Arguments = arguments,
57 | RedirectStandardOutput = true,
58 | RedirectStandardError = true,
59 | UseShellExecute = false,
60 | CreateNoWindow = true
61 | }
62 | }.Start();
63 | }
64 | }
65 |
66 | private void AutoUpdateToggleSwitch_Click(object sender, RoutedEventArgs e)
67 | {
68 | if ((bool)AutoUpdateToggleSwitch.IsChecked!)
69 | {
70 |
71 | _controller.reg.AddToAutoRun("DeskFrame", Process.GetCurrentProcess().MainModule!.FileName);
72 | }
73 | else
74 | {
75 | _controller.reg.RemoveFromAutoRun("DeskFrame");
76 | }
77 | _controller.reg.WriteToRegistryRoot("AutoUpdate", AutoUpdateToggleSwitch.IsChecked);
78 | }
79 |
80 | private void DefaultFrameStyleButton_Click(object sender, RoutedEventArgs e)
81 | {
82 | if (_dWindows != null) _dWindows.Close();
83 |
84 | _instance = new Instance("Default Style", true);
85 | _instance.SettingDefault = true;
86 | _instance.Folder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
87 |
88 | _dWindows = new DeskFrameWindow(_instance);
89 | _dWindows.addFolder.Visibility = Visibility.Hidden;
90 | _dWindows.showFolder.Visibility = Visibility.Visible;
91 | _dWindows.title.Visibility = Visibility.Visible;
92 | _dWindows.WindowBorder.Visibility = Visibility.Visible;
93 | _dWindows.Left = this.Width + this.Left + 10;
94 | _dWindows.Top = this.Top;
95 | _dWindows.Show();
96 |
97 | }
98 | private void Window_LocationChanged(object sender, EventArgs e)
99 | {
100 | if (_dWindows != null)
101 | {
102 | _dWindows.Left = this.Width + this.Left + 10;
103 | _dWindows.Top = this.Top;
104 | }
105 | }
106 | private void ResetDefaultFrameStyleButton_Click(object sender, RoutedEventArgs e)
107 | {
108 | string[] keep = { "AutoUpdate", "blurBackground", "startOnLogin" };
109 | RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\DeskFrame", writable: true)!;
110 | foreach (var name in key.GetValueNames())
111 | {
112 | if (Array.IndexOf(keep, name) == -1)
113 | {
114 | try
115 | {
116 | key.DeleteValue(name);
117 | }
118 | catch
119 | {
120 | }
121 | }
122 | }
123 | key.Close();
124 | }
125 |
126 | private void FluentWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
127 | {
128 | if (_dWindows != null)
129 | {
130 | _dWindows.Close();
131 | }
132 | }
133 | private void DoubleClickToHideSwitch_Click(object sender, RoutedEventArgs e)
134 | {
135 | _controller.reg.WriteToRegistryRoot("DoubleClickToHide", DoubleClickToHideSwitch.IsChecked!);
136 | _window.DoubleClickToHide = (bool)DoubleClickToHideSwitch.IsChecked!;
137 | }
138 |
139 | private void KofiButtonImage_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
140 | {
141 | try
142 | {
143 | ProcessStartInfo sInfo = new ProcessStartInfo($"https://ko-fi.com/J3J61PAH6H") { UseShellExecute = true };
144 | _ = Process.Start(sInfo);
145 | }
146 | catch
147 | {
148 | }
149 | }
150 |
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/DeskFrame/SettingsWindow.xaml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/DeskFrame/ColorPicker/ColorPicker.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/DeskFrame/Util/RegistryHelper.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System.Diagnostics;
3 |
4 | public class RegistryHelper
5 | {
6 | public string regKeyName;
7 | public RegistryHelper(string regkeyname)
8 | {
9 | this.regKeyName = regkeyname;
10 | }
11 | public void WriteToRegistry(string keyName, object value, Instance instance)
12 | {
13 | try
14 | {
15 | if (string.IsNullOrEmpty(instance.Name))
16 | {
17 | Debug.WriteLine("Instance is null reg not writen");
18 | return;
19 | }
20 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey(instance.GetKeyLocation()))
21 | {
22 | key.SetValue(keyName, value);
23 | }
24 | // Debug.WriteLine($"wrote key: {keyName}\t value: {value}\nto: {instance.GetKeyLocation()}");
25 | }
26 | catch { }
27 | }
28 | public void WriteMultiLineTupleRegistry(string keyName, List> list, Instance instance)
29 | {
30 |
31 | if (string.IsNullOrWhiteSpace(keyName))
32 | {
33 | return;
34 | }
35 |
36 | if (instance == null || string.IsNullOrWhiteSpace(instance.Name))
37 | {
38 | Debug.WriteLine("Instance is null reg not written");
39 | return;
40 | }
41 | try
42 | {
43 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey(instance.GetKeyLocation()))
44 | {
45 | string[] values;
46 |
47 | if (list == null || list.Count == 0)
48 | {
49 | values = Array.Empty();
50 | }
51 | else
52 | {
53 | values = list.Select(t => $"{t.Item1},{t.Item2}").ToArray();
54 | }
55 | key.SetValue(keyName, values, RegistryValueKind.MultiString);
56 | }
57 | }
58 | catch
59 | {
60 | }
61 | }
62 |
63 | public void WriteMultiLineRegistry(string keyName, List list, Instance instance)
64 | {
65 | try
66 | {
67 | if (string.IsNullOrEmpty(instance?.Name))
68 | {
69 | Debug.WriteLine("Instance is null reg not written");
70 | return;
71 | }
72 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey(instance.GetKeyLocation()))
73 | {
74 | if (list == null || list.Count == 0)
75 | {
76 | key.SetValue(keyName, new string[0], RegistryValueKind.MultiString);
77 | }
78 | else
79 | {
80 | key.SetValue(keyName, list.ToArray(), RegistryValueKind.MultiString);
81 | }
82 | }
83 | }
84 | catch
85 | {
86 | }
87 | }
88 |
89 | public void WriteIntArrayToRegistry(string keyName, int[] values, Instance instance)
90 | {
91 | try
92 | {
93 | if (string.IsNullOrEmpty(instance?.Name))
94 | {
95 | Debug.WriteLine("Instance is null reg not writen");
96 | return;
97 | }
98 | if (values == null)
99 | {
100 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey(instance.GetKeyLocation()))
101 | {
102 | key.SetValue(keyName, "");
103 | }
104 | return;
105 | }
106 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey(instance.GetKeyLocation()))
107 | {
108 | key.SetValue(keyName, string.Join(",", values));
109 | }
110 | }
111 | catch { }
112 | }
113 | public void WriteToRegistryRoot(string keyName, object value)
114 | {
115 | try
116 | {
117 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey($"SOFTWARE\\{regKeyName}"))
118 | {
119 | key.SetValue(keyName, value);
120 | }
121 | }
122 | catch { }
123 | }
124 | public bool KeyExists(string keyName, Instance instance)
125 | {
126 | try
127 | {
128 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey(instance.GetKeyLocation())!)
129 | {
130 | if (key != null)
131 | {
132 | if (key.GetValue(keyName) != null)
133 | {
134 | Debug.WriteLine($"exists: {keyName},{key.GetValue(keyName)}");
135 |
136 | return true;
137 | }
138 | }
139 | }
140 | Debug.WriteLine($"doesnt exist: {keyName}");
141 | return false;
142 | }
143 | catch
144 | {
145 | Debug.WriteLine($"error opening HKCU\\SOFTWARE\\{regKeyName}, {keyName}");
146 | return false;
147 | }
148 | }
149 |
150 | public bool KeyExistsRoot(string keyName)
151 | {
152 | try
153 | {
154 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey($"SOFTWARE\\{regKeyName}")!)
155 | {
156 | if (key != null)
157 | {
158 | if (key.GetValue(keyName) != null)
159 | {
160 | Debug.WriteLine($"exists: {keyName},{key.GetValue(keyName)}");
161 |
162 | return true;
163 | }
164 | }
165 | }
166 | Debug.WriteLine($"doesnt exist: {keyName}");
167 | return false;
168 | }
169 | catch
170 | {
171 | Debug.WriteLine($"error opening HKCU\\SOFTWARE\\{regKeyName}, {keyName}");
172 | return false;
173 | }
174 | }
175 | public object ReadKeyValueRoot(string keyName)
176 | {
177 | try
178 | {
179 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey($"SOFTWARE\\{regKeyName}")!)
180 | {
181 | if (key != null)
182 | {
183 | object value = key.GetValue(keyName)!;
184 | if (value != null)
185 | {
186 | if (value is bool)
187 | {
188 | Debug.WriteLine($"returned bool for {keyName}");
189 | return (bool)value;
190 | }
191 | else if (bool.TryParse(value.ToString(), out bool boolValue))
192 | {
193 | Debug.WriteLine($"returned Parsed bool for {keyName}");
194 | return boolValue;
195 | }
196 | else
197 | {
198 | Debug.WriteLine($"returned string for {keyName}");
199 | return (string)value;
200 | }
201 |
202 | }
203 | }
204 | }
205 | Debug.WriteLine($"couldn't return for {keyName}");
206 | return null;
207 | }
208 | catch (Exception ex)
209 | {
210 | Debug.WriteLine("Error ReadKeyValueRoot: " + ex.Message);
211 | return null;
212 | }
213 | }
214 | public object ReadKeyValueRootInt(string keyName)
215 | {
216 | try
217 | {
218 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey($"SOFTWARE\\{regKeyName}")!)
219 | {
220 | if (key != null)
221 | {
222 | return Int32.Parse(key.GetValue(keyName).ToString());
223 | }
224 | }
225 |
226 | Debug.WriteLine($"couldn't return value for {keyName}");
227 | return null;
228 | }
229 | catch (Exception ex)
230 | {
231 | Debug.WriteLine("Error ReadKeyValueRootInt: " + ex.Message);
232 | return null;
233 | }
234 | }
235 |
236 | public void AddToAutoRun(string appName, string appPath)
237 | {
238 | try
239 | {
240 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true)!)
241 | {
242 | key.SetValue(appName, appPath);
243 | }
244 | }
245 | catch (Exception ex)
246 | {
247 | Debug.WriteLine("Error adding to autorun: " + ex.Message);
248 | }
249 | }
250 |
251 | public void RemoveFromAutoRun(string appName)
252 | {
253 | try
254 | {
255 | using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true)!)
256 | {
257 | key.DeleteValue(appName, false);
258 | }
259 |
260 | }
261 | catch (Exception ex)
262 | {
263 | Debug.WriteLine("Error removing from autorun: " + ex.Message);
264 | }
265 | }
266 |
267 |
268 |
269 | }
270 |
271 |
--------------------------------------------------------------------------------
/DeskFrame/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Diagnostics;
3 | using System.Security.Policy;
4 | using System.Windows;
5 | using Wpf.Ui.Controls;
6 | using Application = System.Windows.Application;
7 | using static DeskFrame.Util.Interop;
8 | using System.Windows.Interop;
9 | using H.Hooks;
10 | using MouseEventArgs = H.Hooks.MouseEventArgs;
11 | using System.Windows.Automation;
12 | namespace DeskFrame
13 | {
14 | public partial class MainWindow : Window
15 | {
16 | private string url = "https://api.github.com/repos/PinchToDebug/DeskFrame/releases/latest";
17 | bool startOnLogin;
18 | bool reseted = false;
19 | private uint _taskbarRestartMessage;
20 | public static InstanceController _controller;
21 | private LowLevelMouseHook _lowLevelMouseHook;
22 | private static bool _doubleClickToHide;
23 | private DateTime _lastDoubleClickTime = DateTime.MinValue;
24 |
25 | public bool DoubleClickToHide
26 | {
27 | get => _doubleClickToHide;
28 | set
29 | {
30 | if (_doubleClickToHide != value)
31 | {
32 | _doubleClickToHide = value;
33 | OnDoubleToClickHideChanged();
34 | }
35 | }
36 | }
37 | private void OnDoubleToClickHideChanged()
38 | {
39 | if (_doubleClickToHide)
40 | {
41 | _lowLevelMouseHook = new LowLevelMouseHook { AddKeyboardKeys = true };
42 | _lowLevelMouseHook.DoubleClick += HandleGlobalDoubleClick;
43 | _lowLevelMouseHook.Start();
44 | }
45 | else
46 | {
47 | _lowLevelMouseHook.Stop();
48 | }
49 | }
50 |
51 | public MainWindow()
52 | {
53 | InitializeComponent();
54 |
55 | versionHeader.Header += " " + Process.GetCurrentProcess().MainModule!.FileVersionInfo.FileVersion!.ToString();
56 | _controller = new InstanceController();
57 | _controller.InitInstances();
58 | if (_controller.reg.KeyExistsRoot("startOnLogin")) startOnLogin = (bool)_controller.reg.ReadKeyValueRoot("startOnLogin");
59 | AutorunToggle.IsChecked = startOnLogin;
60 | // if (_controller.reg.KeyExistsRoot("blurBackground")) BlurToggle.IsChecked = (bool)_controller.reg.ReadKeyValueRoot("blurBackground");
61 | if (_controller.reg.KeyExistsRoot("DoubleClickToHide")) DoubleClickToHide = (bool)_controller.reg.ReadKeyValueRoot("DoubleClickToHide");
62 | if (_controller.reg.KeyExistsRoot("AutoUpdate") && (bool)_controller.reg.ReadKeyValueRoot("AutoUpdate"))
63 | {
64 | Update();
65 | Debug.WriteLine("Auto update checking for update");
66 | }
67 | else if (!_controller.reg.KeyExistsRoot("AutoUpdate"))
68 | {
69 | _controller.reg.WriteToRegistryRoot("AutoUpdate", "False");
70 | }
71 | }
72 | private void HandleGlobalDoubleClick(object? sender, MouseEventArgs e)
73 | {
74 | if (e.Keys.ToString() != "MouseLeft") return;
75 | if ((DateTime.Now - _lastDoubleClickTime).TotalSeconds < 0.3) return;
76 | _lastDoubleClickTime = DateTime.Now;
77 |
78 | POINT pt = new POINT { X = e.Position.X, Y = e.Position.Y };
79 | IntPtr hwndUnderCursor = WindowFromPoint(pt);
80 | IntPtr desktopListView = GetDesktopListViewHandle();
81 |
82 | if (hwndUnderCursor == desktopListView && !IsDesktopIconHit(pt))
83 | {
84 | Application.Current.Dispatcher.Invoke(() =>
85 | {
86 | _controller.ChangeVisibility();
87 | });
88 | }
89 | }
90 |
91 | private static bool IsDesktopIconHit(POINT screenPt)
92 | {
93 | var element = AutomationElement.FromPoint(new System.Windows.Point(screenPt.X, screenPt.Y));
94 | if (element.Current.ControlType == ControlType.ListItem)
95 | {
96 | return true;
97 | }
98 | return false;
99 | }
100 |
101 | private async void Update()
102 | {
103 | await Updater.CheckUpdateAsync(url, false);
104 | }
105 |
106 | private void addDesktopFrame_Click(object sender, RoutedEventArgs e)
107 | {
108 | _controller.AddInstance();
109 | }
110 | private void Window_Initialized(object sender, EventArgs e)
111 | {
112 | this.ShowInTaskbar = false;
113 | this.Width = 0;
114 | this.Height = 0;
115 | this.ResizeMode = ResizeMode.NoResize;
116 | this.WindowStyle = WindowStyle.None;
117 | this.Visibility = Visibility.Collapsed;
118 | this.Left = -500;
119 | this.Top = -500;
120 |
121 | CloseHide();
122 | }
123 | protected override void OnSourceInitialized(EventArgs e)
124 | {
125 | base.OnSourceInitialized(e);
126 | var hwnd = new WindowInteropHelper(this).Handle;
127 | int exStyle = (int)GetWindowLong(hwnd, GWL_EXSTYLE);
128 | exStyle |= WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE;
129 | SetWindowLong(hwnd, GWL_EXSTYLE, (IntPtr)exStyle);
130 | }
131 | private static IntPtr GetDesktopListViewHandle()
132 | {
133 | IntPtr progman = FindWindow("Progman", null);
134 | IntPtr defView = FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", null);
135 |
136 | if (defView == IntPtr.Zero)
137 | {
138 | IntPtr workerw = IntPtr.Zero;
139 | do
140 | {
141 | workerw = FindWindowEx(IntPtr.Zero, workerw, "WorkerW", null);
142 | defView = FindWindowEx(workerw, IntPtr.Zero, "SHELLDLL_DefView", null);
143 | }
144 | while (workerw != IntPtr.Zero && defView == IntPtr.Zero);
145 | }
146 | return FindWindowEx(defView, IntPtr.Zero, "SysListView32", "FolderView");
147 | }
148 | private void CloseHide()
149 | {
150 | Task.Run(() =>
151 | {
152 | Thread.Sleep(100);
153 | Application.Current.Dispatcher.Invoke(() =>
154 | {
155 | this.Close();
156 | });
157 | });
158 | }
159 | protected override void OnClosing(CancelEventArgs e)
160 | {
161 | base.OnClosing(e);
162 | e.Cancel = true;
163 | this.Hide();
164 | }
165 |
166 | private async void Update_Button_Click(object sender, RoutedEventArgs e)
167 | {
168 | await Updater.CheckUpdateAsync(url, true);
169 |
170 | }
171 | //private void BlurToggle_CheckChanged(object sender, System.Windows.RoutedEventArgs e)
172 | //{
173 | // _controller.reg.WriteToRegistryRoot("blurBackground", BlurToggle.IsChecked!);
174 | // _controller.ChangeBlur((bool)BlurToggle.IsChecked!);
175 | //}
176 | private void AutorunToggle_CheckChanged(object sender, RoutedEventArgs e)
177 | {
178 | if ((bool)AutorunToggle.IsChecked!)
179 | {
180 |
181 | _controller.reg.AddToAutoRun("DeskFrame", Process.GetCurrentProcess().MainModule!.FileName);
182 | }
183 | else
184 | {
185 | _controller.reg.RemoveFromAutoRun("DeskFrame");
186 | }
187 | _controller.reg.WriteToRegistryRoot("startOnLogin", AutorunToggle.IsChecked);
188 | }
189 | private void visitGithub_Buton_Click(object sender, RoutedEventArgs e)
190 | {
191 | try
192 | {
193 | ProcessStartInfo sInfo = new ProcessStartInfo($"https://github.com/PinchToDebug/DeskFrame") { UseShellExecute = true };
194 | _ = Process.Start(sInfo);
195 | }
196 | catch
197 | {
198 | }
199 | }
200 |
201 | private void ExitApp(object sender, RoutedEventArgs e)
202 | {
203 | Application.Current.Shutdown();
204 | }
205 |
206 | private void Settings_Button_Click(object sender, RoutedEventArgs e)
207 | {
208 | new SettingsWindow(_controller, this).Show();
209 | }
210 | private void Window_Loaded(object sender, RoutedEventArgs e)
211 | {
212 | _taskbarRestartMessage = RegisterWindowMessage("TaskbarCreated");
213 | var hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
214 | hwndSource.AddHook(WndProc);
215 | }
216 | private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
217 | {
218 | if (msg == _taskbarRestartMessage)
219 | {
220 | // always recreate on UI thread
221 | Application.Current.Dispatcher.Invoke(() =>
222 | {
223 | TrayIcon.Register();
224 | if (!_controller.isInitializingInstances)
225 | _controller.CheckFrameWindowsLive();
226 | });
227 | }
228 | if (msg == 0x007E) // WM_DISPLAYCHANGE
229 | {
230 | if (!_controller.isInitializingInstances)
231 | {
232 | // System.Windows.Forms.MessageBox.Show("ee");
233 |
234 | _controller.CheckFrameWindowsLive();
235 | Thread.Sleep(200);
236 | DummyWindow();
237 | reseted = true;
238 | }
239 | }
240 | if (msg == 0x001C && reseted) // WM_WININICHANGE
241 | {
242 | if (!_controller.isInitializingInstances)
243 | {
244 |
245 | reseted = false;
246 | _controller.CheckFrameWindowsLive();
247 | Thread.Sleep(200);
248 | DummyWindow();
249 | }
250 | }
251 | return IntPtr.Zero;
252 | }
253 | private void DummyWindow()
254 | {
255 | var window = new DeskFrameWindow(new Instance("empty", false))
256 | {
257 | MinHeight = 1,
258 | MinWidth = 1,
259 | Height = 1,
260 | Width = 1,
261 | Opacity = 0,
262 | };
263 | window.Show();
264 | window.Close();
265 | }
266 | protected override void OnClosed(EventArgs e)
267 | {
268 | if (_lowLevelMouseHook != null)
269 | {
270 | _lowLevelMouseHook.Stop();
271 | }
272 | base.OnClosed(e);
273 | }
274 |
275 | }
276 | }
--------------------------------------------------------------------------------
/DeskFrame/ColorPicker/ColorPicker.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Diagnostics;
3 | using System.Windows;
4 | using System.Windows.Controls;
5 | using System.Windows.Input;
6 | using System.Windows.Interop;
7 | using System.Windows.Media;
8 | using System.Windows.Media.Imaging;
9 | using Wpf.Ui.Extensions;
10 | using Color = System.Windows.Media.Color;
11 | using ColorConverter = System.Windows.Media.ColorConverter;
12 | using Point = System.Windows.Point;
13 | using Rectangle = System.Windows.Shapes.Rectangle;
14 | using TextBox = System.Windows.Controls.TextBox;
15 | using UserControl = System.Windows.Controls.UserControl;
16 |
17 | namespace DeskFrame.ColorPicker
18 | {
19 | public partial class ColorPicker : UserControl, INotifyPropertyChanged
20 | {
21 | public event PropertyChangedEventHandler? PropertyChanged;
22 | Point lastMousePoint;
23 | private byte alpha = 255;
24 | private bool _isMouseDown = false;
25 | private bool _isOnColorSelectRect = false;
26 | private bool _isOnColorStrip = false;
27 | private bool _isOnOpacityStrip = false;
28 | private bool _validColor = true;
29 | public Color ThisColor;
30 | private Color _opacityColorZero;
31 | private Color _opacityColorFifty;
32 | public Color _resultColor;
33 | private TextBox _tb;
34 |
35 | public Color ResultColor
36 | {
37 | get => _resultColor;
38 | set
39 | {
40 | if (_resultColor != value)
41 | {
42 |
43 | _resultColor = value;
44 | OnPropertyChanged(nameof(ResultColor));
45 | }
46 | }
47 | }
48 | public Color OpacityColorZero
49 | {
50 | get => _opacityColorZero;
51 | set
52 | {
53 | if (_opacityColorZero != value)
54 | {
55 | _opacityColorZero = value;
56 | OnPropertyChanged(nameof(OpacityColorZero));
57 | }
58 | }
59 | }
60 | public Color OpacityColorFifty
61 | {
62 | get => _opacityColorFifty;
63 | set
64 | {
65 | if (_opacityColorFifty != value)
66 | {
67 | _opacityColorFifty = value;
68 | OnPropertyChanged(nameof(OpacityColorFifty));
69 | }
70 | }
71 | }
72 |
73 | protected virtual void OnPropertyChanged(string propertyName)
74 | {
75 | if (propertyName == "ResultColor")
76 | {
77 | _tb.Text = ResultColor.ToString();
78 | }
79 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
80 | }
81 | public ColorPicker(TextBox tb)
82 | {
83 | _tb = tb;
84 | InitializeComponent();
85 | this.DataContext = this;
86 | try
87 | {
88 | ThisColor = (Color)ColorConverter.ConvertFromString(_tb.Text);
89 | }
90 | catch
91 | {
92 | _validColor = false;
93 | }
94 | Loaded += ColorWheel_Loaded;
95 | }
96 | private void ColorWheel_Loaded(object sender, RoutedEventArgs e)
97 | {
98 | var hwndSource = (HwndSource)HwndSource.FromVisual(this);
99 | hwndSource.AddHook(WndProc);
100 | if (!_validColor)
101 | {
102 | UpdateColorFromStrip((int)(ColorStrip.Width / 2));
103 | UpdateColorFromRect(ColorSelectRect, new Point(220, 30));
104 | UpdateColorFromOpacity(0);
105 | }
106 | else
107 | {
108 | System.Drawing.Color color = System.Drawing.Color.FromArgb(ThisColor.A, ThisColor.R, ThisColor.G, ThisColor.B);
109 | int x = (int)(ColorSelectRect.ActualWidth * ThisColor.ToHsv().Saturation / 100);
110 | int y = (int)(ColorSelectRect.ActualHeight - (ColorSelectRect.ActualHeight * ThisColor.ToHsv().Value / 100));
111 | alpha = ThisColor.A;
112 | UpdateColorFromOpacity(255 - alpha);
113 | UpdateColorFromStrip((int)((color.GetHue() / 360) * ColorStrip.ActualWidth));
114 | UpdateColorFromRect(ColorSelectRect, new Point(x, y));
115 | Debug.WriteLine($"alpha: {color.A}\nalpha2: {ThisColor.A}\nx: {x}\ny: {y}\nh: {color.GetHue()}");
116 | }
117 | }
118 | private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
119 | {
120 | if (msg == 0x0201) // WM_LBUTTONDOWN
121 | {
122 | HandleMouseDown();
123 | }
124 | if (msg == 0x0200) // WM_MOUSEMOVE
125 | {
126 | HandleMouseMove();
127 | }
128 | if (msg == 0x0202) // WM_LBUTTONUP
129 | {
130 | _isMouseDown = false;
131 | }
132 | return IntPtr.Zero;
133 | }
134 | private void HandleMouseDown()
135 | {
136 | if (ColorStrip.IsMouseOver) _isOnColorStrip = true;
137 | else _isOnColorStrip = false;
138 |
139 | if (ColorSelectRect.IsMouseOver) _isOnColorSelectRect = true;
140 | else _isOnColorSelectRect = false;
141 |
142 | if (OpacityStrip.IsMouseOver) _isOnOpacityStrip = true;
143 | else _isOnOpacityStrip = false;
144 |
145 | if (_isOnColorStrip)
146 | {
147 | _isMouseDown = true;
148 | UpdateColorFromStrip((int)Mouse.GetPosition(ColorStrip).X);
149 | }
150 | else if (_isOnColorSelectRect)
151 | {
152 | _isMouseDown = true;
153 | UpdateColorFromRect(ColorSelectRect, Mouse.GetPosition(ColorSelectRect));
154 | }
155 | else if (_isOnOpacityStrip)
156 | {
157 | _isMouseDown = true;
158 | UpdateColorFromOpacity(Mouse.GetPosition(OpacityStrip).X);
159 | }
160 | }
161 | private void HandleMouseMove()
162 | {
163 | if (_isMouseDown)
164 | {
165 | if (_isOnColorStrip)
166 | {
167 | UpdateColorFromStrip((int)Mouse.GetPosition(ColorStrip).X);
168 | }
169 | else if (_isOnColorSelectRect)
170 | {
171 | UpdateColorFromRect(ColorSelectRect, Mouse.GetPosition(ColorSelectRect));
172 | }
173 | else if (_isOnOpacityStrip)
174 | {
175 | UpdateColorFromOpacity(Mouse.GetPosition(OpacityStrip).X);
176 | }
177 | }
178 | }
179 | private void UpdateColorFromRect(Rectangle element, Point mousePosition)
180 | {
181 | int x = (int)mousePosition.X;
182 | int y = (int)mousePosition.Y;
183 |
184 | if (x < 0) x = 0;
185 | if (x >= element.RenderSize.Width) x = (int)element.RenderSize.Width - 1;
186 | if (y < 0) y = 0;
187 | if (y >= element.RenderSize.Height) y = (int)element.RenderSize.Height - 1;
188 |
189 | RenderTargetBitmap renderTarget = new RenderTargetBitmap(
190 | (int)element.RenderSize.Width,
191 | (int)element.RenderSize.Height, 96, 96,
192 | PixelFormats.Pbgra32);
193 |
194 | renderTarget.Render(element);
195 |
196 | int pitch = renderTarget.PixelWidth * 4;
197 | byte[] pixels = new byte[renderTarget.PixelHeight * pitch];
198 | renderTarget.CopyPixels(pixels, pitch, 0);
199 |
200 | int pixelIndex = Math.Clamp((y * pitch) + (x * 4), 0, pixels.Length - 4);
201 |
202 | Canvas.SetLeft(RectSelector, x - RectSelector.Width / 2);
203 | Canvas.SetTop(RectSelector, y - RectSelector.Height / 2);
204 |
205 | byte blue = pixels[pixelIndex];
206 | byte green = pixels[pixelIndex + 1];
207 | byte red = pixels[pixelIndex + 2];
208 |
209 | RectSelector.Fill = new SolidColorBrush(Color.FromArgb(255, red, green, blue));
210 | ResultColor = Color.FromArgb(alpha, red, green, blue);
211 | OpacityColorZero = Color.FromArgb(255, red, green, blue);
212 | OpacityColorFifty = Color.FromArgb(127, red, green, blue);
213 |
214 | lastMousePoint = mousePosition;
215 | }
216 | private void UpdateColorFromStrip(double mouseX)
217 | {
218 | double normalizedX = Math.Min(Math.Max(mouseX, 0), ColorStrip.Width);
219 |
220 | Canvas.SetLeft(HueSelector, normalizedX - HueSelector.Width / 2);
221 | Canvas.SetTop(HueSelector, Canvas.GetTop(ColorStrip) + (ColorStrip.ActualHeight - HueSelector.ActualHeight) / 2);
222 | var gradientBrush = (LinearGradientBrush)((Rectangle)ColorCanvas.Children[0]).Fill;
223 | var color = GetColorFromGradient(gradientBrush, normalizedX / ColorStrip.Width);
224 | SelectedColor.Color = color;
225 | Color a = color;
226 | a.A = 127;
227 | HueSelector.Fill = new SolidColorBrush(color);
228 | UpdateColorFromRect(ColorSelectRect, lastMousePoint);
229 | }
230 | private void UpdateColorFromOpacity(double mouseX)
231 | {
232 | double normalizedX = Math.Min(Math.Max(mouseX, 0), OpacityStrip.Width);
233 | Canvas.SetLeft(OpacitySelector, normalizedX - OpacitySelector.ActualWidth / 2);
234 | Canvas.SetTop(OpacitySelector, Canvas.GetTop(OpacityStrip) + (OpacityStrip.ActualHeight - OpacitySelector.ActualHeight) / 2);
235 |
236 | OpacityPercentageTB.Text = "Opacity: " + (100 - (int)(normalizedX / 256 * 100)).ToString() + "%";
237 |
238 | _opacityColorZero.A = (byte)Math.Abs(255 - normalizedX);
239 | alpha = _opacityColorZero.A;
240 | ResultColor = _opacityColorZero;
241 | }
242 |
243 | private Color GetColorFromGradient(LinearGradientBrush gradientBrush, double offset)
244 | {
245 | for (int i = 0; i < gradientBrush.GradientStops.Count - 1; i++)
246 | {
247 | var stop1 = gradientBrush.GradientStops[i];
248 | var stop2 = gradientBrush.GradientStops[i + 1];
249 |
250 | if (offset >= stop1.Offset && offset <= stop2.Offset)
251 | {
252 | double progress = (offset - stop1.Offset) / (stop2.Offset - stop1.Offset);
253 | byte r = (byte)(stop1.Color.R + (stop2.Color.R - stop1.Color.R) * progress);
254 | byte g = (byte)(stop1.Color.G + (stop2.Color.G - stop1.Color.G) * progress);
255 | byte b = (byte)(stop1.Color.B + (stop2.Color.B - stop1.Color.B) * progress);
256 |
257 | return Color.FromRgb(r, g, b);
258 | }
259 | }
260 | return Colors.Black;
261 | }
262 | }
263 | }
--------------------------------------------------------------------------------
/DeskFrame/Util/Updater.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.IO;
3 | using System.Text.Json;
4 | using System.Reflection;
5 | using Microsoft.Toolkit.Uwp.Notifications;
6 | using Windows.UI.Notifications;
7 | using System.Net.Http;
8 | using System.Globalization;
9 | using System.Text;
10 | using DeskFrame.Properties;
11 | namespace DeskFrame
12 | {
13 | public class Updater
14 | {
15 | private static string _url = "";
16 | private static string _downloadUrl = "";
17 | private static string tag_name = "";
18 | private static int updateCount = 0;
19 | public static async Task CheckUpdateAsync(string url, bool showToastIfNoUpdate)
20 | {
21 | _url = url;
22 | string currentVersion = Process.GetCurrentProcess().MainModule!.FileVersionInfo.FileVersion!.ToString();
23 | try
24 | {
25 | using (var httpClient = new System.Net.Http.HttpClient())
26 | {
27 | httpClient.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("DeskFrame", currentVersion));
28 | var response = await httpClient.GetStringAsync(_url);
29 | Debug.WriteLine("got response");
30 | using (JsonDocument doc = JsonDocument.Parse(response))
31 | {
32 | var root = doc.RootElement;
33 | string latestVersion = root.GetProperty("tag_name").GetString()!;
34 | tag_name = latestVersion;
35 | string description = root.GetProperty("body").GetString()!;
36 | string published_at = root.GetProperty("published_at").GetString()!;
37 | string name = root.GetProperty("name").GetString()!;
38 | string downloadUrl = root.GetProperty("assets")[0].GetProperty("browser_download_url").GetString()!;
39 | _downloadUrl = downloadUrl;
40 | string emoji = (name.ToLower().Contains("fix"), name.ToLower().Contains("feature")) switch
41 | {
42 | (true, true) => "🚀",
43 | (true, false) => "🪛", // (screwdriver)
44 | (false, true) => "✨",
45 | _ => "🚀"
46 | };
47 |
48 | if (!latestVersion.Contains(currentVersion))
49 | {
50 | var toastBuilder = new ToastContentBuilder()
51 | .AddText($"{emoji} New release! {name}", AdaptiveTextStyle.Header)
52 | .AddText(description, AdaptiveTextStyle.Body)
53 | .AddButton(new ToastButton()
54 | .SetContent("Install")
55 | .AddArgument("action", "install_update")
56 | .SetBackgroundActivation())
57 | .AddButton(new ToastButton()
58 | .SetContent("Close")
59 | .AddArgument("action", "close")
60 | .SetBackgroundActivation());
61 | toastBuilder.Show();
62 | }
63 | else if (showToastIfNoUpdate)
64 | {
65 | var toastBuilder = new ToastContentBuilder()
66 | .AddText("You are up to date!", AdaptiveTextStyle.Header)
67 | .AddText("There is no available update.", AdaptiveTextStyle.Body);
68 | toastBuilder.Show();
69 | }
70 | }
71 | }
72 | updateCount++;
73 | }
74 | catch (Exception e)
75 | {
76 | if (updateCount != 0)
77 | {
78 | var toastBuilder = new ToastContentBuilder()
79 | .AddText("Failed to update.", AdaptiveTextStyle.Header)
80 | .AddText(e.Message, AdaptiveTextStyle.Body);
81 | toastBuilder.Show();
82 | }
83 | Debug.WriteLine($"Update error: {e.Message}");
84 | }
85 | }
86 | public static async Task InstallUpdate()
87 | {
88 | string tag = "update";
89 | string group = "downloads";
90 |
91 | var toast = new ToastContentBuilder()
92 | .AddText($"Updating to {tag_name}", AdaptiveTextStyle.Header)
93 | .AddVisualChild(new AdaptiveProgressBar()
94 | {
95 | Title = $"Progress",
96 | Value = new BindableProgressBarValue("progressValue"),
97 | ValueStringOverride = new BindableString("progressValueString"),
98 | Status = new BindableString("progressStatus")
99 | })
100 | .GetToastContent();
101 |
102 | var notif = new ToastNotification(toast.GetXml())
103 | {
104 | Tag = tag,
105 | Group = group
106 | };
107 | ToastNotificationManagerCompat.CreateToastNotifier().Show(notif);
108 |
109 | using (var httpClient = new HttpClient())
110 | using (var response = await httpClient.GetAsync(_downloadUrl, HttpCompletionOption.ResponseHeadersRead))
111 | {
112 | response.EnsureSuccessStatusCode();
113 | var totalBytes = response.Content.Headers.ContentLength ?? -1L;
114 | var canReportProgress = totalBytes != -1;
115 |
116 | string tempFilePath = Path.Combine(Path.GetTempPath(), $"{Assembly.GetExecutingAssembly().GetName().Name}.exe");
117 |
118 | using (var inputStream = await response.Content.ReadAsStreamAsync())
119 | using (var outputStream = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.None))
120 | {
121 | var buffer = new byte[8192];
122 | long totalRead = 0;
123 | int read;
124 | int lastProgress = -1;
125 |
126 | while ((read = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
127 | {
128 | await outputStream.WriteAsync(buffer, 0, read);
129 | totalRead += read;
130 |
131 | if (canReportProgress)
132 | {
133 | int progress = (int)(((long)totalRead * 100) / totalBytes);
134 | if (progress != lastProgress)
135 | {
136 | lastProgress = progress;
137 |
138 | var data = new NotificationData
139 | {
140 | SequenceNumber = (uint)progress,
141 | Values =
142 | {
143 | ["progressValue"] = (progress / 100.0).ToString("0.##", CultureInfo.InvariantCulture),
144 | ["progressValueString"] = $"{progress}%",
145 | ["progressStatus"] = "Downloading..."
146 | }
147 | };
148 |
149 | ToastNotificationManagerCompat.CreateToastNotifier().Update(data, tag, group);
150 |
151 | }
152 | }
153 | }
154 | }
155 | ToastNotificationManagerCompat.CreateToastNotifier().Hide(notif);
156 | RestartApplication(tempFilePath);
157 | }
158 | }
159 | private static bool HasPermissionToWrite(string currentExecutablePath)
160 | {
161 | string path = Path.GetDirectoryName(currentExecutablePath)!;
162 | ProcessStartInfo psi = new ProcessStartInfo
163 | {
164 | FileName = "cmd.exe",
165 | Arguments = $"/C cd /d \"{path}\" && echo. > DeskFrameUpdatePermissionCheck",
166 | UseShellExecute = false,
167 | RedirectStandardError = true,
168 | RedirectStandardOutput = true,
169 | CreateNoWindow = true
170 | };
171 |
172 | Process proc = Process.Start(psi)!;
173 | proc.WaitForExit();
174 | if (proc.ExitCode == 0)
175 | {
176 | Process.Start(new ProcessStartInfo
177 | {
178 | FileName = "cmd.exe",
179 | Arguments = $"/C cd /d \"{path}\" && del DeskFrameUpdatePermissionCheck",
180 | UseShellExecute = false,
181 | CreateNoWindow = true
182 | });
183 | return true;
184 | }
185 | return false;
186 | }
187 |
188 | private static void ExecuteCommand(string command, bool needAdmin)
189 | {
190 | Debug.WriteLine("Starting CMD...");
191 | string tempCmd = "";
192 | if (needAdmin)
193 | {
194 | tempCmd = Path.Combine(Path.GetTempPath(), "deskframe_update.cmd");
195 | File.WriteAllText(Path.Combine(Path.GetTempPath(), "deskframe_update.cmd"), command, Encoding.UTF8);
196 | }
197 | ProcessStartInfo psi = new ProcessStartInfo
198 | {
199 | FileName = needAdmin ? tempCmd : "cmd.exe",
200 | Arguments = needAdmin ? null : $"/C {command}",
201 | UseShellExecute = needAdmin,
202 | CreateNoWindow = true,
203 | WindowStyle = ProcessWindowStyle.Hidden,
204 | Verb = "runas"
205 | };
206 | Process.Start(psi);
207 |
208 | }
209 |
210 | private static void RestartApplication(string tempPath)
211 | {
212 | string currentExecutablePath = Process.GetCurrentProcess().MainModule!.FileName;
213 | string command = $"timeout /t 2 && move /y \"{tempPath}\" \"{currentExecutablePath}\" & \"{currentExecutablePath}\" && exit ";
214 |
215 | if (HasPermissionToWrite(currentExecutablePath))
216 | {
217 | ExecuteCommand(command, false);
218 | }
219 | else
220 | {
221 | var dialog = new Wpf.Ui.Controls.MessageBox
222 | {
223 | Title = "DeskFrame",
224 | Content = Lang.Deskframe_Update_DialogContent,
225 | PrimaryButtonText = "OK"
226 | };
227 |
228 | var result = dialog.ShowDialogAsync();
229 |
230 | if (result.Result == Wpf.Ui.Controls.MessageBoxResult.Primary)
231 | {
232 | ExecuteCommand(command, true);
233 | }
234 | else
235 | {
236 | return;
237 | }
238 | }
239 | Environment.Exit(0);
240 | }
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/DeskFrame/Util/Interop.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32.SafeHandles;
2 | using System;
3 | using System.Collections;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace DeskFrame.Util
11 | {
12 | public static class Interop
13 | {
14 | [DllImport("user32.dll")]
15 | public static extern uint GetDpiForWindow(IntPtr hwnd);
16 | [DllImport("user32.dll")]
17 | public static extern IntPtr GetParent(IntPtr hWnd);
18 | [DllImport("user32.dll")]
19 | public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
20 | [DllImport("user32.dll")]
21 | public static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase);
22 | [DllImport("user32.dll")]
23 | public static extern bool UpdateWindow(IntPtr hWnd);
24 | [DllImport("user32.dll")]
25 | public static extern bool SetFocus(IntPtr hWnd);
26 | [DllImport("user32.dll")]
27 | public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
28 | [DllImport("user32.dll")]
29 | [return: MarshalAs(UnmanagedType.Bool)]
30 | public static extern bool SetForegroundWindow(IntPtr hWnd);
31 | [DllImport("user32.dll")]
32 | public static extern IntPtr WindowFromPoint(POINT Point);
33 | [DllImport("user32.dll", SetLastError = true)]
34 | public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
35 | [DllImport("user32.dll")]
36 | public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);
37 |
38 | [StructLayout(LayoutKind.Sequential)]
39 | public struct POINT { public int X; public int Y; }
40 |
41 | [DllImport("user32.dll")]
42 | [return: MarshalAs(UnmanagedType.Bool)]
43 | public static extern bool IsWindow(IntPtr hWnd);
44 |
45 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
46 | public static extern uint RegisterWindowMessage(string lpString);
47 |
48 | [DllImport("user32.dll")]
49 | public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
50 | public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
51 |
52 | [DllImport("user32.dll")]
53 | public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
54 | [DllImport("user32.dll")]
55 | public static extern short GetAsyncKeyState(int vKey);
56 |
57 | [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
58 | public static extern int ExtractIconEx(string lpszFile, int nIconIndex, IntPtr[] phiconLarge, IntPtr[]? phiconSmall, int nIcons);
59 |
60 | [DllImport("user32.dll", SetLastError = true)]
61 | public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
62 |
63 | [StructLayout(LayoutKind.Sequential)]
64 | public struct RECT
65 | {
66 | public int Left;
67 | public int Top;
68 | public int Right;
69 | public int Bottom;
70 | }
71 | public struct WINDOWPOS
72 | {
73 | public IntPtr hwnd;
74 | public IntPtr hwndInsertAfter;
75 | public uint x;
76 | public uint y;
77 | public uint cx;
78 | public uint cy;
79 | public uint flags;
80 | }
81 |
82 | public const uint GW_HWNDPREV = 3;
83 | public const uint GW_HWNDNEXT = 2;
84 | public const int GWL_EXSTYLE = -20;
85 | public const int GWL_STYLE = -16;
86 | public const int WS_EX_NOACTIVATE = 0x08000000;
87 | public const int WS_EX_TOOLWINDOW = 0x00000080;
88 | public const int WS_CHILD = 0x40000000;
89 | public const int WS_POPUP = unchecked((int)0x80000000);
90 | public const uint SWP_NOOWNERZORDER = 0x0200;
91 | public const uint SWP_NOSENDCHANGING = 0x0400;
92 | public const uint SWP_SHOWWINDOW = 0x0040;
93 | public const int SW_SHOWNA = 8;
94 |
95 | [DllImport("user32.dll")]
96 | public static extern IntPtr GetTopWindow(IntPtr hWnd);
97 |
98 | [DllImport("user32.dll")]
99 | public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
100 | [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
101 | private static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
102 |
103 | [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
104 | private static extern IntPtr GetWindowLong64(IntPtr hWnd, int nIndex);
105 |
106 | public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
107 | {
108 | return IntPtr.Size == 8 ? GetWindowLong64(hWnd, nIndex) : GetWindowLong32(hWnd, nIndex);
109 | }
110 |
111 |
112 | [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
113 | private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
114 |
115 | [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
116 | private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
117 |
118 | public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
119 | {
120 | return IntPtr.Size == 8
121 | ? SetWindowLongPtr64(hWnd, nIndex, dwNewLong)
122 | : new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
123 | }
124 |
125 |
126 | [DllImport("user32.dll", SetLastError = true)]
127 | [return: MarshalAs(UnmanagedType.Bool)]
128 | public static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList lParam);
129 |
130 | public delegate bool EnumedWindow(IntPtr hwnd, ArrayList lParam);
131 |
132 | public static bool EnumWindowCallback(IntPtr hwnd, ArrayList lParam)
133 | {
134 | lParam.Add(hwnd);
135 | return true;
136 | }
137 | [DllImport("user32.dll", SetLastError = true)]
138 | public static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpszClass, string lpszWindow);
139 | public const int WM_NCACTIVATE = 0x0086;
140 | public const uint WM_SETREDRAW = 0x000B;
141 | public const int WM_MOUSEACTIVATE = 0x0021;
142 | public const int WM_MOVING = 0x0216;
143 | public const int WM_LBUTTONDOWN = 0x0201;
144 | public const int WM_SETFOCUS = 0x0007;
145 | public const int WM_KILLFOCUS = 0x0008;
146 | public const int WM_SIZE = 0x0005;
147 | public const int SWP_NOREDRAW = 0x0008;
148 | public const uint SWP_NOZORDER = 0x0004;
149 |
150 | [StructLayout(LayoutKind.Sequential)]
151 | public struct SHFILEINFO
152 | {
153 | public IntPtr hIcon;
154 | public int iIcon;
155 | public uint dwAttributes;
156 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
157 | public string szDisplayName;
158 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
159 | public string szTypeName;
160 | }
161 |
162 | public const uint SHGFI_ICON = 0x000000100; // Get icon
163 | public const uint SHGFI_LARGEICON = 0x000000000; // Large icon (default)
164 | public const uint SHGFI_SMALLICON = 0x000000001; // Small icon
165 |
166 |
167 | [DllImport("user32.dll", SetLastError = true)]
168 | [return: MarshalAs(UnmanagedType.Bool)]
169 | public static extern bool DestroyIcon(IntPtr hIcon);
170 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
171 | public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int width, int height, uint uFlags);
172 | public const uint SWP_NOACTIVATE = 0x0010;
173 |
174 | public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
175 | public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
176 | public const uint SWP_NOMOVE = 0x0002;
177 | public const uint SWP_NOSIZE = 0x0001;
178 | [StructLayout(LayoutKind.Sequential)]
179 | public struct MARGINS
180 | {
181 | public int Left;
182 | public int Right;
183 | public int Top;
184 | public int Bottom;
185 |
186 | public MARGINS(int left, int right, int top, int bottom)
187 | {
188 | Left = left;
189 | Right = right;
190 | Top = top;
191 | Bottom = bottom;
192 | }
193 | }
194 | [DllImport("dwmapi.dll")]
195 | public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);
196 |
197 | public enum AccentState
198 | {
199 | ACCENT_DISABLED = 0,
200 | ACCENT_ENABLE_GRADIENT = 1,
201 | ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
202 | ACCENT_ENABLE_BLURBEHIND = 3,
203 | ACCENT_INVALID_STATE = 4
204 | }
205 |
206 | [StructLayout(LayoutKind.Sequential)]
207 | public struct AccentPolicy
208 | {
209 | public AccentState AccentState;
210 | public int AccentFlags;
211 | public int GradientColor;
212 | public int AnimationId;
213 | }
214 |
215 | [StructLayout(LayoutKind.Sequential)]
216 | public struct WindowCompositionAttributeData
217 | {
218 | public WindowCompositionAttribute Attribute;
219 | public IntPtr Data;
220 | public int SizeOfData;
221 | }
222 |
223 | public enum WindowCompositionAttribute
224 | {
225 | WCA_ACCENT_POLICY = 19
226 |
227 | }
228 | [DllImport("user32.dll")]
229 | public static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
230 |
231 | [ComImport, Guid("b3d0d38f-bc8d-420e-b3b8-4f3f1c2fbd88"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
232 | public interface IContextMenu
233 | {
234 | void QueryContextMenu(IntPtr hmenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags);
235 | void InvokeCommand(ref CMINVOKECOMMANDINFO pici);
236 | void GetCommandString(uint idCmd, uint uFlags, uint reserved, StringBuilder commandString, uint cch);
237 | }
238 |
239 | [ComImport, Guid("0c5f5b9a-6990-11d2-b8c8-006097a5f6d0"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
240 | public interface IShellItem
241 | {
242 | void BindToHandler();
243 | void GetDisplayName();
244 | void GetAttributes();
245 | }
246 |
247 |
248 |
249 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
250 | public struct CMINVOKECOMMANDINFO
251 | {
252 | public uint cbSize;
253 | public uint fMask;
254 | public IntPtr hwnd;
255 | [MarshalAs(UnmanagedType.LPStr)]
256 | public string lpVerb;
257 | [MarshalAs(UnmanagedType.LPStr)]
258 | public string lpParameters;
259 | [MarshalAs(UnmanagedType.LPStr)]
260 | public string lpDirectory;
261 | public uint nShow;
262 | public uint dwHotKey;
263 | public IntPtr hIcon;
264 | }
265 |
266 | [Flags]
267 | public enum SHGFI : uint
268 | {
269 | Icon = 0x100,
270 | LargeIcon = 0x0,
271 | UseFileAttributes = 0x10,
272 | DisplayName = 0x200,
273 | TypeName = 0x400
274 | }
275 |
276 |
277 | [StructLayout(LayoutKind.Sequential)]
278 | public struct SHELLEXECUTEINFO
279 | {
280 | public int cbSize;
281 | public uint fMask;
282 | public IntPtr hwnd;
283 | [MarshalAs(UnmanagedType.LPTStr)]
284 | public string lpVerb;
285 | [MarshalAs(UnmanagedType.LPTStr)]
286 | public string lpFile;
287 | [MarshalAs(UnmanagedType.LPTStr)]
288 | public string lpParameters;
289 | [MarshalAs(UnmanagedType.LPTStr)]
290 | public string lpDirectory;
291 | public int nShow;
292 | public IntPtr hInstApp;
293 | public IntPtr lpIDList;
294 | public IntPtr lpClass;
295 | public IntPtr hkeyClass;
296 | public uint dwHotKey;
297 | public IntPtr hIcon;
298 | public IntPtr hProcess;
299 | }
300 |
301 |
302 | [DllImport("shell32.dll", CharSet = CharSet.Auto)]
303 | public static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo);
304 |
305 |
306 | [DllImport("shell32.dll", CharSet = CharSet.Auto)]
307 | public static extern int SHCreateItemFromParsingName(string pszPath, IntPtr pbc, ref Guid riid, out IShellItem ppv);
308 |
309 | [DllImport("shell32.dll", CharSet = CharSet.Auto)]
310 | public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
311 |
312 |
313 | public const uint SEE_MASK_INVOKEIDLIST = 0x0000000C;
314 | [DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
315 | public static extern int SHCreateItemFromParsingName(
316 | [MarshalAs(UnmanagedType.LPWStr)] string pszPath,
317 | IntPtr pbc,
318 | ref Guid riid,
319 | [MarshalAs(UnmanagedType.Interface)] out IShellItemImageFactory ppv);
320 |
321 |
322 | [DllImport("gdi32.dll")]
323 | public static extern bool DeleteObject(IntPtr hObject);
324 |
325 | internal static int SHGetFileInfo(string path, int v1, ref SHFILEINFO shinfo, uint v2, int flags)
326 | {
327 | throw new NotImplementedException();
328 | }
329 |
330 | [ComImport]
331 | [Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b")]
332 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
333 |
334 |
335 | public interface IShellItemImageFactory
336 | {
337 | int GetImage(System.Drawing.Size size, int flags, out IntPtr phbm);
338 | }
339 | [DllImport("kernel32.dll", SetLastError = true)]
340 | private static extern bool GetFileInformationByHandle(SafeFileHandle hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);
341 | [StructLayout(LayoutKind.Sequential)]
342 | private struct BY_HANDLE_FILE_INFORMATION
343 | {
344 | public uint FileAttributes;
345 | public long CreationTime;
346 | public long LastAccessTime;
347 | public long LastWriteTime;
348 | public uint VolumeSerialNumber;
349 | public uint FileSizeHigh;
350 | public uint FileSizeLow;
351 | public uint NumberOfLinks;
352 | public uint FileIndexHigh;
353 | public uint FileIndexLow;
354 | }
355 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
356 | private static extern SafeFileHandle CreateFile(
357 | string lpFileName,
358 | uint dwDesiredAccess,
359 | uint dwShareMode,
360 | IntPtr lpSecurityAttributes,
361 | uint dwCreationDisposition,
362 | uint dwFlagsAndAttributes,
363 | IntPtr hTemplateFile);
364 |
365 | private const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
366 | private const uint FILE_READ_ATTRIBUTES = 0x80;
367 | private const uint FILE_SHARE_READWRITE = 0x7;
368 | private const uint OPEN_EXISTING = 3;
369 | public static ulong GetFileId(string path)
370 | {
371 | try
372 | {
373 | using var handle = CreateFile(path, FILE_READ_ATTRIBUTES, FILE_SHARE_READWRITE,
374 | IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);
375 | if (handle.IsInvalid)
376 | return 0;
377 | return GetFileInformationByHandle(handle, out var info) ?
378 | ((ulong)info.FileIndexHigh << 32) | info.FileIndexLow : 0;
379 | }
380 | catch
381 | {
382 | return 0;
383 | }
384 | }
385 |
386 | }
387 |
388 | }
389 |
--------------------------------------------------------------------------------
/DeskFrame/Properties/Lang.zh-CN.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 鼠标悬停时展开
122 | CHK_TB: 鼠标悬停时展开框架
123 |
124 |
125 | 在菜单中显示文件夹大小
126 | CHK_TB: 在标题栏右键菜单中显示当前文件夹大小
127 |
128 |
129 | 优先显示最近访问的项目
130 | CHK_TB: 第一行显示最近访问的项目
131 |
132 |
133 | 显示快捷方式箭头
134 | CHK_TB: 在图标左下角显示快捷方式箭头
135 |
136 |
137 | 空闲不透明度:
138 |
139 |
140 | 动画速度:
141 |
142 |
143 | 在虚拟桌面显示:
144 | Label: 在 1,2,3… 虚拟桌面显示此框架
145 |
146 |
147 | 文件扩展名
148 | CHK: 在标题栏添加快速切换文件扩展名的图标
149 |
150 |
151 | 隐藏文件
152 | CHK: 在标题栏添加快速切换隐藏文件的图标
153 |
154 |
155 | 全部(或例如 1,2,3)
156 | 选择此框架显示在哪些虚拟桌面
157 |
158 |
159 | 标题栏图标:
160 | 标题栏中显示的图标
161 |
162 |
163 | 边框颜色 (hex):
164 |
165 |
166 | 其他
167 | 分类标签
168 |
169 |
170 | 标题栏
171 | 分类标签
172 |
173 |
174 | 文件项目
175 | 分类标签
176 |
177 |
178 | 背景颜色 (hex):
179 |
180 |
181 | 文本颜色 (hex):
182 |
183 |
184 | 文本阴影颜色 (hex):
185 |
186 |
187 | 标题栏文本:
188 | 窗口标题
189 |
190 |
191 | 字体:
192 |
193 |
194 | 字号:
195 |
196 |
197 | 文本对齐:
198 |
199 |
200 | 显示文件 (正则):
201 |
202 |
203 | 隐藏文件 (正则):
204 |
205 |
206 | 搜索…
207 |
208 |
209 | 图标大小:
210 |
211 |
212 | 显示图标文字
213 |
214 |
215 | 恢复
216 | 按钮:恢复设置
217 |
218 |
219 | 更改样式
220 | 按钮
221 |
222 |
223 | 更改文件夹
224 | 按钮
225 |
226 |
227 | DeskFrame 设置
228 | 窗口标题
229 |
230 |
231 | 默认框架样式
232 |
233 |
234 | 重置默认样式
235 |
236 |
237 | 自动更新:启动时及每 6 小时检查
238 |
239 |
240 | 双击桌面切换隐藏所有框架
241 |
242 |
243 | 由…制作
244 |
245 |
246 | 导出设置
247 |
248 |
249 | 排序方式
250 |
251 |
252 | 锁定框架
253 |
254 |
255 | 重新加载
256 |
257 |
258 | 打开文件夹
259 |
260 |
261 | 网格视图
262 |
263 |
264 | 隐藏文件
265 | 切换
266 |
267 |
268 | 文件扩展名
269 | 切换
270 |
271 |
272 | 框架设置
273 |
274 |
275 | 文件:
276 | 末尾保留空格
277 |
278 |
279 | 文件夹:
280 | 末尾保留空格
281 |
282 |
283 | (隐藏)
284 | 隐藏文件
285 |
286 |
287 | 最后更新:
288 | 末尾保留空格
289 |
290 |
291 | 移除
292 |
293 |
294 | 文件夹顺序
295 |
296 |
297 | 名称
298 |
299 |
300 | 修改日期
301 |
302 |
303 | 创建日期
304 |
305 |
306 | 类型
307 |
308 |
309 | 大小
310 |
311 |
312 | 升序
313 |
314 |
315 | 降序
316 |
317 |
318 | 默认
319 |
320 |
321 | 优先
322 |
323 |
324 | 置后
325 |
326 |
327 | 解锁框架
328 |
329 |
330 | 确认
331 |
332 |
333 | 确定要移除吗?
334 |
335 |
336 | 是
337 |
338 |
339 | 否
340 |
341 |
342 | 文件夹大小:
343 | 末尾保留空格
344 |
345 |
346 | 更改视图
347 |
348 |
349 | 详细视图
350 |
351 |
352 | 检查更新
353 |
354 |
355 | 访问 GitHub
356 |
357 |
358 | 登录时启动
359 |
360 |
361 | 设置
362 |
363 |
364 | 添加框架
365 |
366 |
367 | 退出
368 | 关闭应用程序
369 |
370 |
371 | 修改日期
372 |
373 |
374 | 名称
375 |
376 |
377 | 大小
378 |
379 |
380 | 拖放文件或文件夹
381 |
382 |
383 | Frame 设置
384 |
385 |
386 | 在窗口内打开文件夹
387 |
388 |
389 | 你拖入的第一个文件夹或文件决定此框架的类型。有两种类型:
390 |
391 |
392 | 可以从任何位置创建快捷方式以访问文件和文件夹。当你将另一个文件或文件夹拖入其中时,会创建该项目的快捷方式。
393 |
394 |
395 | 显示文件夹的内容。当你将另一个文件或文件夹拖入其中时,该项目会被移动到该文件夹内。
396 |
397 |
398 | 文件夹:
399 |
400 |
401 | 文件:
402 |
403 |
404 | 窗口
405 |
406 |
407 | 调整宽度适应图标
408 |
409 |
410 | 保留滚动条空间
411 |
412 |
413 | 位置 X:
414 |
415 |
416 | 位置 Y:
417 |
418 |
419 | DeskFrame 已在运行
420 |
421 |
422 | 活动颜色(hex):
423 |
424 |
425 | 更新需要管理员权限
426 |
427 |
428 | 隐藏非活动窗口上的图标
429 |
430 |
431 | 拖动
432 |
433 |
434 | 将窗口以10像素的距离对齐
435 |
436 |
437 | 滚动
438 |
439 |
440 | 更改图标大小
441 |
442 |
443 | 开启灰度模式
444 |
445 |
446 | 仅在框架不活动时启用灰度
447 |
448 |
449 | 灰度等级:
450 |
451 |
452 | 自设
453 |
454 |
455 | 删除
456 |
457 |
458 | 开启
459 |
460 |
461 | 关闭
462 |
463 |
--------------------------------------------------------------------------------
/DeskFrame/Properties/Lang.ko-KR.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 커서 위에서 확장
122 | CHK_TB: Open "frame" on cursor over (unroll)
123 |
124 |
125 | 메뉴에 폴더 크기 표시
126 | CHK_TB: Show the folder size of the folder that is shown in the frame in the menu accessed with right-click on the titlebar
127 |
128 |
129 | 최근 사용한 항목 먼저 표시
130 | CHK_TB: Show last accessed items in the first row
131 |
132 |
133 | 바로가기 화살표 표시
134 | CHK_TB: Show the shortcut arrow on the bottom left of icons
135 |
136 |
137 | 유휴 불투명도:
138 |
139 |
140 | 애니메이션 속도:
141 |
142 |
143 | 가상 데스크톱에 표시:
144 | Label: Show the frame on the 1,2,3.. virtual desktop.
145 |
146 |
147 | 파일 확장자
148 | CHK: Add show "file extensions" icon in the titlebar for quick toggling
149 |
150 |
151 | 숨김 파일
152 | CHK: Add show "hidden files" icon in the titlebar for quick toggling
153 |
154 |
155 | 전체 (예: 1,2,3)
156 | Placeholder text in textbox for choosing which virtual desktops the frame should appear on
157 |
158 |
159 | 제목 표시줄 아이콘:
160 | Label: Icons appearing in the titlebar
161 |
162 |
163 | 테두리 색상 (hex):
164 |
165 |
166 | 기타
167 | Label for the category
168 |
169 |
170 | 제목 표시줄
171 | Label for the category
172 |
173 |
174 | 파일 항목
175 | Label for the category
176 |
177 |
178 | 배경 색상 (hex):
179 |
180 |
181 | 텍스트 색상 (hex):
182 |
183 |
184 | 텍스트 그림자 색상 (hex):
185 |
186 |
187 | 제목 표시줄 텍스트:
188 | Title of the window
189 |
190 |
191 | 글꼴:
192 |
193 |
194 | 글자 크기:
195 |
196 |
197 | 글자 정렬:
198 |
199 |
200 | 파일 표시 (정규식):
201 |
202 |
203 | 파일 숨기기 (정규식):
204 |
205 |
206 | 검색...
207 |
208 |
209 | 아이콘 크기:
210 |
211 |
212 | 아이콘 텍스트 표시
213 |
214 |
215 | 되돌리기
216 | Button: revert settings
217 |
218 |
219 | 스타일 변경
220 | Button
221 |
222 |
223 | 폴더 변경
224 | Button
225 |
226 |
227 | DeskFrame 설정
228 | Title of the window
229 |
230 |
231 | 기본 프레임 스타일
232 |
233 |
234 | 기본 스타일로 재설정
235 |
236 |
237 | 자동 업데이트. 시작 시와 6시간마다 확인
238 |
239 |
240 | 데스크톱에서 더블 클릭하여 모든 프레임 숨기기
241 |
242 |
243 | 제작:
244 | Made with + a whitespace
245 |
246 |
247 | 설정 내보내기
248 |
249 |
250 | 정렬 기준
251 |
252 |
253 | 프레임 잠금
254 |
255 |
256 | 새로고침
257 |
258 |
259 | 폴더 열기
260 |
261 |
262 | 그리드 보기
263 |
264 |
265 | 숨김 파일
266 | Toggle
267 |
268 |
269 | 파일 확장자
270 | Toggle
271 |
272 |
273 | 프레임 설정
274 |
275 |
276 | 파일:
277 | whitespace at the end
278 |
279 |
280 | 폴더:
281 | whitespace at the end
282 |
283 |
284 | (숨김)
285 | hidden files
286 |
287 |
288 | 최종 업데이트:
289 | whitespace at the end
290 |
291 |
292 | 삭제
293 |
294 |
295 | 폴더 순서
296 |
297 |
298 | 이름
299 |
300 |
301 | 수정 날짜
302 |
303 |
304 | 생성 날짜
305 |
306 |
307 | 파일 유형
308 |
309 |
310 | 파일 크기
311 |
312 |
313 | 오름차순
314 |
315 |
316 | 내림차순
317 |
318 |
319 | 없음
320 |
321 |
322 | 첫 번째
323 |
324 |
325 | 마지막
326 |
327 |
328 | 프레임 잠금 해제
329 |
330 |
331 | 확인
332 |
333 |
334 | 정말 삭제하시겠습니까?
335 |
336 |
337 | 예
338 |
339 |
340 | 아니요
341 |
342 |
343 | 폴더 크기:
344 | whitespace at the end
345 |
346 |
347 | 보기 변경
348 |
349 |
350 | 자세히 보기
351 |
352 |
353 | 업데이트 확인
354 |
355 |
356 | Github 방문
357 |
358 |
359 | 자동 시작
360 |
361 |
362 | 설정
363 |
364 |
365 | 프레임 추가
366 |
367 |
368 | 종료
369 | Button to close the application
370 |
371 |
372 | 수정 날짜
373 |
374 |
375 | 이름
376 |
377 |
378 | 크기
379 |
380 |
381 | 파일/폴더 놓기
382 |
383 |
384 | Frame 설정
385 |
386 |
387 | 창 안에서 폴더 열기
388 |
389 |
390 | 처음 드래그한 폴더나 파일이 프레임 유형을 결정합니다. 유형은 두 가지입니다:
391 |
392 |
393 | 어디서든 파일과 폴더에 접근할 수 있는 바로가기를 생성합니다. 다른 파일이나 폴더를 드래그하면 해당 항목의 바로가기가 생성됩니다.
394 |
395 |
396 | 폴더의 내용을 표시합니다. 다른 파일이나 폴더를 드래그하면 해당 항목이 그 폴더 안으로 이동됩니다.
397 |
398 |
399 | 폴더:
400 |
401 |
402 | 파일:
403 |
404 |
405 | 창
406 |
407 |
408 | 아이콘 크기에 맞게 너비 조정
409 |
410 |
411 | 스크롤바 공간 예약
412 |
413 |
414 | 위치 X:
415 |
416 |
417 | 위치 Y:
418 |
419 |
420 | DeskFrame이(가) 이미 실행 중입니다
421 |
422 |
423 | 활성 색상 (hex):
424 |
425 |
426 | 업데이트하려면 관리자 권한이 필요합니다
427 |
428 |
429 | 비활성 창에서 아이콘 숨기기
430 |
431 |
432 | 드래그
433 |
434 |
435 | 10픽셀 거리로 창 맞추기
436 |
437 |
438 | 스크롤
439 |
440 |
441 | 아이콘 크기 변경
442 |
443 |
444 | 그레이스케일 켜기
445 |
446 |
447 | 프레임이 비활성 상태일 때만 그레이스케일 적용
448 |
449 |
450 | 명암 단계:
451 |
452 |
453 | 사용자
454 |
455 |
456 | 삭제
457 |
458 |
459 | 켜짐
460 |
461 |
462 | 꺼짐
463 |
464 |
--------------------------------------------------------------------------------
/DeskFrame/Properties/Lang.pl-PL.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Rozwiń po najechaniu kursorem
122 | CHK_TB: Open "frame" on cursor over (unroll)
123 |
124 |
125 | Pokaż rozmiar folderu w menu
126 | CHK_TB: Show the folder size of the folder that is shown in the frame in the menu accessed with right-click on the titlebar
127 |
128 |
129 | Pokaż ostatnio używane elementy jako pierwsze
130 | CHK_TB: Show last accessed items in the first row
131 |
132 |
133 | Pokaż strzałkę skrótu
134 | CHK_TB: Show the shortcut arrow on the bottom left of icons
135 |
136 |
137 | Przezroczystość w bezczynności:
138 |
139 |
140 | Szybkość animacji:
141 |
142 |
143 | Widoczny na wirtualnym pulpicie:
144 | Label: Show the frame on the 1,2,3.. virtual desktop.
145 |
146 |
147 | Rozszerzenia plików
148 | CHK: Add show "file extensions" icon in the titlebar for quick toggling
149 |
150 |
151 | Ukryte pliki
152 | CHK: Add show "hidden files" icon in the titlebar for quick toggling
153 |
154 |
155 | Wszystkie (lub np. 1,2,3)
156 | Placeholder text in textbox for choosing which virtual desktops the frame should appear on
157 |
158 |
159 | Ikony na pasku tytułu:
160 | Label: Icons appearing in the titlebar
161 |
162 |
163 | Kolor obramowania (hex):
164 |
165 |
166 | Różne
167 | Label for the category
168 |
169 |
170 | Pasek tytułu
171 | Label for the category
172 |
173 |
174 | Elementy plików
175 | Label for the category
176 |
177 |
178 | Kolor tła (hex):
179 |
180 |
181 | Kolor tekstu (hex):
182 |
183 |
184 | Kolor cienia tekstu (hex):
185 |
186 |
187 | Tekst paska tytułu:
188 | Title of the window
189 |
190 |
191 | Czcionka:
192 |
193 |
194 | Rozmiar tekstu:
195 |
196 |
197 | Wyrównanie tekstu:
198 |
199 |
200 | Pokaż pliki (regex):
201 |
202 |
203 | Ukryj pliki (regex):
204 |
205 |
206 | Szukaj...
207 |
208 |
209 | Rozmiar ikony:
210 |
211 |
212 | Pokaż tekst ikony
213 |
214 |
215 | Przywróć
216 | Button: revert settings
217 |
218 |
219 | Zmień styl
220 | Button
221 |
222 |
223 | Zmień folder
224 | Button
225 |
226 |
227 | Ustawienia DeskFrame
228 | Title of the window
229 |
230 |
231 | Domyślny styl ramki
232 |
233 |
234 | Przywróć domyślny styl
235 |
236 |
237 | Automatyczna aktualizacja. Sprawdzaj aktualizacje przy starcie i co 6 godzin
238 |
239 |
240 | Dwuklik na pulpicie w celu ukrycia wszystkich ramek
241 |
242 |
243 | Wykonano z
244 | Made with + a whitespace
245 |
246 |
247 | Eksportuj ustawienia
248 |
249 |
250 | Sortuj według
251 |
252 |
253 | Zablokuj ramkę
254 |
255 |
256 | Przeładuj
257 |
258 |
259 | Otwórz folder
260 |
261 |
262 | Widok siatki
263 |
264 |
265 | Ukryte pliki
266 | Toggle
267 |
268 |
269 | Rozszerzenia plików
270 | Toggle
271 |
272 |
273 | Ustawienia ramki
274 |
275 |
276 | Pliki:
277 | whitespace at the end
278 |
279 |
280 | Foldery:
281 | whitespace at the end
282 |
283 |
284 | (ukryte)
285 | hidden files
286 |
287 |
288 | Ostatnia aktualizacja:
289 | whitespace at the end
290 |
291 |
292 | Usuń
293 |
294 |
295 | Kolejność folderów
296 |
297 |
298 | Nazwa
299 |
300 |
301 | Data modyfikacji
302 |
303 |
304 | Data utworzenia
305 |
306 |
307 | Typ pliku
308 |
309 |
310 | Rozmiar pliku
311 |
312 |
313 | Rosnąco
314 |
315 |
316 | Malejąco
317 |
318 |
319 | Brak
320 |
321 |
322 | Pierwszy
323 |
324 |
325 | Ostatni
326 |
327 |
328 | Odblokuj ramkę
329 |
330 |
331 | Potwierdź
332 |
333 |
334 | Czy na pewno chcesz usunąć?
335 |
336 |
337 | Tak
338 |
339 |
340 | Nie
341 |
342 |
343 | Rozmiar folderu:
344 | whitespace at the end
345 |
346 |
347 | Zmień widok
348 |
349 |
350 | Widok szczegółowy
351 |
352 |
353 | Sprawdź aktualizacje
354 |
355 |
356 | Odwiedź Github
357 |
358 |
359 | Uruchamianie
360 |
361 |
362 | Ustawienia
363 |
364 |
365 | Dodaj ramkę
366 |
367 |
368 | Zakończ
369 | Button to close the application
370 |
371 |
372 | Data modyfikacji
373 |
374 |
375 | Nazwa
376 |
377 |
378 | Rozmiar
379 |
380 |
381 | Upuść plik lub folder
382 |
383 |
384 | Ustawienia Frame
385 |
386 |
387 | Otwórz folder w oknie
388 |
389 |
390 | Pierwszy folder lub plik, który przeciągniesz, określa typ ramki. Są dwa typy:
391 |
392 |
393 | Tworzy skróty z dowolnego miejsca, aby uzyskać dostęp do plików i folderów. Gdy przeciągniesz inny plik lub folder, zostanie utworzony skrót tego elementu.
394 |
395 |
396 | Wyświetla zawartość folderu. Gdy przeciągniesz inny plik lub folder, element zostanie przeniesiony do tego folderu.
397 |
398 |
399 | Folder:
400 |
401 |
402 | Plik:
403 |
404 |
405 | Okno
406 |
407 |
408 | Dopasuj szerokość do ikony
409 |
410 |
411 | Zarezerwuj miejsce dla paska
412 |
413 |
414 | Pozycja X:
415 |
416 |
417 | Pozycja Y:
418 |
419 |
420 | DeskFrame już jest uruchomiony
421 |
422 |
423 | Aktywny kolor (hex):
424 |
425 |
426 | Aktualizacja wymaga uprawnień administratora
427 |
428 |
429 | Ukryj ikony w nieaktywnej oknie
430 |
431 |
432 | DRAGOWAĆ
433 |
434 |
435 | Przyciągnij okno na 10 pikseli
436 |
437 |
438 | PRZEWIJ
439 |
440 |
441 | Zmień rozmiar ikony
442 |
443 |
444 | Aktywuj skalę szarości
445 |
446 |
447 | Skala szarości tylko gdy ramka jest nieaktywna
448 |
449 |
450 | Poziom szarości:
451 |
452 |
453 | Własne
454 |
455 |
456 | Usuń
457 |
458 |
459 | Wł
460 |
461 |
462 | Wył
463 |
464 |
--------------------------------------------------------------------------------
/DeskFrame/Properties/Lang.es-ES.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Expandir al pasar el cursor
122 | CHK_TB: Open "frame" on cursor over (unroll)
123 |
124 |
125 | Mostrar tamaño de carpeta en el menú
126 | CHK_TB: Show the folder size of the folder that is shown in the frame in the menu accessed with right-click on the titlebar
127 |
128 |
129 | Mostrar primero los elementos más recientes
130 | CHK_TB: Show last accessed items in the first row
131 |
132 |
133 | Mostrar flecha de acceso directo
134 | CHK_TB: Show the shortcut arrow on the bottom left of icons
135 |
136 |
137 | Opacidad en reposo:
138 |
139 |
140 | Velocidad de animación:
141 |
142 |
143 | Visible en escritorio virtual:
144 | Label: Show the frame on the 1,2,3.. virtual desktop.
145 |
146 |
147 | Extensiones de archivo
148 | CHK: Add show "file extensions" icon in the titlebar for quick toggling
149 |
150 |
151 | Archivos ocultos
152 | CHK: Add show "hidden files" icon in the titlebar for quick toggling
153 |
154 |
155 | Todos (o ej. 1,2,3)
156 | Placeholder text in textbox for choosing which virtual desktops the frame should appear on
157 |
158 |
159 | Iconos en la barra de título:
160 | Label: Icons appearing in the titlebar
161 |
162 |
163 | Color del borde (hex):
164 |
165 |
166 | Varios
167 | Label for the category
168 |
169 |
170 | Barra de título
171 | Label for the category
172 |
173 |
174 | Elementos de archivo
175 | Label for the category
176 |
177 |
178 | Color de fondo (hex):
179 |
180 |
181 | Color del texto (hex):
182 |
183 |
184 | Color de sombra del texto (hex):
185 |
186 |
187 | Texto de la barra de título:
188 | Title of the window
189 |
190 |
191 | Fuente:
192 |
193 |
194 | Tamaño de texto:
195 |
196 |
197 | Alineación de texto:
198 |
199 |
200 | Mostrar archivos (regex):
201 |
202 |
203 | Ocultar archivos (regex):
204 |
205 |
206 | Buscar...
207 |
208 |
209 | Tamaño del icono:
210 |
211 |
212 | Mostrar texto del icono
213 |
214 |
215 | Restaurar
216 | Button: revert settings
217 |
218 |
219 | Cambiar estilo
220 | Button
221 |
222 |
223 | Cambiar carpeta
224 | Button
225 |
226 |
227 | Configuración de DeskFrame
228 | Title of the window
229 |
230 |
231 | Estilo de marco predeterminado
232 |
233 |
234 | Restablecer estilo predeterminado
235 |
236 |
237 | Actualización automática. Revisar al iniciar y cada 6 horas
238 |
239 |
240 | Doble clic en el escritorio para ocultar todos los marcos
241 |
242 |
243 | Hecho con
244 | Made with + a whitespace
245 |
246 |
247 | Exportar configuración
248 |
249 |
250 | Ordenar por
251 |
252 |
253 | Bloquear marco
254 |
255 |
256 | Recargar
257 |
258 |
259 | Abrir carpeta
260 |
261 |
262 | Vista de cuadrícula
263 |
264 |
265 | Archivos ocultos
266 | Toggle
267 |
268 |
269 | Extensiones de archivo
270 | Toggle
271 |
272 |
273 | DeskFrame configuración
274 |
275 |
276 | Archivos:
277 | whitespace at the end
278 |
279 |
280 | Carpetas:
281 | whitespace at the end
282 |
283 |
284 | (oculto)
285 | hidden files
286 |
287 |
288 | Última actualización:
289 | whitespace at the end
290 |
291 |
292 | Eliminar
293 |
294 |
295 | Orden de carpetas
296 |
297 |
298 | Nombre
299 |
300 |
301 | Fecha de modificación
302 |
303 |
304 | Fecha de creación
305 |
306 |
307 | Tipo de archivo
308 |
309 |
310 | Tamaño de archivo
311 |
312 |
313 | Ascendente
314 |
315 |
316 | Descendente
317 |
318 |
319 | Ninguno
320 |
321 |
322 | Primero
323 |
324 |
325 | Último
326 |
327 |
328 | Desbloquear marco
329 |
330 |
331 | Confirmar
332 |
333 |
334 | ¿Está seguro de que desea eliminarlo?
335 |
336 |
337 | Sí
338 |
339 |
340 | No
341 |
342 |
343 | Tamaño de carpeta:
344 | whitespace at the end
345 |
346 |
347 | Cambiar vista
348 |
349 |
350 | Vista detallada
351 |
352 |
353 | Buscar actualizaciones
354 |
355 |
356 | Visitar Github
357 |
358 |
359 | Inicio automático
360 |
361 |
362 | Configuración
363 |
364 |
365 | Agregar marco
366 |
367 |
368 | Salir
369 | Button to close the application
370 |
371 |
372 | Fecha de modificación
373 |
374 |
375 | Nombre
376 |
377 |
378 | Tamaño
379 |
380 |
381 | Suelta archivo o carpeta
382 |
383 |
384 | Configuración de Frame
385 |
386 |
387 | Abrir carpeta dentro de la ventana
388 |
389 |
390 | La primera carpeta o archivo que arrastres decidirá el tipo de marco. Hay dos tipos:
391 |
392 |
393 | Crea accesos directos desde cualquier lugar para acceder a archivos y carpetas. Cuando arrastras otro archivo o carpeta dentro, se crea un acceso directo del elemento.
394 |
395 |
396 | Muestra el contenido de una carpeta. Cuando arrastras otro archivo o carpeta dentro, el elemento se mueve dentro de esa carpeta.
397 |
398 |
399 | Carpeta:
400 |
401 |
402 | Archivo:
403 |
404 |
405 | Ventana
406 |
407 |
408 | Ajustar ancho al tamaño del icono
409 |
410 |
411 | Reservar espacio para la barra
412 |
413 |
414 | Posición X:
415 |
416 |
417 | Posición Y:
418 |
419 |
420 | DeskFrame ya se está ejecutando
421 |
422 |
423 | Color activo (hex):
424 |
425 |
426 | La actualización requiere privilegios de administrador
427 |
428 |
429 | Ocultar iconos en ventana inactiva
430 |
431 |
432 | ARRASTRAR
433 |
434 |
435 | Ajustar ventana a 10 píxeles
436 |
437 |
438 | DESPLAZAR
439 |
440 |
441 | Cambiar tamaño del icono
442 |
443 |
444 | Activar escala de grises
445 |
446 |
447 | Escala de grises al inactivar
448 |
449 |
450 | Nivel de gris:
451 |
452 |
453 | Personal
454 |
455 |
456 | Borrar
457 |
458 |
459 | Activo
460 |
461 |
462 | Inactivo
463 |
464 |
--------------------------------------------------------------------------------
/DeskFrame/Properties/Lang.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Expand on cursor over
122 | CHK_TB: Open "frame" on cursor over (unroll)
123 |
124 |
125 | Show folder size in menu
126 | CHK_TB: Show the folder size of the folder that is shown in the frame in the menu accessed with right-click on the titlebar
127 |
128 |
129 | Show last accessed items first
130 | CHK_TB: Show last accessed items in the first row
131 |
132 |
133 | Show shortcut arrow
134 | CHK_TB: Show the shortcut arrow on the bottom left of icons
135 |
136 |
137 | Idle opacity:
138 |
139 |
140 | Animation speed:
141 |
142 |
143 | Visible on virtual desktop:
144 | Label: Show the frame on the 1,2,3.. virtual desktop.
145 |
146 |
147 | File extensions
148 | CHK: Add show "file extensions" icon in the titlebar for quick toggling
149 |
150 |
151 | Hidden files
152 | CHK: Add show "hidden files" icon in the titlebar for quick toggling
153 |
154 |
155 | All (or e.g. 1,2,3)
156 | Placeholder text in textbox for choosing which virtual desktops the frame should appear on
157 |
158 |
159 | Title bar icons:
160 | Label: Icons appearing in the titlebar
161 |
162 |
163 | Border color (hex):
164 |
165 |
166 | Miscellaneous
167 | Label for the category
168 |
169 |
170 | Title bar
171 | Label for the category
172 |
173 |
174 | File items
175 | Label for the category
176 |
177 |
178 | Background color (hex):
179 |
180 |
181 | Text color (hex):
182 |
183 |
184 | Text shadow color (hex):
185 |
186 |
187 | Title bar text:
188 | Title of the window
189 |
190 |
191 | Font:
192 |
193 |
194 | Text size:
195 |
196 |
197 | Text alignment:
198 |
199 |
200 | Show files (regex):
201 |
202 |
203 | Hide files (regex):
204 |
205 |
206 | Search...
207 |
208 |
209 | Icon size:
210 |
211 |
212 | Show icon text
213 |
214 |
215 | Revert
216 | Button: revert settings
217 |
218 |
219 | Change style
220 | Button
221 |
222 |
223 | Change folder
224 | Button
225 |
226 |
227 | DeskFrame settings
228 | Title of the window
229 |
230 |
231 | Default frame style
232 |
233 |
234 | Reset default style
235 |
236 |
237 | Auto update. Check for update on start and every 6 hours
238 |
239 |
240 | Double click on desktop to toggle hide every frame
241 |
242 |
243 | Made with
244 | Made with + a whitespace
245 |
246 |
247 | Export settings
248 |
249 |
250 | Sort by
251 |
252 |
253 | Lock frame
254 |
255 |
256 | Reload
257 |
258 |
259 | Open folder
260 |
261 |
262 | Grid view
263 |
264 |
265 | Hidden files
266 | Toggle
267 |
268 |
269 | File extensions
270 | Toggle
271 |
272 |
273 | Frame Settings
274 |
275 |
276 | Files:
277 | whitespace at the end
278 |
279 |
280 | Folders:
281 | whitespace at the end
282 |
283 |
284 | (hidden)
285 | hidden files
286 |
287 |
288 | Last Updated:
289 | whitespace at the end
290 |
291 |
292 | Remove
293 |
294 |
295 | Folder order
296 |
297 |
298 | Name
299 |
300 |
301 | Date modified
302 |
303 |
304 | Date created
305 |
306 |
307 | File type
308 |
309 |
310 | File size
311 |
312 |
313 | Ascending
314 |
315 |
316 | Descending
317 |
318 |
319 | None
320 |
321 |
322 | First
323 |
324 |
325 | Last
326 |
327 |
328 | Unlock frame
329 |
330 |
331 | Confirm
332 |
333 |
334 | Are you sure you want to remove it?
335 |
336 |
337 | Yes
338 |
339 |
340 | No
341 |
342 |
343 | Folder Size:
344 | whitespace at the end
345 |
346 |
347 | Change view
348 |
349 |
350 | Details view
351 |
352 |
353 | Check for updates
354 |
355 |
356 | Visit github
357 |
358 |
359 | Start on login
360 |
361 |
362 | Settings
363 |
364 |
365 | Add frame
366 |
367 |
368 | Exit
369 | Button to close the application
370 |
371 |
372 | Date modified
373 |
374 |
375 | Name
376 |
377 |
378 | Size
379 |
380 |
381 | Drop a folder
382 |
383 |
384 | Frame settings
385 | Title of the window
386 |
387 |
388 | Open folder inside window
389 |
390 |
391 | The first folder or file you drag in decides the frame type. There are two types:
392 |
393 |
394 | Creates shortcuts from anywhere to access files and folders. When you drag another file or folder into it, it creates a shortcut of the item.
395 |
396 |
397 | Shows the contents of a folder. When you drag another file or folder into it, it moves the item inside that folder.
398 |
399 |
400 | Folder:
401 |
402 |
403 | File:
404 |
405 |
406 | Window
407 |
408 |
409 | Resize width to fit icon size
410 | TextBlock
411 |
412 |
413 | Reserve space for scrollbar
414 | TextBlock
415 |
416 |
417 | Position X:
418 | TextBlock
419 |
420 |
421 | Position Y:
422 | TextBlock
423 |
424 |
425 | DeskFrame is already running
426 |
427 |
428 | Active color (hex)
429 |
430 |
431 | Updating requires administrator privileges
432 | Content of dialog
433 |
434 |
435 | Hide icons on inactive window
436 |
437 |
438 | DRAG
439 | Drag button
440 |
441 |
442 | Snap frame with 10 pixel distance
443 |
444 |
445 | SCROLL
446 | Button
447 |
448 |
449 | Change icon size
450 | Button
451 |
452 |
453 | Enable grayscale
454 | CheckBox
455 |
456 |
457 | Grayscale only when frame is inactive
458 | CheckBox
459 |
460 |
461 | Gray level:
462 |
463 |
464 | Custom
465 |
466 |
467 | Delete
468 | Delete button
469 |
470 |
471 | Enabled
472 | Enable/Disable ToggleSwitch
473 |
474 |
475 | Disabled
476 | Enable/Disable ToggleSwitch
477 |
478 |
--------------------------------------------------------------------------------