diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj
index 72695d8..031b21d 100644
--- a/ColorControl/ColorControl.csproj
+++ b/ColorControl/ColorControl.csproj
@@ -18,8 +18,8 @@
Maassoft
Maassoft
0
- 9.6.2.0
- 9.6.2.0
+ 9.6.3.0
+ 9.6.3.0
false
true
false
@@ -102,6 +102,7 @@
+
diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs
index 2c66fba..9dbb87e 100644
--- a/ColorControl/MainForm.Designer.cs
+++ b/ColorControl/MainForm.Designer.cs
@@ -136,7 +136,7 @@
chkModules.Name = "chkModules";
chkModules.Size = new System.Drawing.Size(507, 76);
chkModules.TabIndex = 0;
- chkModules.SelectedIndexChanged += chkModules_SelectedIndexChanged;
+ chkModules.ItemCheck += chkModules_ItemCheck;
//
// grpMiscellaneousOptions
//
diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs
index 919ec47..b2ce3c0 100644
--- a/ColorControl/MainForm.cs
+++ b/ColorControl/MainForm.cs
@@ -11,6 +11,7 @@ using ColorControl.Shared.Forms;
using ColorControl.Shared.Native;
using ColorControl.Shared.Services;
using ColorControl.XForms;
+using Linearstar.Windows.RawInput;
using Microsoft.Extensions.DependencyInjection;
using NLog;
using novideo_srgb;
@@ -70,7 +71,6 @@ namespace ColorControl
private GamePanel _gamePanel;
- //private KeyboardHookManager _keyboardHookManager;
private IntPtr _screenStateNotify;
private Dictionary _shortcuts = new();
@@ -80,6 +80,8 @@ namespace ColorControl
{
InitializeComponent();
+ KeyboardShortcutManager.MainHandle = Handle;
+
StartUpParams = appContextProvider.GetAppContext().StartUpParams;
appContextProvider.GetAppContext().SynchronizationContext = AsyncOperationManager.SynchronizationContext;
@@ -90,6 +92,8 @@ namespace ColorControl
LoadConfig();
+ KeyboardShortcutManager.SetUseRawInput(_config.UseRawInput);
+
LoadModules();
MessageForms.MainForm = this;
@@ -139,7 +143,7 @@ namespace ColorControl
chkFixChromeFonts.Checked = Utils.IsChromeFixInstalled();
}
- _shortcuts.Add(SHORTCUTID_SCREENSAVER, StartScreenSaver);
+ InitShortcut(SHORTCUTID_SCREENSAVER, _config.ScreenSaverShortcut, StartScreenSaver);
InitModules();
InitInfo();
@@ -322,7 +326,7 @@ namespace ColorControl
if (!string.IsNullOrEmpty(shortcut))
{
- Utils.RegisterShortcut(Handle, shortcutId, shortcut);
+ KeyboardShortcutManager.RegisterShortcut(shortcutId, shortcut);
}
}
@@ -341,14 +345,6 @@ namespace ColorControl
InitShortcut(LgPanel.SHORTCUTID_LGQA, _serviceManager.LgService.Config.QuickAccessShortcut, _serviceManager.LgService.ToggleQuickAccessForm);
return _lgPanel;
-
- // New shortcut manager, not working yet
- //if (_keyboardHookManager == null)
- //{
- // _keyboardHookManager = new KeyboardHookManager();
- // _keyboardHookManager.Start();
- //}
- //_keyboardHookManager.RegisterHotkey(NonInvasiveKeyboardHookLibrary.ModifierKeys.Control | NonInvasiveKeyboardHookLibrary.ModifierKeys.Alt, (int)Keys.F9, new Action(TestKey));
}
catch (Exception e)
{
@@ -383,16 +379,6 @@ namespace ColorControl
}
}
- private void TestKey()
- {
- BeginInvoke(async () =>
- {
- var preset = _serviceManager.LgService.GetPresets().FirstOrDefault(p => p.name == "Backlight 20");
-
- await _serviceManager.LgService.ApplyPreset(preset);
- });
- }
-
private void InitInfo()
{
_currentVersionInfo = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);
@@ -512,7 +498,7 @@ namespace ColorControl
// 5. Catch when a HotKey is pressed !
if (m.Msg == NativeConstants.WM_HOTKEY && !IsShortcutControlFocused())
{
- var id = m.WParam.ToInt32();
+ var id = (int)m.WParam;
if (_shortcuts.TryGetValue(id, out var action))
{
@@ -546,6 +532,16 @@ namespace ColorControl
}
}
}
+ else if (m.Msg == NativeConstants.WM_INPUT)
+ {
+ // Create an RawInputData from the handle stored in lParam.
+ var data = RawInputData.FromHandle(m.LParam);
+
+ if (data is RawInputKeyboardData keyboard)
+ {
+ KeyboardShortcutManager.HandleRawKeyboardInput(keyboard);
+ }
+ }
else if (m.Msg == NativeConstants.WM_QUERYENDSESSION)
{
SystemShutdown = true;
@@ -595,7 +591,7 @@ namespace ColorControl
private void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
@@ -659,11 +655,6 @@ namespace ColorControl
chkGdiScaling.Checked = _config.UseGdiScaling;
chkOptionsUseDarkMode.Checked = _config.UseDarkMode;
- if (!string.IsNullOrEmpty(_config.ScreenSaverShortcut))
- {
- Utils.RegisterShortcut(Handle, SHORTCUTID_SCREENSAVER, _config.ScreenSaverShortcut);
- }
-
_skipResize = true;
try
{
@@ -759,7 +750,7 @@ NOTE: installing the service may cause a User Account Control popup.");
private void edtShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
@@ -975,18 +966,14 @@ NOTE: installing the service may cause a User Account Control popup.");
{
var shortcut = edtBlankScreenSaverShortcut.Text.Trim();
- if (!Utils.ValidateShortcut(shortcut))
+ if (!KeyboardShortcutManager.ValidateShortcut(shortcut))
{
return;
}
- var oldShortcut = _config.ScreenSaverShortcut;
-
- var clear = !string.IsNullOrEmpty(oldShortcut);
-
_config.ScreenSaverShortcut = shortcut;
- Utils.RegisterShortcut(Handle, SHORTCUTID_SCREENSAVER, shortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_SCREENSAVER, shortcut);
}
private void chkMinimizeOnClose_CheckedChanged(object sender, EventArgs e)
@@ -1334,6 +1321,8 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
//Environment.Exit(0);
//InstallUpdate("");
//await Test();
+
+ //_serviceManager.NvService.TestResolution();
}
private async Task Test()
@@ -1393,23 +1382,6 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
}
}
- private void chkModules_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (!_initialized)
- {
- return;
- }
-
- for (var i = 0; i < chkModules.Items.Count; i++)
- {
- var item = chkModules.Items[i].ToString();
-
- var module = _config.Modules.First(m => m.DisplayName == item.ToString());
-
- module.IsActive = chkModules.GetItemChecked(i);
- }
- }
-
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if ((keyData == (Keys.Control | Keys.PageUp) || keyData == (Keys.Control | Keys.PageDown)) && IsShortcutControlFocused())
@@ -1420,7 +1392,7 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
{
var keyEvent = new KeyEventArgs(keyData);
- control.Text = Utils.FormatKeyboardShortcut(keyEvent);
+ control.Text = KeyboardShortcutManager.FormatKeyboardShortcut(keyEvent);
}
return true;
@@ -1451,8 +1423,15 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
MaxValue = 5000,
Value = _config.ProcessMonitorPollingInterval
};
+ var useRawInputField = new MessageForms.FieldDefinition
+ {
+ FieldType = MessageForms.FieldType.CheckBox,
+ Label = "Use Raw Input for shortcuts (hot keys)",
+ SubLabel = "This enables shortcuts to work during applications/games that block certain keys (like WinKey or Control). NOTE: if the application in the foreground runs with higher privileges than ColorControl, Raw Input does not work and normal hot keys are used",
+ Value = _config.UseRawInput
+ };
- var values = MessageForms.ShowDialog("Advanced settings", new[] { processPollingIntervalField });
+ var values = MessageForms.ShowDialog("Advanced settings", new[] { processPollingIntervalField, useRawInputField });
if (values?.Any() != true)
{
@@ -1460,11 +1439,32 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
}
_config.ProcessMonitorPollingInterval = processPollingIntervalField.ValueAsInt;
+ _config.UseRawInput = useRawInputField.ValueAsBool;
+
+ KeyboardShortcutManager.SetUseRawInput(_config.UseRawInput);
}
private void btnOptionsLog_Click(object sender, EventArgs e)
{
LogWindow.CreateAndShow();
}
+
+ private void chkModules_ItemCheck(object sender, ItemCheckEventArgs e)
+ {
+ if (chkModules.Items.Count != _config.Modules.Count)
+ {
+ return;
+ }
+
+ var index = e.Index;
+
+ if (index < 0)
+ {
+ return;
+ }
+
+ var module = _config.Modules[index];
+ module.IsActive = e.NewValue == CheckState.Checked;
+ }
}
}
\ No newline at end of file
diff --git a/ColorControl/NonInvasiveKeyboardHookLibrary/KeybindStruct.cs b/ColorControl/NonInvasiveKeyboardHookLibrary/KeybindStruct.cs
deleted file mode 100644
index 69f64a4..0000000
--- a/ColorControl/NonInvasiveKeyboardHookLibrary/KeybindStruct.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace NonInvasiveKeyboardHookLibrary
-{
- ///
- /// A struct to represent a keybind (key + modifiers)
- /// When the keybind struct is compared to another keybind struct, the equality is based on the
- /// modifiers and the virtual key code.
- ///
- internal class KeybindStruct : IEquatable
- {
- public readonly int VirtualKeyCode;
- public readonly List Modifiers;
- public readonly Guid? Identifier;
-
- public KeybindStruct(IEnumerable modifiers, int virtualKeyCode, Guid? identifier = null)
- {
- this.VirtualKeyCode = virtualKeyCode;
- this.Modifiers = new List(modifiers);
- this.Identifier = identifier;
- }
-
- public bool Equals(KeybindStruct other)
- {
- if (other == null)
- return false;
-
- if (this.VirtualKeyCode != other.VirtualKeyCode)
- return false;
-
- if (this.Modifiers.Count != other.Modifiers.Count)
- return false;
-
- foreach (var modifier in this.Modifiers)
- {
- if (!other.Modifiers.Contains(modifier))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public override bool Equals(object obj)
- {
- if (ReferenceEquals(null, obj)) return false;
- if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != this.GetType()) return false;
-
- return Equals((KeybindStruct) obj);
- }
-
- public override int GetHashCode()
- {
- var hash = 13;
- hash = (hash * 7) + VirtualKeyCode.GetHashCode();
-
- // Sum the modifiers separately, so that their order does not affect the final hash
- var modifiersHashSum = 0;
- foreach (var modifier in this.Modifiers)
- {
- modifiersHashSum += modifier.GetHashCode();
- }
-
- hash = (hash * 7) + modifiersHashSum;
-
- return hash;
- }
- }
-}
diff --git a/ColorControl/NonInvasiveKeyboardHookLibrary/KeyboardHookManager.cs b/ColorControl/NonInvasiveKeyboardHookLibrary/KeyboardHookManager.cs
deleted file mode 100644
index 74913b2..0000000
--- a/ColorControl/NonInvasiveKeyboardHookLibrary/KeyboardHookManager.cs
+++ /dev/null
@@ -1,330 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Runtime.InteropServices;
-
-namespace NonInvasiveKeyboardHookLibrary
-{
- internal struct KeyboardParams
- {
- public IntPtr wParam;
- public int vkCode;
-
- public KeyboardParams(IntPtr wParam, int vkCode)
- {
- this.wParam = wParam;
- this.vkCode = vkCode;
- }
- }
-
- ///
- /// A hotkey manager that uses a low-level global keyboard hook, but eventually only fires events for
- /// pre-registered hotkeys, i.e. not invading a user's privacy.
- ///
- public class KeyboardHookManager
- {
- #region Private Attributes
- ///
- /// Keeps track of all registered hotkeys
- ///
- private readonly Dictionary _registeredCallbacks;
- ///
- /// Keeps track of modifier keys that are held down
- ///
- private readonly HashSet _downModifierKeys;
- ///
- /// Keeps track of all keys that are held down to prevent firing callbacks
- /// more than once for a single keypress
- ///
- private readonly HashSet _downKeys;
- private readonly object _modifiersLock = new object();
- private LowLevelKeyboardProc _hook;
- private bool _isStarted;
- #endregion
-
- #region Constructors
- ///
- /// Instantiates an empty keyboard hook manager.
- /// It is best practice to keep a single instance per process.
- /// Start() must be called to start the low-level keyboard hook manager
- ///
- public KeyboardHookManager()
- {
- this._registeredCallbacks = new Dictionary();
- this._downModifierKeys = new HashSet();
- this._downKeys = new HashSet();
- }
- #endregion
-
- #region Public API
- ///
- /// Starts the low-level keyboard hook.
- /// Hotkeys can be registered regardless of the low-level keyboard hook's state, but their callbacks
- /// will only ever be invoked if the low-level keyboard hook is running and intercepting keys.
- ///
- public void Start()
- {
- if (this._isStarted) return;
-
- this._hook = this.HookCallback;
- _hookId = SetHook(this._hook);
- this._isStarted = true;
- }
-
- ///
- /// Pauses the low-level keyboard hook (without unregistering the existing hotkeys)
- ///
- public void Stop()
- {
- if (this._isStarted)
- {
- UnhookWindowsHookEx(_hookId);
- this._isStarted = false;
- }
- }
-
- ///
- /// Registers a hotkey.
- ///
- /// The virtual key code of the hotkey
- /// The callback action to invoke when this hotkey is pressed
- /// Thrown when the given key is already mapped to a callback
- /// /// Unique identifier of this hotkey, which can be used to remove it later
- public Guid RegisterHotkey(int virtualKeyCode, Action action)
- {
- return this.RegisterHotkey(new ModifierKeys[0], virtualKeyCode, action);
- }
-
- ///
- /// Registers a new key combination with one or more modifiers
- ///
- /// Modifiers that must be held while hitting the key. Multiple modifiers can be provided using the flags bitwise OR operation
- /// The virtual key code of the standard key
- /// The callback action to invoke when this combination is pressed
- /// Thrown when the given key combination is already mapped to a callback
- /// Unique identifier of this hotkey, which can be used to remove it later
- public Guid RegisterHotkey(ModifierKeys modifiers, int virtualKeyCode, Action action)
- {
- var allModifiers = Enum.GetValues(typeof(ModifierKeys)).Cast().ToArray();
-
- // Get the modifiers that were chained with bitwise OR operation as an array of modifiers
- var selectedModifiers = allModifiers.Where(modifier => modifiers.HasFlag(modifier)).ToArray();
-
- return RegisterHotkey(selectedModifiers, virtualKeyCode, action);
- }
-
- ///
- /// Registers a new key combination.
- ///
- /// Modifiers that must be held while hitting the key
- /// The virtual key code of the standard key
- /// The callback action to invoke when this combination is pressed
- /// Thrown when the given key combination is already mapped to a callback
- /// Unique identifier of this hotkey, which can be used to remove it later
- public Guid RegisterHotkey(ModifierKeys[] modifiers, int virtualKeyCode, Action action)
- {
- var keybindIdentity = Guid.NewGuid();
- var keybind = new KeybindStruct(modifiers, virtualKeyCode, keybindIdentity);
- if (this._registeredCallbacks.ContainsKey(keybind))
- {
- throw new HotkeyAlreadyRegisteredException();
- }
-
- this._registeredCallbacks[keybind] = action;
- return keybindIdentity;
- }
-
- ///
- /// Unregisters all hotkeys (the low-level keyboard hook continues running)
- ///
- public void UnregisterAll()
- {
- this._registeredCallbacks.Clear();
- }
-
- ///
- /// Unregisters a specific single-key hotkey
- ///
- /// Virtual key code of the unregistered key
- /// Thrown when the given key combination is not registered
- public void UnregisterHotkey(int virtualKeyCode)
- {
- this.UnregisterHotkey(new ModifierKeys[0], virtualKeyCode);
- }
-
- ///
- /// Unregisters a specific key combination
- ///
- /// The modifiers of the combination
- /// The key of the combination
- /// Thrown when the given key combination is not registered
- public void UnregisterHotkey(ModifierKeys[] modifiers, int virtualKeyCode)
- {
- var keybind = new KeybindStruct(modifiers, virtualKeyCode);
-
- if (!this._registeredCallbacks.Remove(keybind))
- {
- throw new HotkeyNotRegisteredException();
- }
- }
-
- ///
- /// Unregisters a specific key by its unique identifier
- ///
- /// Keybind GUID, as returned by RegisterHotkey
- public void UnregisterHotkey(Guid keybindIdentity)
- {
- var keybindToRemove = this._registeredCallbacks.Keys.FirstOrDefault(keybind =>
- keybind.Identifier.HasValue && keybind.Identifier.Value.Equals(keybindIdentity));
-
- if (keybindToRemove == null || !this._registeredCallbacks.Remove(keybindToRemove))
- {
- throw new HotkeyNotRegisteredException();
- }
- }
- #endregion
-
- #region Private methods
- private void HandleKeyPress(int virtualKeyCode)
- {
- var currentKey = new KeybindStruct(this._downModifierKeys, virtualKeyCode);
-
- if (!this._registeredCallbacks.ContainsKey(currentKey))
- {
- return;
- }
-
- if (this._registeredCallbacks.TryGetValue(currentKey, out var callback))
- {
- callback.Invoke();
- }
- }
- #endregion
-
- #region Low level keyboard hook
- // Source: https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
- private const int WH_KEYBOARD_LL = 13;
- private const int WM_KEYDOWN = 0x0100;
- private const int WM_KEYUP = 0x0101;
- private const int WM_SYSKEYDOWN = 0x0104;
- private const int WM_SYSKEYUP = 0x0105;
-
- private static IntPtr _hookId = IntPtr.Zero;
-
- private static IntPtr SetHook(LowLevelKeyboardProc proc)
- {
- var userLibrary = LoadLibrary("User32");
-
- return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
- userLibrary, 0);
- }
-
- private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
- {
- if (nCode >= 0)
- {
- var vkCode = Marshal.ReadInt32(lParam);
-
- // Debug.WriteLine("Starting");
- // To prevent slowing keyboard input down, we use handle keyboard inputs in a separate thread
- //ThreadPool.QueueUserWorkItem(this.HandleSingleKeyboardInput, new KeyboardParams(wParam, vkCode));
- // Debug.WriteLine("Ending");
-
- HandleSingleKeyboardInput(new KeyboardParams(wParam, vkCode));
-
- //return IntPtr.Zero;
- }
-
- return CallNextHookEx(_hookId, nCode, wParam, lParam);
- }
-
- ///
- /// Handles a keyboard event based on the KeyboardParams it receives
- ///
- /// KeyboardParams struct (object type to comply with QueueUserWorkItem)
- private void HandleSingleKeyboardInput(object keyboardParamsObj)
- {
- var keyboardParams = (KeyboardParams)keyboardParamsObj;
- var wParam = keyboardParams.wParam;
- var vkCode = keyboardParams.vkCode;
-
- var modifierKey = ModifierKeysUtilities.GetModifierKeyFromCode(vkCode);
-
- Debug.WriteLine("Modifiers: " + string.Join("+", _downModifierKeys) + ", ModKey: " + modifierKey + ", Key: " + vkCode);
-
- // If the keyboard event is a KeyDown event (i.e. key pressed)
- if (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
- {
- // In this case, we only care about modifier keys
- if (modifierKey != null)
- {
- lock (this._modifiersLock)
- {
- this._downModifierKeys.Add(modifierKey.Value);
- }
- }
-
- // Trigger callbacks that are registered for this key, but only once per key press
- if (!this._downKeys.Contains(vkCode))
- {
- this.HandleKeyPress(vkCode);
- this._downKeys.Add(vkCode);
- }
- }
-
- // If the keyboard event is a KeyUp event (i.e. key released)
- if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
- {
- // If the released key is a modifier key, remove it from the HashSet of modifier keys
- if (modifierKey != null)
- {
- lock (this._modifiersLock)
- {
- this._downModifierKeys.Remove(modifierKey.Value);
- }
- }
-
- this._downKeys.Remove(vkCode);
- }
- }
-
- private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- private static extern IntPtr SetWindowsHookEx(int idHook,
- LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool UnhookWindowsHookEx(IntPtr hhk);
-
-
- [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
- IntPtr wParam, IntPtr lParam);
-
- ///
- /// Loads the library.
- ///
- /// Name of the library
- /// A handle to the library
- [DllImport("kernel32.dll")]
- private static extern IntPtr LoadLibrary(string lpFileName);
- #endregion
- }
-
- #region Exceptions
- public class NonInvasiveKeyboardHookException : Exception
- {
- }
-
- public class HotkeyAlreadyRegisteredException : NonInvasiveKeyboardHookException
- {
- }
-
- public class HotkeyNotRegisteredException : NonInvasiveKeyboardHookException
- {
- }
- #endregion
-}
diff --git a/ColorControl/NonInvasiveKeyboardHookLibrary/ModifierKeys.cs b/ColorControl/NonInvasiveKeyboardHookLibrary/ModifierKeys.cs
deleted file mode 100644
index 9413bd0..0000000
--- a/ColorControl/NonInvasiveKeyboardHookLibrary/ModifierKeys.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-
-namespace NonInvasiveKeyboardHookLibrary
-{
- [Flags]
- public enum ModifierKeys
- {
- Alt = 1,
- Control = 2,
- Shift = 4,
- WindowsKey = 8,
- }
-
- public static class ModifierKeysUtilities
- {
- public static ModifierKeys? GetModifierKeyFromCode(int keyCode)
- {
- switch (keyCode)
- {
- case 0xA0:
- case 0xA1:
- case 0x10:
- return ModifierKeys.Shift;
-
- case 0xA2:
- case 0xA3:
- case 0x11:
- return ModifierKeys.Control;
-
- case 0x12:
- case 0xA4:
- case 0xA5:
- return ModifierKeys.Alt;
-
- case 0x5B:
- case 0x5C:
- return ModifierKeys.WindowsKey;
-
- default:
- return null;
- }
- }
- }
-}
diff --git a/ColorControl/Services/AMD/AmdPanel.cs b/ColorControl/Services/AMD/AmdPanel.cs
index 51109b5..db5973d 100644
--- a/ColorControl/Services/AMD/AmdPanel.cs
+++ b/ColorControl/Services/AMD/AmdPanel.cs
@@ -55,7 +55,7 @@ namespace ColorControl.Services.AMD
foreach (var preset in _amdService.GetPresets())
{
AddOrUpdateItemAmd(preset);
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut);
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
}
@@ -171,12 +171,12 @@ namespace ColorControl.Services.AMD
private void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void edtShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private AmdPreset GetSelectedAmdPreset()
@@ -276,7 +276,7 @@ namespace ColorControl.Services.AMD
{
var shortcut = edtAmdShortcut.Text.Trim();
- if (!Utils.ValidateShortcut(shortcut))
+ if (!KeyboardShortcutManager.ValidateShortcut(shortcut))
{
return;
}
@@ -297,15 +297,13 @@ namespace ColorControl.Services.AMD
return;
}
- var clear = !string.IsNullOrEmpty(preset.shortcut);
-
preset.shortcut = shortcut;
preset.name = name;
preset.ShowInQuickAccess = chkAmdQuickAccess.Checked;
AddOrUpdateItemAmd();
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
private void btnCloneAmd_Click(object sender, EventArgs e)
@@ -607,11 +605,9 @@ namespace ColorControl.Services.AMD
return;
}
- var clear = !string.IsNullOrEmpty(_config.AmdQuickAccessShortcut);
-
_config.AmdQuickAccessShortcut = shortcut;
- Utils.RegisterShortcut(_mainHandle, SHORTCUTID_AMDQA, _config.AmdQuickAccessShortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_AMDQA, _config.AmdQuickAccessShortcut);
}
private void lvLgPresets_ColumnClick(object sender, ColumnClickEventArgs e)
diff --git a/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs b/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs
index 9d15633..f24ef92 100644
--- a/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs
+++ b/ColorControl/Services/EventDispatcher/ProcessEventDispatcher.cs
@@ -75,6 +75,7 @@ namespace ColorControl.Services.EventDispatcher
}
await DispatchEventAsync(Event_ProcessChanged, MonitorContext);
+ DispatchEvent(Event_ProcessChanged, MonitorContext);
}
catch (Exception ex)
{
diff --git a/ColorControl/Services/GameLauncher/GamePanel.cs b/ColorControl/Services/GameLauncher/GamePanel.cs
index 7dc74e2..7b6cc5d 100644
--- a/ColorControl/Services/GameLauncher/GamePanel.cs
+++ b/ColorControl/Services/GameLauncher/GamePanel.cs
@@ -59,7 +59,7 @@ namespace ColorControl.Services.GameLauncher
foreach (var preset in _gameService.GetPresets())
{
AddOrUpdateItemGame(preset);
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut);
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
}
@@ -75,12 +75,12 @@ namespace ColorControl.Services.GameLauncher
private void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void edtShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private GamePreset GetSelectedGamePreset()
@@ -214,7 +214,7 @@ namespace ColorControl.Services.GameLauncher
private void SaveGamePreset()
{
var shortcut = string.Empty;
- if (!Utils.ValidateShortcut(shortcut))
+ if (!KeyboardShortcutManager.ValidateShortcut(shortcut))
{
return;
}
@@ -235,13 +235,7 @@ namespace ColorControl.Services.GameLauncher
preset.RunAsAdministrator = chkGameRunAsAdmin.Checked;
preset.ShowInQuickAccess = chkGameQuickAccess.Checked;
- var clear = !string.IsNullOrEmpty(preset.shortcut);
-
- var shortcutChanged = !shortcut.Equals(preset.shortcut);
- if (shortcutChanged)
- {
- preset.shortcut = shortcut;
- }
+ preset.shortcut = shortcut;
var text = edtGamePrelaunchSteps.Text;
@@ -257,10 +251,7 @@ namespace ColorControl.Services.GameLauncher
AddOrUpdateItemGame();
- if (shortcutChanged)
- {
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut, clear);
- }
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
private void btnGameBrowse_Click(object sender, EventArgs e)
@@ -377,11 +368,9 @@ namespace ColorControl.Services.GameLauncher
return;
}
- var clear = !string.IsNullOrEmpty(_config.GameQuickAccessShortcut);
-
_config.GameQuickAccessShortcut = shortcut;
- Utils.RegisterShortcut(_mainHandle, SHORTCUTID_GAMEQA, _config.GameQuickAccessShortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_GAMEQA, _config.GameQuickAccessShortcut);
}
private void mnuGameActions_Opening(object sender, CancelEventArgs e)
diff --git a/ColorControl/Services/LG/LgPanel.cs b/ColorControl/Services/LG/LgPanel.cs
index 1571773..31f05a1 100644
--- a/ColorControl/Services/LG/LgPanel.cs
+++ b/ColorControl/Services/LG/LgPanel.cs
@@ -111,12 +111,12 @@ namespace ColorControl.Services.LG
private void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void edtShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private void FillLgPresets()
@@ -126,7 +126,7 @@ namespace ColorControl.Services.LG
foreach (var preset in _lgService.GetPresets())
{
AddOrUpdateItemLg(preset);
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut);
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
}
@@ -241,7 +241,7 @@ namespace ColorControl.Services.LG
private void btnSetShortcutLg_Click(object sender, EventArgs e)
{
var shortcut = edtShortcutLg.Text.Trim();
- if (!Utils.ValidateShortcut(shortcut))
+ if (!KeyboardShortcutManager.ValidateShortcut(shortcut))
{
return;
}
@@ -288,11 +288,7 @@ namespace ColorControl.Services.LG
edtLgPresetIncludedProcesses.Text,
edtLgPresetExcludedProcesses.Text);
- var shortcutChanged = !shortcut.Equals(preset.shortcut);
- if (shortcutChanged)
- {
- preset.shortcut = shortcut;
- }
+ preset.shortcut = shortcut;
var text = edtStepsLg.Text;
@@ -300,10 +296,7 @@ namespace ColorControl.Services.LG
AddOrUpdateItemLg();
- if (shortcutChanged)
- {
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut, clear);
- }
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
public void UpdateInfo()
@@ -737,7 +730,6 @@ You can also activate this option by using the Expert-button and selecting Wake-
var form = MessageForms.ShowProgress("Connecting to device...");
var result = false;
- Enabled = false;
try
{
result = await device.TestConnection();
@@ -745,7 +737,6 @@ You can also activate this option by using the Expert-button and selecting Wake-
finally
{
form.Close();
- Enabled = true;
}
if (!result && MessageForms.QuestionYesNo("Unable to connect to the device. Are you sure you want to add it?") != DialogResult.Yes)
@@ -1083,12 +1074,12 @@ Do you want to continue?"
private void edtLgGameBarShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void edtLgGameBarShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private void btnLgDeviceOptionsHelp_Click(object sender, EventArgs e)
@@ -1230,11 +1221,10 @@ Do you want to continue?";
_lgService.Config.ShutdownDelay = values[1].ValueAsInt;
var shortcutQA = values[2].Value.ToString();
- var clear = !string.IsNullOrEmpty(_lgService.Config.QuickAccessShortcut);
_lgService.Config.QuickAccessShortcut = shortcutQA;
- Utils.RegisterShortcut(_mainHandle, SHORTCUTID_LGQA, _lgService.Config.QuickAccessShortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_LGQA, _lgService.Config.QuickAccessShortcut);
var shortcutGB = values[3].Value.ToString();
_lgService.Config.GameBarShortcut = shortcutGB;
@@ -1245,7 +1235,7 @@ Do you want to continue?";
}
else
{
- Utils.RegisterShortcut(_mainHandle, SHORTCUTID_GAMEBAR, shortcutGB);
+ KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_GAMEBAR, shortcutGB);
}
_lgService.Config.ShowAdvancedActions = values[4].ValueAsBool;
diff --git a/ColorControl/Services/NVIDIA/NvPanel.cs b/ColorControl/Services/NVIDIA/NvPanel.cs
index bad49be..7a88f60 100644
--- a/ColorControl/Services/NVIDIA/NvPanel.cs
+++ b/ColorControl/Services/NVIDIA/NvPanel.cs
@@ -112,7 +112,7 @@ namespace ColorControl.Services.NVIDIA
foreach (var preset in _nvService.GetPresets())
{
AddOrUpdateItem(preset);
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut);
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
}
@@ -982,14 +982,14 @@ namespace ColorControl.Services.NVIDIA
private void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void btnSetShortcut_Click(object sender, EventArgs e)
{
var shortcut = edtShortcut.Text.Trim();
- if (!Utils.ValidateShortcut(shortcut))
+ if (!KeyboardShortcutManager.ValidateShortcut(shortcut))
{
return;
}
@@ -1010,20 +1010,18 @@ namespace ColorControl.Services.NVIDIA
return;
}
- var clear = !string.IsNullOrEmpty(preset.shortcut);
-
preset.shortcut = shortcut;
preset.name = name;
preset.ShowInQuickAccess = chkNvShowInQuickAccess.Checked;
AddOrUpdateItem();
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
private void edtShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private void edtShortcut_TextChanged(object sender, EventArgs e)
@@ -1236,11 +1234,9 @@ namespace ColorControl.Services.NVIDIA
var shortcut = (string)quickAccessField.Value;
- var clear = !string.IsNullOrEmpty(_config.NvQuickAccessShortcut);
-
_config.NvQuickAccessShortcut = shortcut;
- Utils.RegisterShortcut(_mainHandle, SHORTCUTID_NVQA, _config.NvQuickAccessShortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_NVQA, _config.NvQuickAccessShortcut);
_nvService.Config.ShowOverclocking = enableOcField.ValueAsBool;
_nvService.Config.ApplyNovideoOnStartup = enableNovideoField.ValueAsBool;
diff --git a/ColorControl/Services/NVIDIA/NvService.cs b/ColorControl/Services/NVIDIA/NvService.cs
index 116617d..787cc89 100644
--- a/ColorControl/Services/NVIDIA/NvService.cs
+++ b/ColorControl/Services/NVIDIA/NvService.cs
@@ -13,6 +13,7 @@ using NvAPIWrapper.Display;
using NvAPIWrapper.GPU;
using NvAPIWrapper.Native;
using NvAPIWrapper.Native.Display;
+using NvAPIWrapper.Native.Display.Structures;
using NvAPIWrapper.Native.GPU.Structures;
using NWin32;
using NWin32.NativeTypes;
@@ -769,6 +770,49 @@ namespace ColorControl.Services.NVIDIA
return info.HasValue ? info.Value.ContentType : InfoFrameVideoContentType.Auto;
}
+ public void TestResolution()
+ {
+ var display = GetCurrentDisplay();
+ var displayDevice = display.DisplayDevice;
+
+ //var timing = displayDevice.CurrentTiming;
+
+ //var res = new CustomResolution(3840, 2160, ColorFormat.A8R8G8B8, timing);
+
+ //displayDevice.TrialCustomResolution(res);
+
+ var info = displayDevice.HDMIVideoFrameOverrideInformation ?? displayDevice.HDMIVideoFrameCurrentInformation;
+
+ if (info.HasValue)
+ {
+ var infoValue = info.Value;
+
+ var newInfo = new InfoFrameVideo(
+ infoValue.VideoIdentificationCode.Value,
+ InfoFrameVideoPixelRepetition.None,
+ infoValue.ColorFormat,
+ InfoFrameVideoColorimetry.UseExtendedColorimetry,
+ InfoFrameVideoExtendedColorimetry.BT2020,
+ infoValue.RGBQuantization,
+ infoValue.YCCQuantization,
+ InfoFrameVideoITC.ITContent,
+ infoValue.ContentType,
+ InfoFrameVideoScanInfo.NoData,
+ InfoFrameBoolean.Auto,
+ InfoFrameVideoAspectRatioActivePortion.Auto,
+ InfoFrameVideoAspectRatioCodedFrame.Auto,
+ InfoFrameVideoNonUniformPictureScaling.NoData,
+ InfoFrameVideoBarData.NotPresent,
+ null,
+ null,
+ null,
+ null
+ );
+
+ displayDevice.SetHDMIVideoFrameInformation(newInfo, true);
+ }
+ }
+
public Display[] GetDisplays()
{
return Display.GetDisplays();
diff --git a/ColorControl/Services/Samsung/SamTvConnection.cs b/ColorControl/Services/Samsung/SamTvConnection.cs
index b1b3706..3ebebcb 100644
--- a/ColorControl/Services/Samsung/SamTvConnection.cs
+++ b/ColorControl/Services/Samsung/SamTvConnection.cs
@@ -47,7 +47,6 @@ namespace ColorControl.Services.Samsung
{
_connection?.Dispose();
- ConnectionClosed = false;
_commandCount = 0;
// Not creating the web socket from main thread can cause a stackoverflow in combase32.dll
@@ -64,6 +63,8 @@ namespace ColorControl.Services.Samsung
{
await _connection.ConnectAsync(uri).AsTask().WaitAsync(TimeSpan.FromSeconds(5));
+ ConnectionClosed = false;
+
_messageWriter = new DataWriter(_connection.OutputStream);
return true;
diff --git a/ColorControl/Services/Samsung/SamsungDevice.cs b/ColorControl/Services/Samsung/SamsungDevice.cs
index a69e777..b454c33 100644
--- a/ColorControl/Services/Samsung/SamsungDevice.cs
+++ b/ColorControl/Services/Samsung/SamsungDevice.cs
@@ -1,5 +1,6 @@
using ColorControl.Services.Common;
using ColorControl.Shared.Common;
+using ColorControl.Shared.Forms;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using NLog;
@@ -39,6 +40,11 @@ namespace ColorControl.Services.Samsung
External
}
+ public enum ServiceMenuType
+ {
+ Default,
+ }
+
public delegate void GenericDelegate(object sender);
class SamsungDevice
@@ -107,6 +113,7 @@ namespace ColorControl.Services.Samsung
IsDummy = isDummy;
AddInvokableAction("WOL", WakeAction);
+ AddInvokableAction("ServiceMenu", ServiceMenuAction, true);
AddInternalPresetAction(new SamsungPreset("PictureOff", null, new[] { "KEY_AD:1200", "KEY_DOWN:300", "KEY_DOWN:300", "KEY_ENTER" }));
AddInternalPresetAction(new SamsungPreset("PictureOn", null, new[] { "KEY_RETURN:1000", "KEY_RETURN", "KEY_RETURN" }));
@@ -260,7 +267,7 @@ namespace ColorControl.Services.Samsung
{
try
{
- var result = Utils.PingHost(IpAddress);
+ var result = await Utils.PingHost(IpAddress);
Logger.Debug($"Ping result: {result}");
@@ -353,7 +360,7 @@ namespace ColorControl.Services.Samsung
internal async Task TestConnectionAsync()
{
- var result = Utils.PingHost(IpAddress);
+ var result = await Utils.PingHost(IpAddress);
if (result)
{
@@ -463,8 +470,9 @@ namespace ColorControl.Services.Samsung
var keySpec = step.Split(':');
var delay = config.DefaultButtonDelay;
+ var cmd = "Click";
var key = step;
- if (keySpec.Length == 2)
+ if (keySpec.Length >= 2)
{
delay = Utils.ParseInt(keySpec[1]);
if (delay > 0)
@@ -472,6 +480,10 @@ namespace ColorControl.Services.Samsung
key = keySpec[0];
}
}
+ if (keySpec.Length >= 3)
+ {
+ cmd = keySpec[2];
+ }
var index = key.IndexOf("(");
string[] parameters = null;
@@ -498,7 +510,7 @@ namespace ColorControl.Services.Samsung
if (executeKey)
{
- await SendKeyAsync(key);
+ await SendKeyAsync(key, cmd);
delay = delay == 0 ? config.DefaultButtonDelay : delay;
}
@@ -509,7 +521,7 @@ namespace ColorControl.Services.Samsung
}
}
- private async Task ExecuteActionAsync(InvokableAction action, string[] parameters, Shared.Common.AppContext appContext, SamsungServiceConfig config)
+ public async Task ExecuteActionAsync(InvokableAction action, string[] parameters, Shared.Common.AppContext appContext, SamsungServiceConfig config)
{
if (action.Preset != null)
{
@@ -517,13 +529,17 @@ namespace ColorControl.Services.Samsung
return;
}
+ if (action.AsyncFunction != null)
+ {
+ await action.AsyncFunction(null);
+ }
}
- private async Task SendKeyAsync(string key)
+ private async Task SendKeyAsync(string key, string cmd = "Click")
{
var dynamic = new
{
- Cmd = "Click",
+ Cmd = cmd,
DataOfCmd = key,
Option = "false",
TypeOfRemote = "SendRemoteKey"
@@ -620,15 +636,27 @@ namespace ColorControl.Services.Samsung
internal async Task> GetAppsAsync(bool force)
{
- var dynamic = new
+ var messages = new List
{
- @event = "ed.installedApp.get",
- to = "host",
+ new RequestMessage("ms.channel.emit", new
+ {
+ data = "",
+ @event = "ed.edenApp.get",
+ to = "host",
+ }),
+ //new RequestMessage("ms.channel.emit", new
+ //{
+ // data = "",
+ // @event = "ed.installedApp.get",
+ // to = "host",
+ //})
};
- var message = new RequestMessage("ms.channel.emit", dynamic);
+ foreach (var message in messages)
+ {
+ var result = await _samTvConnection.SendCommandAsync(message, true);
+ }
- var result = await _samTvConnection.SendCommandAsync(message, true);
return new List();
}
@@ -644,14 +672,15 @@ namespace ColorControl.Services.Samsung
_invokableActions.Add(action);
}
- private void AddInvokableAction(string name, Func, Task> function)
+ private void AddInvokableAction(string name, Func, Task> function, bool advanced = false)
{
var action = new InvokableAction
{
Name = name,
AsyncFunction = function,
Category = "misc",
- Title = name
+ Title = name,
+ Advanced = advanced
};
_invokableActions.Add(action);
@@ -659,13 +688,93 @@ namespace ColorControl.Services.Samsung
internal IEnumerable GetInvokableActions(bool showAdvanced)
{
- return _invokableActions;
+ return _invokableActions.Where(a => showAdvanced || !a.Advanced);
}
private async Task WakeAction(Dictionary _)
{
return await WakeAndConnect();
}
+
+ private async Task ServiceMenuAction(Dictionary _)
+ {
+ var preset1 = new SamsungPreset("ServiceMenuStep1", null, new[] { "KEY_MUTE:600", "KEY_1:600", "KEY_1:600", "KEY_9:600", "KEY_ENTER:2000" });
+ var preset2 = new SamsungPreset("ServiceMenuStep2", null, new[] { "KEY_1", "KEY_2", "KEY_3", "KEY_4", "KEY_UP" });
+ var preset3 = new SamsungPreset("ServiceMenuStep3", null, new[] { "KEY_VOLUP:5100:Press", "KEY_VOLUP:500:Release" });
+ var rebootPreset = new SamsungPreset("ServiceMenuStep4", null, new[] { "KEY_POWER:5000", "WOL" });
+
+ var serviceMenuTypes = new[] { ServiceMenuType.Default }.Select(t => Utils.GetDescription(t));
+
+ if (!MessageForms.ShowDialog($"Access Service Menu", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = "Service Menu Type",
+ SubLabel = "'Default' will not reset your settings. Click 'Next >' to continue or 'X' to stop",
+ FieldType = MessageForms.FieldType.DropDown,
+ Values = serviceMenuTypes,
+ Value = ServiceMenuType.Default
+ } }, okButtonText: "Next >").Any())
+ {
+ return true;
+ }
+
+ await ExecutePresetWithProgressAsync(preset1, "Step 1: opening Service Menu. It is normal to see messages like 'Not Available'.");
+
+ if (!MessageForms.ShowDialog($"Access Service Menu - Step 2", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = "Service Menu opened?",
+ SubLabel = "If the menu is opened with the 'Hospitality Mode' item highlighted and the rest disabled, click 'Next >' to continue or 'X' to stop",
+ FieldType = MessageForms.FieldType.Label
+ } }, okButtonText: "Next >").Any())
+ {
+ return true;
+ }
+
+ await ExecutePresetWithProgressAsync(preset2, "Step 2: accessing Service Menu...");
+
+ var values = MessageForms.ShowDialog($"Access Service Menu - Step 3", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = "Service Menu - Advanced",
+ SubLabel = "If the 'Advanced' item is highlighted and you want to access these settings, click 'Next >' or click 'X' to skip",
+ FieldType = MessageForms.FieldType.Label
+ } }, okButtonText: "Next >");
+
+ if (values.Any())
+ {
+ await ExecutePresetWithProgressAsync(preset3, "Step 3: accessing Advanced Service Menu...");
+ }
+
+ if (!MessageForms.ShowDialog($"Reboot TV - Final Step", new[] {
+ new MessageForms.FieldDefinition
+ {
+ Label = "Reboot TV",
+ SubLabel = "After you have made the necessary changes, click 'Reboot TV' to reboot the TV or click 'X' to close. If the TV turns not back on automatically, power it on manually.",
+ FieldType = MessageForms.FieldType.Label
+ } }, okButtonText: "Reboot TV").Any())
+ {
+ return true;
+ }
+
+ await ExecutePresetWithProgressAsync(rebootPreset, "Final Step: rebooting TV...");
+
+ return true;
+ }
+
+ private async Task ExecutePresetWithProgressAsync(SamsungPreset preset, string text)
+ {
+ var progressForm = MessageForms.ShowProgress(text);
+ try
+ {
+ //await Task.Delay(5000);
+ await ExecutePresetAsync(preset);
+ }
+ finally
+ {
+ progressForm.Close();
+ }
+ }
}
}
diff --git a/ColorControl/Services/Samsung/SamsungPanel.Designer.cs b/ColorControl/Services/Samsung/SamsungPanel.Designer.cs
index d87a506..5a53199 100644
--- a/ColorControl/Services/Samsung/SamsungPanel.Designer.cs
+++ b/ColorControl/Services/Samsung/SamsungPanel.Designer.cs
@@ -30,6 +30,8 @@
{
components = new System.ComponentModel.Container();
scSamsungController = new System.Windows.Forms.SplitContainer();
+ btnExpert = new System.Windows.Forms.Button();
+ mnuExpert = new System.Windows.Forms.ContextMenuStrip(components);
btnSamsungDeviceOptionsSettings = new System.Windows.Forms.Button();
btnSamsungSettings = new System.Windows.Forms.Button();
chkSamsungQuickAccess = new System.Windows.Forms.CheckBox();
@@ -85,9 +87,11 @@
mnuLgSettings = new System.Windows.Forms.ContextMenuStrip(components);
miTestPowerOffOn = new System.Windows.Forms.ToolStripMenuItem();
miNvSettings = new System.Windows.Forms.ToolStripMenuItem();
+ miExpertDummy = new System.Windows.Forms.ToolStripMenuItem();
((System.ComponentModel.ISupportInitialize)scSamsungController).BeginInit();
scSamsungController.Panel1.SuspendLayout();
scSamsungController.SuspendLayout();
+ mnuExpert.SuspendLayout();
mnuLgButtons.SuspendLayout();
mnuLgSettings.SuspendLayout();
SuspendLayout();
@@ -101,6 +105,7 @@
//
// scSamsungController.Panel1
//
+ scSamsungController.Panel1.Controls.Add(btnExpert);
scSamsungController.Panel1.Controls.Add(btnSamsungDeviceOptionsSettings);
scSamsungController.Panel1.Controls.Add(btnSamsungSettings);
scSamsungController.Panel1.Controls.Add(chkSamsungQuickAccess);
@@ -154,6 +159,26 @@
scSamsungController.SplitterWidth = 5;
scSamsungController.TabIndex = 43;
//
+ // btnExpert
+ //
+ btnExpert.ContextMenuStrip = mnuExpert;
+ btnExpert.Location = new System.Drawing.Point(382, 39);
+ btnExpert.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ btnExpert.Name = "btnExpert";
+ btnExpert.Size = new System.Drawing.Size(88, 27);
+ btnExpert.TabIndex = 66;
+ btnExpert.Text = "Expert...";
+ btnExpert.UseVisualStyleBackColor = true;
+ btnExpert.Click += btnExpert_Click;
+ //
+ // mnuExpert
+ //
+ mnuExpert.ImageScalingSize = new System.Drawing.Size(20, 20);
+ mnuExpert.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miExpertDummy });
+ mnuExpert.Name = "mnuLgButtons";
+ mnuExpert.Size = new System.Drawing.Size(181, 48);
+ mnuExpert.Opening += mnuExpert_Opening;
+ //
// btnSamsungDeviceOptionsSettings
//
btnSamsungDeviceOptionsSettings.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
@@ -762,6 +787,12 @@
miNvSettings.Text = "Settings";
miNvSettings.Click += miNvSettings_Click;
//
+ // miExpertDummy
+ //
+ miExpertDummy.Name = "miExpertDummy";
+ miExpertDummy.Size = new System.Drawing.Size(180, 22);
+ miExpertDummy.Text = "Dummy";
+ //
// SamsungPanel
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
@@ -774,6 +805,7 @@
scSamsungController.Panel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)scSamsungController).EndInit();
scSamsungController.ResumeLayout(false);
+ mnuExpert.ResumeLayout(false);
mnuLgButtons.ResumeLayout(false);
mnuLgSettings.ResumeLayout(false);
ResumeLayout(false);
@@ -837,5 +869,8 @@
private System.Windows.Forms.ToolStripMenuItem miTestPowerOffOn;
private System.Windows.Forms.ToolStripMenuItem miNvSettings;
private System.Windows.Forms.Button btnSamsungDeviceOptionsSettings;
+ private System.Windows.Forms.Button btnExpert;
+ private System.Windows.Forms.ContextMenuStrip mnuExpert;
+ private System.Windows.Forms.ToolStripMenuItem miExpertDummy;
}
}
diff --git a/ColorControl/Services/Samsung/SamsungPanel.cs b/ColorControl/Services/Samsung/SamsungPanel.cs
index 7eff30e..4bdfe46 100644
--- a/ColorControl/Services/Samsung/SamsungPanel.cs
+++ b/ColorControl/Services/Samsung/SamsungPanel.cs
@@ -109,12 +109,12 @@ namespace ColorControl.Services.Samsung
private void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void edtShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private void FillPresets()
@@ -124,7 +124,7 @@ namespace ColorControl.Services.Samsung
foreach (var preset in _samsungService.GetPresets())
{
AddOrUpdateItem(preset);
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut);
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
}
@@ -239,7 +239,7 @@ namespace ColorControl.Services.Samsung
private void btnSetShortcutLg_Click(object sender, EventArgs e)
{
var shortcut = edtShortcutLg.Text.Trim();
- if (!Utils.ValidateShortcut(shortcut))
+ if (!KeyboardShortcutManager.ValidateShortcut(shortcut))
{
return;
}
@@ -286,11 +286,7 @@ namespace ColorControl.Services.Samsung
edtSamsungPresetIncludedProcesses.Text,
edtSamsungPresetExcludedProcesses.Text);
- var shortcutChanged = !shortcut.Equals(preset.shortcut);
- if (shortcutChanged)
- {
- preset.shortcut = shortcut;
- }
+ preset.shortcut = shortcut;
var text = edtStepsLg.Text;
@@ -298,10 +294,7 @@ namespace ColorControl.Services.Samsung
AddOrUpdateItem();
- if (shortcutChanged)
- {
- Utils.RegisterShortcut(_mainHandle, preset.id, preset.shortcut, clear);
- }
+ KeyboardShortcutManager.RegisterShortcut(preset.id, preset.shortcut);
}
public void UpdateInfo()
@@ -734,7 +727,6 @@ Use 'Settings > Test power off/on' to test this functionality."
var form = MessageForms.ShowProgress("Connecting to device...");
var result = false;
- Enabled = false;
try
{
result = await device.TestConnectionAsync();
@@ -742,7 +734,6 @@ Use 'Settings > Test power off/on' to test this functionality."
finally
{
form.Close();
- Enabled = true;
}
if (!result && MessageForms.QuestionYesNo("Unable to connect to the device. Are you sure you want to add it?") != DialogResult.Yes)
@@ -796,7 +787,7 @@ Use 'Settings > Test power off/on' to test this functionality."
var device = _samsungService.GetPresetDevice(preset);
- BuildActionMenu(device, mnuLgActions.DropDownItems, mnuLgActions.Name, miLgAddAction_Click);
+ BuildActionMenu(device, mnuLgActions.DropDownItems, mnuLgActions.Name, miLgAddAction_Click, _samsungService.Config.ShowAdvancedActions);
ServiceFormUtils.BuildServicePresetsMenu(mnuLgNvPresets, _nvService, "NVIDIA", miLgAddNvPreset_Click);
ServiceFormUtils.BuildServicePresetsMenu(mnuLgAmdPresets, _amdService, "AMD", miLgAddAmdPreset_Click);
}
@@ -885,12 +876,12 @@ Do you want to continue?"
private void edtSamsungGameBarShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
private void edtSamsungGameBarShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
private void btnSamsungDeviceOptionsHelp_Click(object sender, EventArgs e)
@@ -1016,8 +1007,15 @@ Do you want to continue?";
Value = _samsungService.Config.SetSelectedDeviceByPowerOn
};
+ var showAdvancedField = new MessageForms.FieldDefinition
+ {
+ FieldType = MessageForms.FieldType.CheckBox,
+ Label = "Show advanced actions under the Expert-button (Service Menu)",
+ SubLabel = "WARNING: entering the Service Menu is not recommended. This app and its creator are in no way accountable for any damages it may cause to your tv.",
+ Value = _samsungService.Config.ShowAdvancedActions
+ };
- var values = MessageForms.ShowDialog("Samsung controller settings", new[] { powerRetries, shutDownDelayField, buttonDelayField, quickAccessShortcutField, setDeviceField });
+ var values = MessageForms.ShowDialog("Samsung controller settings", new[] { powerRetries, shutDownDelayField, buttonDelayField, quickAccessShortcutField, setDeviceField, showAdvancedField });
if (values?.Any() != true)
{
@@ -1029,13 +1027,13 @@ Do you want to continue?";
_samsungService.Config.DefaultButtonDelay = buttonDelayField.ValueAsInt;
var shortcutQA = quickAccessShortcutField.Value.ToString();
- var clear = !string.IsNullOrEmpty(_samsungService.Config.QuickAccessShortcut);
_samsungService.Config.QuickAccessShortcut = shortcutQA;
- Utils.RegisterShortcut(_mainHandle, SHORTCUTID_SAMSUNGQA, _samsungService.Config.QuickAccessShortcut, clear);
+ KeyboardShortcutManager.RegisterShortcut(SHORTCUTID_SAMSUNGQA, _samsungService.Config.QuickAccessShortcut);
_samsungService.Config.SetSelectedDeviceByPowerOn = setDeviceField.ValueAsBool;
+ _samsungService.Config.ShowAdvancedActions = showAdvancedField.ValueAsBool;
}
private void clbLgPower_SelectedIndexChanged(object sender, EventArgs e)
@@ -1086,5 +1084,44 @@ Do you want to continue?";
device.Options.TurnScreenOnAfterScreenSaver = turnOnField.ValueAsBool;
device.Options.HandleManualScreenSaver = manualField.ValueAsBool;
}
+
+ private void btnExpert_Click(object sender, EventArgs e)
+ {
+ mnuExpert.ShowCustom(btnExpert);
+ }
+
+ private void mnuExpert_Opening(object sender, CancelEventArgs e)
+ {
+ miExpertDummy.Visible = false;
+
+ var device = _samsungService.SelectedDevice;
+
+ if (device == null)
+ {
+ return;
+ }
+
+ var actions = device.GetInvokableActions(_samsungService.Config.ShowAdvancedActions);
+
+ foreach (var action in actions)
+ {
+ FormUtils.BuildMenuItem(mnuExpert.Items, action.Name, action.Name, action, mnuExpertClick);
+ }
+ }
+
+ private async void mnuExpertClick(object sender, EventArgs e)
+ {
+ var item = (ToolStripMenuItem)sender;
+ var action = (SamsungDevice.InvokableAction)item.Tag;
+
+ var device = _samsungService.SelectedDevice;
+
+ if (device == null)
+ {
+ return;
+ }
+
+ await device.ExecuteActionAsync(action, null, Shared.Common.AppContext.CurrentContext, _samsungService.Config);
+ }
}
}
diff --git a/ColorControl/Services/Samsung/SamsungPanel.resx b/ColorControl/Services/Samsung/SamsungPanel.resx
index ab6c3a4..1341989 100644
--- a/ColorControl/Services/Samsung/SamsungPanel.resx
+++ b/ColorControl/Services/Samsung/SamsungPanel.resx
@@ -117,10 +117,13 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ 147, 17
+
288, 16
- 147, 17
+ 19, 20
\ No newline at end of file
diff --git a/ColorControl/Services/Samsung/SamsungServiceConfig.cs b/ColorControl/Services/Samsung/SamsungServiceConfig.cs
index af3de5f..3413acd 100644
--- a/ColorControl/Services/Samsung/SamsungServiceConfig.cs
+++ b/ColorControl/Services/Samsung/SamsungServiceConfig.cs
@@ -13,6 +13,7 @@ namespace ColorControl.Services.Samsung
public bool SetSelectedDeviceByPowerOn { get; set; }
public string QuickAccessShortcut { get; set; }
public int DefaultButtonDelay { get; set; }
+ public bool ShowAdvancedActions { get; set; }
public SamsungServiceConfig()
{
diff --git a/ColorControl/Svc/ColorControlBackgroundService.cs b/ColorControl/Svc/ColorControlBackgroundService.cs
index ef5bc18..415bccd 100644
--- a/ColorControl/Svc/ColorControlBackgroundService.cs
+++ b/ColorControl/Svc/ColorControlBackgroundService.cs
@@ -242,7 +242,7 @@ namespace ColorControl.Svc
await Task.Delay(1000);
- var result = Utils.PingHost(wakeDevice.IpAddress);
+ var result = await Utils.PingHost(wakeDevice.IpAddress);
if (result)
{
diff --git a/NLogViewer/NLogViewer.xaml.cs b/NLogViewer/NLogViewer.xaml.cs
index d25d949..8a62cf5 100644
--- a/NLogViewer/NLogViewer.xaml.cs
+++ b/NLogViewer/NLogViewer.xaml.cs
@@ -559,13 +559,16 @@ namespace DJ
foreach (var line in lines)
{
- var parts = line.Split("|");
+ // Replace \0 in case of corruption
+ var cleanedLine = line.Replace("\0", "");
+
+ var parts = cleanedLine.Split("|");
if (parts.Length < 4)
{
- if (lastEventInfo != null && !string.IsNullOrWhiteSpace(line))
+ if (lastEventInfo != null && !string.IsNullOrWhiteSpace(cleanedLine))
{
- lastEventInfo.Message += "\r\n" + line;
+ lastEventInfo.Message += "\r\n" + cleanedLine;
continue;
}
@@ -575,7 +578,7 @@ namespace DJ
continue;
}
- parts = new string[] { DateTime.Now.ToString(), "info", "", line };
+ parts = new string[] { DateTime.Now.ToString(), "info", "", cleanedLine };
}
var timeStamp = DateTime.Parse(parts[0]);
diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs
index dbb374a..066ae76 100644
--- a/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs
+++ b/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs
@@ -33,6 +33,10 @@
///
AdobeRGB,
+ Unknown1,
+
+ BT2020,
+
///
/// Auto (Unspecified)
///
diff --git a/Shared/Common/KeyboardShortcutManager.cs b/Shared/Common/KeyboardShortcutManager.cs
new file mode 100644
index 0000000..d747e75
--- /dev/null
+++ b/Shared/Common/KeyboardShortcutManager.cs
@@ -0,0 +1,333 @@
+using ColorControl.Shared.Forms;
+using Linearstar.Windows.RawInput;
+using Linearstar.Windows.RawInput.Native;
+using NWin32;
+
+namespace ColorControl.Shared.Common
+{
+ public class KeyboardShortcutManager
+ {
+ [Flags]
+ public enum ModKeys : int
+ {
+ None = 0,
+ Alt = 1,
+ Control = 2,
+ Shift = 4,
+ Win = 8
+ }
+
+ public static nint MainHandle { get; set; }
+ public static bool UseRawInput { get; private set; }
+
+ private static bool WinKeyDown = false;
+
+ private static List KeysWithoutModifiers = new List { Keys.F13, Keys.F14, Keys.F15, Keys.F16, Keys.F17, Keys.F18, Keys.F19, Keys.F20, Keys.F21, Keys.F22, Keys.F23, Keys.F24 };
+ private static List Modifiers = new List { Keys.ControlKey, Keys.Menu, Keys.ShiftKey, Keys.LWin };
+
+ private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
+
+ private static readonly HashSet _downModifierKeys = new HashSet();
+ private static readonly HashSet _downKeys = new HashSet();
+
+ private static readonly object _modifiersLock = new object();
+
+ private static Dictionary _registeredShortcuts = new Dictionary();
+
+ public static void SetUseRawInput(bool useRawInput)
+ {
+ if (UseRawInput == useRawInput)
+ {
+ return;
+ }
+
+ UseRawInput = useRawInput;
+
+ if (useRawInput)
+ {
+ UnregisterHotKeys();
+
+ RawInputDevice.RegisterDevice(HidUsageAndPage.Keyboard, RawInputDeviceFlags.InputSink, MainHandle);
+ }
+ else
+ {
+ RawInputDevice.UnregisterDevice(HidUsageAndPage.Keyboard);
+
+ RegisterHotKeys();
+ }
+ }
+
+ private static void UnregisterHotKeys()
+ {
+ foreach (var shortcut in _registeredShortcuts.Values.Where(s => s.HotKeyRegistered).ToList())
+ {
+ shortcut.UnregisterHotKey(MainHandle);
+ }
+ }
+
+ private static void RegisterHotKeys()
+ {
+ foreach (var shortcut in _registeredShortcuts.Values.Where(s => !s.HotKeyRegistered).ToList())
+ {
+ shortcut.RegisterHotKey(MainHandle);
+ }
+ }
+
+ public static void HandleRawKeyboardInput(RawInputKeyboardData data)
+ {
+ var keyboard = data.Keyboard;
+
+ //Debug.WriteLine($"Key: {keyboard}");
+
+ var add = !keyboard.Flags.HasFlag(RawKeyboardFlags.Up);
+
+ var keys = (Keys)keyboard.VirutalKey;
+
+ var isModifier = Modifiers.Contains(keys);
+ var modKey = KeysToModKeys(keys);
+ var changed = false;
+
+ lock (_modifiersLock)
+ {
+ if (add)
+ {
+ if (isModifier)
+ {
+ changed = _downModifierKeys.Add(modKey);
+ }
+ else
+ {
+ changed = _downKeys.Add((Keys)keyboard.VirutalKey);
+ }
+ }
+ else
+ {
+ if (isModifier)
+ {
+ changed = _downModifierKeys.Remove(modKey);
+ }
+ else
+ {
+ changed = _downKeys.Remove((Keys)keyboard.VirutalKey);
+ }
+ }
+ }
+
+ if (!changed || _downKeys.Count != 1 || !(_downModifierKeys.Any() || KeysWithoutModifiers.Contains(_downKeys.First())))
+ {
+ return;
+ }
+
+ var sum = _downModifierKeys.Sum(k => (int)k) * 1000;
+ sum += _downKeys.Sum(k => (int)k);
+
+ var shortcut = _registeredShortcuts.Values.FirstOrDefault(s => (s.Modifiers * 1000 + s.VirtualKeyCode) == sum);
+
+ if (shortcut == null)
+ {
+ return;
+ }
+
+ NativeMethods.SendMessageW(MainHandle, NativeConstants.WM_HOTKEY, (uint)shortcut.Id, 0);
+ }
+
+ public static bool RegisterShortcut(int id, string shortcut)
+ {
+ var clear = string.IsNullOrWhiteSpace(shortcut);
+
+ var shortcutStruct = GetShortcutById(id);
+
+ if (shortcutStruct == null)
+ {
+ if (clear)
+ {
+ return true;
+ }
+
+ var (mods, key) = ParseShortcut(shortcut);
+
+ shortcutStruct = new ShortcutStruct(mods, key, id, shortcut);
+
+ _registeredShortcuts[id] = shortcutStruct;
+ }
+ else if (clear)
+ {
+ shortcutStruct.UnregisterHotKey(id);
+
+ _registeredShortcuts.Remove(id);
+
+ return true;
+ }
+ else
+ {
+ var (mods, key) = ParseShortcut(shortcut);
+
+ if (shortcutStruct.Modifiers == mods && shortcutStruct.VirtualKeyCode == key)
+ {
+ return true;
+ }
+
+ shortcutStruct.SetModifiers(mods);
+ shortcutStruct.SetKey(key);
+ shortcutStruct.SetShortcut(shortcut);
+ shortcutStruct.UnregisterHotKey(MainHandle);
+ }
+
+ //if (UseRawInput)
+ //{
+ // return true;
+ //}
+
+ return shortcutStruct.RegisterHotKey(MainHandle);
+ }
+
+ private static ShortcutStruct GetShortcutById(int id)
+ {
+ if (_registeredShortcuts.TryGetValue(id, out var shortcut))
+ {
+ return shortcut;
+ }
+
+ return null;
+ }
+
+ public static (int mods, int key) ParseShortcut(string shortcut)
+ {
+ int mods = 0;
+ var key = 0;
+
+ shortcut = shortcut.Replace(",", "");
+ shortcut = shortcut.Replace("+", "");
+ shortcut = shortcut.Replace(" ", " ");
+ var parts = shortcut.Split(' ');
+
+ if (parts.Length > 0)
+ {
+ for (int i = 0; i + 1 < parts.Length; i++)
+ {
+ switch (parts[i])
+ {
+ case "Alt":
+ mods += (int)ModKeys.Alt;
+ break;
+ case "Control":
+ mods += (int)ModKeys.Control;
+ break;
+ case "Shift":
+ mods += (int)ModKeys.Shift;
+ break;
+ case "Win":
+ mods += (int)ModKeys.Win;
+ break;
+ }
+ }
+
+ var keyName = parts[parts.Length - 1];
+
+ key = (int)Enum.Parse(typeof(Keys), keyName);
+ }
+
+ return (mods, key);
+ }
+
+ public static Keys ShortcutToKeys(string shortcut)
+ {
+ var (mods, key) = ParseShortcut(shortcut);
+
+ var keys = Keys.None;
+
+ if (((uint)mods & (uint)ModKeys.Alt) > 0)
+ {
+ keys |= Keys.Alt;
+ }
+ if (((uint)mods & (uint)ModKeys.Control) > 0)
+ {
+ keys |= Keys.Control;
+ }
+ if (((uint)mods & (uint)ModKeys.Shift) > 0)
+ {
+ keys |= Keys.Shift;
+ }
+ if (((uint)mods & (uint)ModKeys.Win) > 0)
+ {
+ keys |= Keys.Control;
+ }
+
+ keys |= (Keys)key;
+
+ return keys;
+ }
+
+ public static ModKeys KeysToModKeys(Keys key)
+ {
+ return key switch
+ {
+ Keys.ControlKey => ModKeys.Control,
+ Keys.Menu => ModKeys.Alt,
+ Keys.ShiftKey => ModKeys.Shift,
+ Keys.LWin => ModKeys.Win,
+ _ => ModKeys.None,
+ };
+ }
+
+ public static string FormatKeyboardShortcut(KeyEventArgs keyEvent)
+ {
+ var pressedModifiers = keyEvent.Modifiers;
+
+ //Debug.WriteLine("KD: " + e.Modifiers + ", " + e.KeyCode);
+
+ var shortcutString = pressedModifiers > 0 ? pressedModifiers.ToString() : "";
+ if (keyEvent.KeyCode == Keys.LWin || WinKeyDown)
+ {
+ WinKeyDown = true;
+ if (!string.IsNullOrEmpty(shortcutString))
+ {
+ shortcutString += ", ";
+ }
+ shortcutString += "Win";
+ }
+
+ var empty = string.IsNullOrEmpty(shortcutString);
+ if ((!empty || KeysWithoutModifiers.Contains(keyEvent.KeyCode)) && keyEvent.KeyCode != Keys.ControlKey && keyEvent.KeyCode != Keys.ShiftKey && keyEvent.KeyCode != Keys.Menu && keyEvent.KeyCode != Keys.LWin)
+ {
+ if (!empty)
+ {
+ shortcutString += " + ";
+ }
+ shortcutString += keyEvent.KeyCode.ToString();
+ }
+
+ if (string.IsNullOrEmpty(shortcutString))
+ {
+ keyEvent.SuppressKeyPress = true;
+ }
+
+ return shortcutString;
+ }
+
+ public static bool ValidateShortcut(string shortcut)
+ {
+ var valid = string.IsNullOrWhiteSpace(shortcut) || shortcut.Contains("+") || ShortcutIsAllowedWithoutModifier(shortcut);
+
+ if (!valid)
+ {
+ MessageForms.WarningOk("Invalid shortcut. The shortcut should have modifiers and a normal key or be F13-F24.");
+ }
+
+ return valid;
+ }
+
+ public static bool ShortcutIsAllowedWithoutModifier(string shortcut)
+ {
+ return Enum.TryParse(shortcut, out var key) && KeysWithoutModifiers.Contains(key);
+ }
+
+ public static void HandleKeyboardShortcutUp(KeyEventArgs keyEvent)
+ {
+ if (keyEvent.KeyCode == Keys.LWin)
+ {
+ WinKeyDown = false;
+ }
+ }
+ }
+}
diff --git a/Shared/Common/ShortcutStruct.cs b/Shared/Common/ShortcutStruct.cs
new file mode 100644
index 0000000..54cba16
--- /dev/null
+++ b/Shared/Common/ShortcutStruct.cs
@@ -0,0 +1,68 @@
+using ColorControl.Shared.Native;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace ColorControl.Shared.Common
+{
+ internal class ShortcutStruct
+ {
+ private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
+
+ public int VirtualKeyCode { get; private set; }
+ public int Modifiers { get; private set; }
+ public int Id { get; }
+ public string Shortcut { get; private set; }
+ public bool HotKeyRegistered { get; set; }
+
+ public ShortcutStruct(int modifiers, int virtualKeyCode, int id, string shortcut)
+ {
+ VirtualKeyCode = virtualKeyCode;
+ Modifiers = modifiers;
+ Id = id;
+ Shortcut = shortcut;
+ }
+
+ internal void SetModifiers(int mods)
+ {
+ Modifiers = mods;
+ }
+
+ internal void SetKey(int key)
+ {
+ VirtualKeyCode = key;
+ }
+
+ internal void SetShortcut(string shortcut)
+ {
+ Shortcut = shortcut;
+ }
+
+ internal bool RegisterHotKey(nint handle)
+ {
+ var result = WinApi.RegisterHotKey(handle, Id, Modifiers, VirtualKeyCode);
+ if (!result)
+ {
+ var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
+ Logger.Error($"Could not register shortcut {Shortcut}: {errorMessage}");
+ }
+ else
+ {
+ HotKeyRegistered = true;
+ }
+
+ return result;
+ }
+
+ internal void UnregisterHotKey(nint handle)
+ {
+ if (!HotKeyRegistered)
+ {
+ return;
+ }
+
+ WinApi.UnregisterHotKey(handle, Id);
+
+ HotKeyRegistered = false;
+ }
+ }
+}
diff --git a/Shared/Common/Utils.cs b/Shared/Common/Utils.cs
index d5b90fd..4b00489 100644
--- a/Shared/Common/Utils.cs
+++ b/Shared/Common/Utils.cs
@@ -1,5 +1,4 @@
using ColorControl.Shared.Contracts;
-using ColorControl.Shared.Forms;
using ColorControl.Shared.Native;
using Microsoft.Win32;
using Microsoft.Win32.TaskScheduler;
@@ -28,15 +27,6 @@ namespace ColorControl.Shared.Common
{
public static class Utils
{
- [Flags]
- public enum ModKeys : int
- {
- Alt = 1,
- Control = 2,
- Shift = 4,
- Win = 8
- }
-
public const int WM_BRINGTOFRONT = NativeConstants.WM_USER + 1;
public static string PKEY_PNPX_IpAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12297";
@@ -49,8 +39,6 @@ namespace ColorControl.Shared.Common
public static bool UseDedicatedElevatedProcess = false;
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
- private static bool WinKeyDown = false;
- private static Keys[] KeysWithoutModifiers = new[] { Keys.F13, Keys.F14, Keys.F15, Keys.F16, Keys.F17, Keys.F18, Keys.F19, Keys.F20, Keys.F21, Keys.F22, Keys.F23, Keys.F24 };
public static string SERVICE_NAME = "Color Control Service";
@@ -123,73 +111,6 @@ The best and suggested method to provide this is via a Windows Service. Only whe
return path;
}
- public static (int mods, int key) ParseShortcut(string shortcut)
- {
- int mods = 0;
- var key = 0;
-
- shortcut = shortcut.Replace(",", "");
- shortcut = shortcut.Replace("+", "");
- shortcut = shortcut.Replace(" ", " ");
- var parts = shortcut.Split(' ');
-
- if (parts.Length > 0)
- {
- for (int i = 0; i + 1 < parts.Length; i++)
- {
- switch (parts[i])
- {
- case "Alt":
- mods += (int)ModKeys.Alt;
- break;
- case "Control":
- mods += (int)ModKeys.Control;
- break;
- case "Shift":
- mods += (int)ModKeys.Shift;
- break;
- case "Win":
- mods += (int)ModKeys.Win;
- break;
- }
- }
-
- var keyName = parts[parts.Length - 1];
-
- key = (int)Enum.Parse(typeof(Keys), keyName);
- }
-
- return (mods, key);
- }
-
- public static Keys ShortcutToKeys(string shortcut)
- {
- var (mods, key) = ParseShortcut(shortcut);
-
- var keys = Keys.None;
-
- if (((uint)mods & (uint)ModKeys.Alt) > 0)
- {
- keys |= Keys.Alt;
- }
- if (((uint)mods & (uint)ModKeys.Control) > 0)
- {
- keys |= Keys.Control;
- }
- if (((uint)mods & (uint)ModKeys.Shift) > 0)
- {
- keys |= Keys.Shift;
- }
- if (((uint)mods & (uint)ModKeys.Win) > 0)
- {
- keys |= Keys.Control;
- }
-
- keys |= (Keys)key;
-
- return keys;
- }
-
private static bool? _IsAdministrator;
public static bool IsAdministrator()
@@ -601,29 +522,6 @@ The best and suggested method to provide this is via a Windows Service. Only whe
}
}
- public static bool RegisterShortcut(nint handle, int id, string shortcut, bool clear = false)
- {
- if (clear)
- {
- WinApi.UnregisterHotKey(handle, id);
- }
-
- if (!string.IsNullOrEmpty(shortcut))
- {
- var (mods, key) = ParseShortcut(shortcut);
- var result = WinApi.RegisterHotKey(handle, id, mods, key);
- if (!result)
- {
- var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
- Logger.Error($"Could not register shortcut {shortcut}: {errorMessage}");
- }
-
- return result;
- }
-
- return true;
- }
-
public static void CheckWin32Error(string message)
{
var errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
@@ -631,66 +529,6 @@ The best and suggested method to provide this is via a Windows Service. Only whe
throw new Exception($"{message}: {errorMessage}");
}
- public static string FormatKeyboardShortcut(KeyEventArgs keyEvent)
- {
- var pressedModifiers = keyEvent.Modifiers;
-
- //Debug.WriteLine("KD: " + e.Modifiers + ", " + e.KeyCode);
-
- var shortcutString = pressedModifiers > 0 ? pressedModifiers.ToString() : "";
- if (keyEvent.KeyCode == Keys.LWin || WinKeyDown)
- {
- WinKeyDown = true;
- if (!string.IsNullOrEmpty(shortcutString))
- {
- shortcutString += ", ";
- }
- shortcutString += "Win";
- }
-
- var empty = string.IsNullOrEmpty(shortcutString);
- if ((!empty || KeysWithoutModifiers.Contains(keyEvent.KeyCode)) && keyEvent.KeyCode != Keys.ControlKey && keyEvent.KeyCode != Keys.ShiftKey && keyEvent.KeyCode != Keys.Menu && keyEvent.KeyCode != Keys.LWin)
- {
- if (!empty)
- {
- shortcutString += " + ";
- }
- shortcutString += keyEvent.KeyCode.ToString();
- }
-
- if (string.IsNullOrEmpty(shortcutString))
- {
- keyEvent.SuppressKeyPress = true;
- }
-
- return shortcutString;
- }
-
- public static bool ValidateShortcut(string shortcut)
- {
- var valid = string.IsNullOrWhiteSpace(shortcut) || shortcut.Contains("+") || ShortcutIsAllowedWithoutModifier(shortcut);
-
- if (!valid)
- {
- MessageForms.WarningOk("Invalid shortcut. The shortcut should have modifiers and a normal key or be F13-F24.");
- }
-
- return valid;
- }
-
- public static bool ShortcutIsAllowedWithoutModifier(string shortcut)
- {
- return Enum.TryParse(shortcut, out var key) && KeysWithoutModifiers.Contains(key);
- }
-
- public static void HandleKeyboardShortcutUp(KeyEventArgs keyEvent)
- {
- if (keyEvent.KeyCode == Keys.LWin)
- {
- WinKeyDown = false;
- }
- }
-
public static bool OpenConsole()
{
if (ConsoleOpened)
@@ -1023,12 +861,13 @@ The best and suggested method to provide this is via a Windows Service. Only whe
StartProcess("sc.exe", @$"delete ""{SERVICE_NAME}""", wait: true);
}
- public static bool PingHost(string nameOrAddress)
+ public static async Task PingHost(string nameOrAddress)
{
try
{
using var pinger = new Ping();
- var reply = pinger.Send(nameOrAddress);
+ var reply = await pinger.SendPingAsync(nameOrAddress, 2000);
+
return reply.Status == IPStatus.Success;
}
catch (PingException)
diff --git a/Shared/Contracts/Config.cs b/Shared/Contracts/Config.cs
index dbc9fba..c7c2671 100644
--- a/Shared/Contracts/Config.cs
+++ b/Shared/Contracts/Config.cs
@@ -39,6 +39,7 @@
public int ProcessMonitorPollingInterval { get; set; }
public string LogLevel { get; set; }
public List Modules { get; set; }
+ public bool UseRawInput { get; set; }
public Config()
{
diff --git a/Shared/Forms/MessageForms.cs b/Shared/Forms/MessageForms.cs
index d891bdf..2cb298e 100644
--- a/Shared/Forms/MessageForms.cs
+++ b/Shared/Forms/MessageForms.cs
@@ -14,7 +14,8 @@ namespace ColorControl.Shared.Forms
Flags,
Shortcut,
CheckBox,
- TrackBar
+ TrackBar,
+ Label
}
public class FieldDefinition
@@ -41,12 +42,12 @@ namespace ColorControl.Shared.Forms
public void edtShortcut_KeyDown(object sender, KeyEventArgs e)
{
- ((TextBox)sender).Text = Utils.FormatKeyboardShortcut(e);
+ ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e);
}
public void edtShortcut_KeyUp(object sender, KeyEventArgs e)
{
- Utils.HandleKeyboardShortcutUp(e);
+ KeyboardShortcutManager.HandleKeyboardShortcutUp(e);
}
public void TrackBar_Scroll(object sender, EventArgs e)
@@ -146,6 +147,7 @@ namespace ColorControl.Shared.Forms
var labels = new List