mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-22 00:22:18 -05:00
fix modules, add raw input, add service menu to Samsung controller
This commit is contained in:
1 parent
3c5c2b3e4e
commit
2c5b08af72
27 files changed
+810
-785
No files matched your search
@@ -18,8 +18,8 @@
|
||||
<PublisherName>Maassoft</PublisherName>
|
||||
<Company>Maassoft</Company>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>9.6.2.0</ApplicationVersion>
|
||||
<Version>9.6.2.0</Version>
|
||||
<ApplicationVersion>9.6.3.0</ApplicationVersion>
|
||||
<Version>9.6.3.0</Version>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
@@ -102,6 +102,7 @@
|
||||
<PackageReference Include="System.Management" Version="7.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.4.13" />
|
||||
<PackageReference Include="RawInput.Sharp" Version="0.1.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="XForms\LogWindow.xaml">
|
||||
|
||||
Generated
+1
-1
@@ -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
|
||||
//
|
||||
|
||||
+54
-54
@@ -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<int, Action> _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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NonInvasiveKeyboardHookLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
internal class KeybindStruct : IEquatable<KeybindStruct>
|
||||
{
|
||||
public readonly int VirtualKeyCode;
|
||||
public readonly List<ModifierKeys> Modifiers;
|
||||
public readonly Guid? Identifier;
|
||||
|
||||
public KeybindStruct(IEnumerable<ModifierKeys> modifiers, int virtualKeyCode, Guid? identifier = null)
|
||||
{
|
||||
this.VirtualKeyCode = virtualKeyCode;
|
||||
this.Modifiers = new List<ModifierKeys>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class KeyboardHookManager
|
||||
{
|
||||
#region Private Attributes
|
||||
/// <summary>
|
||||
/// Keeps track of all registered hotkeys
|
||||
/// </summary>
|
||||
private readonly Dictionary<KeybindStruct, Action> _registeredCallbacks;
|
||||
/// <summary>
|
||||
/// Keeps track of modifier keys that are held down
|
||||
/// </summary>
|
||||
private readonly HashSet<ModifierKeys> _downModifierKeys;
|
||||
/// <summary>
|
||||
/// Keeps track of all keys that are held down to prevent firing callbacks
|
||||
/// more than once for a single keypress
|
||||
/// </summary>
|
||||
private readonly HashSet<int> _downKeys;
|
||||
private readonly object _modifiersLock = new object();
|
||||
private LowLevelKeyboardProc _hook;
|
||||
private bool _isStarted;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
public KeyboardHookManager()
|
||||
{
|
||||
this._registeredCallbacks = new Dictionary<KeybindStruct, Action>();
|
||||
this._downModifierKeys = new HashSet<ModifierKeys>();
|
||||
this._downKeys = new HashSet<int>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
if (this._isStarted) return;
|
||||
|
||||
this._hook = this.HookCallback;
|
||||
_hookId = SetHook(this._hook);
|
||||
this._isStarted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses the low-level keyboard hook (without unregistering the existing hotkeys)
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (this._isStarted)
|
||||
{
|
||||
UnhookWindowsHookEx(_hookId);
|
||||
this._isStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a hotkey.
|
||||
/// </summary>
|
||||
/// <param name="virtualKeyCode">The virtual key code of the hotkey</param>
|
||||
/// <param name="action">The callback action to invoke when this hotkey is pressed</param>
|
||||
/// <exception cref="HotkeyAlreadyRegisteredException">Thrown when the given key is already mapped to a callback</exception>
|
||||
/// /// <returns>Unique identifier of this hotkey, which can be used to remove it later</returns>
|
||||
public Guid RegisterHotkey(int virtualKeyCode, Action action)
|
||||
{
|
||||
return this.RegisterHotkey(new ModifierKeys[0], virtualKeyCode, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new key combination with one or more modifiers
|
||||
/// </summary>
|
||||
/// <param name="modifiers">Modifiers that must be held while hitting the key. Multiple modifiers can be provided using the flags bitwise OR operation</param>
|
||||
/// <param name="virtualKeyCode">The virtual key code of the standard key</param>
|
||||
/// <param name="action">The callback action to invoke when this combination is pressed</param>
|
||||
/// <exception cref="HotkeyAlreadyRegisteredException">Thrown when the given key combination is already mapped to a callback</exception>
|
||||
/// <returns>Unique identifier of this hotkey, which can be used to remove it later</returns>
|
||||
public Guid RegisterHotkey(ModifierKeys modifiers, int virtualKeyCode, Action action)
|
||||
{
|
||||
var allModifiers = Enum.GetValues(typeof(ModifierKeys)).Cast<ModifierKeys>().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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new key combination.
|
||||
/// </summary>
|
||||
/// <param name="modifiers">Modifiers that must be held while hitting the key</param>
|
||||
/// <param name="virtualKeyCode">The virtual key code of the standard key</param>
|
||||
/// <param name="action">The callback action to invoke when this combination is pressed</param>
|
||||
/// <exception cref="HotkeyAlreadyRegisteredException">Thrown when the given key combination is already mapped to a callback</exception>
|
||||
/// <returns>Unique identifier of this hotkey, which can be used to remove it later</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters all hotkeys (the low-level keyboard hook continues running)
|
||||
/// </summary>
|
||||
public void UnregisterAll()
|
||||
{
|
||||
this._registeredCallbacks.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a specific single-key hotkey
|
||||
/// </summary>
|
||||
/// <param name="virtualKeyCode">Virtual key code of the unregistered key</param>
|
||||
/// <exception cref="HotkeyNotRegisteredException">Thrown when the given key combination is not registered</exception>
|
||||
public void UnregisterHotkey(int virtualKeyCode)
|
||||
{
|
||||
this.UnregisterHotkey(new ModifierKeys[0], virtualKeyCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a specific key combination
|
||||
/// </summary>
|
||||
/// <param name="modifiers">The modifiers of the combination</param>
|
||||
/// <param name="virtualKeyCode">The key of the combination</param>
|
||||
/// <exception cref="HotkeyNotRegisteredException">Thrown when the given key combination is not registered</exception>
|
||||
public void UnregisterHotkey(ModifierKeys[] modifiers, int virtualKeyCode)
|
||||
{
|
||||
var keybind = new KeybindStruct(modifiers, virtualKeyCode);
|
||||
|
||||
if (!this._registeredCallbacks.Remove(keybind))
|
||||
{
|
||||
throw new HotkeyNotRegisteredException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a specific key by its unique identifier
|
||||
/// </summary>
|
||||
/// <param name="keybindIdentity">Keybind GUID, as returned by RegisterHotkey</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a keyboard event based on the KeyboardParams it receives
|
||||
/// </summary>
|
||||
/// <param name="keyboardParamsObj">KeyboardParams struct (object type to comply with QueueUserWorkItem)</param>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// Loads the library.
|
||||
/// </summary>
|
||||
/// <param name="lpFileName">Name of the library</param>
|
||||
/// <returns>A handle to the library</returns>
|
||||
[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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -75,6 +75,7 @@ namespace ColorControl.Services.EventDispatcher
|
||||
}
|
||||
|
||||
await DispatchEventAsync(Event_ProcessChanged, MonitorContext);
|
||||
DispatchEvent(Event_ProcessChanged, MonitorContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<bool> 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<IEnumerable<SamsungApp>> GetAppsAsync(bool force)
|
||||
{
|
||||
var dynamic = new
|
||||
var messages = new List<RequestMessage>
|
||||
{
|
||||
@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<SamsungApp>();
|
||||
}
|
||||
@@ -644,14 +672,15 @@ namespace ColorControl.Services.Samsung
|
||||
_invokableActions.Add(action);
|
||||
}
|
||||
|
||||
private void AddInvokableAction(string name, Func<Dictionary<string, object>, Task<bool>> function)
|
||||
private void AddInvokableAction(string name, Func<Dictionary<string, object>, Task<bool>> 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<InvokableAction> GetInvokableActions(bool showAdvanced)
|
||||
{
|
||||
return _invokableActions;
|
||||
return _invokableActions.Where(a => showAdvanced || !a.Advanced);
|
||||
}
|
||||
|
||||
private async Task<bool> WakeAction(Dictionary<string, object> _)
|
||||
{
|
||||
return await WakeAndConnect();
|
||||
}
|
||||
|
||||
private async Task<bool> ServiceMenuAction(Dictionary<string, object> _)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,10 +117,13 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="mnuExpert.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>147, 17</value>
|
||||
</metadata>
|
||||
<metadata name="mnuLgButtons.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>288, 16</value>
|
||||
</metadata>
|
||||
<metadata name="mnuLgSettings.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>147, 17</value>
|
||||
<value>19, 20</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
/// </summary>
|
||||
AdobeRGB,
|
||||
|
||||
Unknown1,
|
||||
|
||||
BT2020,
|
||||
|
||||
/// <summary>
|
||||
/// Auto (Unspecified)
|
||||
/// </summary>
|
||||
|
||||
@@ -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<Keys> KeysWithoutModifiers = new List<Keys> { 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<Keys> Modifiers = new List<Keys> { Keys.ControlKey, Keys.Menu, Keys.ShiftKey, Keys.LWin };
|
||||
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
private static readonly HashSet<ModKeys> _downModifierKeys = new HashSet<ModKeys>();
|
||||
private static readonly HashSet<Keys> _downKeys = new HashSet<Keys>();
|
||||
|
||||
private static readonly object _modifiersLock = new object();
|
||||
|
||||
private static Dictionary<int, ShortcutStruct> _registeredShortcuts = new Dictionary<int, ShortcutStruct>();
|
||||
|
||||
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<Keys>(shortcut, out var key) && KeysWithoutModifiers.Contains(key);
|
||||
}
|
||||
|
||||
public static void HandleKeyboardShortcutUp(KeyEventArgs keyEvent)
|
||||
{
|
||||
if (keyEvent.KeyCode == Keys.LWin)
|
||||
{
|
||||
WinKeyDown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-164
@@ -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<Keys>(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<bool> 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)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
public int ProcessMonitorPollingInterval { get; set; }
|
||||
public string LogLevel { get; set; }
|
||||
public List<Module> Modules { get; set; }
|
||||
public bool UseRawInput { get; set; }
|
||||
|
||||
public Config()
|
||||
{
|
||||
|
||||
@@ -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<Label>();
|
||||
var counter = 1;
|
||||
const int DefaultLeft = 20;
|
||||
const int DefaultWidth = 400;
|
||||
var currentLeft = DefaultLeft;
|
||||
|
||||
var columns = fields.Count() > 10 ? 2 : 1;
|
||||
@@ -156,21 +158,24 @@ namespace ColorControl.Shared.Forms
|
||||
var lastTop = top;
|
||||
|
||||
var label = field.Label;
|
||||
Label textLabel = null;
|
||||
|
||||
if (field.FieldType != FieldType.CheckBox)
|
||||
{
|
||||
var textLabel = new Label() { Left = currentLeft, Top = top, Text = label, AutoSize = true };
|
||||
textLabel = new Label() { Left = currentLeft, Top = top, Text = label, AutoSize = true, MaximumSize = new Size(DefaultWidth, 0) };
|
||||
labels.Add(textLabel);
|
||||
top += 20;
|
||||
groupBox.Controls.Add(textLabel);
|
||||
top += textLabel.Height + 4;
|
||||
}
|
||||
|
||||
Label textSubLabel = null;
|
||||
|
||||
if (field.SubLabel != null)
|
||||
{
|
||||
var textSubLabel = new Label() { Left = currentLeft, Top = top, Text = field.SubLabel, AutoSize = true };
|
||||
textSubLabel = new Label() { Left = currentLeft, Top = top, Text = field.SubLabel, AutoSize = true, MaximumSize = new Size(DefaultWidth, 0) };
|
||||
labels.Add(textSubLabel);
|
||||
top += 20;
|
||||
groupBox.Controls.Add(textSubLabel);
|
||||
top += textSubLabel.Height + 4;
|
||||
}
|
||||
|
||||
Control control;
|
||||
@@ -178,7 +183,7 @@ namespace ColorControl.Shared.Forms
|
||||
switch (field.FieldType)
|
||||
{
|
||||
case FieldType.Text:
|
||||
var textBox = new MaskedTextBox() { Left = currentLeft, Top = top, Width = 400 };
|
||||
var textBox = new MaskedTextBox() { Left = currentLeft, Top = top, Width = DefaultWidth };
|
||||
|
||||
if (label.Contains("Ip-address"))
|
||||
{
|
||||
@@ -238,7 +243,7 @@ namespace ColorControl.Shared.Forms
|
||||
{
|
||||
Left = currentLeft,
|
||||
Top = top,
|
||||
Width = 400,
|
||||
Width = DefaultWidth,
|
||||
DropDownStyle = ComboBoxStyle.DropDownList
|
||||
};
|
||||
|
||||
@@ -260,6 +265,12 @@ namespace ColorControl.Shared.Forms
|
||||
|
||||
top += 4;
|
||||
|
||||
if (textSubLabel != null)
|
||||
{
|
||||
top -= textSubLabel.Height + 4;
|
||||
labels.Last().Top = top + 20;
|
||||
}
|
||||
|
||||
var checkBox = new CheckBox
|
||||
{
|
||||
Left = currentLeft,
|
||||
@@ -278,7 +289,7 @@ namespace ColorControl.Shared.Forms
|
||||
{
|
||||
Left = currentLeft,
|
||||
Top = top,
|
||||
Width = 400,
|
||||
Width = DefaultWidth,
|
||||
Height = 100,
|
||||
MultiColumn = true
|
||||
};
|
||||
@@ -348,6 +359,12 @@ namespace ColorControl.Shared.Forms
|
||||
control = trackBar;
|
||||
break;
|
||||
|
||||
case FieldType.Label:
|
||||
control = textLabel;
|
||||
|
||||
top += 20;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
@@ -380,7 +397,7 @@ namespace ColorControl.Shared.Forms
|
||||
prompt.Width = groupBox.Width;
|
||||
}
|
||||
|
||||
var maxHeight = boxes.Max(c => c.Height + c.Top) + 20;
|
||||
var maxHeight = Math.Max(boxes.Max(c => c.Height + c.Top), labels.Max(l => l.Height + l.Top)) + 20;
|
||||
|
||||
if (groupBox.Height < maxHeight)
|
||||
{
|
||||
@@ -461,14 +478,16 @@ namespace ColorControl.Shared.Forms
|
||||
{
|
||||
var prompt = new Form()
|
||||
{
|
||||
Width = 300,
|
||||
Height = 100,
|
||||
FormBorderStyle = FormBorderStyle.FixedToolWindow,
|
||||
Text = caption,
|
||||
Width = 400,
|
||||
Height = 120,
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog,
|
||||
StartPosition = FormStartPosition.CenterScreen,
|
||||
ControlBox = false
|
||||
ControlBox = false,
|
||||
BackColor = FormUtils.CurrentBackColor,
|
||||
ForeColor = FormUtils.CurrentForeColor,
|
||||
|
||||
};
|
||||
var textLabel = new Label() { Left = 20, Top = 25, Text = caption, AutoSize = true };
|
||||
var textLabel = new Label() { Left = 20, Top = 30, Text = caption, AutoSize = true, MaximumSize = new Size(prompt.Width - 40, 0) };
|
||||
prompt.Controls.Add(textLabel);
|
||||
|
||||
prompt.Show(MainForm);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<PackageReference Include="System.Management" Version="7.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.4.13" />
|
||||
<PackageReference Include="RawInput.Sharp" Version="0.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in new issue
Block a user