diff --git a/vibrance.GUI/.gitignore b/vibrance.GUI/.gitignore new file mode 100644 index 0000000..60b2ea0 --- /dev/null +++ b/vibrance.GUI/.gitignore @@ -0,0 +1,400 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# 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 +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# 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 +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml \ No newline at end of file diff --git a/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs b/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs index 7e98d3d..843c069 100644 --- a/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs +++ b/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; -using System.Text; using System.Windows.Forms; using vibrance.GUI.AMD.vendor; using vibrance.GUI.common; @@ -13,6 +12,29 @@ namespace vibrance.GUI.AMD { public class AmdDynamicVibranceProxy : IVibranceProxy { + #region DllImports + [DllImport("gdi32.dll")] + public static extern bool GetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp); + + [DllImport("gdi32.dll")] + public static extern bool SetDeviceGammaRamp(IntPtr hDC, ref RAMP lpRamp); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct RAMP + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + public UInt16[] Red; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + public UInt16[] Green; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + public UInt16[] Blue; + } + #endregion + + public const int AmdMinLevel = 0; + public const int AmdMaxLevel = 300; + public const int AmdDefaultLevel = 100; + private readonly IAmdAdapter _amdAdapter; private List _applicationSettings; private readonly Dictionary>> _windowsResolutionSettings; @@ -69,6 +91,33 @@ public void SetNeverSwitchResolution(bool neverChangeResolution) _vibranceInfo.neverChangeResolution = neverChangeResolution; } + public void SetNeverChangeColorSettings(bool neverChangeColorSettings) + { + _vibranceInfo.neverChangeColorSettings = neverChangeColorSettings; + } + + public void SetWindowsColorSettings(int brightness, int contrast, int gamma) + { + _vibranceInfo.userColorSettings.brightness = brightness; + _vibranceInfo.userColorSettings.contrast = contrast; + _vibranceInfo.userColorSettings.gamma = gamma; + } + + public void SetWindowsColorBrightness(int brightness) + { + _vibranceInfo.userColorSettings.brightness = brightness; + } + + public void SetWindowsColorContrast(int contrast) + { + _vibranceInfo.userColorSettings.contrast = contrast; + } + + public void SetWindowsColorGamma(int gamma) + { + _vibranceInfo.userColorSettings.gamma = gamma; + } + public void SetVibranceWindowsLevel(int vibranceWindowsLevel) { _vibranceInfo.userVibranceSettingDefault = vibranceWindowsLevel; @@ -112,26 +161,38 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, e.ProcessName, StringComparison.OrdinalIgnoreCase)); if (applicationSetting != null) { - //test if a resolution change is needed Screen screen = Screen.FromHandle(e.Handle); - if (_vibranceInfo.neverChangeResolution == false && - applicationSetting.IsResolutionChangeNeeded && + _gameScreen = screen; + + //apply application specific saturation + if (_vibranceInfo.userVibranceSettingDefault != applicationSetting.IngameLevel) + { + if (_vibranceInfo.affectPrimaryMonitorOnly) + { + _amdAdapter.SetSaturationOnDisplay(applicationSetting.IngameLevel, screen.DeviceName); + } + else + { + _amdAdapter.SetSaturationOnAllDisplays(applicationSetting.IngameLevel); + } + } + + //test if a resolution change is needed + if (_vibranceInfo.neverChangeResolution == false && applicationSetting.IsResolutionChangeNeeded && IsResolutionChangeNeeded(screen, applicationSetting.ResolutionSettings) && _windowsResolutionSettings.ContainsKey(screen.DeviceName) && _windowsResolutionSettings[screen.DeviceName].Item2.Contains(applicationSetting.ResolutionSettings)) { - _gameScreen = screen; PerformResolutionChange(screen, applicationSetting.ResolutionSettings); + _vibranceInfo.isResolutionChangeApplied = true; } - _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); - if (_vibranceInfo.affectPrimaryMonitorOnly) - { - _amdAdapter.SetSaturationOnDisplay(applicationSetting.IngameLevel, screen.DeviceName); - } - else + //test if color settings change is needed + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) { - _amdAdapter.SetSaturationOnAllDisplays(applicationSetting.IngameLevel); + DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); + _vibranceInfo.isColorSettingApplied = true; } } else @@ -140,17 +201,33 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) if (GetForegroundWindow() != processHandle) return; + //apply Windows saturation + _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); + //test if a resolution change is needed - Screen screen = Screen.FromHandle(processHandle); - if (_vibranceInfo.neverChangeResolution == false && - _gameScreen != null && _gameScreen.Equals(screen) && - _windowsResolutionSettings.ContainsKey(screen.DeviceName) && - IsResolutionChangeNeeded(screen, _windowsResolutionSettings[screen.DeviceName].Item1)) + Screen currentScreen = Screen.FromHandle(processHandle); + if (_vibranceInfo.neverChangeResolution == false && _vibranceInfo.isResolutionChangeApplied == true && + _gameScreen != null && _gameScreen.Equals(currentScreen) && + _windowsResolutionSettings.ContainsKey(currentScreen.DeviceName) && + IsResolutionChangeNeeded(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1)) { - PerformResolutionChange(screen, _windowsResolutionSettings[screen.DeviceName].Item1); + PerformResolutionChange(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1); + _vibranceInfo.isResolutionChangeApplied = false; } - _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); + //apply windows color settings if color settings were previously changed + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true) + { + if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(currentScreen.DeviceName)) + { + DeviceGammaRampHelper.SetGammaRamp(_gameScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma); + } + else + { + Screen.AllScreens.ToList().ForEach(screen => DeviceGammaRampHelper.SetGammaRamp(screen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma)); + } + _vibranceInfo.isColorSettingApplied = false; + } } } } diff --git a/vibrance.GUI/FodyWeavers.xml b/vibrance.GUI/FodyWeavers.xml index 2e6d4a7..345454c 100644 --- a/vibrance.GUI/FodyWeavers.xml +++ b/vibrance.GUI/FodyWeavers.xml @@ -1,5 +1,4 @@  - - - + + \ No newline at end of file diff --git a/vibrance.GUI/FodyWeavers.xsd b/vibrance.GUI/FodyWeavers.xsd new file mode 100644 index 0000000..44a5374 --- /dev/null +++ b/vibrance.GUI/FodyWeavers.xsd @@ -0,0 +1,111 @@ + + + + + + + + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks + + + + + A list of 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. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with line breaks. + + + + + The order of preloaded assemblies, delimited with line breaks. + + + + + + This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. + + + + + Controls if .pdbs for reference assemblies are also embedded. + + + + + Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. + + + + + As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. + + + + + 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. + + + + + Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. + + + + + A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | + + + + + A list of 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 |. + + + + + A list of unmanaged 64 bit assembly names to include, delimited with |. + + + + + The order of preloaded assemblies, delimited with |. + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs b/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs index 8f2a5b3..6a843e9 100644 --- a/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs +++ b/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs @@ -1,14 +1,10 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; -using System.Media; using System.Runtime.InteropServices; using System.Text; -using System.Threading; using System.Windows.Forms; -using System.Windows.Forms.VisualStyles; using vibrance.GUI.common; namespace vibrance.GUI.NVIDIA @@ -80,13 +76,6 @@ class NvidiaDynamicVibranceProxy : IVibranceProxy CharSet = CharSet.Auto)] static extern bool isWindowActive(ref IntPtr hwnd); - [DllImport( - "vibranceDLL.dll", - EntryPoint = "?isCsgoStarted@vibrance@vibranceDLL@@QAE_NPAPAUHWND__@@@Z", - CallingConvention = CallingConvention.StdCall, - CharSet = CharSet.Ansi)] - static extern bool isCsgoStarted(ref IntPtr hwnd); - [DllImport( "vibranceDLL.dll", EntryPoint = "?equalsDVCLevel@vibrance@vibranceDLL@@QAE_NHH@Z", @@ -101,12 +90,6 @@ class NvidiaDynamicVibranceProxy : IVibranceProxy CharSet = CharSet.Auto)] static extern NvSystemType getGpuSystemType(int gpuHandle); - [DllImport("user32.dll", CharSet = CharSet.Ansi)] - static extern int GetWindowTextLength([In] IntPtr hWnd); - - [DllImport("user32.dll", CharSet = CharSet.Ansi)] - static extern int GetWindowTextA([In] IntPtr hWnd, [In, Out] StringBuilder lpString, [In] int nMaxCount); - [DllImport( "vibranceDLL.dll", EntryPoint = "?getAssociatedNvidiaDisplayHandle@vibrance@vibranceDLL@@QAEHPBDH@Z", @@ -214,23 +197,38 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) if (applicationSetting != null) { int displayHandle = GetApplicationDisplayHandle(e.Handle); - //test if changing the vibrance value is needed - if (displayHandle != -1 && !equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) + if (displayHandle == -1) + { + return; + } + + Screen screen = Screen.FromHandle(e.Handle); + _gameScreen = screen; + + //test if digital vibrance change is needed + if (!equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) { - //test if a resolution change is needed - Screen screen = Screen.FromHandle(e.Handle); - if (_vibranceInfo.neverChangeResolution == false && - applicationSetting.IsResolutionChangeNeeded && - IsResolutionChangeNeeded(screen, applicationSetting.ResolutionSettings) && - _windowsResolutionSettings.ContainsKey(screen.DeviceName) && - _windowsResolutionSettings[screen.DeviceName].Item2.Contains(applicationSetting.ResolutionSettings)) - { - PerformResolutionChange(screen, applicationSetting.ResolutionSettings); - } - _gameScreen = screen; _vibranceInfo.defaultHandle = displayHandle; setDVCLevel(_vibranceInfo.defaultHandle, applicationSetting.IngameLevel); } + + //test if a resolution change is needed + if (_vibranceInfo.neverChangeResolution == false && applicationSetting.IsResolutionChangeNeeded && + IsResolutionChangeNeeded(screen, applicationSetting.ResolutionSettings) && + _windowsResolutionSettings.ContainsKey(screen.DeviceName) && + _windowsResolutionSettings[screen.DeviceName].Item2.Contains(applicationSetting.ResolutionSettings)) + { + PerformResolutionChange(screen, applicationSetting.ResolutionSettings); + _vibranceInfo.isResolutionChangeApplied = true; + } + + //test if color settings change is needed + 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 { @@ -241,29 +239,43 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) //test if a resolution change is needed Screen currentScreen = Screen.FromHandle(processHandle); - if (_vibranceInfo.neverChangeResolution == false && - _gameScreen != null && - _gameScreen.Equals(currentScreen) && - _windowsResolutionSettings.ContainsKey(currentScreen.DeviceName) && - IsResolutionChangeNeeded(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1)) - { - PerformResolutionChange(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1); - } //test if changing the vibrance value is needed if (_vibranceInfo.affectPrimaryMonitorOnly && !equalsDVCLevel(_vibranceInfo.defaultHandle, _vibranceInfo.userVibranceSettingDefault)) { - if(_gameScreen != null && !_gameScreen.DeviceName.Equals(currentScreen.DeviceName)) + if (_gameScreen != null && !_gameScreen.DeviceName.Equals(currentScreen.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.neverChangeResolution == false && _vibranceInfo.isResolutionChangeApplied == true && + _gameScreen != null && _gameScreen.Equals(currentScreen) && + _windowsResolutionSettings.ContainsKey(currentScreen.DeviceName) && + IsResolutionChangeNeeded(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1)) + { + PerformResolutionChange(currentScreen, _windowsResolutionSettings[currentScreen.DeviceName].Item1); + _vibranceInfo.isResolutionChangeApplied = false; + } + + //apply windows color settings if color settings were previously changed + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true) + { + if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(currentScreen.DeviceName)) + { + DeviceGammaRampHelper.SetGammaRamp(_gameScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma); + } + else + { + Screen.AllScreens.ToList().ForEach(screen => DeviceGammaRampHelper.SetGammaRamp(screen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma)); + } + _vibranceInfo.isColorSettingApplied = false; + } } } } @@ -328,6 +340,33 @@ public void SetNeverSwitchResolution(bool neverChangeResolution) _vibranceInfo.neverChangeResolution = neverChangeResolution; } + public void SetNeverChangeColorSettings(bool neverChangeColorSettings) + { + _vibranceInfo.neverChangeColorSettings = neverChangeColorSettings; + } + + public void SetWindowsColorSettings(int brightness, int contrast, int gamma) + { + _vibranceInfo.userColorSettings.brightness = brightness; + _vibranceInfo.userColorSettings.contrast = contrast; + _vibranceInfo.userColorSettings.gamma = gamma; + } + + public void SetWindowsColorBrightness(int brightness) + { + _vibranceInfo.userColorSettings.brightness = brightness; + } + + public void SetWindowsColorContrast(int contrast) + { + _vibranceInfo.userColorSettings.contrast = contrast; + } + + public void SetWindowsColorGamma(int gamma) + { + _vibranceInfo.userColorSettings.gamma = gamma; + } + public void SetVibranceWindowsLevel(int vibranceWindowsLevel) { _vibranceInfo.userVibranceSettingDefault = vibranceWindowsLevel; diff --git a/vibrance.GUI/Program.cs b/vibrance.GUI/Program.cs index 472db5b..15ac80d 100644 --- a/vibrance.GUI/Program.cs +++ b/vibrance.GUI/Program.cs @@ -16,8 +16,11 @@ namespace vibrance.GUI { static class Program { + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetProcessDPIAware(); + private const string ErrorGraphicsAdapterUnknown = "Failed to determine your Graphic GraphicsAdapter type (NVIDIA/AMD). Make sure you have installed a proper GPU driver. Intel laptops are not supported as stated on the website. When installing your GPU driver did not work, please contact @juvlarN at twitter. Press Yes to open twitter in your browser now. Error: "; - private const string ErrorGraphicsAdapterAmbiguous = "Both NVIDIA and AMD graphic drivers have been found on your system. This can happen when you recently switched your graphic card and did not uninstall the old drivers. Make sure to uninstall unused graphic drivers to keep your system safe and stable. Use the program \"Display Driver Uninstaller\" to uninstall your old drivers!\n\nPress Yes to open \"Display Driver Uninstaller\" download website now.\nPress No to quit vibranceGUI."; + private const string ErrorGraphicsAdapterAmbiguous = "Both NVIDIA and AMD graphic drivers have been found on your system. This can happen when you recently switched your graphic card and did not uninstall the old drivers. Make sure to uninstall unused graphic drivers to keep your system safe and stable. Use the program \"Display Driver Uninstaller\" to uninstall your old drivers!\n\nIn case you want to do it manually: The related files are located in your Windows folder and are called \"nvapi.dll\" (NVIDIA) and \"atiadlxx.dll\" (AMD) and \"atiadlxy.dll\" (AMD). You are free to rename/delete the files that you no longer need but proceed with caution!\n\nPress Yes to open \"Display Driver Uninstaller\" download website in your Browser now.\nPress No to quit vibranceGUI."; private const string MessageBoxCaption = "vibranceGUI Error"; [STAThread] @@ -31,6 +34,11 @@ static void Main(string[] args) return; } + if (Environment.OSVersion.Version.Major >= 6) + { + SetProcessDPIAware(); + } + Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); NativeMethods.SetDllDirectory(CommonUtils.GetVibrance_GUI_AppDataPath()); @@ -38,19 +46,23 @@ static void Main(string[] args) GraphicsAdapter adapter = GraphicsAdapterHelper.GetAdapter(); Form vibranceGui = null; - if (adapter == GraphicsAdapter.Amd) + bool isForcedAmdAdapterExecution = args.Contains("--force-amd"); + bool isForcedNvidiaAdapterExecution = args.Contains("--force-nvidia"); + + if (adapter == GraphicsAdapter.Amd || isForcedAmdAdapterExecution) { Func, Dictionary>>, IVibranceProxy> getProxy = (x, y) => new AmdDynamicVibranceProxy(Environment.Is64BitOperatingSystem ? new AmdAdapter64() : (IAmdAdapter)new AmdAdapter32(), x, y); - vibranceGui = new VibranceGUI(getProxy, - 100, - 0, - 300, - 100, - x => x.ToString()); + vibranceGui = new VibranceGUI(getProxy, + GraphicsAdapter.Amd, + AmdDynamicVibranceProxy.AmdDefaultLevel, + AmdDynamicVibranceProxy.AmdMinLevel, + AmdDynamicVibranceProxy.AmdMaxLevel, + AmdDynamicVibranceProxy.AmdDefaultLevel, + isForcedAmdAdapterExecution); } - else if (adapter == GraphicsAdapter.Nvidia) + else if (adapter == GraphicsAdapter.Nvidia || isForcedNvidiaAdapterExecution) { const string nvidiaAdapterName = "vibranceDLL.dll"; string resourceName = $"{typeof(Program).Namespace}.NVIDIA.{nvidiaAdapterName}"; @@ -62,11 +74,12 @@ static void Main(string[] args) vibranceGui = new VibranceGUI( (x, y) => new NvidiaDynamicVibranceProxy(x, y), + GraphicsAdapter.Nvidia, NvidiaDynamicVibranceProxy.NvapiDefaultLevel, NvidiaDynamicVibranceProxy.NvapiDefaultLevel, NvidiaDynamicVibranceProxy.NvapiMaxLevel, NvidiaDynamicVibranceProxy.NvapiDefaultLevel, - x => NvidiaVibranceValueWrapper.Find(x).Percentage); + isForcedNvidiaAdapterExecution); } else if (adapter == GraphicsAdapter.Unknown) { @@ -78,9 +91,9 @@ static void Main(string[] args) } return; } - else if(adapter == GraphicsAdapter.Ambiguous) + else if (adapter == GraphicsAdapter.Ambiguous) { - if(MessageBox.Show(ErrorGraphicsAdapterAmbiguous, MessageBoxCaption, MessageBoxButtons.YesNo, + if (MessageBox.Show(ErrorGraphicsAdapterAmbiguous, MessageBoxCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes) { System.Diagnostics.Process.Start("http://www.guru3d.com/files-details/display-driver-uninstaller-download.html"); @@ -92,10 +105,24 @@ static void Main(string[] args) vibranceGui.WindowState = FormWindowState.Minimized; ((VibranceGUI)vibranceGui).SetAllowVisible(false); } - vibranceGui.Text += String.Format(" ({0}, {1})", adapter.ToString().ToUpper(), Application.ProductVersion); + vibranceGui.Text += buildFormTitleText(adapter, isForcedAmdAdapterExecution, isForcedNvidiaAdapterExecution); Application.Run(vibranceGui); GC.KeepAlive(mutex); } + + static string buildFormTitleText(GraphicsAdapter adapter, bool isForcedAmdAdapterExecution, bool isForcedNvidiaAdapterExecution) + { + string forcedExecution = ""; + if (isForcedAmdAdapterExecution) + { + forcedExecution = "*AMD forced*"; + } + else if (isForcedNvidiaAdapterExecution) + { + forcedExecution = "*NVIDIA forced*"; + } + return String.Format(" ({0}, {1}) {2}", adapter.ToString().ToUpper(), Application.ProductVersion, forcedExecution); + } } } diff --git a/vibrance.GUI/Properties/AssemblyInfo.cs b/vibrance.GUI/Properties/AssemblyInfo.cs index 425abd0..86dd716 100644 --- a/vibrance.GUI/Properties/AssemblyInfo.cs +++ b/vibrance.GUI/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.3.1.1")] -[assembly: AssemblyFileVersion("2.3.1.1")] +[assembly: AssemblyVersion("2.5.0")] +[assembly: AssemblyFileVersion("2.5.0")] diff --git a/vibrance.GUI/common/ApplicationSetting.cs b/vibrance.GUI/common/ApplicationSetting.cs index e4d55c1..b478689 100644 --- a/vibrance.GUI/common/ApplicationSetting.cs +++ b/vibrance.GUI/common/ApplicationSetting.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Xml.Serialization; namespace vibrance.GUI.common @@ -8,19 +9,25 @@ public class ApplicationSetting public string Name { get; set; } public string FileName { get; set; } public int IngameLevel { get; set; } + public int Brightness { get; set; } = 50; + public int Contrast { get; set; } = 50; + public int Gamma { get; set; } = 100; public bool IsResolutionChangeNeeded { get; set; } [XmlElement(IsNullable = true)] public ResolutionModeWrapper ResolutionSettings { get; set; } public ApplicationSetting(){ } - public ApplicationSetting(string name, string fileName, int ingameLevel, ResolutionModeWrapper resolutionSettings, bool isResolutionChangeNeeded) + public ApplicationSetting(string name, string fileName, int ingameLevel, ResolutionModeWrapper resolutionSettings, bool isResolutionChangeNeeded, int brightness, int contrast, int gamma) { this.Name = name; this.FileName = fileName; this.IngameLevel = ingameLevel; this.ResolutionSettings = resolutionSettings; this.IsResolutionChangeNeeded = isResolutionChangeNeeded; + this.Brightness = brightness; + this.Contrast = contrast; + this.Gamma = gamma; } public override bool Equals(object obj) diff --git a/vibrance.GUI/common/Definitions.cs b/vibrance.GUI/common/Definitions.cs index 5bda3f2..d550a11 100644 --- a/vibrance.GUI/common/Definitions.cs +++ b/vibrance.GUI/common/Definitions.cs @@ -18,5 +18,15 @@ public struct VibranceInfo public List displayHandles; public bool affectPrimaryMonitorOnly; public bool neverChangeResolution; + public bool neverChangeColorSettings; + public bool isColorSettingApplied; + public bool isResolutionChangeApplied; + public ColorSettings userColorSettings; + public struct ColorSettings + { + public int brightness; + public int contrast; + public int gamma; + } } } diff --git a/vibrance.GUI/common/DeviceGammaRampHelper.cs b/vibrance.GUI/common/DeviceGammaRampHelper.cs new file mode 100644 index 0000000..b9a08c5 --- /dev/null +++ b/vibrance.GUI/common/DeviceGammaRampHelper.cs @@ -0,0 +1,217 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Emit; +using System.Runtime.InteropServices; +using System.Text; +using System.Windows.Forms; + +namespace vibrance.GUI.common +{ + class DeviceGammaRampHelper + { + + public static void SetGammaRamp(Screen screen, int brightness = 50, int contrast = 50, int gamma = 100) + { + if(brightness == 0 || contrast == 0 || gamma == 0) + { + return; + } + SetGammaRamp(screen, (double)brightness / 100, (double)contrast / 100, (double)gamma / 100); + } + /// + /// Applies gamma, brightness, contrast to the selected screen. + /// + /// Screen to apply the gamma ramp to + /// Gamma, default value 1. + /// Brightness, default value 0.5 + /// Contrast, default value 0.5. + public static void SetGammaRamp(Screen screen, double brightness = 0.5, double contrast = 0.5, double gamma = 1.0) + { + var hdc = GetScreenDeviceContext(screen); + var newGammaRamp = CalculateGammaRamp(hdc, gamma, brightness, contrast); + ApplyGammaRamp(hdc, newGammaRamp); + ReleaseDeviceContext(hdc); + } + + /// + /// Gets the current gamma ramp for the selected screen. + /// + /// Screen to get the gamma ramp of + public static GammaRamp GetGammaRamp(Screen screen) + { + GammaRamp currentGammaRamp = new GammaRamp(); + var hdc = GetScreenDeviceContext(screen); + NativeAPI.GetDeviceGammaRamp(hdc, ref currentGammaRamp); + ReleaseDeviceContext(hdc); + return currentGammaRamp; + } + + + private static IntPtr GetScreenDeviceContext(Screen screen) + { + var hdc = NativeAPI.CreateDC(screen.DeviceName, null, null, IntPtr.Zero); + if (hdc == IntPtr.Zero) + { + VibranceGUI.Log(string.Format("Failed to create screen device context for screen {0}", screen.DeviceName)); + } + return hdc; + } + + private static void ReleaseDeviceContext(IntPtr hdc) + { + if (NativeAPI.ReleaseDC(IntPtr.Zero, hdc) == 0) + { + VibranceGUI.Log(string.Format("Failed to release device context handle {0}", hdc.ToString())); + } + } + + /// + /// Calculate the device lookup table (LUT). Credits to https://github.com/falahati in https://github.com/falahati/NvAPIWrapper/issues/20#issuecomment-634551206 + /// + /// The brightness value + /// The contrast value + /// The Gamma value + /// + private static ushort[] CalculateLUT(double brightness = 0.5, double contrast = 0.5, double gamma = 1) + { + + const int dataPoints = 256; + + // Limit gamma in range [0.4-2.8] + gamma = Math.Min(Math.Max(gamma, 0.4), 2.8); + + // Normalize contrast in range [-1,1] + contrast = (Math.Min(Math.Max(contrast, 0), 1) - 0.5) * 2; + + // Normalize brightness in range [-1,1] + brightness = (Math.Min(Math.Max(brightness, 0), 1) - 0.5) * 2; + + // Calculate curve offset resulted from contrast + var offset = contrast > 0 ? contrast * -25.4 : contrast * -32; + + // Calculate the total range of curve + var range = (dataPoints - 1) + offset * 2; + + // Add brightness to the curve offset + offset += brightness * (range / 5); + + // Fill the gamma curve + var result = new ushort[dataPoints]; + for (var i = 0; i < result.Length; i++) + { + var factor = (i + offset) / range; + + factor = Math.Pow(factor, 1 / gamma); + + factor = Math.Min(Math.Max(factor, 0), 1); + + result[i] = (ushort)Math.Round(factor * ushort.MaxValue); + } + + return result; + } + + private static GammaRamp CalculateGammaRamp(IntPtr hdc, double gamma, double brightness, double contrast) + { + ushort[] Red = new ushort[256]; + ushort[] Green = new ushort[256]; + ushort[] Blue = new ushort[256]; + + Red = CalculateLUT(brightness, contrast, gamma); + Green = CalculateLUT(brightness, contrast, gamma); + Blue = CalculateLUT(brightness, contrast, gamma); + + GammaRamp ramp = new GammaRamp(Red, Green, Blue); + return ramp; + } + + private static void ApplyGammaRamp(IntPtr hdc, GammaRamp ramp) + { + if (!NativeAPI.SetDeviceGammaRamp(hdc, ref ramp)) + { + VibranceGUI.Log(string.Format("Failed to set device gamma ramp for handle {0}", hdc.ToString())); + } + } + + public static bool IsGammaRampEqualToWindowsValues(VibranceInfo vibranceInfo, ApplicationSetting applicationSetting) + { + return vibranceInfo.userColorSettings.brightness == applicationSetting.Brightness && vibranceInfo.userColorSettings.contrast == applicationSetting.Contrast && vibranceInfo.userColorSettings.gamma == applicationSetting.Gamma; + } + + public static bool IsGammaRampDefault(VibranceInfo vibranceInfo) + { + return 50 == vibranceInfo.userColorSettings.brightness && 50 == vibranceInfo.userColorSettings.contrast && 100 == vibranceInfo.userColorSettings.gamma; + } + + // constant data + public const int GAMMA_RAMP_SIZE = 256; + + // types + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct GammaRamp + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = GAMMA_RAMP_SIZE)] + public UInt16[] Red; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = GAMMA_RAMP_SIZE)] + public UInt16[] Green; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = GAMMA_RAMP_SIZE)] + public UInt16[] Blue; + + // constructor + /// + /// Define red, blue and green arrays. + /// + /// Red array. + /// Green array. + /// Blue array. + public GammaRamp(UInt16[] r = null, UInt16[] g = null, UInt16[] b = null) + { + Red = r == null ? new UInt16[GAMMA_RAMP_SIZE] : r; + Green = g == null ? new UInt16[GAMMA_RAMP_SIZE] : g; + Blue = b == null ? new UInt16[GAMMA_RAMP_SIZE] : b; + } + + public override bool Equals(object obj) + { + if (obj is GammaRamp) + { + return false; + } + GammaRamp other = (GammaRamp)obj; + return this.Red.Equals(other.Red) && this.Blue.Equals(other.Blue) && this.Green.Equals(other.Green); + } + + public override int GetHashCode() + { + int hashCode = -1058441243; + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Red); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Green); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Blue); + return hashCode; + } + }; + + + // Windows Native API + private class NativeAPI + { + [DllImport("gdi32.dll")] + public static extern IntPtr CreateDC(string lpszDriver, string lpszDevice, string lpszOutput, IntPtr lpInitData); + + [DllImport("user32.dll", EntryPoint = "ReleaseDC")] + public static extern int ReleaseDC([In] IntPtr hWnd, [In] IntPtr hDC); + + [DllImport("user32.dll", EntryPoint = "GetDC")] + public static extern IntPtr GetDC([In] IntPtr hWnd); + + + // extern methods + [DllImport("gdi32.dll")] + public static extern bool SetDeviceGammaRamp(IntPtr hDC, ref GammaRamp lpRamp); + [DllImport("gdi32.dll")] + public static extern bool GetDeviceGammaRamp(IntPtr hDC, ref GammaRamp lpRamp); + } + } +} diff --git a/vibrance.GUI/common/ISettingsController.cs b/vibrance.GUI/common/ISettingsController.cs index 15d38da..ab6d61a 100644 --- a/vibrance.GUI/common/ISettingsController.cs +++ b/vibrance.GUI/common/ISettingsController.cs @@ -5,8 +5,10 @@ namespace vibrance.GUI.common { internal interface ISettingsController { - bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, List applicationSettings); + bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, string neverChangeColorSettings, List applicationSettings, + string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel); bool SetVibranceSetting(string szKeyName, string value); - void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, out List applicationSettings); + 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); } } \ No newline at end of file diff --git a/vibrance.GUI/common/IVibranceProxy.cs b/vibrance.GUI/common/IVibranceProxy.cs index 53b6a49..efe55c2 100644 --- a/vibrance.GUI/common/IVibranceProxy.cs +++ b/vibrance.GUI/common/IVibranceProxy.cs @@ -15,5 +15,11 @@ public interface IVibranceProxy VibranceInfo GetVibranceInfo(); GraphicsAdapter GraphicsAdapter { get; } void SetNeverSwitchResolution(bool neverSwitchResolution); + void SetNeverChangeColorSettings(bool neverChangeColorSettings); + void SetWindowsColorSettings(int brightness, int contrast, int gamma); + + void SetWindowsColorBrightness(int brightness); + void SetWindowsColorContrast(int contrast); + void SetWindowsColorGamma(int gamma); } } \ No newline at end of file diff --git a/vibrance.GUI/common/ProcessExplorer.Designer.cs b/vibrance.GUI/common/ProcessExplorer.Designer.cs index f1af214..fcbcb3e 100644 --- a/vibrance.GUI/common/ProcessExplorer.Designer.cs +++ b/vibrance.GUI/common/ProcessExplorer.Designer.cs @@ -38,9 +38,11 @@ private void InitializeComponent() // // listView // - this.listView.Location = new System.Drawing.Point(12, 41); + this.listView.HideSelection = false; + this.listView.Location = new System.Drawing.Point(18, 63); + this.listView.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.listView.Name = "listView"; - this.listView.Size = new System.Drawing.Size(615, 236); + this.listView.Size = new System.Drawing.Size(920, 361); this.listView.TabIndex = 0; this.listView.UseCompatibleStateImageBehavior = false; this.listView.DoubleClick += new System.EventHandler(this.listView_DoubleClick); @@ -53,9 +55,10 @@ private void InitializeComponent() // // button // - this.button.Location = new System.Drawing.Point(13, 12); + this.button.Location = new System.Drawing.Point(20, 18); + this.button.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.button.Name = "button"; - this.button.Size = new System.Drawing.Size(119, 23); + this.button.Size = new System.Drawing.Size(178, 35); this.button.TabIndex = 1; this.button.Text = "Reload Processes"; this.button.UseVisualStyleBackColor = true; @@ -68,13 +71,14 @@ private void InitializeComponent() // // ProcessExplorer // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(639, 289); + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(958, 445); this.Controls.Add(this.button); this.Controls.Add(this.listView); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.Name = "ProcessExplorer"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "vibranceGUI Process Explorer"; diff --git a/vibrance.GUI/common/ResolutionModeWrapper.cs b/vibrance.GUI/common/ResolutionModeWrapper.cs index b9fa2e1..f2eb8ad 100644 --- a/vibrance.GUI/common/ResolutionModeWrapper.cs +++ b/vibrance.GUI/common/ResolutionModeWrapper.cs @@ -54,5 +54,16 @@ public override bool Equals(object obj) } return false; } + + public override int GetHashCode() + { + int hashCode = -281771422; + hashCode = hashCode * -1521134295 + DmPelsWidth.GetHashCode(); + hashCode = hashCode * -1521134295 + DmPelsHeight.GetHashCode(); + hashCode = hashCode * -1521134295 + DmBitsPerPel.GetHashCode(); + hashCode = hashCode * -1521134295 + DmDisplayFrequency.GetHashCode(); + hashCode = hashCode * -1521134295 + DmDisplayFixedOutput.GetHashCode(); + return hashCode; + } } } diff --git a/vibrance.GUI/common/SettingsController.cs b/vibrance.GUI/common/SettingsController.cs index f7dcfee..90a1b6c 100644 --- a/vibrance.GUI/common/SettingsController.cs +++ b/vibrance.GUI/common/SettingsController.cs @@ -6,6 +6,7 @@ using System.Text; using System.Xml; using System.Xml.Serialization; +using vibrance.GUI.AMD; using vibrance.GUI.NVIDIA; namespace vibrance.GUI.common @@ -32,12 +33,18 @@ private static extern bool WritePrivateProfileString(string lpAppName, const string SzKeyNameRefreshRate = "refreshRate"; const string SzKeyNameAffectPrimaryMonitorOnly = "affectPrimaryMonitorOnly"; const string SzKeyNameNeverSwitchResolution = "neverSwitchResolution"; + const string SzKeyNameNeverChangeColorSettings = "neverChangeColorSettings"; + const string SzKeyNameBrightnessWindowsLevel = "brightnessWindowsLevel"; + const string SzKeyNameContrastWindowsLevel = "contrastWindowsLevel"; + const string SzKeyNameGammaWindowsLevel = "gammaWindowsLevel"; + private string _fileName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToString() + "\\vibranceGUI\\vibranceGUI.ini"; private string _fileNameApplicationSettings = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToString() + "\\vibranceGUI\\applicationData.xml"; - public bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, List applicationSettings) + public bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, string neverChangeColorSettings, List applicationSettings, + string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel) { if (!PrepareFile()) { @@ -47,6 +54,10 @@ public bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitor WritePrivateProfileString(SzSectionName, SzKeyNameInactive, windowsLevel, _fileName); WritePrivateProfileString(SzSectionName, SzKeyNameAffectPrimaryMonitorOnly, affectPrimaryMonitorOnly, _fileName); WritePrivateProfileString(SzSectionName, SzKeyNameNeverSwitchResolution, neverSwitchResolution, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameNeverChangeColorSettings, neverChangeColorSettings, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameBrightnessWindowsLevel, brightnessWindowsLevel, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameContrastWindowsLevel, contrastWindowsLevel, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameGammaWindowsLevel, gammaWindowsLevel, _fileName); try { @@ -93,7 +104,8 @@ private bool PrepareFile() return true; } - public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, out List applicationSettings) + 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) { int defaultLevel = 0; int maxLevel = 0; @@ -104,17 +116,20 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran } if (graphicsAdapter == GraphicsAdapter.Amd) { - // todo - defaultLevel = 100; - maxLevel = 300; + defaultLevel = AmdDynamicVibranceProxy.AmdDefaultLevel; + maxLevel = AmdDynamicVibranceProxy.AmdMaxLevel; } if (!IsFileExisting(_fileName) || !IsFileExisting(_fileNameApplicationSettings)) { vibranceWindowsLevel = defaultLevel; - affectPrimaryMonitorOnly = false; + affectPrimaryMonitorOnly = true; applicationSettings = new List(); - neverSwitchResolution = false; + neverSwitchResolution = true; + neverChangeColorSettings = true; + brightnessWindowsLevel = 50; + contrastWindowsLevel = 50; + gammaWindowsLevel = 100; return; } @@ -139,7 +154,7 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran StringBuilder szValueAffectPrimaryMonitorOnly = new StringBuilder(1024); GetPrivateProfileString(SzSectionName, SzKeyNameAffectPrimaryMonitorOnly, - "false", + "true", szValueAffectPrimaryMonitorOnly, Convert.ToUInt32(szValueAffectPrimaryMonitorOnly.Capacity), _fileName); @@ -147,23 +162,63 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran StringBuilder szValueNeverSwitchResolution = new StringBuilder(1024); GetPrivateProfileString(SzSectionName, SzKeyNameNeverSwitchResolution, - "false", + "true", szValueNeverSwitchResolution, Convert.ToUInt32(szValueNeverSwitchResolution.Capacity), _fileName); + StringBuilder szValueNeverChangeColorSettings = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameNeverChangeColorSettings, + "true", + szValueNeverChangeColorSettings, + Convert.ToUInt32(szValueNeverChangeColorSettings.Capacity), + _fileName); + + StringBuilder szValueBrightnessWindowsLevel = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameBrightnessWindowsLevel, + "50", + szValueBrightnessWindowsLevel, + Convert.ToUInt32(szValueBrightnessWindowsLevel.Capacity), + _fileName); + + StringBuilder szValueContrastWindowsLevel = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameContrastWindowsLevel, + "50", + szValueContrastWindowsLevel, + Convert.ToUInt32(szValueContrastWindowsLevel.Capacity), + _fileName); + + StringBuilder szValueGammaWindowsLevel = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameGammaWindowsLevel, + "100", + szValueGammaWindowsLevel, + Convert.ToUInt32(szValueGammaWindowsLevel.Capacity), + _fileName); + try { vibranceWindowsLevel = int.Parse(szValueInactive.ToString()); affectPrimaryMonitorOnly = bool.Parse(szValueAffectPrimaryMonitorOnly.ToString()); neverSwitchResolution = bool.Parse(szValueNeverSwitchResolution.ToString()); + neverChangeColorSettings = bool.Parse(szValueNeverChangeColorSettings.ToString()); + brightnessWindowsLevel = int.Parse(szValueBrightnessWindowsLevel.ToString()); + contrastWindowsLevel = int.Parse(szValueContrastWindowsLevel.ToString()); + gammaWindowsLevel = int.Parse(szValueGammaWindowsLevel.ToString()); } catch (Exception) { vibranceWindowsLevel = defaultLevel; affectPrimaryMonitorOnly = false; applicationSettings = new List(); - neverSwitchResolution = false; + neverSwitchResolution = true; + neverChangeColorSettings = true; + brightnessWindowsLevel = 50; + contrastWindowsLevel = 50; + gammaWindowsLevel = 100; return; } diff --git a/vibrance.GUI/common/TrackbarLabelHelper.cs b/vibrance.GUI/common/TrackbarLabelHelper.cs new file mode 100644 index 0000000..132f1b6 --- /dev/null +++ b/vibrance.GUI/common/TrackbarLabelHelper.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using vibrance.GUI.NVIDIA; + +namespace vibrance.GUI.common +{ + internal class TrackbarLabelHelper + { + public static string ResolveVibranceLabelLevel(GraphicsAdapter graphicsAdapter, int value) + { + switch (graphicsAdapter) + { + case GraphicsAdapter.Nvidia: + return NvidiaVibranceValueWrapper.Find(value).Percentage; + case GraphicsAdapter.Amd: + return ResolvePercentageLabelLevel(value); + case GraphicsAdapter.Ambiguous: + case GraphicsAdapter.Unknown: + default: + return ""; + } + } + + public static string ResolveBrightnessLabelLevel(int value) + { + return ResolvePercentageLabelLevel(value); + } + + public static string ResolveContrastLabelLevel(int value) + { + return ResolvePercentageLabelLevel(value); + } + + public static string ResolveGammaLabelLevel(int value) + { + return string.Format("{0:F2}", (double)value / 100); + } + + private static string ResolvePercentageLabelLevel(int value) + { + return string.Format("{0}%", value); + } + } +} diff --git a/vibrance.GUI/common/VibranceGUI.Designer.cs b/vibrance.GUI/common/VibranceGUI.Designer.cs index c5f99c0..096c31b 100644 --- a/vibrance.GUI/common/VibranceGUI.Designer.cs +++ b/vibrance.GUI/common/VibranceGUI.Designer.cs @@ -36,7 +36,7 @@ private void InitializeComponent() this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.backgroundWorker = new System.ComponentModel.BackgroundWorker(); this.checkBoxAutostart = new System.Windows.Forms.CheckBox(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.groupBoxSettings = new System.Windows.Forms.GroupBox(); this.checkBoxNeverChangeResolutions = new System.Windows.Forms.CheckBox(); this.checkBoxPrimaryMonitorOnly = new System.Windows.Forms.CheckBox(); this.groupBox3 = new System.Windows.Forms.GroupBox(); @@ -50,16 +50,34 @@ private void InitializeComponent() this.buttonPaypal = new System.Windows.Forms.Button(); this.labelPaypal = new System.Windows.Forms.Label(); this.toolTip = new System.Windows.Forms.ToolTip(this.components); + this.checkBoxNeverChangeColorSettings = new System.Windows.Forms.CheckBox(); this.groupBox5 = new System.Windows.Forms.GroupBox(); this.buttonProcessExplorer = new System.Windows.Forms.Button(); this.buttonRemoveProgram = new System.Windows.Forms.Button(); this.listApplications = new System.Windows.Forms.ListView(); this.buttonAddProgram = new System.Windows.Forms.Button(); + this.groupBoxColorSettings = new System.Windows.Forms.GroupBox(); + this.groupBox8 = new System.Windows.Forms.GroupBox(); + this.labelGamma = new System.Windows.Forms.Label(); + this.trackBarGamma = new System.Windows.Forms.TrackBar(); + this.groupBox9 = new System.Windows.Forms.GroupBox(); + this.labelContrast = new System.Windows.Forms.Label(); + this.trackBarContrast = new System.Windows.Forms.TrackBar(); + this.groupBox10 = new System.Windows.Forms.GroupBox(); + this.labelBrightness = new System.Windows.Forms.Label(); + this.trackBarBrightness = new System.Windows.Forms.TrackBar(); this.contextMenuStrip.SuspendLayout(); - this.groupBox1.SuspendLayout(); + this.groupBoxSettings.SuspendLayout(); this.groupBox3.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBarWindowsLevel)).BeginInit(); this.groupBox5.SuspendLayout(); + this.groupBoxColorSettings.SuspendLayout(); + this.groupBox8.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarGamma)).BeginInit(); + this.groupBox9.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarContrast)).BeginInit(); + this.groupBox10.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarBrightness)).BeginInit(); this.SuspendLayout(); // // notifyIcon @@ -75,11 +93,12 @@ private void InitializeComponent() // // contextMenuStrip // + this.contextMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24); this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.twitterToolStripTextBox, this.exitToolStripMenuItem}); this.contextMenuStrip.Name = "contextMenuStrip"; - this.contextMenuStrip.Size = new System.Drawing.Size(217, 48); + this.contextMenuStrip.Size = new System.Drawing.Size(303, 68); this.contextMenuStrip.Text = "Vibrance Control"; // // twitterToolStripTextBox @@ -88,7 +107,7 @@ private void InitializeComponent() this.twitterToolStripTextBox.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(6)))), ((int)(((byte)(69)))), ((int)(((byte)(173))))); this.twitterToolStripTextBox.Image = ((System.Drawing.Image)(resources.GetObject("twitterToolStripTextBox.Image"))); this.twitterToolStripTextBox.Name = "twitterToolStripTextBox"; - this.twitterToolStripTextBox.Size = new System.Drawing.Size(216, 22); + this.twitterToolStripTextBox.Size = new System.Drawing.Size(302, 32); this.twitterToolStripTextBox.Text = "https://twitter.com/juvlarN"; this.twitterToolStripTextBox.Click += new System.EventHandler(this.twitterToolStripTextBox_Click); // @@ -96,7 +115,7 @@ private void InitializeComponent() // this.exitToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("exitToolStripMenuItem.Image"))); this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; - this.exitToolStripMenuItem.Size = new System.Drawing.Size(216, 22); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(302, 32); this.exitToolStripMenuItem.Text = "Exit"; this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); // @@ -109,46 +128,52 @@ private void InitializeComponent() // checkBoxAutostart // this.checkBoxAutostart.AutoSize = true; - this.checkBoxAutostart.Location = new System.Drawing.Point(6, 19); + this.checkBoxAutostart.Location = new System.Drawing.Point(9, 29); + this.checkBoxAutostart.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.checkBoxAutostart.Name = "checkBoxAutostart"; - this.checkBoxAutostart.Size = new System.Drawing.Size(131, 17); + this.checkBoxAutostart.Size = new System.Drawing.Size(194, 24); this.checkBoxAutostart.TabIndex = 8; this.checkBoxAutostart.Text = "Autostart vibranceGUI"; this.checkBoxAutostart.UseVisualStyleBackColor = true; this.checkBoxAutostart.CheckedChanged += new System.EventHandler(this.checkBoxAutostart_CheckedChanged); // - // groupBox1 - // - this.groupBox1.Controls.Add(this.checkBoxNeverChangeResolutions); - this.groupBox1.Controls.Add(this.checkBoxPrimaryMonitorOnly); - this.groupBox1.Controls.Add(this.groupBox3); - this.groupBox1.Controls.Add(this.checkBoxAutostart); - this.groupBox1.Location = new System.Drawing.Point(13, 82); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(397, 143); - this.groupBox1.TabIndex = 15; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Settings"; + // groupBoxSettings + // + this.groupBoxSettings.Controls.Add(this.checkBoxNeverChangeResolutions); + this.groupBoxSettings.Controls.Add(this.checkBoxPrimaryMonitorOnly); + this.groupBoxSettings.Controls.Add(this.groupBox3); + this.groupBoxSettings.Controls.Add(this.checkBoxAutostart); + this.groupBoxSettings.Location = new System.Drawing.Point(15, 137); + this.groupBoxSettings.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxSettings.Name = "groupBoxSettings"; + this.groupBoxSettings.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxSettings.Size = new System.Drawing.Size(600, 250); + this.groupBoxSettings.TabIndex = 15; + this.groupBoxSettings.TabStop = false; + this.groupBoxSettings.Text = "Settings"; // // checkBoxNeverChangeResolutions // this.checkBoxNeverChangeResolutions.AutoSize = true; - this.checkBoxNeverChangeResolutions.Location = new System.Drawing.Point(163, 42); + this.checkBoxNeverChangeResolutions.Checked = true; + this.checkBoxNeverChangeResolutions.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBoxNeverChangeResolutions.Location = new System.Drawing.Point(9, 99); + this.checkBoxNeverChangeResolutions.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.checkBoxNeverChangeResolutions.Name = "checkBoxNeverChangeResolutions"; - this.checkBoxNeverChangeResolutions.Size = new System.Drawing.Size(147, 17); + this.checkBoxNeverChangeResolutions.Size = new System.Drawing.Size(282, 24); this.checkBoxNeverChangeResolutions.TabIndex = 16; - this.checkBoxNeverChangeResolutions.Text = "Never change resolutions"; - this.toolTip.SetToolTip(this.checkBoxNeverChangeResolutions, "When checking this, VibranceGUI will never change the resolution on any of your m" + - "onitors."); + this.checkBoxNeverChangeResolutions.Text = "Never change Windows resolutions"; + this.toolTip.SetToolTip(this.checkBoxNeverChangeResolutions, resources.GetString("checkBoxNeverChangeResolutions.ToolTip")); this.checkBoxNeverChangeResolutions.UseVisualStyleBackColor = true; this.checkBoxNeverChangeResolutions.CheckedChanged += new System.EventHandler(this.checkBoxNeverChangeResolutions_CheckedChanged); // // checkBoxPrimaryMonitorOnly // this.checkBoxPrimaryMonitorOnly.AutoSize = true; - this.checkBoxPrimaryMonitorOnly.Location = new System.Drawing.Point(6, 42); + this.checkBoxPrimaryMonitorOnly.Location = new System.Drawing.Point(9, 65); + this.checkBoxPrimaryMonitorOnly.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.checkBoxPrimaryMonitorOnly.Name = "checkBoxPrimaryMonitorOnly"; - this.checkBoxPrimaryMonitorOnly.Size = new System.Drawing.Size(151, 17); + this.checkBoxPrimaryMonitorOnly.Size = new System.Drawing.Size(223, 24); this.checkBoxPrimaryMonitorOnly.TabIndex = 15; this.checkBoxPrimaryMonitorOnly.Text = "Affect Primary Monitor only"; this.toolTip.SetToolTip(this.checkBoxPrimaryMonitorOnly, "When checking this, VibranceGUI will only change vibrance values on your primary " + @@ -160,9 +185,11 @@ private void InitializeComponent() // this.groupBox3.Controls.Add(this.labelWindowsLevel); this.groupBox3.Controls.Add(this.trackBarWindowsLevel); - this.groupBox3.Location = new System.Drawing.Point(7, 65); + this.groupBox3.Location = new System.Drawing.Point(8, 129); + this.groupBox3.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(182, 72); + this.groupBox3.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox3.Size = new System.Drawing.Size(273, 111); this.groupBox3.TabIndex = 12; this.groupBox3.TabStop = false; this.groupBox3.Text = "Windows Vibrance Level"; @@ -170,53 +197,60 @@ private void InitializeComponent() // labelWindowsLevel // this.labelWindowsLevel.AutoSize = true; - this.labelWindowsLevel.Location = new System.Drawing.Point(148, 22); + this.labelWindowsLevel.Location = new System.Drawing.Point(222, 34); + this.labelWindowsLevel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.labelWindowsLevel.Name = "labelWindowsLevel"; - this.labelWindowsLevel.Size = new System.Drawing.Size(0, 13); + this.labelWindowsLevel.Size = new System.Drawing.Size(41, 20); this.labelWindowsLevel.TabIndex = 1; + this.labelWindowsLevel.Text = "50%"; // // trackBarWindowsLevel // - this.trackBarWindowsLevel.Location = new System.Drawing.Point(15, 22); + this.trackBarWindowsLevel.Location = new System.Drawing.Point(22, 34); + this.trackBarWindowsLevel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.trackBarWindowsLevel.Maximum = 63; this.trackBarWindowsLevel.Name = "trackBarWindowsLevel"; - this.trackBarWindowsLevel.Size = new System.Drawing.Size(131, 45); + this.trackBarWindowsLevel.Size = new System.Drawing.Size(196, 69); this.trackBarWindowsLevel.TabIndex = 0; this.trackBarWindowsLevel.Scroll += new System.EventHandler(this.trackBarWindowsLevel_Scroll); // // statusLabel // this.statusLabel.AutoSize = true; - this.statusLabel.Location = new System.Drawing.Point(106, 502); + this.statusLabel.Location = new System.Drawing.Point(152, 1136); + this.statusLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.statusLabel.Name = "statusLabel"; - this.statusLabel.Size = new System.Drawing.Size(61, 13); + this.statusLabel.Size = new System.Drawing.Size(90, 20); this.statusLabel.TabIndex = 14; this.statusLabel.Text = "Initializing..."; // // observerStatusLabel // this.observerStatusLabel.AutoSize = true; - this.observerStatusLabel.Location = new System.Drawing.Point(12, 502); + this.observerStatusLabel.Location = new System.Drawing.Point(11, 1136); + this.observerStatusLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.observerStatusLabel.Name = "observerStatusLabel"; - this.observerStatusLabel.Size = new System.Drawing.Size(87, 13); + this.observerStatusLabel.Size = new System.Drawing.Size(129, 20); this.observerStatusLabel.TabIndex = 13; this.observerStatusLabel.Text = "Observer status: "; // // labelTwitter // this.labelTwitter.AutoSize = true; - this.labelTwitter.Location = new System.Drawing.Point(10, 11); + this.labelTwitter.Location = new System.Drawing.Point(15, 17); + this.labelTwitter.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.labelTwitter.Name = "labelTwitter"; - this.labelTwitter.Size = new System.Drawing.Size(192, 13); + this.labelTwitter.Size = new System.Drawing.Size(283, 20); this.labelTwitter.TabIndex = 11; this.labelTwitter.Text = "Follow @juvlarN on twitter for updates: "; // // linkLabelTwitter // this.linkLabelTwitter.AutoSize = true; - this.linkLabelTwitter.Location = new System.Drawing.Point(208, 11); + this.linkLabelTwitter.Location = new System.Drawing.Point(312, 17); + this.linkLabelTwitter.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.linkLabelTwitter.Name = "linkLabelTwitter"; - this.linkLabelTwitter.Size = new System.Drawing.Size(132, 13); + this.linkLabelTwitter.Size = new System.Drawing.Size(185, 20); this.linkLabelTwitter.TabIndex = 10; this.linkLabelTwitter.TabStop = true; this.linkLabelTwitter.Text = "https://twitter.com/juvlarN"; @@ -232,9 +266,10 @@ private void InitializeComponent() this.buttonPaypal.Anchor = System.Windows.Forms.AnchorStyles.None; this.buttonPaypal.BackColor = System.Drawing.Color.Transparent; this.buttonPaypal.Image = ((System.Drawing.Image)(resources.GetObject("buttonPaypal.Image"))); - this.buttonPaypal.Location = new System.Drawing.Point(211, 28); + this.buttonPaypal.Location = new System.Drawing.Point(316, 42); + this.buttonPaypal.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.buttonPaypal.Name = "buttonPaypal"; - this.buttonPaypal.Size = new System.Drawing.Size(90, 55); + this.buttonPaypal.Size = new System.Drawing.Size(135, 85); this.buttonPaypal.TabIndex = 16; this.toolTip.SetToolTip(this.buttonPaypal, "Click here to donate to vibranceGUI through Paypal"); this.buttonPaypal.UseVisualStyleBackColor = false; @@ -243,9 +278,10 @@ private void InitializeComponent() // labelPaypal // this.labelPaypal.AutoSize = true; - this.labelPaypal.Location = new System.Drawing.Point(10, 48); + this.labelPaypal.Location = new System.Drawing.Point(15, 74); + this.labelPaypal.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.labelPaypal.Name = "labelPaypal"; - this.labelPaypal.Size = new System.Drawing.Size(183, 13); + this.labelPaypal.Size = new System.Drawing.Size(274, 20); this.labelPaypal.TabIndex = 17; this.labelPaypal.Text = "Like the program? Consider donating:"; // @@ -256,24 +292,43 @@ private void InitializeComponent() this.toolTip.IsBalloon = true; this.toolTip.ReshowDelay = 100; // + // checkBoxNeverChangeColorSettings + // + this.checkBoxNeverChangeColorSettings.AutoSize = true; + this.checkBoxNeverChangeColorSettings.Checked = true; + this.checkBoxNeverChangeColorSettings.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBoxNeverChangeColorSettings.Location = new System.Drawing.Point(11, 38); + this.checkBoxNeverChangeColorSettings.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.checkBoxNeverChangeColorSettings.Name = "checkBoxNeverChangeColorSettings"; + this.checkBoxNeverChangeColorSettings.Size = new System.Drawing.Size(231, 24); + this.checkBoxNeverChangeColorSettings.TabIndex = 17; + this.checkBoxNeverChangeColorSettings.Text = "Never change color settings"; + this.toolTip.SetToolTip(this.checkBoxNeverChangeColorSettings, "When checking this, VibranceGUI will never change the color settings (brightness," + + " contrast, gamma) on any of your monitors."); + this.checkBoxNeverChangeColorSettings.UseVisualStyleBackColor = true; + this.checkBoxNeverChangeColorSettings.CheckedChanged += new System.EventHandler(this.checkBoxNeverChangeColorSettings_CheckedChanged); + // // groupBox5 // this.groupBox5.Controls.Add(this.buttonProcessExplorer); this.groupBox5.Controls.Add(this.buttonRemoveProgram); this.groupBox5.Controls.Add(this.listApplications); this.groupBox5.Controls.Add(this.buttonAddProgram); - this.groupBox5.Location = new System.Drawing.Point(13, 231); + this.groupBox5.Location = new System.Drawing.Point(15, 757); + this.groupBox5.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.groupBox5.Name = "groupBox5"; - this.groupBox5.Size = new System.Drawing.Size(397, 227); + this.groupBox5.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox5.Size = new System.Drawing.Size(600, 349); this.groupBox5.TabIndex = 18; this.groupBox5.TabStop = false; this.groupBox5.Text = "Program Settings"; // // buttonProcessExplorer // - this.buttonProcessExplorer.Location = new System.Drawing.Point(7, 20); + this.buttonProcessExplorer.Location = new System.Drawing.Point(10, 31); + this.buttonProcessExplorer.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.buttonProcessExplorer.Name = "buttonProcessExplorer"; - this.buttonProcessExplorer.Size = new System.Drawing.Size(75, 23); + this.buttonProcessExplorer.Size = new System.Drawing.Size(112, 35); this.buttonProcessExplorer.TabIndex = 3; this.buttonProcessExplorer.Text = "Add"; this.buttonProcessExplorer.UseVisualStyleBackColor = true; @@ -281,9 +336,10 @@ private void InitializeComponent() // // buttonRemoveProgram // - this.buttonRemoveProgram.Location = new System.Drawing.Point(186, 20); + this.buttonRemoveProgram.Location = new System.Drawing.Point(279, 31); + this.buttonRemoveProgram.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.buttonRemoveProgram.Name = "buttonRemoveProgram"; - this.buttonRemoveProgram.Size = new System.Drawing.Size(75, 23); + this.buttonRemoveProgram.Size = new System.Drawing.Size(112, 35); this.buttonRemoveProgram.TabIndex = 2; this.buttonRemoveProgram.Text = "Remove"; this.buttonRemoveProgram.UseVisualStyleBackColor = true; @@ -291,38 +347,164 @@ private void InitializeComponent() // // listApplications // - this.listApplications.Location = new System.Drawing.Point(7, 49); + this.listApplications.HideSelection = false; + this.listApplications.Location = new System.Drawing.Point(10, 75); + this.listApplications.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.listApplications.Name = "listApplications"; - this.listApplications.Size = new System.Drawing.Size(384, 172); + this.listApplications.Size = new System.Drawing.Size(574, 262); this.listApplications.TabIndex = 1; this.listApplications.UseCompatibleStateImageBehavior = false; this.listApplications.DoubleClick += new System.EventHandler(this.listApplications_DoubleClick); // // buttonAddProgram // - this.buttonAddProgram.Location = new System.Drawing.Point(88, 20); + this.buttonAddProgram.Location = new System.Drawing.Point(132, 31); + this.buttonAddProgram.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.buttonAddProgram.Name = "buttonAddProgram"; - this.buttonAddProgram.Size = new System.Drawing.Size(92, 23); + this.buttonAddProgram.Size = new System.Drawing.Size(138, 35); this.buttonAddProgram.TabIndex = 0; this.buttonAddProgram.Text = "Add manually"; this.buttonAddProgram.UseVisualStyleBackColor = true; this.buttonAddProgram.Click += new System.EventHandler(this.buttonAddProgram_Click); // + // groupBoxColorSettings + // + this.groupBoxColorSettings.Controls.Add(this.groupBox8); + this.groupBoxColorSettings.Controls.Add(this.groupBox9); + this.groupBoxColorSettings.Controls.Add(this.groupBox10); + this.groupBoxColorSettings.Controls.Add(this.checkBoxNeverChangeColorSettings); + this.groupBoxColorSettings.Location = new System.Drawing.Point(15, 397); + this.groupBoxColorSettings.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxColorSettings.Name = "groupBoxColorSettings"; + this.groupBoxColorSettings.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxColorSettings.Size = new System.Drawing.Size(600, 350); + this.groupBoxColorSettings.TabIndex = 19; + this.groupBoxColorSettings.TabStop = false; + this.groupBoxColorSettings.Text = "Color Settings (EXPERIMENTAL)"; + // + // groupBox8 + // + this.groupBox8.Controls.Add(this.labelGamma); + this.groupBox8.Controls.Add(this.trackBarGamma); + this.groupBox8.Location = new System.Drawing.Point(11, 210); + this.groupBox8.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox8.Name = "groupBox8"; + this.groupBox8.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox8.Size = new System.Drawing.Size(273, 111); + this.groupBox8.TabIndex = 14; + this.groupBox8.TabStop = false; + this.groupBox8.Text = "Windows Gamma"; + // + // labelGamma + // + this.labelGamma.AutoSize = true; + this.labelGamma.Location = new System.Drawing.Point(222, 34); + this.labelGamma.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelGamma.Name = "labelGamma"; + this.labelGamma.Size = new System.Drawing.Size(18, 20); + this.labelGamma.TabIndex = 1; + this.labelGamma.Text = "1"; + // + // trackBarGamma + // + this.trackBarGamma.Enabled = false; + this.trackBarGamma.Location = new System.Drawing.Point(22, 34); + this.trackBarGamma.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.trackBarGamma.Maximum = 240; + this.trackBarGamma.Minimum = 30; + this.trackBarGamma.Name = "trackBarGamma"; + this.trackBarGamma.Size = new System.Drawing.Size(196, 69); + this.trackBarGamma.TabIndex = 0; + this.trackBarGamma.Value = 100; + this.trackBarGamma.Scroll += new System.EventHandler(this.trackBarGamma_Scroll); + // + // groupBox9 + // + this.groupBox9.Controls.Add(this.labelContrast); + this.groupBox9.Controls.Add(this.trackBarContrast); + this.groupBox9.Location = new System.Drawing.Point(315, 89); + this.groupBox9.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox9.Name = "groupBox9"; + this.groupBox9.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox9.Size = new System.Drawing.Size(273, 111); + this.groupBox9.TabIndex = 18; + this.groupBox9.TabStop = false; + this.groupBox9.Text = "Windows Contrast"; + // + // labelContrast + // + this.labelContrast.AutoSize = true; + this.labelContrast.Location = new System.Drawing.Point(222, 34); + this.labelContrast.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelContrast.Name = "labelContrast"; + this.labelContrast.Size = new System.Drawing.Size(41, 20); + this.labelContrast.TabIndex = 1; + this.labelContrast.Text = "50%"; + // + // trackBarContrast + // + this.trackBarContrast.Enabled = false; + this.trackBarContrast.Location = new System.Drawing.Point(22, 34); + this.trackBarContrast.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.trackBarContrast.Maximum = 100; + this.trackBarContrast.Name = "trackBarContrast"; + this.trackBarContrast.Size = new System.Drawing.Size(196, 69); + this.trackBarContrast.TabIndex = 0; + this.trackBarContrast.Value = 50; + this.trackBarContrast.Scroll += new System.EventHandler(this.trackBarContrast_Scroll); + // + // groupBox10 + // + this.groupBox10.Controls.Add(this.labelBrightness); + this.groupBox10.Controls.Add(this.trackBarBrightness); + this.groupBox10.Location = new System.Drawing.Point(11, 89); + this.groupBox10.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox10.Name = "groupBox10"; + this.groupBox10.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox10.Size = new System.Drawing.Size(273, 111); + this.groupBox10.TabIndex = 13; + this.groupBox10.TabStop = false; + this.groupBox10.Text = "Windows Brightness"; + // + // labelBrightness + // + this.labelBrightness.AutoSize = true; + this.labelBrightness.Location = new System.Drawing.Point(222, 34); + this.labelBrightness.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelBrightness.Name = "labelBrightness"; + this.labelBrightness.Size = new System.Drawing.Size(41, 20); + this.labelBrightness.TabIndex = 1; + this.labelBrightness.Text = "50%"; + // + // trackBarBrightness + // + this.trackBarBrightness.Enabled = false; + this.trackBarBrightness.Location = new System.Drawing.Point(22, 34); + this.trackBarBrightness.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.trackBarBrightness.Maximum = 100; + this.trackBarBrightness.Name = "trackBarBrightness"; + this.trackBarBrightness.Size = new System.Drawing.Size(196, 69); + this.trackBarBrightness.TabIndex = 0; + this.trackBarBrightness.Value = 50; + this.trackBarBrightness.Scroll += new System.EventHandler(this.trackBarBrightness_Scroll); + // // VibranceGUI // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(419, 524); + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(628, 1161); + this.Controls.Add(this.groupBoxColorSettings); this.Controls.Add(this.groupBox5); this.Controls.Add(this.labelPaypal); this.Controls.Add(this.buttonPaypal); - this.Controls.Add(this.groupBox1); + this.Controls.Add(this.groupBoxSettings); this.Controls.Add(this.statusLabel); this.Controls.Add(this.observerStatusLabel); this.Controls.Add(this.labelTwitter); this.Controls.Add(this.linkLabelTwitter); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.MaximizeBox = false; this.Name = "VibranceGUI"; this.Text = "vibranceGUI"; @@ -331,12 +513,23 @@ private void InitializeComponent() this.Shown += new System.EventHandler(this.Form1_Shown); this.Resize += new System.EventHandler(this.Form1_Resize); this.contextMenuStrip.ResumeLayout(false); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); + this.groupBoxSettings.ResumeLayout(false); + this.groupBoxSettings.PerformLayout(); this.groupBox3.ResumeLayout(false); this.groupBox3.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBarWindowsLevel)).EndInit(); this.groupBox5.ResumeLayout(false); + this.groupBoxColorSettings.ResumeLayout(false); + this.groupBoxColorSettings.PerformLayout(); + this.groupBox8.ResumeLayout(false); + this.groupBox8.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarGamma)).EndInit(); + this.groupBox9.ResumeLayout(false); + this.groupBox9.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarContrast)).EndInit(); + this.groupBox10.ResumeLayout(false); + this.groupBox10.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarBrightness)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -350,7 +543,7 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.ComponentModel.BackgroundWorker backgroundWorker; private System.Windows.Forms.CheckBox checkBoxAutostart; - private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBoxSettings; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.Label labelWindowsLevel; private System.Windows.Forms.TrackBar trackBarWindowsLevel; @@ -369,6 +562,17 @@ private void InitializeComponent() private System.Windows.Forms.Button buttonAddProgram; private System.Windows.Forms.Button buttonProcessExplorer; private System.Windows.Forms.CheckBox checkBoxNeverChangeResolutions; + private System.Windows.Forms.CheckBox checkBoxNeverChangeColorSettings; + private System.Windows.Forms.GroupBox groupBoxColorSettings; + private System.Windows.Forms.GroupBox groupBox8; + private System.Windows.Forms.Label labelGamma; + private System.Windows.Forms.TrackBar trackBarGamma; + private System.Windows.Forms.GroupBox groupBox9; + private System.Windows.Forms.Label labelContrast; + private System.Windows.Forms.TrackBar trackBarContrast; + private System.Windows.Forms.GroupBox groupBox10; + private System.Windows.Forms.Label labelBrightness; + private System.Windows.Forms.TrackBar trackBarBrightness; } } diff --git a/vibrance.GUI/common/VibranceGUI.cs b/vibrance.GUI/common/VibranceGUI.cs index fe5804c..f1973d5 100644 --- a/vibrance.GUI/common/VibranceGUI.cs +++ b/vibrance.GUI/common/VibranceGUI.cs @@ -15,11 +15,11 @@ namespace vibrance.GUI.common { public partial class VibranceGUI : Form { + private GraphicsAdapter _graphicsAdapter; private readonly int _defaultWindowsLevel; private readonly int _minTrackBarValue; private readonly int _maxTrackBarValue; private readonly int _defaultIngameValue; - private readonly Func _resolveLabelLevel; private readonly IVibranceProxy _v; private IRegistryController _registryController; private const string AppName = "vibranceGUI"; @@ -31,20 +31,24 @@ public partial class VibranceGUI : Form private readonly List _supportedResolutionList; private readonly Dictionary>> _windowsResolutionSettings; + private readonly bool _isForcedExecution; + public VibranceGUI( - Func, Dictionary>>, IVibranceProxy> getProxy, - int defaultWindowsLevel, + Func, Dictionary>>, IVibranceProxy> getProxy, + GraphicsAdapter graphicsAdapter, + int defaultWindowsLevel, int minTrackBarValue, int maxTrackBarValue, int defaultIngameValue, - Func resolveLabelLevel) + bool isForcedExecution) { + _graphicsAdapter = graphicsAdapter; _defaultWindowsLevel = defaultWindowsLevel; _minTrackBarValue = minTrackBarValue; _maxTrackBarValue = maxTrackBarValue; _defaultIngameValue = defaultIngameValue; - _resolveLabelLevel = resolveLabelLevel; _allowVisible = true; + _isForcedExecution = isForcedExecution; InitializeComponent(); @@ -52,18 +56,18 @@ public VibranceGUI( trackBarWindowsLevel.Maximum = maxTrackBarValue; _windowsResolutionSettings = new Dictionary>>(); - foreach(Screen screen in Screen.AllScreens) + foreach (Screen screen in Screen.AllScreens) { Devmode currentResolutionMode; if (ResolutionHelper.GetCurrentResolutionSettings(out currentResolutionMode, screen.DeviceName)) { List availableResolutions = ResolutionHelper.EnumerateSupportedResolutionModes(screen.DeviceName); - if(screen.Primary) + if (screen.Primary) { _supportedResolutionList = availableResolutions; } var tuple = new Tuple>(new ResolutionModeWrapper(currentResolutionMode), availableResolutions); - _windowsResolutionSettings.Add(screen.DeviceName, tuple); + _windowsResolutionSettings.Add(screen.DeviceName, tuple); } else { @@ -118,6 +122,10 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) int vibranceWindowsLevel = _defaultWindowsLevel; bool affectPrimaryMonitorOnly = false; bool neverSwitchResolution = false; + bool neverChangeColorSettings = false; + int brightnessWindowsLevel = 50; + int contrastWindowsLevel = 50; + int gammaWindowsLevel = 100; while (!this.IsHandleCreated) { @@ -128,12 +136,12 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { this.Invoke((MethodInvoker)delegate { - ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution); + ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); }); } else { - ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution); + ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); } if (_v.GetVibranceInfo().isInitialized) @@ -147,6 +155,8 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) _v.SetVibranceWindowsLevel(vibranceWindowsLevel); _v.SetAffectPrimaryMonitorOnly(affectPrimaryMonitorOnly); _v.SetNeverSwitchResolution(neverSwitchResolution); + _v.SetNeverChangeColorSettings(neverChangeColorSettings); + _v.SetWindowsColorSettings(brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel); } } @@ -171,7 +181,37 @@ private void exitToolStripMenuItem_Click(object sender, EventArgs e) private void trackBarWindowsLevel_Scroll(object sender, EventArgs e) { _v.SetVibranceWindowsLevel(trackBarWindowsLevel.Value); - labelWindowsLevel.Text = _resolveLabelLevel(trackBarWindowsLevel.Value); + labelWindowsLevel.Text = TrackbarLabelHelper.ResolveVibranceLabelLevel(_graphicsAdapter, trackBarWindowsLevel.Value); + if (!settingsBackgroundWorker.IsBusy) + { + settingsBackgroundWorker.RunWorkerAsync(); + } + } + + private void trackBarBrightness_Scroll(object sender, EventArgs e) + { + _v.SetWindowsColorBrightness(trackBarBrightness.Value); + labelBrightness.Text = TrackbarLabelHelper.ResolveBrightnessLabelLevel(trackBarBrightness.Value); + if (!settingsBackgroundWorker.IsBusy) + { + settingsBackgroundWorker.RunWorkerAsync(); + } + } + + + private void trackBarContrast_Scroll(object sender, EventArgs e) + { + _v.SetWindowsColorContrast(trackBarContrast.Value); + labelContrast.Text = TrackbarLabelHelper.ResolveContrastLabelLevel(trackBarContrast.Value); + if (!settingsBackgroundWorker.IsBusy) + { + settingsBackgroundWorker.RunWorkerAsync(); + } + } + private void trackBarGamma_Scroll(object sender, EventArgs e) + { + _v.SetWindowsColorGamma(trackBarGamma.Value); + labelGamma.Text = TrackbarLabelHelper.ResolveGammaLabelLevel(trackBarGamma.Value); if (!settingsBackgroundWorker.IsBusy) { settingsBackgroundWorker.RunWorkerAsync(); @@ -187,15 +227,23 @@ private void settingsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) private void ForceSaveVibranceSettings() { int windowsLevel = 0; - bool affectPrimaryMonitorOnly = false; - bool neverSwitchResolution = false; + bool affectPrimaryMonitorOnly = true; + bool neverSwitchResolution = true; + bool neverChangeColorSettings = true; + int brightnessWindowsLevel = 50; + int contrastWindowsLevel = 50; + int gammaWindowsLevel = 100; this.Invoke((MethodInvoker)delegate { windowsLevel = trackBarWindowsLevel.Value; affectPrimaryMonitorOnly = checkBoxPrimaryMonitorOnly.Checked; neverSwitchResolution = checkBoxNeverChangeResolutions.Checked; + neverChangeColorSettings = checkBoxNeverChangeColorSettings.Checked; + brightnessWindowsLevel = trackBarBrightness.Value; + contrastWindowsLevel = trackBarContrast.Value; + gammaWindowsLevel = trackBarGamma.Value; }); - SaveVibranceSettings(windowsLevel, affectPrimaryMonitorOnly, neverSwitchResolution); + SaveVibranceSettings(windowsLevel, affectPrimaryMonitorOnly, neverSwitchResolution, neverChangeColorSettings, brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel); } private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) @@ -240,7 +288,7 @@ private void checkBoxPrimaryMonitorOnly_CheckedChanged(object sender, EventArgs this.settingsBackgroundWorker.RunWorkerAsync(); } } - + private void checkBoxNeverChangeResolutions_CheckedChanged(object sender, EventArgs e) { if (this._v == null) @@ -261,10 +309,15 @@ private void checkBoxAutostart_CheckedChanged(object sender, EventArgs e) if (this.checkBoxAutostart.Checked) { string pathToExe = "\"" + Application.ExecutablePath + "\" -minimized"; + if (_isForcedExecution) + { + pathToExe += string.Format(" --force-{0}", _graphicsAdapter.ToString().ToLower()); + } + if (!autostartController.IsProgramRegistered(AppName)) { - this.notifyIcon.BalloonTipText = autostartController.RegisterProgram(AppName, pathToExe) - ? "Registered to Autostart!" + this.notifyIcon.BalloonTipText = autostartController.RegisterProgram(AppName, pathToExe) + ? "Registered to Autostart!" : "Registering to Autostart failed!"; } else if (!autostartController.IsStartupPathUnchanged(AppName, pathToExe)) @@ -280,14 +333,34 @@ private void checkBoxAutostart_CheckedChanged(object sender, EventArgs e) } else { - this.notifyIcon.BalloonTipText = autostartController.UnregisterProgram(AppName) - ? "Unregistered from Autostart!" + this.notifyIcon.BalloonTipText = autostartController.UnregisterProgram(AppName) + ? "Unregistered from Autostart!" : "Unregistering from Autostart failed!"; } notifyIcon.ShowBalloonTip(250); } + + private void checkBoxNeverChangeColorSettings_CheckedChanged(object sender, EventArgs e) + { + if (this._v == null) + { + return; + } + + this._v.SetNeverChangeColorSettings(this.checkBoxNeverChangeColorSettings.Checked); + + trackBarBrightness.Enabled = !this.checkBoxNeverChangeColorSettings.Checked; + trackBarContrast.Enabled = !this.checkBoxNeverChangeColorSettings.Checked; + trackBarGamma.Enabled = !this.checkBoxNeverChangeColorSettings.Checked; + + if (!this.settingsBackgroundWorker.IsBusy) + { + this.settingsBackgroundWorker.RunWorkerAsync(); + } + } + private void twitterToolStripTextBox_Click(object sender, EventArgs e) { Process.Start(TwitterLink); @@ -308,6 +381,8 @@ private void SetGuiEnabledFlag(bool flag) this.buttonAddProgram.Enabled = flag; this.buttonProcessExplorer.Enabled = flag; this.buttonRemoveProgram.Enabled = flag; + this.checkBoxNeverChangeResolutions.Enabled = flag; + this.checkBoxNeverChangeColorSettings.Enabled = flag; }); } @@ -333,7 +408,7 @@ private void CleanUp() public static void Log(Exception ex) { - using (StreamWriter w = File.AppendText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "vibranceGUI.log"))) + using (StreamWriter w = File.AppendText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "vibranceGUI\\vibranceGUI.log"))) { w.Write("\r\nLog Entry : "); w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), @@ -350,7 +425,7 @@ public static void Log(Exception ex) public static void Log(string msg) { - using (StreamWriter w = File.AppendText("vibranceGUI_log.txt")) + using (StreamWriter w = File.AppendText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "vibranceGUI\\vibranceGUI.log"))) { w.Write("\r\nLog Entry : "); w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), @@ -360,29 +435,32 @@ public static void Log(string msg) } } - private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution) + private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, + out bool neverChangeColorSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel) { _registryController = new RegistryController(); this.checkBoxAutostart.Checked = _registryController.IsProgramRegistered(AppName); SettingsController settingsController = new SettingsController(); - settingsController.ReadVibranceSettings(_v.GraphicsAdapter, out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out _applicationSettings); + settingsController.ReadVibranceSettings(_v.GraphicsAdapter, out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, + out neverChangeColorSettings, out _applicationSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); if (this.IsHandleCreated) { //no null check needed, SettingsController will always return matching values. - labelWindowsLevel.Text = _resolveLabelLevel(vibranceWindowsLevel); + labelWindowsLevel.Text = TrackbarLabelHelper.ResolveVibranceLabelLevel(_graphicsAdapter, vibranceWindowsLevel); trackBarWindowsLevel.Value = vibranceWindowsLevel; checkBoxPrimaryMonitorOnly.Checked = affectPrimaryMonitorOnly; checkBoxNeverChangeResolutions.Checked = neverSwitchResolution; + checkBoxNeverChangeColorSettings.Checked = neverChangeColorSettings; foreach (ApplicationSetting application in _applicationSettings.ToList()) { if (!File.Exists(application.FileName)) { _applicationSettings.Remove(application); continue; - } + } InitializeApplicationList(); @@ -399,7 +477,7 @@ private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectP } } - private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnly, bool neverSwitchResolution) + private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnly, bool neverSwitchResolution, bool neverChangeColorSettings, int brightnessWindowsLevel, int contrastWindowsLevel, int gammaWindowsLevel) { SettingsController settingsController = new SettingsController(); @@ -407,7 +485,11 @@ private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnl windowsLevel.ToString(), affectPrimaryMonitorOnly.ToString(), neverSwitchResolution.ToString(), - _applicationSettings + neverChangeColorSettings.ToString(), + _applicationSettings, + brightnessWindowsLevel.ToString(), + contrastWindowsLevel.ToString(), + gammaWindowsLevel.ToString() ); } @@ -422,7 +504,7 @@ private void buttonAddProgram_Click(object sender, EventArgs e) OpenFileDialog fileDialog = new OpenFileDialog(); DialogResult result = fileDialog.ShowDialog(); - if (result == DialogResult.OK && fileDialog.CheckFileExists && fileDialog.SafeFileName != null + if (result == DialogResult.OK && fileDialog.CheckFileExists && fileDialog.SafeFileName != null && _applicationSettings.FirstOrDefault(x => x.FileName.ToLower() == fileDialog.FileName.ToLower()) == null) { Icon icon = Icon.ExtractAssociatedIcon(fileDialog.FileName); @@ -436,7 +518,7 @@ private void buttonAddProgram_Click(object sender, EventArgs e) public void AddProgramExtern(ProcessExplorerEntry processExplorerEntry) { - if(this.InvokeRequired) + if (this.InvokeRequired) { this.Invoke((MethodInvoker)delegate { @@ -452,11 +534,11 @@ public void AddProgramExtern(ProcessExplorerEntry processExplorerEntry) private void AddProgramIntern(ProcessExplorerEntry processExplorerEntry) { InitializeApplicationList(); - - if(!File.Exists(processExplorerEntry.Path) || _applicationSettings.FirstOrDefault(x => x.FileName.ToLower() == processExplorerEntry.Path.ToLower()) != null) + + if (!File.Exists(processExplorerEntry.Path) || _applicationSettings.FirstOrDefault(x => x.FileName.ToLower() == processExplorerEntry.Path.ToLower()) != null) { this.listApplications.SelectedIndices.Clear(); - return; + return; } Icon icon = processExplorerEntry.Icon; @@ -507,7 +589,7 @@ private void listApplications_DoubleClick(object sender, EventArgs e) if (selectedItem != null) { ApplicationSetting actualSetting = _applicationSettings.FirstOrDefault(x => x.FileName == selectedItem.Tag.ToString()); - VibranceSettings settingsWindow = new VibranceSettings(_v, _minTrackBarValue, _maxTrackBarValue, _defaultIngameValue, selectedItem, actualSetting, _supportedResolutionList, _resolveLabelLevel); + VibranceSettings settingsWindow = new VibranceSettings(_v, _minTrackBarValue, _maxTrackBarValue, _defaultIngameValue, selectedItem, actualSetting, _supportedResolutionList, _graphicsAdapter); DialogResult result = settingsWindow.ShowDialog(); if (result == DialogResult.OK) { @@ -519,7 +601,7 @@ private void listApplications_DoubleClick(object sender, EventArgs e) _applicationSettings.Add(newSetting); ForceSaveVibranceSettings(); } - else if(actualSetting == null) + else if (actualSetting == null) { removeApplicationListItem(selectedItem); } diff --git a/vibrance.GUI/common/VibranceGUI.resx b/vibrance.GUI/common/VibranceGUI.resx index d4d1e79..9b3d071 100644 --- a/vibrance.GUI/common/VibranceGUI.resx +++ b/vibrance.GUI/common/VibranceGUI.resx @@ -124,343 +124,6 @@ 894, 14 - - - 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 - YII= - - AAABAAcAMDAAAAEAIACoJQAAdgAAACgoAAABACAAaBoAAB4mAABgYAAAAQAgAKiUAACGQAAAGBgAAAEA @@ -2128,6 +1791,343 @@ AAD//wAAAAAAD/8AAAD//4BAAAAAD/8AAAD////gAAAAH/8AAAD////wAAAAH/8AAAD////wAAAAP/8A AAD////4AAAAf/8AAAD////8AAAA//8AAAD////+AAAB//8AAAD/////gAAD//8AAAD/////wAAP//8A AAD/////+AA///8AAAA= + + + + + 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 + YII= @@ -2136,6 +2136,9 @@ 216, 53 + + When checking this, VibranceGUI will never change the resolution on any of your monitors. This is a very specific setting, primarily targeted for (Borderless) Windowed window mode, so only use it if you are sure what you are doing. + 17, 53 diff --git a/vibrance.GUI/common/VibranceSettings.Designer.cs b/vibrance.GUI/common/VibranceSettings.Designer.cs index 5f5afa0..0f9e870 100644 --- a/vibrance.GUI/common/VibranceSettings.Designer.cs +++ b/vibrance.GUI/common/VibranceSettings.Designer.cs @@ -39,46 +39,68 @@ private void InitializeComponent() this.groupBox1 = new System.Windows.Forms.GroupBox(); this.labelResolution = new System.Windows.Forms.Label(); this.checkBoxResolution = new System.Windows.Forms.CheckBox(); + this.groupBoxBrightness = new System.Windows.Forms.GroupBox(); + this.trackBarBrightness = new System.Windows.Forms.TrackBar(); + this.labelBrightness = new System.Windows.Forms.Label(); + this.groupBoxContrast = new System.Windows.Forms.GroupBox(); + this.trackBarContrast = new System.Windows.Forms.TrackBar(); + this.labelContrast = new System.Windows.Forms.Label(); + this.groupBoxGamma = new System.Windows.Forms.GroupBox(); + this.trackBarGamma = new System.Windows.Forms.TrackBar(); + this.labelGamma = new System.Windows.Forms.Label(); + this.buttonReset = new System.Windows.Forms.Button(); + this.labelValidation = new System.Windows.Forms.Label(); this.groupBox2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.trackBarIngameLevel)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); this.groupBox1.SuspendLayout(); + this.groupBoxBrightness.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarBrightness)).BeginInit(); + this.groupBoxContrast.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarContrast)).BeginInit(); + this.groupBoxGamma.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarGamma)).BeginInit(); this.SuspendLayout(); // // groupBox2 // this.groupBox2.Controls.Add(this.trackBarIngameLevel); this.groupBox2.Controls.Add(this.labelIngameLevel); - this.groupBox2.Location = new System.Drawing.Point(12, 63); + this.groupBox2.Location = new System.Drawing.Point(18, 97); + this.groupBox2.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(246, 72); + this.groupBox2.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox2.Size = new System.Drawing.Size(369, 111); this.groupBox2.TabIndex = 13; this.groupBox2.TabStop = false; this.groupBox2.Text = "Ingame Vibrance Level"; // // trackBarIngameLevel // - this.trackBarIngameLevel.Location = new System.Drawing.Point(16, 23); + this.trackBarIngameLevel.Location = new System.Drawing.Point(24, 35); + this.trackBarIngameLevel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.trackBarIngameLevel.Maximum = 63; this.trackBarIngameLevel.Name = "trackBarIngameLevel"; - this.trackBarIngameLevel.Size = new System.Drawing.Size(131, 45); + this.trackBarIngameLevel.Size = new System.Drawing.Size(196, 69); this.trackBarIngameLevel.TabIndex = 9; this.trackBarIngameLevel.Scroll += new System.EventHandler(this.trackBarIngameLevel_Scroll); // // labelIngameLevel // this.labelIngameLevel.AutoSize = true; - this.labelIngameLevel.Location = new System.Drawing.Point(149, 26); + this.labelIngameLevel.Location = new System.Drawing.Point(224, 40); + this.labelIngameLevel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.labelIngameLevel.Name = "labelIngameLevel"; - this.labelIngameLevel.Size = new System.Drawing.Size(27, 13); + this.labelIngameLevel.Size = new System.Drawing.Size(41, 20); this.labelIngameLevel.TabIndex = 10; this.labelIngameLevel.Text = "50%"; // // buttonSave // - this.buttonSave.Location = new System.Drawing.Point(100, 231); + this.buttonSave.Location = new System.Drawing.Point(247, 760); + this.buttonSave.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.buttonSave.Name = "buttonSave"; - this.buttonSave.Size = new System.Drawing.Size(75, 23); + this.buttonSave.Size = new System.Drawing.Size(140, 37); this.buttonSave.TabIndex = 14; this.buttonSave.Text = "Save"; this.buttonSave.UseVisualStyleBackColor = true; @@ -87,18 +109,20 @@ private void InitializeComponent() // labelTitle // this.labelTitle.AutoSize = true; - this.labelTitle.Location = new System.Drawing.Point(66, 9); - this.labelTitle.MaximumSize = new System.Drawing.Size(150, 0); + this.labelTitle.Location = new System.Drawing.Point(99, 14); + this.labelTitle.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelTitle.MaximumSize = new System.Drawing.Size(225, 0); this.labelTitle.Name = "labelTitle"; - this.labelTitle.Size = new System.Drawing.Size(63, 13); + this.labelTitle.Size = new System.Drawing.Size(95, 20); this.labelTitle.TabIndex = 15; this.labelTitle.Text = "Settings for "; // // pictureBox // - this.pictureBox.Location = new System.Drawing.Point(12, 9); + this.pictureBox.Location = new System.Drawing.Point(18, 14); + this.pictureBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.pictureBox.Name = "pictureBox"; - this.pictureBox.Size = new System.Drawing.Size(48, 48); + this.pictureBox.Size = new System.Drawing.Size(72, 74); this.pictureBox.TabIndex = 16; this.pictureBox.TabStop = false; // @@ -106,9 +130,10 @@ private void InitializeComponent() // this.cBoxResolution.Enabled = false; this.cBoxResolution.FormattingEnabled = true; - this.cBoxResolution.Location = new System.Drawing.Point(6, 57); + this.cBoxResolution.Location = new System.Drawing.Point(9, 88); + this.cBoxResolution.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.cBoxResolution.Name = "cBoxResolution"; - this.cBoxResolution.Size = new System.Drawing.Size(234, 21); + this.cBoxResolution.Size = new System.Drawing.Size(349, 28); this.cBoxResolution.TabIndex = 17; // // groupBox1 @@ -116,9 +141,11 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.labelResolution); this.groupBox1.Controls.Add(this.checkBoxResolution); this.groupBox1.Controls.Add(this.cBoxResolution); - this.groupBox1.Location = new System.Drawing.Point(12, 141); + this.groupBox1.Location = new System.Drawing.Point(18, 581); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(246, 84); + this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBox1.Size = new System.Drawing.Size(369, 131); this.groupBox1.TabIndex = 19; this.groupBox1.TabStop = false; this.groupBox1.Text = "Ingame Resolution"; @@ -127,28 +154,160 @@ private void InitializeComponent() // this.labelResolution.AutoSize = true; this.labelResolution.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.labelResolution.Location = new System.Drawing.Point(4, 18); + this.labelResolution.Location = new System.Drawing.Point(6, 28); + this.labelResolution.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.labelResolution.Name = "labelResolution"; - this.labelResolution.Size = new System.Drawing.Size(225, 13); + this.labelResolution.Size = new System.Drawing.Size(360, 20); this.labelResolution.TabIndex = 19; this.labelResolution.Text = "For (Borderless) Windowed Mode players only!"; // // checkBoxResolution // this.checkBoxResolution.AutoSize = true; - this.checkBoxResolution.Location = new System.Drawing.Point(6, 34); + this.checkBoxResolution.Location = new System.Drawing.Point(9, 52); + this.checkBoxResolution.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.checkBoxResolution.Name = "checkBoxResolution"; - this.checkBoxResolution.Size = new System.Drawing.Size(183, 17); + this.checkBoxResolution.Size = new System.Drawing.Size(271, 24); this.checkBoxResolution.TabIndex = 18; this.checkBoxResolution.Text = "Change Resolution when Ingame"; this.checkBoxResolution.UseVisualStyleBackColor = true; this.checkBoxResolution.CheckedChanged += new System.EventHandler(this.checkBoxResolution_CheckedChanged); // + // groupBoxBrightness + // + this.groupBoxBrightness.Controls.Add(this.trackBarBrightness); + this.groupBoxBrightness.Controls.Add(this.labelBrightness); + this.groupBoxBrightness.Location = new System.Drawing.Point(18, 218); + this.groupBoxBrightness.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxBrightness.Name = "groupBoxBrightness"; + this.groupBoxBrightness.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxBrightness.Size = new System.Drawing.Size(369, 111); + this.groupBoxBrightness.TabIndex = 21; + this.groupBoxBrightness.TabStop = false; + this.groupBoxBrightness.Text = "Ingame Brightness (EXPERIMENTAL)"; + // + // trackBarBrightness + // + this.trackBarBrightness.Location = new System.Drawing.Point(24, 35); + this.trackBarBrightness.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.trackBarBrightness.Maximum = 100; + this.trackBarBrightness.Name = "trackBarBrightness"; + this.trackBarBrightness.Size = new System.Drawing.Size(196, 69); + this.trackBarBrightness.TabIndex = 9; + this.trackBarBrightness.Value = 50; + this.trackBarBrightness.Scroll += new System.EventHandler(this.trackBarBrightness_Scroll); + // + // labelBrightness + // + this.labelBrightness.AutoSize = true; + this.labelBrightness.Location = new System.Drawing.Point(224, 40); + this.labelBrightness.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelBrightness.Name = "labelBrightness"; + this.labelBrightness.Size = new System.Drawing.Size(41, 20); + this.labelBrightness.TabIndex = 10; + this.labelBrightness.Text = "50%"; + // + // groupBoxContrast + // + this.groupBoxContrast.Controls.Add(this.trackBarContrast); + this.groupBoxContrast.Controls.Add(this.labelContrast); + this.groupBoxContrast.Location = new System.Drawing.Point(18, 339); + this.groupBoxContrast.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxContrast.Name = "groupBoxContrast"; + this.groupBoxContrast.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxContrast.Size = new System.Drawing.Size(369, 111); + this.groupBoxContrast.TabIndex = 22; + this.groupBoxContrast.TabStop = false; + this.groupBoxContrast.Text = "Ingame Contrast (EXPERIMENTAL)"; + // + // trackBarContrast + // + this.trackBarContrast.Location = new System.Drawing.Point(24, 35); + this.trackBarContrast.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.trackBarContrast.Maximum = 100; + this.trackBarContrast.Name = "trackBarContrast"; + this.trackBarContrast.Size = new System.Drawing.Size(196, 69); + this.trackBarContrast.TabIndex = 9; + this.trackBarContrast.Value = 50; + this.trackBarContrast.Scroll += new System.EventHandler(this.trackBarContrast_Scroll); + // + // labelContrast + // + this.labelContrast.AutoSize = true; + this.labelContrast.Location = new System.Drawing.Point(224, 40); + this.labelContrast.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelContrast.Name = "labelContrast"; + this.labelContrast.Size = new System.Drawing.Size(41, 20); + this.labelContrast.TabIndex = 10; + this.labelContrast.Text = "50%"; + // + // groupBoxGamma + // + this.groupBoxGamma.Controls.Add(this.trackBarGamma); + this.groupBoxGamma.Controls.Add(this.labelGamma); + this.groupBoxGamma.Location = new System.Drawing.Point(18, 460); + this.groupBoxGamma.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxGamma.Name = "groupBoxGamma"; + this.groupBoxGamma.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.groupBoxGamma.Size = new System.Drawing.Size(369, 111); + this.groupBoxGamma.TabIndex = 23; + this.groupBoxGamma.TabStop = false; + this.groupBoxGamma.Text = "Ingame Gamma (EXPERIMENTAL)"; + // + // trackBarGamma + // + this.trackBarGamma.Location = new System.Drawing.Point(24, 35); + this.trackBarGamma.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.trackBarGamma.Maximum = 240; + this.trackBarGamma.Minimum = 30; + this.trackBarGamma.Name = "trackBarGamma"; + this.trackBarGamma.Size = new System.Drawing.Size(196, 69); + this.trackBarGamma.TabIndex = 9; + this.trackBarGamma.Value = 100; + this.trackBarGamma.Scroll += new System.EventHandler(this.trackBarGamma_Scroll); + // + // labelGamma + // + this.labelGamma.AutoSize = true; + this.labelGamma.Location = new System.Drawing.Point(224, 40); + this.labelGamma.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelGamma.Name = "labelGamma"; + this.labelGamma.Size = new System.Drawing.Size(18, 20); + this.labelGamma.TabIndex = 10; + this.labelGamma.Text = "1"; + // + // buttonReset + // + this.buttonReset.Location = new System.Drawing.Point(18, 760); + this.buttonReset.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.buttonReset.Name = "buttonReset"; + this.buttonReset.Size = new System.Drawing.Size(140, 37); + this.buttonReset.TabIndex = 24; + this.buttonReset.Text = "Reset values"; + this.buttonReset.UseVisualStyleBackColor = true; + this.buttonReset.Click += new System.EventHandler(this.buttonReset_Click); + // + // labelValidation + // + this.labelValidation.AutoSize = true; + this.labelValidation.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelValidation.ForeColor = System.Drawing.Color.Red; + this.labelValidation.Location = new System.Drawing.Point(14, 717); + this.labelValidation.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelValidation.Name = "labelValidation"; + this.labelValidation.Size = new System.Drawing.Size(0, 20); + this.labelValidation.TabIndex = 20; + // // VibranceSettings // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(270, 266); + this.AutoScaleDimensions = new System.Drawing.SizeF(144F, 144F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.ClientSize = new System.Drawing.Size(405, 811); + this.Controls.Add(this.labelValidation); + this.Controls.Add(this.buttonReset); + this.Controls.Add(this.groupBoxGamma); + this.Controls.Add(this.groupBoxContrast); + this.Controls.Add(this.groupBoxBrightness); this.Controls.Add(this.groupBox1); this.Controls.Add(this.pictureBox); this.Controls.Add(this.labelTitle); @@ -156,6 +315,7 @@ private void InitializeComponent() this.Controls.Add(this.groupBox2); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.MaximizeBox = false; this.Name = "VibranceSettings"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; @@ -166,6 +326,15 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); + this.groupBoxBrightness.ResumeLayout(false); + this.groupBoxBrightness.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarBrightness)).EndInit(); + this.groupBoxContrast.ResumeLayout(false); + this.groupBoxContrast.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarContrast)).EndInit(); + this.groupBoxGamma.ResumeLayout(false); + this.groupBoxGamma.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarGamma)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -183,5 +352,16 @@ private void InitializeComponent() private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.CheckBox checkBoxResolution; private System.Windows.Forms.Label labelResolution; + private System.Windows.Forms.GroupBox groupBoxBrightness; + private System.Windows.Forms.TrackBar trackBarBrightness; + private System.Windows.Forms.Label labelBrightness; + private System.Windows.Forms.GroupBox groupBoxContrast; + private System.Windows.Forms.TrackBar trackBarContrast; + private System.Windows.Forms.Label labelContrast; + private System.Windows.Forms.GroupBox groupBoxGamma; + private System.Windows.Forms.TrackBar trackBarGamma; + private System.Windows.Forms.Label labelGamma; + private System.Windows.Forms.Button buttonReset; + private System.Windows.Forms.Label labelValidation; } } \ No newline at end of file diff --git a/vibrance.GUI/common/VibranceSettings.cs b/vibrance.GUI/common/VibranceSettings.cs index 819a44e..819a2ae 100644 --- a/vibrance.GUI/common/VibranceSettings.cs +++ b/vibrance.GUI/common/VibranceSettings.cs @@ -1,44 +1,86 @@ using System; using System.Collections.Generic; +using System.Text.RegularExpressions; using System.Windows.Forms; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; +using System.Xml.Linq; +using System.Drawing; namespace vibrance.GUI.common { public partial class VibranceSettings : Form { private IVibranceProxy _v; + private GraphicsAdapter _graphicsAdapter; private ListViewItem _sender; - private readonly Func _resolveLabelLevel; + private int _vibranceDefaultValue; - public VibranceSettings(IVibranceProxy v, int minValue, int maxValue, int defaultValue, ListViewItem sender, ApplicationSetting setting, List supportedResolutionList, Func resolveLabelLevel) + public VibranceSettings(IVibranceProxy v, int minValue, int maxValue, int defaultValue, ListViewItem sender, ApplicationSetting setting, List supportedResolutionList, GraphicsAdapter graphicsAdapter) { InitializeComponent(); + this._vibranceDefaultValue = defaultValue; this.trackBarIngameLevel.Minimum = minValue; this.trackBarIngameLevel.Maximum = maxValue; this.trackBarIngameLevel.Value = defaultValue; this._sender = sender; - _resolveLabelLevel = resolveLabelLevel; + this._graphicsAdapter = graphicsAdapter; this._v = v; - labelIngameLevel.Text = _resolveLabelLevel(trackBarIngameLevel.Value); + labelIngameLevel.Text = TrackbarLabelHelper.ResolveVibranceLabelLevel(_graphicsAdapter, trackBarIngameLevel.Value); this.labelTitle.Text += $@"""{sender.Text}"""; this.pictureBox.Image = this._sender.ListView.LargeImageList.Images[this._sender.ImageIndex]; this.cBoxResolution.DataSource = supportedResolutionList; + + if(_v.GetVibranceInfo().neverChangeColorSettings) + { + this.trackBarBrightness.Enabled = false; + this.trackBarContrast.Enabled = false; + this.trackBarGamma.Enabled = false; + } + + if(_v.GetVibranceInfo().neverChangeResolution) + { + this.cBoxResolution.Enabled = false; + this.checkBoxResolution.Enabled = false; + this.checkBoxResolution.Checked = false; + } + // If the setting is new, we don't need to set the progress bar value if (setting != null) { // Sets the progress bar value to the Ingame Vibrance setting this.trackBarIngameLevel.Value = setting.IngameLevel; + this.trackBarBrightness.Value = setting.Brightness; + this.trackBarContrast.Value = setting.Contrast; + this.trackBarGamma.Value = setting.Gamma; this.cBoxResolution.SelectedItem = setting.ResolutionSettings; this.checkBoxResolution.Checked = setting.IsResolutionChangeNeeded; - // Necessary to reload the label which tells the percentage - trackBarIngameLevel_Scroll(null, null); + reloadTrackbarLabels(); } } private void trackBarIngameLevel_Scroll(object sender, EventArgs e) { _v.SetVibranceIngameLevel(trackBarIngameLevel.Value); - labelIngameLevel.Text = _resolveLabelLevel(trackBarIngameLevel.Value); + labelIngameLevel.Text = TrackbarLabelHelper.ResolveVibranceLabelLevel(_graphicsAdapter, trackBarIngameLevel.Value); + validateIngameValues(); + } + + private void trackBarBrightness_Scroll(object sender, EventArgs e) + { + labelBrightness.Text = TrackbarLabelHelper.ResolveBrightnessLabelLevel(trackBarBrightness.Value); + validateIngameValues(); + } + + private void trackBarContrast_Scroll(object sender, EventArgs e) + { + labelContrast.Text = TrackbarLabelHelper.ResolveContrastLabelLevel(trackBarContrast.Value); + validateIngameValues(); + } + + private void trackBarGamma_Scroll(object sender, EventArgs e) + { + labelGamma.Text = TrackbarLabelHelper.ResolveGammaLabelLevel(trackBarGamma.Value); + validateIngameValues(); } private void buttonSave_Click(object sender, EventArgs e) @@ -50,12 +92,57 @@ private void buttonSave_Click(object sender, EventArgs e) public ApplicationSetting GetApplicationSetting() { return new ApplicationSetting(_sender.Text, _sender.Tag.ToString(), this.trackBarIngameLevel.Value, - (ResolutionModeWrapper)this.cBoxResolution.SelectedItem, this.checkBoxResolution.Checked); + (ResolutionModeWrapper)this.cBoxResolution.SelectedItem, this.checkBoxResolution.Checked, + this.trackBarBrightness.Value, this.trackBarContrast.Value, this.trackBarGamma.Value); } private void checkBoxResolution_CheckedChanged(object sender, EventArgs e) { this.cBoxResolution.Enabled = this.checkBoxResolution.Checked; } + + private void buttonReset_Click(object sender, EventArgs e) + { + this.trackBarIngameLevel.Value = this._vibranceDefaultValue; + this.trackBarBrightness.Value = 50; + this.trackBarContrast.Value = 50; + this.trackBarGamma.Value = 100; + this.checkBoxResolution.Checked = false; + this.cBoxResolution.SelectedIndex = 0; + + reloadTrackbarLabels(); + } + + private void reloadTrackbarLabels() + { + // Fake a scroll event, to reload the label which tells the percentage + trackBarIngameLevel_Scroll(null, null); + trackBarBrightness_Scroll(null, null); + trackBarContrast_Scroll(null, null); + trackBarGamma_Scroll(null, null); + } + + private void validateIngameValues() + { + if(matchesWindowsValues()) + { + labelValidation.ForeColor = Color.Red; + labelValidation.Text = "⚠️ Ingame settings match your Windows settings!" + Environment.NewLine + "No color change will happen."; + } + else + { + labelValidation.ForeColor = Color.Green; + labelValidation.Text = "Validation of ingame settings was successful"; + } + } + + private bool matchesWindowsValues() + { + VibranceInfo vibranceInfo = _v.GetVibranceInfo(); + return vibranceInfo.userVibranceSettingDefault == trackBarIngameLevel.Value && + vibranceInfo.userColorSettings.brightness == trackBarBrightness.Value && + vibranceInfo.userColorSettings.contrast == trackBarContrast.Value && + vibranceInfo.userColorSettings.gamma == trackBarGamma.Value; + } } } diff --git a/vibrance.GUI/common/WinEventHook.cs b/vibrance.GUI/common/WinEventHook.cs index 3ad9b5a..8b5915f 100644 --- a/vibrance.GUI/common/WinEventHook.cs +++ b/vibrance.GUI/common/WinEventHook.cs @@ -186,7 +186,7 @@ private struct WinEvent private WinEventHook() { - _winEventHookHandle = SetWinEventHook(WinEvent.EventSystemForeground, WinEvent.EventSystemForeground, IntPtr.Zero, _procDelegate, 0, 0, WinEvent.WineventOutofcontext); + _winEventHookHandle = SetWinEventHook(WinEvent.EventSystemForeground, WinEvent.EventSystemMinimizeend, IntPtr.Zero, _procDelegate, 0, 0, WinEvent.WineventOutofcontext); } public void RemoveWinEventHook() @@ -201,11 +201,7 @@ public void RemoveWinEventHook() } catch (Exception ex) { - VibranceGUI.Log(new Exception("UnhookWinEvent(winEventHookHandle) failed.")); - } - finally - { - + VibranceGUI.Log(new Exception("UnhookWinEvent(winEventHookHandle) failed.", ex)); } } diff --git a/vibrance.GUI/packages.config b/vibrance.GUI/packages.config index f3c5e08..202a3eb 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 71e63a8..e96eeb8 100644 --- a/vibrance.GUI/vibrance.GUI.csproj +++ b/vibrance.GUI/vibrance.GUI.csproj @@ -1,5 +1,6 @@  + Debug @@ -27,7 +28,8 @@ 1.0.0.%2a false true - 535f6299 + + x86 @@ -76,6 +78,9 @@ MinimumRecommendedRules.ruleset + + ..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll + ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll @@ -123,6 +128,8 @@ + + @@ -185,6 +192,7 @@ + @@ -208,13 +216,14 @@ - - Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Aktivieren Sie die Wiederherstellung von NuGet-Paketen, um die fehlende Datei herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". + 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}". - + + +