Neuerstellung

This commit is contained in:
maier_S
2022-03-11 14:59:36 +01:00
parent 072072202a
commit cc720e6421
128 changed files with 16224 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
using System.Windows.Input;
namespace NHotkey.Wpf
{
static class Extensions
{
public static bool HasFlag(this ModifierKeys modifiers, ModifierKeys flag)
{
return (modifiers & flag) == flag;
}
public static bool HasFlag(this HotkeyFlags flags, HotkeyFlags flag)
{
return (flags & flag) == flag;
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
namespace NHotkey.Wpf
{
public class HotkeyAlreadyRegisteredEventArgs : EventArgs
{
private readonly string _name;
public HotkeyAlreadyRegisteredEventArgs(string name)
{
_name = name;
}
public string Name
{
get { return _name; }
}
}
}

View File

@@ -0,0 +1,249 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
namespace NHotkey.Wpf
{
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Design",
"CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable",
Justification = "This is a singleton; disposing it would break it")]
public class HotkeyManager : HotkeyManagerBase
{
#region Singleton implementation
public static HotkeyManager Current { get { return LazyInitializer.Instance; } }
private static class LazyInitializer
{
static LazyInitializer() { }
public static readonly HotkeyManager Instance = new HotkeyManager();
}
public void AddOrReplace(string v, object incrementKeys, object onIncrement)
{
throw new NotImplementedException();
}
#endregion
#region Attached property for KeyBindings
[AttachedPropertyBrowsableForType(typeof(KeyBinding))]
public static bool GetRegisterGlobalHotkey(KeyBinding binding)
{
return (bool)binding.GetValue(RegisterGlobalHotkeyProperty);
}
public static void SetRegisterGlobalHotkey(KeyBinding binding, bool value)
{
binding.SetValue(RegisterGlobalHotkeyProperty, value);
}
public static readonly DependencyProperty RegisterGlobalHotkeyProperty =
DependencyProperty.RegisterAttached(
"RegisterGlobalHotkey",
typeof(bool),
typeof(HotkeyManager),
new PropertyMetadata(
false,
RegisterGlobalHotkeyPropertyChanged));
private static void RegisterGlobalHotkeyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var keyBinding = d as KeyBinding;
if (keyBinding == null)
return;
bool oldValue = (bool) e.OldValue;
bool newValue = (bool) e.NewValue;
if (DesignerProperties.GetIsInDesignMode(d))
return;
if (oldValue && !newValue)
{
Current.RemoveKeyBinding(keyBinding);
}
else if (newValue && !oldValue)
{
Current.AddKeyBinding(keyBinding);
}
}
#endregion
#region HotkeyAlreadyRegistered event
public static event EventHandler<HotkeyAlreadyRegisteredEventArgs> HotkeyAlreadyRegistered;
private static void OnHotkeyAlreadyRegistered(string name)
{
var handler = HotkeyAlreadyRegistered;
if (handler != null)
handler(null, new HotkeyAlreadyRegisteredEventArgs(name));
}
#endregion
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
private readonly HwndSource _source;
private readonly WeakReferenceCollection<KeyBinding> _keyBindings;
private HotkeyManager()
{
_keyBindings = new WeakReferenceCollection<KeyBinding>();
var parameters = new HwndSourceParameters("Hotkey sink")
{
HwndSourceHook = HandleMessage,
ParentWindow = HwndMessage
};
_source = new HwndSource(parameters);
SetHwnd(_source.Handle);
}
public void AddOrReplace(string name, KeyGesture gesture, EventHandler<HotkeyEventArgs> handler)
{
AddOrReplace(name, gesture, false, handler);
}
public void AddOrReplace(string name, KeyGesture gesture, bool noRepeat, EventHandler<HotkeyEventArgs> handler)
{
AddOrReplace(name, gesture.Key, gesture.Modifiers, noRepeat, handler);
}
public void AddOrReplace(string name, Key key, ModifierKeys modifiers, EventHandler<HotkeyEventArgs> handler)
{
AddOrReplace(name, key, modifiers, false, handler);
}
public void AddOrReplace(string name, Key key, ModifierKeys modifiers, bool noRepeat, EventHandler<HotkeyEventArgs> handler)
{
var flags = GetFlags(modifiers, noRepeat);
var vk = (uint)KeyInterop.VirtualKeyFromKey(key);
AddOrReplace(name, vk, flags, handler);
}
private static HotkeyFlags GetFlags(ModifierKeys modifiers, bool noRepeat)
{
var flags = HotkeyFlags.None;
if (modifiers.HasFlag(ModifierKeys.Shift))
flags |= HotkeyFlags.Shift;
if (modifiers.HasFlag(ModifierKeys.Control))
flags |= HotkeyFlags.Control;
if (modifiers.HasFlag(ModifierKeys.Alt))
flags |= HotkeyFlags.Alt;
if (modifiers.HasFlag(ModifierKeys.Windows))
flags |= HotkeyFlags.Windows;
if (noRepeat)
flags |= HotkeyFlags.NoRepeat;
return flags;
}
private static ModifierKeys GetModifiers(HotkeyFlags flags)
{
var modifiers = ModifierKeys.None;
if (flags.HasFlag(HotkeyFlags.Shift))
modifiers |= ModifierKeys.Shift;
if (flags.HasFlag(HotkeyFlags.Control))
modifiers |= ModifierKeys.Control;
if (flags.HasFlag(HotkeyFlags.Alt))
modifiers |= ModifierKeys.Alt;
if (flags.HasFlag(HotkeyFlags.Windows))
modifiers |= ModifierKeys.Windows;
return modifiers;
}
private void AddKeyBinding(KeyBinding keyBinding)
{
var gesture = (KeyGesture)keyBinding.Gesture;
string name = GetNameForKeyBinding(gesture);
try
{
AddOrReplace(name, gesture.Key, gesture.Modifiers, null);
_keyBindings.Add(keyBinding);
}
catch (HotkeyAlreadyRegisteredException)
{
OnHotkeyAlreadyRegistered(name);
}
}
private void RemoveKeyBinding(KeyBinding keyBinding)
{
var gesture = (KeyGesture)keyBinding.Gesture;
string name = GetNameForKeyBinding(gesture);
Remove(name);
_keyBindings.Remove(keyBinding);
}
private readonly KeyGestureConverter _gestureConverter = new KeyGestureConverter();
private string GetNameForKeyBinding(KeyGesture gesture)
{
string name = gesture.DisplayString;
if (string.IsNullOrEmpty(name))
name = _gestureConverter.ConvertToString(gesture);
return name;
}
private IntPtr HandleMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
{
Hotkey hotkey;
var result = HandleHotkeyMessage(hwnd, msg, wparam, lparam, ref handled, out hotkey);
if (handled)
return result;
if (hotkey != null)
handled = ExecuteBoundCommand(hotkey);
return result;
}
private bool ExecuteBoundCommand(Hotkey hotkey)
{
var key = KeyInterop.KeyFromVirtualKey((int)hotkey.VirtualKey);
var modifiers = GetModifiers(hotkey.Flags);
bool handled = false;
foreach (var binding in _keyBindings)
{
if (binding.Key == key && binding.Modifiers == modifiers)
{
handled |= ExecuteCommand(binding);
}
}
return handled;
}
private static bool ExecuteCommand(InputBinding binding)
{
var command = binding.Command;
var parameter = binding.CommandParameter;
var target = binding.CommandTarget;
if (command == null)
return false;
var routedCommand = command as RoutedCommand;
if (routedCommand != null)
{
if (routedCommand.CanExecute(parameter, target))
{
routedCommand.Execute(parameter, target);
return true;
}
}
else
{
if (command.CanExecute(parameter))
{
command.Execute(parameter);
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFrameworks>net40;net45;netcoreapp3.0;net6.0-windows</TargetFrameworks>
<UseWPF>true</UseWPF>
</PropertyGroup>
<PropertyGroup Label="Package properties">
<Description>A managed library to handle global hotkeys in WPF applications. This package contains the concrete HotkeyManager implementation for WPF.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NHotkey\NHotkey.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,7 @@
using System.Windows.Markup;
// Mapping a custom namespace to the standard WPF namespace is usually something to avoid,
// however in this case we're only importing one type (HotkeyManager), and it's unlikely to
// collide with another type in a future version of WPF. So in this case, we do it for the
// sake of simplicity, so that the user doesn't need to map the namespace manually.
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "NHotkey.Wpf")]

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace NHotkey.Wpf
{
class WeakReferenceCollection<T> : IEnumerable<T>
where T : class
{
private readonly List<WeakReference> _references = new List<WeakReference>();
public IEnumerator<T> GetEnumerator()
{
var references = _references.ToList();
foreach (var reference in references)
{
var target = reference.Target;
if (target != null)
yield return (T) target;
}
Trim();
}
public void Add(T item)
{
_references.Add(new WeakReference(item));
}
public void Remove(T item)
{
_references.RemoveAll(r => (r.Target ?? item) == item);
}
public void Trim()
{
_references.RemoveAll(r => !r.IsAlive);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}