Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion installer/Installer.iss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId=68d780d4-b946-4154-8815-e4632e5ec5d8
AppId=4B2411E5-1AE9-450C-AF2F-9A515ECBB9DF
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
Expand Down
Binary file modified installer/InvLock-Installer.exe
Binary file not shown.
15 changes: 15 additions & 0 deletions src/InvLock/BlurWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Window x:Class="InvLock.BlurWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:InvLock"
mc:Ignorable="d"
Loaded="Window_Loaded"
WindowStyle="None"
MouseDown="Window_MouseDown"
AllowsTransparency="True"
Background="Black"
Opacity="0"
Title="BlurWindow" Height="450" Width="800">
</Window>
26 changes: 26 additions & 0 deletions src/InvLock/BlurWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using InvLock.Utilities;

using System.Windows;

namespace InvLock;

/// <summary>
/// Interaction logic for BlurWindow.xaml
/// </summary>
public partial class BlurWindow : Window
{
public BlurWindow()
{
InitializeComponent();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowsApi.EnableBlur(this);
}

private void Window_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
DragMove();
}
}
33 changes: 31 additions & 2 deletions src/InvLock/DataContexts/MainWindowDataContext.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
using CommunityToolkit.Mvvm.Input;

using InvLock.Utilities;

using SharpHook.Native;

using System.ComponentModel;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace InvLock.DataContexts;

internal partial class MainWindowDataContext(Func<LockWindow?> lockWindowAccessor)
internal partial class MainWindowDataContext(Func<LockWindow?> lockWindowAccessor) : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;

#if DEBUG
public string Title => $"{App.AppName} - Dev {AppVersion}";
#else
Expand All @@ -16,10 +22,28 @@ internal partial class MainWindowDataContext(Func<LockWindow?> lockWindowAccesso

public string AppName => App.AppName;

public string AppVersion => Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "Unknown";
public string AppVersion => Assembly.GetEntryAssembly()?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion ?? "Unknown";

public Settings Settings { get; } = Settings.Load();

public bool IsAutoStartEnabled
{
get => StartupManager.IsAutoStartEnabled();
set
{
if (value)
{
_ = StartupManager.EnableAutoStart();
}
else
{
_ = StartupManager.DisableAutoStart();
}

OnPropertyChanged();
}
}

[RelayCommand]
public async Task RecordLockShortcut()
{
Expand Down Expand Up @@ -55,4 +79,9 @@ public async Task RecordUnlockShortcut()
Settings.UnlockShortcut = unlockShortcut;
}
}

protected void OnPropertyChanged([CallerMemberName] string? name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
6 changes: 6 additions & 0 deletions src/InvLock/InvLock.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
<UseWPF>true</UseWPF>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationIcon>Assets\logo.ico</ApplicationIcon>
<Version>1.1.0.0</Version>
<AssemblyVersion>1.1.0.0</AssemblyVersion>
<FileVersion>1.1.0.0</FileVersion>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
</PropertyGroup>

<ItemGroup>
Expand All @@ -17,9 +21,11 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="CuteUtils" Version="1.0.0" />
<PackageReference Include="Interop.IWshRuntimeLibrary" Version="1.0.1" />
<PackageReference Include="SharpHook" Version="5.3.8" />
<PackageReference Include="WPF-UI" Version="4.0.0" />
<PackageReference Include="WPF-UI.Tray" Version="4.0.0" />
<PackageReference Include="WpfScreenHelper" Version="2.1.1" />
</ItemGroup>

<ItemGroup>
Expand Down
35 changes: 32 additions & 3 deletions src/InvLock/LockWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ public partial class LockWindow : Window
private readonly SimpleGlobalHook hook = new SimpleGlobalHook();
private readonly Dictionary<KeyCode, DateTime> pressedKeys = [];
private readonly Settings settings;
private readonly List<BlurWindow> blurWindows = [];
private List<IntPtr> windows = [];
private Point lastMousePosition;
private bool isOpen = true;
private bool suppressInput = false;

Expand Down Expand Up @@ -120,11 +122,32 @@ private void ActivateLockScreen()
MinimizeWindows();
}

isOpen = true;
suppressInput = true;

Dispatcher.Invoke(() =>
{
lastMousePosition = WpfScreenHelper.MouseHelper.MousePosition;

if (settings.BlurScreen)
{
foreach (Rect bounds in WpfScreenHelper.Screen.AllScreens.Select(s => s.WpfBounds))
{
BlurWindow blurWindow = new()
{
Width = bounds.Width,
Height = bounds.Height,
Left = bounds.Left,
Top = bounds.Top,
};

blurWindows.Add(blurWindow);
blurWindow.Show();
}

_ = WindowsApi.SetCursorPosition(new Point(100000, 100000));
}

isOpen = true;
suppressInput = true;

_ = Activate();

textBlock.Text = settings.LockText;
Expand Down Expand Up @@ -155,6 +178,9 @@ private void DeactivateLockScreen()

isOpen = true;

_ = WindowsApi.SetCursorPosition(lastMousePosition);
blurWindows.ForEach(w => w.Close());

textBlock.Text = settings.UnlockText;
textBlock.Stroke = (Brush)FindResource("PaletteGreenBrush");

Expand Down Expand Up @@ -203,6 +229,9 @@ private async void SystemEvents_SessionSwitch(object sender, Microsoft.Win32.Ses

isOpen = true;

_ = WindowsApi.SetCursorPosition(lastMousePosition);
blurWindows.ForEach(w => w.Close());

_ = Activate();

await Task.Delay(500);
Expand Down
21 changes: 21 additions & 0 deletions src/InvLock/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,34 @@
</ComboBox>
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=Clock24}" Height="75">
<ui:CardControl.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Run at startup" />
<ui:TextBlock Grid.Row="1" Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" FontSize="12" Text="Start InvLock when you sign in to Windows" />
</Grid>
</ui:CardControl.Header>
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding IsAutoStartEnabled}" OffContent="Off" OnContent="On" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=Window24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Show desktop while locked" />
</ui:CardControl.Header>
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.HideWindows}" OffContent="Off" OnContent="On" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=Blur24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Blur screen while locked" />
</ui:CardControl.Header>
<ui:ToggleSwitch Grid.Column="1" IsChecked="{Binding Settings.BlurScreen}" OffContent="Off" OnContent="On" />
</ui:CardControl>

<ui:CardControl Margin="0,0,0,12" Icon="{ui:SymbolIcon Symbol=WindowShield24}" Height="75">
<ui:CardControl.Header>
<ui:TextBlock Grid.Row="0" FontTypography="Body" Text="Use windows lock screen to unlock" />
Expand Down
1 change: 1 addition & 0 deletions src/InvLock/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ private void FluentWindow_Closing(object sender, System.ComponentModel.CancelEve
e.Cancel = true;

ShowInTaskbar = false;
WindowState = WindowState.Minimized;
Visibility = Visibility.Collapsed;
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/InvLock/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class Settings : INotifyPropertyChanged
private static readonly string settingsPath = Path.Combine(App.ApplicationDataPath, "settings.json");
private bool useWindowsLockScreen = true;
private bool hideWindows = false;
private bool blurScreen = false;
private string lockText = "Lock Screen Active";
private string theme = "Windows default";
private HashSet<KeyCode> lockShortcut = [KeyCode.VcLeftControl, KeyCode.VcLeftShift, KeyCode.VcL];
Expand All @@ -34,6 +35,16 @@ public bool HideWindows
}
}

public bool BlurScreen
{
get => blurScreen;
set
{
blurScreen = value;
OnPropertyChanged();
}
}

public bool UseWindowsLockScreen
{
get => useWindowsLockScreen;
Expand Down
81 changes: 81 additions & 0 deletions src/InvLock/Utilities/StartupManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using IWshRuntimeLibrary;

using System.IO;
using System.Reflection;
using System.Windows;

namespace InvLock.Utilities;

public enum AutoStartStatus
{
Success = 0,
InvalidParameters = 1,
AlreadyEnabled = 2,
AlreadyDisabled = 3,
UnexpectedError = 4
}

public static class StartupManager
{
private static readonly string appPath = Path.ChangeExtension(Assembly.GetEntryAssembly()?.Location ?? throw new InvalidOperationException("Failed to get the application path."), ".exe");
private static readonly string startupFolder = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
private static readonly string shortcutPath = Path.Combine(startupFolder, Path.GetFileNameWithoutExtension(appPath) + ".lnk");

public static bool IsAutoStartEnabled()
{
return System.IO.File.Exists(shortcutPath);
}

public static AutoStartStatus EnableAutoStart()
{
if (IsAutoStartEnabled())
{
return AutoStartStatus.AlreadyEnabled;
}

try
{
WshShell shell = new WshShell();
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(shortcutPath);
shortcut.TargetPath = appPath;
shortcut.WorkingDirectory = Path.GetDirectoryName(appPath);
shortcut.Save();
return AutoStartStatus.Success;
}
catch
{
return AutoStartStatus.UnexpectedError;
}
}

public static AutoStartStatus DisableAutoStart()
{
if (!IsAutoStartEnabled())
{
return AutoStartStatus.AlreadyDisabled;
}

try
{
System.IO.File.Delete(shortcutPath);
return AutoStartStatus.Success;
}
catch
{
return AutoStartStatus.UnexpectedError;
}
}

public static void ToggleAutoStart()
{
AutoStartStatus status = IsAutoStartEnabled() ? DisableAutoStart() : EnableAutoStart();

_ = status switch
{
AutoStartStatus.Success => MessageBox.Show("Auto-start setting changed successfully."),
AutoStartStatus.AlreadyEnabled => MessageBox.Show("Auto-start is already enabled."),
AutoStartStatus.AlreadyDisabled => MessageBox.Show("Auto-start is already disabled."),
_ => MessageBox.Show("Failed to change auto-start setting."),
};
}
}
Loading