diff --git a/.gitignore b/.gitignore index 16a4d98..c222abf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,33 @@ -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + .DS_Store .AppleDouble .LSOverride # Icon must ends with two \r. -Icon +Icon + # Thumbnails ._* @@ -34,186 +35,189 @@ Icon # Files that might appear on external disk .Spotlight-V100 .Trashes - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -build/ -bld/ -[Bb]in/ -[Oo]bj/ - -# Roslyn cache directories -*.ide/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -#NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding addin-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# If using the old MSBuild-Integrated Package Restore, uncomment this: -#!**/packages/repositories.config - -# Windows Azure Build Output -csx/ -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# If using the old MSBuild-Integrated Package Restore, uncomment this: +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +.vs/ +.nuget/ \ No newline at end of file diff --git a/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs b/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs index 843c069..30fac20 100644 --- a/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs +++ b/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs @@ -96,6 +96,88 @@ public void SetNeverChangeColorSettings(bool neverChangeColorSettings) _vibranceInfo.neverChangeColorSettings = neverChangeColorSettings; } + public void SetProfileToggleEnabled(bool profileToggleEnabled) + { + _vibranceInfo.isProfileToggleEnabled = profileToggleEnabled; + _vibranceInfo.isProfileToggleOn = true; + } + + public void SetProfileToggleState(bool isProfileToggleOn) + { + _vibranceInfo.isProfileToggleOn = isProfileToggleOn; + } + + public bool IsProfileToggleEnabled() + { + return _vibranceInfo.isProfileToggleEnabled; + } + + public bool IsProfileToggleOn() + { + return _vibranceInfo.isProfileToggleOn; + } + + public void ApplyProfileToggle(IntPtr windowHandle, string processName, bool isProfileToggleOn) + { + if (_applicationSettings.Count == 0) + { + return; + } + + ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, processName, StringComparison.OrdinalIgnoreCase)); + if (applicationSetting == null) + { + return; + } + + Screen screen = Screen.FromHandle(windowHandle); + if (screen == null) + { + return; + } + + _gameScreen = screen; + + if (isProfileToggleOn) + { + if (_vibranceInfo.userVibranceSettingDefault != applicationSetting.IngameLevel) + { + if (_vibranceInfo.affectPrimaryMonitorOnly) + { + _amdAdapter.SetSaturationOnDisplay(applicationSetting.IngameLevel, screen.DeviceName); + } + else + { + _amdAdapter.SetSaturationOnAllDisplays(applicationSetting.IngameLevel); + } + } + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) + { + DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); + _vibranceInfo.isColorSettingApplied = true; + } + } + else + { + _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true) + { + if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(screen.DeviceName)) + { + DeviceGammaRampHelper.SetGammaRamp(_gameScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma); + } + else + { + Screen.AllScreens.ToList().ForEach(currentScreen => DeviceGammaRampHelper.SetGammaRamp(currentScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma)); + } + _vibranceInfo.isColorSettingApplied = false; + } + } + } + public void SetWindowsColorSettings(int brightness, int contrast, int gamma) { _vibranceInfo.userColorSettings.brightness = brightness; @@ -158,6 +240,7 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) { if (_applicationSettings.Count > 0) { + bool shouldApplyProfileSettings = !_vibranceInfo.isProfileToggleEnabled || _vibranceInfo.isProfileToggleOn; ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, e.ProcessName, StringComparison.OrdinalIgnoreCase)); if (applicationSetting != null) { @@ -165,7 +248,7 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) _gameScreen = screen; //apply application specific saturation - if (_vibranceInfo.userVibranceSettingDefault != applicationSetting.IngameLevel) + if (shouldApplyProfileSettings && _vibranceInfo.userVibranceSettingDefault != applicationSetting.IngameLevel) { if (_vibranceInfo.affectPrimaryMonitorOnly) { @@ -188,7 +271,7 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) } //test if color settings change is needed - if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) { DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); @@ -247,4 +330,4 @@ private static void PerformResolutionChange(Screen screen, ResolutionModeWrapper ResolutionHelper.ChangeResolutionEx(resolutionSettings, screen.DeviceName); } } -} \ No newline at end of file +} diff --git a/vibrance.GUI/App.config b/vibrance.GUI/App.config index e22aa48..5ef5b79 100644 --- a/vibrance.GUI/App.config +++ b/vibrance.GUI/App.config @@ -2,5 +2,5 @@ - + diff --git a/vibrance.GUI/FodyWeavers.xsd b/vibrance.GUI/FodyWeavers.xsd index 44a5374..f2dbece 100644 --- a/vibrance.GUI/FodyWeavers.xsd +++ b/vibrance.GUI/FodyWeavers.xsd @@ -17,14 +17,39 @@ A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. + + - A list of unmanaged 32 bit assembly names to include, delimited with line breaks. + Obsolete, use UnmanagedWinX86Assemblies instead + + + + + A list of unmanaged X86 (32 bit) assembly names to include, delimited with line breaks. - A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + Obsolete, use UnmanagedWinX64Assemblies instead. + + + + + A list of unmanaged X64 (64 bit) assembly names to include, delimited with line breaks. + + + + + A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with line breaks. @@ -43,6 +68,16 @@ Controls if .pdbs for reference assemblies are also embedded. + + + Controls if runtime assemblies are also embedded. + + + + + Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. @@ -53,6 +88,11 @@ As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + The attach method no longer subscribes to the `AppDomain.AssemblyResolve` (.NET 4.x) and `AssemblyLoadContext.Resolving` (.NET 6.0+) events. + + Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. @@ -73,14 +113,39 @@ A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + + A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. + + - A list of unmanaged 32 bit assembly names to include, delimited with |. + Obsolete, use UnmanagedWinX86Assemblies instead + + + + + A list of unmanaged X86 (32 bit) assembly names to include, delimited with |. - A list of unmanaged 64 bit assembly names to include, delimited with |. + Obsolete, use UnmanagedWinX64Assemblies instead + + + + + A list of unmanaged X64 (64 bit) assembly names to include, delimited with |. + + + + + A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with |. diff --git a/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs b/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs index 6a843e9..463a16e 100644 --- a/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs +++ b/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs @@ -193,6 +193,7 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) { if (_applicationSettings.Count > 0) { + bool shouldApplyProfileSettings = !_vibranceInfo.isProfileToggleEnabled || _vibranceInfo.isProfileToggleOn; ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, e.ProcessName, StringComparison.OrdinalIgnoreCase)); if (applicationSetting != null) { @@ -206,7 +207,7 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) _gameScreen = screen; //test if digital vibrance change is needed - if (!equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) + if (shouldApplyProfileSettings && !equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) { _vibranceInfo.defaultHandle = displayHandle; setDVCLevel(_vibranceInfo.defaultHandle, applicationSetting.IngameLevel); @@ -223,7 +224,7 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) } //test if color settings change is needed - if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) { DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); @@ -345,6 +346,99 @@ public void SetNeverChangeColorSettings(bool neverChangeColorSettings) _vibranceInfo.neverChangeColorSettings = neverChangeColorSettings; } + public void SetProfileToggleEnabled(bool profileToggleEnabled) + { + _vibranceInfo.isProfileToggleEnabled = profileToggleEnabled; + _vibranceInfo.isProfileToggleOn = true; + } + + public void SetProfileToggleState(bool isProfileToggleOn) + { + _vibranceInfo.isProfileToggleOn = isProfileToggleOn; + } + + public bool IsProfileToggleEnabled() + { + return _vibranceInfo.isProfileToggleEnabled; + } + + public bool IsProfileToggleOn() + { + return _vibranceInfo.isProfileToggleOn; + } + + public void ApplyProfileToggle(IntPtr windowHandle, string processName, bool isProfileToggleOn) + { + if (_applicationSettings.Count == 0) + { + return; + } + + ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, processName, StringComparison.OrdinalIgnoreCase)); + if (applicationSetting == null) + { + return; + } + + int displayHandle = GetApplicationDisplayHandle(windowHandle); + if (displayHandle == -1) + { + return; + } + + Screen screen = Screen.FromHandle(windowHandle); + if (screen == null) + { + return; + } + + _gameScreen = screen; + + if (isProfileToggleOn) + { + if (!equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) + { + _vibranceInfo.defaultHandle = displayHandle; + setDVCLevel(_vibranceInfo.defaultHandle, applicationSetting.IngameLevel); + } + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) + { + DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); + _vibranceInfo.isColorSettingApplied = true; + } + } + else + { + if (_vibranceInfo.affectPrimaryMonitorOnly && !equalsDVCLevel(_vibranceInfo.defaultHandle, _vibranceInfo.userVibranceSettingDefault)) + { + if (_gameScreen != null && !_gameScreen.DeviceName.Equals(screen.DeviceName)) + { + return; + } + setDVCLevel(_vibranceInfo.defaultHandle, _vibranceInfo.userVibranceSettingDefault); + } + else if (!_vibranceInfo.affectPrimaryMonitorOnly && !_vibranceInfo.displayHandles.TrueForAll(handle => equalsDVCLevel(handle, _vibranceInfo.userVibranceSettingDefault))) + { + _vibranceInfo.displayHandles.ForEach(handle => setDVCLevel(handle, _vibranceInfo.userVibranceSettingDefault)); + } + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true) + { + if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(screen.DeviceName)) + { + DeviceGammaRampHelper.SetGammaRamp(_gameScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma); + } + else + { + Screen.AllScreens.ToList().ForEach(currentScreen => DeviceGammaRampHelper.SetGammaRamp(currentScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma)); + } + _vibranceInfo.isColorSettingApplied = false; + } + } + } + public void SetWindowsColorSettings(int brightness, int contrast, int gamma) { _vibranceInfo.userColorSettings.brightness = brightness; diff --git a/vibrance.GUI/Properties/Resources.Designer.cs b/vibrance.GUI/Properties/Resources.Designer.cs index 17b2040..2f6843b 100644 --- a/vibrance.GUI/Properties/Resources.Designer.cs +++ b/vibrance.GUI/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -13,13 +13,13 @@ namespace vibrance.GUI.Properties { /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,7 +33,7 @@ internal Resources() { } /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ internal Resources() { } /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { diff --git a/vibrance.GUI/Properties/Settings.Designer.cs b/vibrance.GUI/Properties/Settings.Designer.cs index 8d4aa00..c111172 100644 --- a/vibrance.GUI/Properties/Settings.Designer.cs +++ b/vibrance.GUI/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.18444 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace vibrance.GUI.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/vibrance.GUI/common/Definitions.cs b/vibrance.GUI/common/Definitions.cs index d550a11..8f5156e 100644 --- a/vibrance.GUI/common/Definitions.cs +++ b/vibrance.GUI/common/Definitions.cs @@ -19,6 +19,8 @@ public struct VibranceInfo public bool affectPrimaryMonitorOnly; public bool neverChangeResolution; public bool neverChangeColorSettings; + public bool isProfileToggleEnabled; + public bool isProfileToggleOn; public bool isColorSettingApplied; public bool isResolutionChangeApplied; public ColorSettings userColorSettings; diff --git a/vibrance.GUI/common/ISettingsController.cs b/vibrance.GUI/common/ISettingsController.cs index ab6d61a..3a894c0 100644 --- a/vibrance.GUI/common/ISettingsController.cs +++ b/vibrance.GUI/common/ISettingsController.cs @@ -6,9 +6,10 @@ namespace vibrance.GUI.common internal interface ISettingsController { bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, string neverChangeColorSettings, List applicationSettings, - string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel); + string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel, string profileToggleEnabled, string profileToggleHotkey, string profileToggleState); bool SetVibranceSetting(string szKeyName, string value); void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, - out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel); + out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel, + out bool profileToggleEnabled, out string profileToggleHotkey, out bool profileToggleState); } -} \ No newline at end of file +} diff --git a/vibrance.GUI/common/IVibranceProxy.cs b/vibrance.GUI/common/IVibranceProxy.cs index efe55c2..ed25970 100644 --- a/vibrance.GUI/common/IVibranceProxy.cs +++ b/vibrance.GUI/common/IVibranceProxy.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using vibrance.GUI.NVIDIA; namespace vibrance.GUI.common @@ -17,9 +18,14 @@ public interface IVibranceProxy void SetNeverSwitchResolution(bool neverSwitchResolution); void SetNeverChangeColorSettings(bool neverChangeColorSettings); void SetWindowsColorSettings(int brightness, int contrast, int gamma); + void SetProfileToggleEnabled(bool profileToggleEnabled); + void SetProfileToggleState(bool isProfileToggleOn); + bool IsProfileToggleEnabled(); + bool IsProfileToggleOn(); + void ApplyProfileToggle(IntPtr windowHandle, string processName, bool isProfileToggleOn); void SetWindowsColorBrightness(int brightness); void SetWindowsColorContrast(int contrast); void SetWindowsColorGamma(int gamma); } -} \ No newline at end of file +} diff --git a/vibrance.GUI/common/SettingsController.cs b/vibrance.GUI/common/SettingsController.cs index 90a1b6c..3fd5228 100644 --- a/vibrance.GUI/common/SettingsController.cs +++ b/vibrance.GUI/common/SettingsController.cs @@ -37,6 +37,9 @@ private static extern bool WritePrivateProfileString(string lpAppName, const string SzKeyNameBrightnessWindowsLevel = "brightnessWindowsLevel"; const string SzKeyNameContrastWindowsLevel = "contrastWindowsLevel"; const string SzKeyNameGammaWindowsLevel = "gammaWindowsLevel"; + const string SzKeyNameProfileToggleEnabled = "profileToggleEnabled"; + const string SzKeyNameProfileToggleHotkey = "profileToggleHotkey"; + const string SzKeyNameProfileToggleState = "profileToggleState"; private string _fileName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToString() + "\\vibranceGUI\\vibranceGUI.ini"; @@ -44,7 +47,7 @@ private static extern bool WritePrivateProfileString(string lpAppName, public bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, string neverChangeColorSettings, List applicationSettings, - string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel) + string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel, string profileToggleEnabled, string profileToggleHotkey, string profileToggleState) { if (!PrepareFile()) { @@ -58,6 +61,9 @@ public bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitor WritePrivateProfileString(SzSectionName, SzKeyNameBrightnessWindowsLevel, brightnessWindowsLevel, _fileName); WritePrivateProfileString(SzSectionName, SzKeyNameContrastWindowsLevel, contrastWindowsLevel, _fileName); WritePrivateProfileString(SzSectionName, SzKeyNameGammaWindowsLevel, gammaWindowsLevel, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameProfileToggleEnabled, profileToggleEnabled, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameProfileToggleHotkey, profileToggleHotkey ?? string.Empty, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameProfileToggleState, profileToggleState, _fileName); try { @@ -105,7 +111,8 @@ private bool PrepareFile() } public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, - out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel) + out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel, + out bool profileToggleEnabled, out string profileToggleHotkey, out bool profileToggleState) { int defaultLevel = 0; int maxLevel = 0; @@ -130,6 +137,9 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran brightnessWindowsLevel = 50; contrastWindowsLevel = 50; gammaWindowsLevel = 100; + profileToggleEnabled = false; + profileToggleHotkey = string.Empty; + profileToggleState = true; return; } @@ -199,6 +209,30 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran Convert.ToUInt32(szValueGammaWindowsLevel.Capacity), _fileName); + StringBuilder szValueProfileToggleEnabled = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameProfileToggleEnabled, + "false", + szValueProfileToggleEnabled, + Convert.ToUInt32(szValueProfileToggleEnabled.Capacity), + _fileName); + + StringBuilder szValueProfileToggleHotkey = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameProfileToggleHotkey, + string.Empty, + szValueProfileToggleHotkey, + Convert.ToUInt32(szValueProfileToggleHotkey.Capacity), + _fileName); + + StringBuilder szValueProfileToggleState = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameProfileToggleState, + "true", + szValueProfileToggleState, + Convert.ToUInt32(szValueProfileToggleState.Capacity), + _fileName); + try { vibranceWindowsLevel = int.Parse(szValueInactive.ToString()); @@ -208,6 +242,9 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran brightnessWindowsLevel = int.Parse(szValueBrightnessWindowsLevel.ToString()); contrastWindowsLevel = int.Parse(szValueContrastWindowsLevel.ToString()); gammaWindowsLevel = int.Parse(szValueGammaWindowsLevel.ToString()); + profileToggleEnabled = bool.Parse(szValueProfileToggleEnabled.ToString()); + profileToggleHotkey = szValueProfileToggleHotkey.ToString(); + profileToggleState = bool.Parse(szValueProfileToggleState.ToString()); } catch (Exception) { @@ -219,6 +256,9 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran brightnessWindowsLevel = 50; contrastWindowsLevel = 50; gammaWindowsLevel = 100; + profileToggleEnabled = false; + profileToggleHotkey = string.Empty; + profileToggleState = true; return; } diff --git a/vibrance.GUI/common/VibranceGUI.Designer.cs b/vibrance.GUI/common/VibranceGUI.Designer.cs index 096c31b..4dac357 100644 --- a/vibrance.GUI/common/VibranceGUI.Designer.cs +++ b/vibrance.GUI/common/VibranceGUI.Designer.cs @@ -36,6 +36,9 @@ private void InitializeComponent() this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.backgroundWorker = new System.ComponentModel.BackgroundWorker(); this.checkBoxAutostart = new System.Windows.Forms.CheckBox(); + this.checkBoxProfileToggleEnabled = new System.Windows.Forms.CheckBox(); + this.labelProfileToggleHotkey = new System.Windows.Forms.Label(); + this.textBoxProfileToggleHotkey = new System.Windows.Forms.TextBox(); this.groupBoxSettings = new System.Windows.Forms.GroupBox(); this.checkBoxNeverChangeResolutions = new System.Windows.Forms.CheckBox(); this.checkBoxPrimaryMonitorOnly = new System.Windows.Forms.CheckBox(); @@ -137,8 +140,46 @@ private void InitializeComponent() this.checkBoxAutostart.UseVisualStyleBackColor = true; this.checkBoxAutostart.CheckedChanged += new System.EventHandler(this.checkBoxAutostart_CheckedChanged); // + // checkBoxProfileToggleEnabled + // + this.checkBoxProfileToggleEnabled.AutoSize = true; + this.checkBoxProfileToggleEnabled.Location = new System.Drawing.Point(315, 29); + this.checkBoxProfileToggleEnabled.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.checkBoxProfileToggleEnabled.Name = "checkBoxProfileToggleEnabled"; + this.checkBoxProfileToggleEnabled.Size = new System.Drawing.Size(256, 24); + this.checkBoxProfileToggleEnabled.TabIndex = 17; + this.checkBoxProfileToggleEnabled.Text = "Enable profile toggle hotkey"; + this.toolTip.SetToolTip(this.checkBoxProfileToggleEnabled, "Enable a global hotkey that toggles profile settings on the active application."); + this.checkBoxProfileToggleEnabled.UseVisualStyleBackColor = true; + this.checkBoxProfileToggleEnabled.CheckedChanged += new System.EventHandler(this.checkBoxProfileToggleEnabled_CheckedChanged); + // + // labelProfileToggleHotkey + // + this.labelProfileToggleHotkey.AutoSize = true; + this.labelProfileToggleHotkey.Location = new System.Drawing.Point(311, 65); + this.labelProfileToggleHotkey.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelProfileToggleHotkey.Name = "labelProfileToggleHotkey"; + this.labelProfileToggleHotkey.Size = new System.Drawing.Size(237, 20); + this.labelProfileToggleHotkey.TabIndex = 18; + this.labelProfileToggleHotkey.Text = "Profile toggle hotkey (press keys)"; + this.labelProfileToggleHotkey.Visible = false; + // + // textBoxProfileToggleHotkey + // + this.textBoxProfileToggleHotkey.Location = new System.Drawing.Point(315, 89); + this.textBoxProfileToggleHotkey.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.textBoxProfileToggleHotkey.Name = "textBoxProfileToggleHotkey"; + this.textBoxProfileToggleHotkey.ReadOnly = true; + this.textBoxProfileToggleHotkey.Size = new System.Drawing.Size(269, 26); + this.textBoxProfileToggleHotkey.TabIndex = 19; + this.textBoxProfileToggleHotkey.Visible = false; + this.textBoxProfileToggleHotkey.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBoxProfileToggleHotkey_KeyDown); + // // groupBoxSettings // + this.groupBoxSettings.Controls.Add(this.textBoxProfileToggleHotkey); + this.groupBoxSettings.Controls.Add(this.labelProfileToggleHotkey); + this.groupBoxSettings.Controls.Add(this.checkBoxProfileToggleEnabled); this.groupBoxSettings.Controls.Add(this.checkBoxNeverChangeResolutions); this.groupBoxSettings.Controls.Add(this.checkBoxPrimaryMonitorOnly); this.groupBoxSettings.Controls.Add(this.groupBox3); @@ -543,6 +584,9 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.ComponentModel.BackgroundWorker backgroundWorker; private System.Windows.Forms.CheckBox checkBoxAutostart; + private System.Windows.Forms.CheckBox checkBoxProfileToggleEnabled; + private System.Windows.Forms.Label labelProfileToggleHotkey; + private System.Windows.Forms.TextBox textBoxProfileToggleHotkey; private System.Windows.Forms.GroupBox groupBoxSettings; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.Label labelWindowsLevel; @@ -575,4 +619,3 @@ private void InitializeComponent() private System.Windows.Forms.TrackBar trackBarBrightness; } } - diff --git a/vibrance.GUI/common/VibranceGUI.cs b/vibrance.GUI/common/VibranceGUI.cs index f1973d5..611c051 100644 --- a/vibrance.GUI/common/VibranceGUI.cs +++ b/vibrance.GUI/common/VibranceGUI.cs @@ -25,6 +25,11 @@ public partial class VibranceGUI : Form private const string AppName = "vibranceGUI"; private const string TwitterLink = "https://twitter.com/juvlarN"; private const string PaypalDonationLink = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JDQFNKNNEW356"; + private const int WmHotkey = 0x0312; + private const int ProfileToggleHotkeyId = 1; + private const uint HotkeyModAlt = 0x0001; + private const uint HotkeyModControl = 0x0002; + private const uint HotkeyModShift = 0x0004; private bool _allowVisible; private List _applicationSettings; @@ -32,6 +37,18 @@ public partial class VibranceGUI : Form private readonly Dictionary>> _windowsResolutionSettings; private readonly bool _isForcedExecution; + private bool _isLoadingSettings; + private bool _isProfileToggleHotkeyRegistered; + private string _profileToggleHotkey; + + [DllImport("user32.dll")] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + + [DllImport("user32.dll")] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); public VibranceGUI( Func, Dictionary>>, IVibranceProxy> getProxy, @@ -126,6 +143,9 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) int brightnessWindowsLevel = 50; int contrastWindowsLevel = 50; int gammaWindowsLevel = 100; + bool profileToggleEnabled = false; + string profileToggleHotkey = string.Empty; + bool profileToggleState = true; while (!this.IsHandleCreated) { @@ -136,12 +156,12 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { this.Invoke((MethodInvoker)delegate { - ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); + ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel, out profileToggleEnabled, out profileToggleHotkey, out profileToggleState); }); } else { - ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); + ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel, out profileToggleEnabled, out profileToggleHotkey, out profileToggleState); } if (_v.GetVibranceInfo().isInitialized) @@ -157,6 +177,23 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) _v.SetNeverSwitchResolution(neverSwitchResolution); _v.SetNeverChangeColorSettings(neverChangeColorSettings); _v.SetWindowsColorSettings(brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel); + bool isProfileToggleFeatureEnabled = profileToggleEnabled && !string.IsNullOrWhiteSpace(profileToggleHotkey); + _v.SetProfileToggleEnabled(isProfileToggleFeatureEnabled); + if (isProfileToggleFeatureEnabled) + { + _v.SetProfileToggleState(profileToggleState); + } + if (this.InvokeRequired) + { + this.Invoke((MethodInvoker)delegate + { + UpdateProfileToggleHotkey(profileToggleHotkey, isProfileToggleFeatureEnabled); + }); + } + else + { + UpdateProfileToggleHotkey(profileToggleHotkey, isProfileToggleFeatureEnabled); + } } } @@ -233,6 +270,9 @@ private void ForceSaveVibranceSettings() int brightnessWindowsLevel = 50; int contrastWindowsLevel = 50; int gammaWindowsLevel = 100; + bool profileToggleEnabled = false; + string profileToggleHotkey = string.Empty; + bool profileToggleState = true; this.Invoke((MethodInvoker)delegate { windowsLevel = trackBarWindowsLevel.Value; @@ -242,8 +282,11 @@ private void ForceSaveVibranceSettings() brightnessWindowsLevel = trackBarBrightness.Value; contrastWindowsLevel = trackBarContrast.Value; gammaWindowsLevel = trackBarGamma.Value; + profileToggleEnabled = checkBoxProfileToggleEnabled.Checked; + profileToggleHotkey = textBoxProfileToggleHotkey.Text; + profileToggleState = _v.IsProfileToggleOn(); }); - SaveVibranceSettings(windowsLevel, affectPrimaryMonitorOnly, neverSwitchResolution, neverChangeColorSettings, brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel); + SaveVibranceSettings(windowsLevel, affectPrimaryMonitorOnly, neverSwitchResolution, neverChangeColorSettings, brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel, profileToggleEnabled, profileToggleHotkey, profileToggleState); } private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) @@ -341,6 +384,58 @@ private void checkBoxAutostart_CheckedChanged(object sender, EventArgs e) notifyIcon.ShowBalloonTip(250); } + private void checkBoxProfileToggleEnabled_CheckedChanged(object sender, EventArgs e) + { + if (_v == null || _isLoadingSettings) + { + return; + } + + bool enabled = checkBoxProfileToggleEnabled.Checked; + bool shouldEnable = enabled && !string.IsNullOrWhiteSpace(textBoxProfileToggleHotkey.Text); + _v.SetProfileToggleEnabled(shouldEnable); + if (!enabled) + { + _v.SetProfileToggleState(true); + } + ToggleProfileHotkeyControls(enabled); + UpdateProfileToggleHotkey(textBoxProfileToggleHotkey.Text, shouldEnable); + + if (!this.settingsBackgroundWorker.IsBusy) + { + this.settingsBackgroundWorker.RunWorkerAsync(); + } + } + + private void textBoxProfileToggleHotkey_KeyDown(object sender, KeyEventArgs e) + { + e.SuppressKeyPress = true; + if (!checkBoxProfileToggleEnabled.Checked) + { + return; + } + + string hotkey = BuildHotkeyString(e); + if (string.IsNullOrWhiteSpace(hotkey)) + { + return; + } + + textBoxProfileToggleHotkey.Text = hotkey; + bool shouldEnable = checkBoxProfileToggleEnabled.Checked && !string.IsNullOrWhiteSpace(hotkey); + _v.SetProfileToggleEnabled(shouldEnable); + UpdateProfileToggleHotkey(hotkey, shouldEnable); + if (!this.settingsBackgroundWorker.IsBusy) + { + this.settingsBackgroundWorker.RunWorkerAsync(); + } + + this.BeginInvoke((MethodInvoker)delegate + { + this.ActiveControl = null; + }); + } + private void checkBoxNeverChangeColorSettings_CheckedChanged(object sender, EventArgs e) { @@ -361,6 +456,164 @@ private void checkBoxNeverChangeColorSettings_CheckedChanged(object sender, Even } } + private void ToggleProfileHotkeyControls(bool enabled) + { + labelProfileToggleHotkey.Visible = enabled; + textBoxProfileToggleHotkey.Visible = enabled; + } + + private void UpdateProfileToggleHotkey(string hotkey, bool enabled) + { + _profileToggleHotkey = hotkey ?? string.Empty; + if (!enabled) + { + UnregisterProfileToggleHotkey(); + return; + } + + RegisterProfileToggleHotkey(); + } + + private void RegisterProfileToggleHotkey() + { + UnregisterProfileToggleHotkey(); + if (string.IsNullOrWhiteSpace(_profileToggleHotkey)) + { + return; + } + + if (!TryParseHotkey(_profileToggleHotkey, out uint modifiers, out uint key)) + { + return; + } + + _isProfileToggleHotkeyRegistered = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key); + } + + private void UnregisterProfileToggleHotkey() + { + if (_isProfileToggleHotkeyRegistered) + { + UnregisterHotKey(this.Handle, ProfileToggleHotkeyId); + _isProfileToggleHotkeyRegistered = false; + } + } + + private string BuildHotkeyString(KeyEventArgs e) + { + List parts = new List(); + if (e.Control) + { + parts.Add("Ctrl"); + } + if (e.Alt) + { + parts.Add("Alt"); + } + if (e.Shift) + { + parts.Add("Shift"); + } + + Keys keyCode = e.KeyCode; + if (keyCode == Keys.ControlKey || keyCode == Keys.Menu || keyCode == Keys.ShiftKey) + { + return string.Empty; + } + + parts.Add(keyCode.ToString()); + return string.Join("+", parts); + } + + private bool TryParseHotkey(string hotkey, out uint modifiers, out uint key) + { + modifiers = 0; + key = 0; + if (string.IsNullOrWhiteSpace(hotkey)) + { + return false; + } + + string[] parts = hotkey.Split(new[] { '+' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string part in parts) + { + string normalized = part.Trim(); + if (string.Equals(normalized, "Ctrl", StringComparison.OrdinalIgnoreCase) || + string.Equals(normalized, "Control", StringComparison.OrdinalIgnoreCase)) + { + modifiers |= HotkeyModControl; + continue; + } + if (string.Equals(normalized, "Alt", StringComparison.OrdinalIgnoreCase)) + { + modifiers |= HotkeyModAlt; + continue; + } + if (string.Equals(normalized, "Shift", StringComparison.OrdinalIgnoreCase)) + { + modifiers |= HotkeyModShift; + continue; + } + + if (Enum.TryParse(normalized, true, out Keys parsedKey)) + { + key = (uint)parsedKey; + } + } + + return key != 0; + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == WmHotkey && m.WParam.ToInt32() == ProfileToggleHotkeyId) + { + ToggleProfileForActiveWindow(); + } + base.WndProc(ref m); + } + + private void ToggleProfileForActiveWindow() + { + if (_v == null || !_v.IsProfileToggleEnabled()) + { + return; + } + + IntPtr foregroundWindow = GetForegroundWindow(); + if (foregroundWindow == IntPtr.Zero) + { + return; + } + + uint processId; + if (GetWindowThreadProcessId(foregroundWindow, out processId) == 0 || processId == 0) + { + return; + } + + string processName; + try + { + using (Process process = Process.GetProcessById((int)processId)) + { + processName = process.ProcessName; + } + } + catch (Exception ex) + { + Log(ex); + return; + } + + bool newToggleState = !_v.IsProfileToggleOn(); + _v.SetProfileToggleState(newToggleState); + _v.ApplyProfileToggle(foregroundWindow, processName, newToggleState); + } + + [DllImport("user32.dll", SetLastError = true)] + private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); + private void twitterToolStripTextBox_Click(object sender, EventArgs e) { Process.Start(TwitterLink); @@ -383,6 +636,7 @@ private void SetGuiEnabledFlag(bool flag) this.buttonRemoveProgram.Enabled = flag; this.checkBoxNeverChangeResolutions.Enabled = flag; this.checkBoxNeverChangeColorSettings.Enabled = flag; + this.checkBoxProfileToggleEnabled.Enabled = flag; }); } @@ -397,6 +651,7 @@ private void CleanUp() { _v.HandleDvcExit(); _v.SetShouldRun(false); + UnregisterProfileToggleHotkey(); _v.UnloadLibraryEx(); } } @@ -436,17 +691,20 @@ public static void Log(string msg) } private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, - out bool neverChangeColorSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel) + out bool neverChangeColorSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel, + out bool profileToggleEnabled, out string profileToggleHotkey, out bool profileToggleState) { _registryController = new RegistryController(); this.checkBoxAutostart.Checked = _registryController.IsProgramRegistered(AppName); SettingsController settingsController = new SettingsController(); settingsController.ReadVibranceSettings(_v.GraphicsAdapter, out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, - out neverChangeColorSettings, out _applicationSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); + out neverChangeColorSettings, out _applicationSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel, + out profileToggleEnabled, out profileToggleHotkey, out profileToggleState); if (this.IsHandleCreated) { + _isLoadingSettings = true; //no null check needed, SettingsController will always return matching values. labelWindowsLevel.Text = TrackbarLabelHelper.ResolveVibranceLabelLevel(_graphicsAdapter, vibranceWindowsLevel); @@ -454,6 +712,13 @@ private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectP checkBoxPrimaryMonitorOnly.Checked = affectPrimaryMonitorOnly; checkBoxNeverChangeResolutions.Checked = neverSwitchResolution; checkBoxNeverChangeColorSettings.Checked = neverChangeColorSettings; + checkBoxProfileToggleEnabled.Checked = profileToggleEnabled; + textBoxProfileToggleHotkey.Text = profileToggleHotkey; + ToggleProfileHotkeyControls(profileToggleEnabled); + _profileToggleHotkey = profileToggleHotkey; + _isLoadingSettings = false; + _v.SetProfileToggleState(profileToggleState); + UpdateProfileToggleHotkey(profileToggleHotkey, profileToggleEnabled); foreach (ApplicationSetting application in _applicationSettings.ToList()) { if (!File.Exists(application.FileName)) @@ -477,7 +742,7 @@ private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectP } } - private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnly, bool neverSwitchResolution, bool neverChangeColorSettings, int brightnessWindowsLevel, int contrastWindowsLevel, int gammaWindowsLevel) + private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnly, bool neverSwitchResolution, bool neverChangeColorSettings, int brightnessWindowsLevel, int contrastWindowsLevel, int gammaWindowsLevel, bool profileToggleEnabled, string profileToggleHotkey, bool profileToggleState) { SettingsController settingsController = new SettingsController(); @@ -489,7 +754,10 @@ private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnl _applicationSettings, brightnessWindowsLevel.ToString(), contrastWindowsLevel.ToString(), - gammaWindowsLevel.ToString() + gammaWindowsLevel.ToString(), + profileToggleEnabled.ToString(), + profileToggleHotkey, + profileToggleState.ToString() ); } @@ -636,4 +904,4 @@ private void buttonProcessExplorer_Click(object sender, EventArgs e) ex.Show(); } } -} \ No newline at end of file +} diff --git a/vibrance.GUI/packages.config b/vibrance.GUI/packages.config index 202a3eb..223f9e6 100644 --- a/vibrance.GUI/packages.config +++ b/vibrance.GUI/packages.config @@ -1,6 +1,6 @@  - - - + + + \ No newline at end of file diff --git a/vibrance.GUI/vibrance.GUI.csproj b/vibrance.GUI/vibrance.GUI.csproj index e96eeb8..ecda38d 100644 --- a/vibrance.GUI/vibrance.GUI.csproj +++ b/vibrance.GUI/vibrance.GUI.csproj @@ -1,6 +1,6 @@  - - + + Debug @@ -10,7 +10,7 @@ Properties vibrance.GUI vibrance.GUI - v4.0 + v4.8 512 false @@ -67,6 +67,7 @@ x86 prompt MinimumRecommendedRules.ruleset + false bin\x86\Release\ @@ -76,13 +77,14 @@ x86 prompt MinimumRecommendedRules.ruleset + false - - ..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll + + ..\packages\CommonServiceLocator.2.0.7\lib\net48\CommonServiceLocator.dll - - ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll + + ..\packages\Costura.Fody.6.0.0\lib\netstandard2.0\Costura.dll @@ -216,14 +218,6 @@ - - - Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". - - - - - + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file