Giter Site home page Giter Site logo

willy-kimura / hotkeylistener Goto Github PK

View Code? Open in Web Editor NEW
47.0 6.0 14.0 6.28 MB

A library for registering system-wide hotkeys that can be used to trigger features in .NET applications.

License: MIT License

C# 100.00%
hotkey hotkey-functionality hotkey-client hotkey-enabler hotkeys register-hotkey hotkey-selection hotkey-listener hotkey-replacer hotkey-change

hotkeylistener's Introduction

HotkeyListener

nuget-downloads buymeacoffee

hotkey-listener-logo

HotkeyListener is a .NET library that allows registering system-wide hotkeys that can be used to trigger features in .NET applications. It also provides support for enabling standard Windows and User controls to select hotkeys at runtime.

Here's a screenshot and preview of the demo app Text Clipper that uses this library:

Text Clipper is a small utility that lets users save a list of important texts from any application by selecting any text and hitting a customizable hotkey. The user can then double-click on any clipped text to copy it to the Clipboard and paste it anywhere. text-clipper-demo

Installation

To install via the NuGet Package Manager Console, run:

Install-Package HotkeyListener

Features

  • Supports .NET Framework 4.0 and higher.
  • Manages system-wide hotkeys in a CRUD-like fashion. Suspending and resuming of hotkeys is also supported.
  • Detects the pressed hotkeys, allowing you to define what happens once a specific hotkey is invoked.
  • Captures the active application from where a hotkey was pressed and its related information, e.g. Title.
  • Lets you capture any selected text from an active application. To get a glimpse of what's possible with this feature, think of how WordWeb is able to lookup the definition of any phrase you've selected at the press of a hotkey... Or how Cintanotes lets you save highlighted texts as notes from any active application in an instant. That's precisely what you can achieve. See Text Clipper for preview.
  • The HotkeySelector class lets you enable any control to be used for selecting hotkeys at runtime. This is a key feature for applications that provide end-users with customizable hotkey inputs. Also see Text Clipper for preview.

Usage

Adding Hotkeys

First, ensure you import the library's namespace:

using WK.Libraries.HotkeyListenerNS;

...then instantiate the class and add some hotkeys:

var hkl = new HotkeyListener();

// Define a new hotkey using the Hotkey class. 
// Parameters are: [modifiers], [keys].
Hotkey hotkey1 = new Hotkey(Keys.Control | Keys.Shift, Keys.J);

// You can also define a hotkey in string format. 
// Visit 'https://kutt.it/winkeys' for more info.
Hotkey hotkey2 = new Hotkey("Control+Shift+D4");

hkl.Add(hotkey1);
hkl.Add(hotkey2);

The Add() method also allows adding an array of hotkeys:

hkl.Add(new[] { hotkey1, hotkey2 });

Important: If you're building an application that has no external user-option for changing or customizing the default hotkey(s) set, something you'll need to consider when working with global hotkeys is that there are a number of predefined keys or key-combinations already in use within a number of applications such as Google Chrome - for example Control+Tab. This then means that you might need to find the right key or key-combination to use when shipping your applications.

Listening to Hotkeys

To listen to key presses, use the HotkeyPressed event:

// Add a HotkeyPressed event.
hkl.HotkeyPressed += Hkl_HotkeyPressed;

private void Hkl_HotkeyPressed(object sender, HotkeyEventArgs e)
{
    if (e.Hotkey == hotkey1)
        MessageBox.Show($"First hotkey '{hotkey1}' was pressed.");
    
    if (e.Hotkey == hotkey2)
        MessageBox.Show($"Second hotkey '{hotkey2}'was pressed.");
}

Unlike with the standard KeyDown and KeyUp events, here only the registered hotkeys will be detected.

If you'd like to get the details of the active application where a hotkey was pressed, use the SourceApplication argument property:

private void Hkl_HotkeyPressed(object sender, HotkeyEventArgs e)
{
    if (e.Hotkey == hotkey1)
    {
    	MessageBox.Show(
            "Application:" + e.SourceApplication.Name + "\n" +
            "Title: " + e.SourceApplication.Title + "\n" +
            "ID: " + e.SourceApplication.ID + "\n" +
            "Handle: " + e.SourceApplication.Handle + "\n" +
            "Path: " + e.SourceApplication.Path + "\n"
        );
    }
}

As a special feature, if you'd like to get any text selected from the active application when a hotkey was pressed, use argument's property e.SourceApplication.Selection:

private void Hkl_HotkeyPressed(object sender, HotkeyEventArgs e)
{
    if (e.Hotkey == hotkey2)
    {
        // Get the selected text, if any.
        string selection = e.SourceApplication.Selection;
    	
        // If some text was actually selected, display a MessageBox.
        if (selection != string.Empty)
            MessageBox.Show(selection);
    }
}

Updating Hotkeys

You can update hotkeys using the Update() method. It works the same way as .NET string replacement method where you provide the current string and its replacement option.

Here, simply provide the current hotkey and its replacement option:

hkl.Update(hotkey1, new Hotkey(Keys.Control | Keys.Alt, Keys.T));

Hotkey updates can occur even when your application is running. However, something important you need to note is to always use variables to store hotkeys and pass them as references when updating since in this way, during a hotkey's update, it can be directly detected in the HotkeyPressed event at runtime.

Here's what I mean:

Hotkey hotkey3 = new Hotkey(Keys.Control | Keys.Alt, Keys.T);

// To update our hotkey, simply pass the current hotkey with 
// a 'ref' keyword to the variable and its replacement hotkey.
hkl.Update(ref hotkey3, new Hotkey(Keys.Alt, Keys.T);

This will ensure that both the hotkey and its variable have been updated to reflect the changes made. This design will come in handy if your application saves user settings after update.

Here's another classical example of updating a hotkey:

Hotkey hotkey1 = new Hotkey(Keys.Control | Keys.Alt, Keys.T);
Hotkey hotkey2 = new Hotkey(Keys.Alt, Keys.T);

// Once we reference the variable hotkey1, this will 
// update the hotkey and listen to its key-presses.
hkl.Update(ref hotkey1, hotkey2);

If you'd like to listen to hotkey updates, use the HotkeyUpdated event:

// Add a HotkeyUpdated event.
hkl.HotkeyUpdated += HotkeyListener_HotkeyUpdated;

private void HotkeyListener_HotkeyUpdated(object sender, HotkeyListener.HotkeyUpdatedEventArgs e)
{
	if (e.UpdatedHotkey == hotkey1)
	{
		// Do something...
	}
}

A more illustrative example of using the HotkeyUpdated event is provided in the demo.

Removing Hotkeys

To remove a hotkey, we use the Remove() method. This method has two variants:

Remove(): This accepts a single hotkey or an array of hotkeys.

RemoveAll(): This removes all the registered hotkeys.

Below are some examples:

// Remove a single hotkey.
hkl.Remove(hotkey1);
// Let's use an array of already registered hotkeys.
Hotkey[] hotkeys = new Hotkey[] 
{ 
    new Hotkey(Keys.Alt, Keys.E), 
    new Hotkey(Keys.Alt, Keys.J) 
};

// Remove the array of hotkeys.
hkl.Remove(hotkeys);
// This will remove all the registered hotkeys.
hkl.RemoveAll();

As a good practice, you can always call the method RemoveAll() whenever your application exits to clear the list of registered hotkeys with your application.

Suspending/Resuming Hotkeys

Suspending hotkeys simply refers to disabling or deactivating hotkeys while resuming refers to enabling or reactivating hotkeys for continued use.

These two methods are very applicable in scenarios where a user would prefer to change a specific hotkey while its currently active.

You can either suspend a specific individual hotkey or all the hotkeys:

Hotkey hotkey1 = new Hotkey(Keys.Control | Keys.Shift, Keys.E);
Hotkey hotkey2 = new Hotkey(Keys.Alt, Keys.X);

// Suspend a specific hotkey.
hkl.Suspend(hotkey1);

// ...or suspend all hotkeys.
hkl.Suspend();

To determine whether a specific hotkey has been suspended, use the hotkey's Suspended property:

if (hotkey1.Suspended) 
{
    // Do something...
}

A classic usage scenario.

We'll let us imagine we have two hotkeys Control+Shift+E and Alt+X, but the user prefers to change Control+Shift+E to Alt+X and Alt+X to something else. In this case, we cannot simply change one hotkey to another if at all the hotkeys are currently active. So what do we do? We first of all need to suspend these two hotkeys to prevent them from being detected or listened to, change the respective hotkeys, then resume listening to the hotkeys having made the necessary changes.

Here's the example:

Hotkey hotkey1 = new Hotkey(Keys.Control | Keys.Shift, Keys.E);
Hotkey hotkey2 = new Hotkey(Keys.Alt, Keys.X);

// Suspend all hotkeys.
hkl.Suspend();

// Update hotkeys with newer keys.
hkl.Update(ref hotkey1, new Hotkey(Keys.Alt, Keys.X));
hkl.Update(ref hotkey2, new Hotkey(Keys.Shift, Keys.PrintScreen));

// Resume listening to the hotkeys.
hkl.Resume();

Let's dive a little deeper now...

Suspending Hotkey Selection Forms

Whenever you're dealing with selection of hotkeys at runtime, you also need to take into account that all hotkeys are still active and so changing the keys may be difficult. Due to this, the hotkeys need to be disabled whenever a user opens the Form where the hotkey selection controls are hosted.

With this need comes the method SuspendOn() that allows suspension of all registered hotkeys once a form hosting the hotkey-selection controls is opened. This will allow the user to update any specific hotkey without unnecessarily invoking it:

// Suspend our Settings Form from listening to hotkey presses when active.
hkl.SuspendOn(settingsForm);

You can also choose to perform an action or call a method once the form has been closed or is inactive:

hotkeyListener.SuspendOn(settingsForm, delegate() { SaveSettings(); });

Let's now find out more on how to work with Hotkey Listener using one very important class that comes with it - the HotkeySelector class.

The HotkeySelector Class

As noted earlier, HotkeyListener would have been pretty much half-baked had the ability to provide hotkey selection for end-users not been there. That's the whole intention of this class. It is able to "convert" any control into an actual hotkey selector for usage at runtime.

Here's a preview of a stunning application, Sharp64, that uses this feature:

sample-hotkey-selector-usage

You can also refer to the demo for a preview of this feature.

Enabling Hotkey Selection For Controls

Firstly off, instantiate a new HotkeySelector instance:

var hks = new HotkeySelector();

To enable any control for hotkey selection, use the Enable() method:

hks.Enable(textBox1);

When enabling a control, you can set the default hotkey to be displayed:

// We'll use the hotkey we defined in our previous examples.
hks.Enable(textBox1, hotkey1);

...or we can create a new hotkey then set it as the default hotkey for a selector control:

// Create a new hotkey.
Hotkey hotkey2 = new Hotkey(Keys.Control | Keys.Shift, Keys.J);

// ...then set the default hotkey for a selector.
hks.Enable(textBox1, hotkey1);

To set a hotkey without necessarily enabling the control for hotkey selection, use the Set() method:

hks.Set(textbox1, hotkey1);

HotkeySelector also helps detect whether a key or key-combination is a Windows-registered hotkey or not and therefore unavailable for use, for example Control+Alt+Delete, so no need to account for such scenarios.

Made with ๐Ÿ˜Š + โค๏ธ by Willy Kimura.

hotkeylistener's People

Contributors

merlincooper avatar mfroeh avatar willy-kimura avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

hotkeylistener's Issues

Win32Exception thrown in even the most basic program

While using this in my program I noticed I was getting a lot of exceptions. I created a new temporary program that is the most basic possible and I'm still seeing them in the output window of Visual Studio 2019.

Here is my code:

using System;
using System.Windows.Forms;
using WK.Libraries.HotkeyListenerNS;

namespace TestApp
{
    public partial class Form1 : Form
    {
        private HotkeyListener keyhook;

        public Form1()
        {
            InitializeComponent();
            keyhook = new HotkeyListener();
            keyhook.Add(new Hotkey("Control+Alt+L"));
            keyhook.HotkeyPressed += Hkl_HotkeyPressed;
        }

        private void Hkl_HotkeyPressed(object sender, HotkeyEventArgs e)
        {
            Console.WriteLine("hotkey received");
        }
    }
}

No exception is thrown until I press the hotkey combo, and then I get this (each time I press the hotkey):

''TestApp.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'. Symbols loaded.
'TestApp.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\Users\scottismyname\source\repos\TestApp\TestApp\bin\Debug\TestApp.exe'. Symbols loaded.
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll'. Symbols loaded.
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'. Symbols loaded.
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll'. Symbols loaded.
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\Users\scottismyname\source\repos\TestApp\TestApp\bin\Debug\HotkeyListener.dll'. 
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'. Symbols loaded.
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll'. 
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll'. Symbols loaded.
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Accessibility\v4.0_4.0.0.0__b03f5f7f11d50a3a\Accessibility.dll'. Symbols loaded.
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\UIAutomationClient\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationClient.dll'. 
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\UIAutomationTypes\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationTypes.dll'. 
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll'. 
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\UIAutomationProvider\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationProvider.dll'. 
'TestApp.exe' (CLR v4.0.30319: TestApp.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\UIAutomationClientsideProviders\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationClientsideProviders.dll'. 
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll
hotkey received

Strange behavior of Google Chrome

Hi!

I just made C# program using HotkeyListener and registred 4 hotkeys:

  • Ctrl + Shift + ~
  • Ctrl + Shift + 1
  • Ctrl + Shift + 2
  • Ctrl + Shift + 3

Now when program is running it's accepting hot keys if focused or not. That's what I wanted.
But when Google Chrome is opened and if I press any of those 4 hotkeys, Chrome opens inspect Window.
If I close my program and try same hot keys nothing happens in Chrome.

I tried also other hotkeys, but behavior in chrome stay the same.

What could be wrong?

image

public partial class Form1 : Form
{
static List<S7.Net.Types.DataItem> list = new List<S7.Net.Types.DataItem>();
static Plc plc = new Plc(CpuType.S71200, "192.168.0.90", 0, 1);
static HotkeyListener hkl = new HotkeyListener();
static Hotkey hotkey1 = new Hotkey(Keys.Control | Keys.Shift, Keys.Oemtilde);
static Hotkey hotkey2 = new Hotkey(Keys.Control | Keys.Shift, Keys.D1);
static Hotkey hotkey3 = new Hotkey(Keys.Control | Keys.Shift, Keys.D2);
static Hotkey hotkey4 = new Hotkey(Keys.Control | Keys.Shift, Keys.D3);

     private void Form1_Load(object sender, EventArgs e)
    {
        hkl.Add(new[] { hotkey1, hotkey2, hotkey3, hotkey4 });
        hkl.HotkeyPressed += Hkl_HotkeyPressed;
    }

    private void Hkl_HotkeyPressed(object sender, HotkeyEventArgs e)
    {
        if (e.Hotkey == hotkey1)
            Console.WriteLine("HK1");

        if (e.Hotkey == hotkey2)
            Console.WriteLine("HK2");

        if (e.Hotkey == hotkey3)
            Console.WriteLine("HK3");

        if (e.Hotkey == hotkey4)
            Console.WriteLine("HK4");
        
    }
   private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        hkl.RemoveAll();
    }

}

Screen resizes

I have a simple C# Windows Form App (.Net Framework 4.6)

HotkeyListener works perfectly. The one issue I have is that when I hit a define hot key, the screen resizes.

Any ideas?

Most appreciated

Hotkey Manager

Hi!

I am looking for a way to do a hotkey editor like the one in Visual Studio for example, a list with hotkeys and you could assign 1 hotkey per row. Can I easily serialize all hotkeys with your library? In a first stage, it would be just select which action-> change hotkey and a small modal window will pop to capture your new hotkey and reassign it

System.Windows.Forms.Keys.VolumeUp gives VolumeUp + None which doesn't work

it gives me 'VolumeUpNone' not found (pardon my french) :

System.ArgumentException
HResult=0x80070057
Message=La valeur demandรฉe 'VolumeUpNone' est introuvable.
Source=mscorlib
Arborescence des appels de procรฉdureย :
ร  System.Enum.EnumResult.SetFailure(ParseFailureKind failure, String failureMessageID, Object failureMessageFormatArgument)
ร  System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)
ร  System.Enum.Parse(Type enumType, String value, Boolean ignoreCase)
ร  WK.Libraries.HotkeyListenerNS.HotkeyListener.Convert(String hotkey)
ร  WK.Libraries.HotkeyListenerNS.Helpers.HotkeyHandle.WndProc(Message& m)
ร  System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
ร  System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
ร  System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
ร  MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
ร  System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
ร  System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
ร  System.Windows.Application.RunDispatcher(Object ignore)
ร  System.Windows.Application.RunInternal(Window window)
ร  System.Windows.Application.Run(Window window)
ร  System.Windows.Application.Run()
ร  Volmatic.App.Main()

Here is the bit that I use :
volume_up = new Hotkey(System.Windows.Forms.Keys.VolumeUp);

The error happens only after I press the VolumeUp key.


I just found a workaround!
volume_up = new Hotkey(System.Windows.Forms.Keys.VolumeUp);
volume_up.KeyCode = System.Windows.Forms.Keys.VolumeUp;
Console.WriteLine(volume_up.KeyCode);
Modifying the keycode after creating the variable allows to remove the "None" that seems to be the problem.

edit :
Actually it does not work but gives VolumeUpVolumeUp

Doing this tho :
volume_up = new Hotkey(System.Windows.Forms.Keys.Control, System.Windows.Forms.Keys.F);
volume_up.KeyCode = System.Windows.Forms.Keys.VolumeUp;
Console.WriteLine(volume_up.KeyCode);

gives me "VolumeUp" but then the handling function does not capture anything.

I therefore do not have a valid workaround.

ScrollLock based combo's

Hi @Willy-Kimura,

Would it be possible to catch ScrollLock based keycombo's with your codebase? Currently ScrollLock is detected, but as soon as a second key is pressed, the ScrollLock part disappears.

I've had some users (HASS.Agent) ask for it, and thought I'd ask you first before trying myself.

Thanks again for sharing your amazing library :)

Compile Error in VS 2019

After cloning you git repository and compile i get an error "System.ArgumentException
HResult=0x80070057
Nachricht = Die Assembly "C:\Users\XXX\source\repos\HotkeyListener\HotkeyListener\obj\Debug\HotkeyListener.dll" enthรคlt keine UserControl-Typen.
Quelle = UserControlTestContainer
Stapelรผberwachung:
at Microsoft.VisualStudio.Tools.UserControlTestContainer.UserControlTestContainer_Load(Object sender, EventArgs e)
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
"

AccessViolationException on Windows 11

I've been using your nuget for a while on W10, works really great, thanks for sharing :)

Recently I made the switch to W11, and now when using the same code, I get the following exception:

[MAIN] AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at MS.Internal.Automation.UiaCoreApi.RawTextRange_GetText(SafeTextRangeHandle hobj, Int32 maxLength, String& result)
   at System.Windows.Automation.Text.TextPatternRange.GetText(Int32 maxLength)
   at WK.Libraries.HotkeyListenerNS.Helpers.TextSelectionReader.<>c.<GetTextFromAutomationElement>b__5_0(TextPatternRange r)
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.String.Join(String separator, IEnumerable`1 values)
   at WK.Libraries.HotkeyListenerNS.Helpers.TextSelectionReader.GetTextFromAutomationElement()
   at WK.Libraries.HotkeyListenerNS.Helpers.TextSelectionReader.<.ctor>b__0_0()
   at WK.Libraries.HotkeyListenerNS.Helpers.TextSelectionReader.TryGetSelectedTextFromActiveControl()
   at WK.Libraries.HotkeyListenerNS.Helpers.SourceAttributes.GetSelection()
   at WK.Libraries.HotkeyListenerNS.Helpers.HotkeyHandle.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at Program.Main()

It looks like the TextSelectionReader is causing a crash, perhaps it's breaking some security measures.

Do you have the time to look into this, or could you give me some pointers on how to remove/disable the TextSelectionReader from your source?

Thanks!

How do I change hotkeys

I have been trying for literally hours now and cannot get it to work!

hotkey1 is already set to F7 on startup. I want the user to change the keybind to something else of their choice. How do I go about do so?

` private void Form1_KeyDown(object sender, KeyEventArgs e)

    {

        var hkl = new HotkeyListener();

        if (recordPOS.Text == "Change")

        {

            recordPOS.Text = e.KeyCode.ToString();

            Keys[] keys = (Keys[])typeof(Keys).GetEnumValues();
            Keys pickedKey = keys.FirstOrDefault(k => k.ToString() == recordPOS.Text);

            hkl.Update(ref hotkey1, new Hotkey(pickedKey));
        }
    }`

key PageDown

"PageDown" key registration works like "Next" key

Exception raised in UIAutomationClientsideProviders.dll (see GetTextFromAutomationElement)

Hi again,

Thanks for the release of the 1.3 which I have followed closely.

I'm trying to register a simple {p} hotkey (no modifier) but when I press the key it raises an exception (actually two but they are similar) which I have listed below.

System.ArgumentException
image

`A first chance exception of type 'System.ArgumentException' occurred in UIAutomationClientsideProviders.dll

Additional information: Value does not fall within the expected range.`

System.Windows.Automation.ElementNotAvailableException
image

`An exception of type 'System.Windows.Automation.ElementNotAvailableException' occurred in UIAutomationClient.dll and wasn't handled before a managed/native boundary

Additional information: The target element corresponds to UI that is no longer available (for example, the parent window has closed).`

Win Key Exception

When I use the key 'RWin' the app crashes, for example (CTRL+RWIN+J) :
Hotkey hotkey1 = new Hotkey(Keys.Control | Keys.LWin, Keys.J);

Here the exception generated:

An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Value not found 'LWinJ'

It says LWinJ, LWIN be joined with the next key.

How I can fix it?

Question: Sending an hotkey stored class Hotkey to windows application

Found today the HotkeyListener on NuGet.

Would like to use it in an application were the user can define a hotkey which will be used to remotely control another application. But I seem to miss how I can send the short-cut.

P.S.: The application I'm working on is using the Win32 function keybd_event - which is already superseded by another function. Thus I will have to update the code anyway. But if possible I would right away start using a more convenient solution.

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-keybd_event

save hotkey in settings

Hello,
i use your library in a project and it works very well. Is it possible to store the hotkey in Settings.settings or something else? Can i find an example for this?

thanks a lot and best regards
Benno

KeyNotFoundException when hotkey is pressed twice and suspending

If a defined hotkey is pressed twice and is currently suspended, I get a KeyNotFoundException.

Hotkey hotkey1 = new Hotkey(Keys.Escape);
if (e.Hotkey == hotkey1)
            {
                Debug.WriteLine("Hotkey pressed");
                hkl.Suspend();
            }

Execute this code and press the Escape key twice.

System.Collections.Generic.KeyNotFoundException
  HResult=0x80131577
  Nachricht = Der angegebene Schlรผssel war nicht im Wรถrterbuch angegeben.
  Quelle = mscorlib
  Stapelรผberwachung:
   bei System.Collections.Generic.Dictionary2.get_Item(TKey key)
   bei WK.Libraries.HotkeyListenerNS.Helpers.HotkeyHandle.WndProc(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   bei System.Windows.Forms.Application.Run(Form mainForm)
   bei HotkeyBugTest.Program.Main() in C:\Users\Eddy\source\repos\HotkeyBugTest\HotkeyBugTest\Program.cs: Zeile19

  Diese Ausnahme wurde ursprรผnglich von dieser Aufrufliste ausgelรถst:
    [Externer Code]
    HotkeyBugTest.Program.Main() in Program.cs

.net 5.0 support

Trying to use it in a .net 5.0 project. While resolving "Hotkey", the below error happens:

CS0012: The type 'Keys' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Windows.Forms', Version = 4.0.0.0

Any workaround for using in .net 5.0 ?

Prevent RegisterHotKey from stopping the default key action?

Hi again,

Is there a functionality to prevent RegisterHotKey from stopping the default action ? The problem is, this is stopping the F2 key from working for other applications, such as Excel.

Couldn't you add a e.Cancel field in the HotkeyEventArgs for exemple ? If set to false, a SendKeys.Send("{F2}"); would be sent to the focused window ?

WPF support for HotkeySelector

Hello, this project is awesome.

Do you have any plans to add WPF support for the HotkeySelector?

I have tried to make my own which does work.

It uses System.Windows.Controls.TextBox

Add references to these (WPF) assemblies:

WindowsBase
PresentationCore
PresentationFrameWork

HotkeySelectorWPF.cs

#region Copyright

/*
 * Developer    : Willy Kimura (WK).
 * Library      : HotkeySelector.
 * License      : MIT.
 * 
 */

#endregion

using System;
using System.Collections;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Windows.Controls;

namespace WK.Libraries.HotkeyListenerNS
{
    /// <summary>
    /// Provides support for enabling standard Windows controls 
    /// and User controls to select hotkeys at runtime. 
    /// Combined with the <see cref="HotkeyListener"/> class, 
    /// you can easily enable the selection and registering of 
    /// hotkeys for a seamless end-user experience.
    /// </summary>
    //[DebuggerStepThrough]
    [Description("Provides support for enabling standard Windows controls " +
                 "and User controls to select hotkeys at runtime.")]
    public partial class HotkeySelectorWPF : Component
    {
        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="HotkeySelector"/> class.
        /// </summary>
        public HotkeySelectorWPF() { }

        /// <summary>
        /// Initializes a new instance of the <see cref="HotkeySelector"/> class.
        /// </summary>
        public HotkeySelectorWPF(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        #endregion

        #region Fields

        // These variables store the selected hotkey and modifier key(s).
        private Keys _hotkey = Keys.None;
        private Keys _modifiers = Keys.None;

        // ArrayLists used to enforce the use of proper modifiers.
        // Shift+A isn't a valid hotkey, for instance.
        private ArrayList _needNonShiftModifier = null;
        private ArrayList _needNonAltGrModifier = null;

        // Stores the list of enabled hotkey selection controls.
        private List<System.Windows.Controls.Control> _controls = new List<System.Windows.Controls.Control>();

        #endregion

        #region Properties

        #region Public

        /// <summary>
        /// Gets or sets the text to be displayed in a 
        /// control when no hotkey has been set. 
        /// (Preferred default text is "None")
        /// </summary>
        public string EmptyHotkeyText { get; set; } = "None";

        /// <summary>
        /// Gets or sets the text to be displayed in a control 
        /// when an invalid or unsupported hotkey is pressed.
        /// (Preferred default text is "(Unsupported)")
        /// </summary>
        public string InvalidHotkeyText { get; set; } = "Unsupported";

        #endregion

        #endregion

        #region Methods

        #region Public

        /// <summary>
        /// Enables a control for hotkey selection and previewing.
        /// This will make use of the control's Text property to 
        /// preview the current hotkey selected.
        /// </summary>
        /// <param name="control">The control to enable.</param>
        public bool Enable(System.Windows.Controls.TextBox control)
        {
            try
            {
                control.Text = EmptyHotkeyText;

                control.KeyDown += new System.Windows.Input.KeyEventHandler(OnKeyDown);
                control.KeyUp += new System.Windows.Input.KeyEventHandler(OnKeyUp);

                ResetModifiers();

                try
                {
                    _controls.Add(control);
                }
                catch (Exception) { }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Enables a control for hotkey selection and previewing.
        /// This will make use of the control's Text property to 
        /// preview the current hotkey selected.
        /// </summary>
        /// <param name="control">The control to enable.</param>
        /// <param name="hotkey">Assign the default hotkey to be previewed in the control.</param>
        public bool Enable(System.Windows.Controls.TextBox control, Hotkey hotkey)
        {
            try
            {
                Enable(control);

                _hotkey = hotkey.KeyCode;
                _modifiers = hotkey.Modifiers;

                Refresh(control);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Disables a control for hotkey selection and previewing.
        /// </summary>
        /// <param name="control">The control to disable.</param>
        /// <param name="clearKeys">Clear the control's previewed keys?</param>
        public bool Disable(System.Windows.Controls.TextBox control, bool clearKeys = true)
        {
            try
            {
                control.KeyDown -= OnKeyDown;
                control.KeyUp -= OnKeyUp;

                if (clearKeys)
                    control.Text = string.Empty;

                try
                {
                    if (_controls.Contains(control))
                        _controls.Remove(control);
                }
                catch (Exception) { }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether a specific 
        /// control is enabled for hotkey selection.
        /// </summary>
        /// <param name="control">The control to determine.</param>
        public bool IsEnabled(System.Windows.Controls.TextBox control)
        {
            if (_controls.Contains(control))
                return true;
            else
                return false;
        }

        /// <summary>
        /// Sets a hotkey selection to be previewed in a control. 
        /// Thsi does not automatically enable the control for 
        /// hotkey selection. For this, please use the <see cref="Enable(Control)"/> method.
        /// </summary>
        /// <param name="control">The control to set.</param>
        /// <param name="hotkey">Provide a standard key or key combination string.</param>
        public bool Set(System.Windows.Controls.TextBox control, Hotkey hotkey)
        {
            try
            {
                Refresh(control);

                control.Text = Convert(hotkey);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Sets a hotkey selection to be previewed in a control. 
        /// Thsi does not automatically enable the control for 
        /// hotkey selection. For this, please use the <see cref="Enable(Control)"/> method.
        /// </summary>
        /// <param name="control">The control to set.</param>
        /// <param name="key">Provide a standard key selection.</param>
        /// <param name="modifiers">Provide a modifier key selection.</param>
        public bool Set(System.Windows.Controls.TextBox control, Keys key, Keys modifiers)
        {
            try
            {
                _hotkey = key;
                _modifiers = modifiers;

                Refresh(control);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Clears the currently previewed hotkey 
        /// selection displayed in a control.
        /// </summary>
        public void Clear(System.Windows.Controls.TextBox control)
        {
            this._hotkey = Keys.None;
            this._modifiers = Keys.None;

            Refresh(control);
        }

        /// <summary>
        /// (Variant of the <see cref="Clear(System.Windows.Controls.TextBox)"/> method) 
        /// Clears the currently previewed hotkey 
        /// selection displayed in a control.
        /// </summary>
        public void Reset(System.Windows.Controls.TextBox control)
        {
            this._hotkey = Keys.None;
            this._modifiers = Keys.None;

            Refresh(control);
        }

        /// <summary>
        /// [Helper] Converts keys or key combinations to their string types.
        /// </summary>
        /// <param name="hotkey">The hotkey to convert.</param>
        public string Convert(Hotkey hotkey)
        {
            try
            {
                _hotkey = hotkey.KeyCode;
                _modifiers = hotkey.Modifiers;

                string parsedHotkey = string.Empty;

                // No modifier or shift only, and a hotkey that needs another modifier.
                if ((_modifiers == Keys.Shift || _modifiers == Keys.None))
                {
                    if (_needNonShiftModifier != null && _needNonShiftModifier.Contains((int)this._hotkey))
                    {
                        if (this._modifiers == Keys.None)
                        {
                            // Set Ctrl+Alt as the modifier unless Ctrl+Alt+<key> won't work.
                            if (_needNonAltGrModifier.Contains((int)this._hotkey) == false)
                            {
                                this._modifiers = Keys.Alt | Keys.Control;
                            }
                            else
                            {
                                // ...In that case, use Shift+Alt instead.
                                this._modifiers = Keys.Alt | Keys.Shift;
                            }
                        }
                        else
                        {
                            // User pressed Shift and an invalid key (e.g. a letter or a number), 
                            // that needs another set of modifier keys.
                            this._hotkey = Keys.None;
                        }
                    }
                }

                // Without this code, pressing only Ctrl 
                // will show up as "Control + ControlKey", etc.
                if (this._hotkey == Keys.Menu || /* Alt */
                    this._hotkey == Keys.ShiftKey ||
                    this._hotkey == Keys.ControlKey)
                {
                    this._hotkey = Keys.None;
                }

                if (this._modifiers == Keys.None)
                {
                    // LWin/RWin don't work as hotkeys...
                    // (neither do they work as modifier keys in .NET 2.0).
                    if (_hotkey == Keys.None || _hotkey == Keys.LWin || _hotkey == Keys.RWin)
                    {
                        parsedHotkey = string.Empty;
                    }
                    else
                    {
                        parsedHotkey = this._hotkey.ToString();
                    }
                }
                else
                {
                    parsedHotkey = this._modifiers.ToString() + " + " + this._hotkey.ToString();
                }

                return parsedHotkey;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }

        #endregion

        #region Private

        /// <summary>
        /// Resets the hotkey modifiers to their defaults.
        /// </summary>
        private void ResetModifiers()
        {
            // Fill the ArrayLists that contain  
            // all invalid hotkey combinations.
            _needNonShiftModifier = new ArrayList();
            _needNonAltGrModifier = new ArrayList();

            PopulateModifierLists();
        }

        /// <summary>
        /// Populates the ArrayLists specifying disallowed Hotkeys 
        /// such as Shift+A, Ctrl+Alt+4 (produces 'dollar' sign).
        /// </summary>
        private void PopulateModifierLists()
        {
            // Shift + 0 - 9, A - Z.
            for (Keys k = Keys.D0; k <= Keys.Z; k++)
                _needNonShiftModifier.Add((int)k);

            // Shift + Numpad keys.
            for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++)
                _needNonShiftModifier.Add((int)k);

            // Shift + Misc (,;<./ etc).
            for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++)
                _needNonShiftModifier.Add((int)k);

            // Shift + Space, PgUp, PgDn, End, Home.
            for (Keys k = Keys.Space; k <= Keys.Home; k++)
                _needNonShiftModifier.Add((int)k);

            // Misc keys that we can't loop through.
            _needNonShiftModifier.Add((int)Keys.Insert);
            _needNonShiftModifier.Add((int)Keys.Help);
            _needNonShiftModifier.Add((int)Keys.Multiply);
            _needNonShiftModifier.Add((int)Keys.Add);
            _needNonShiftModifier.Add((int)Keys.Subtract);
            _needNonShiftModifier.Add((int)Keys.Divide);
            _needNonShiftModifier.Add((int)Keys.Decimal);
            _needNonShiftModifier.Add((int)Keys.Return);
            _needNonShiftModifier.Add((int)Keys.Escape);
            _needNonShiftModifier.Add((int)Keys.NumLock);
            _needNonShiftModifier.Add((int)Keys.Scroll);
            _needNonShiftModifier.Add((int)Keys.Pause);

            // Ctrl+Alt + 0 - 9.
            for (Keys k = Keys.D0; k <= Keys.D9; k++)
                _needNonAltGrModifier.Add((int)k);
        }

        /// <summary>
        /// Refreshes the previewed hotkey combination displayed in a control.
        /// </summary>
        /// <param name="control">
        /// The control providing hotkey selection.
        /// </param>
        private void Refresh(System.Windows.Controls.TextBox control)
        {
            Refresh(control, false);
        }

        /// <summary>
        /// Refreshes the previewed hotkey combination displayed in a control.
        /// </summary>
        /// <param name="control">
        /// The control providing hotkey selection.
        /// </param>
        /// <param name="internalCall">
        /// Specifies whether this function is 
        /// called internally or by the user.
        /// </param>
        private void Refresh(System.Windows.Controls.TextBox control, bool internalCall)
        {
            try
            {
                string parsedHotkey = string.Empty;

                // No hotkey set.
                if (this._hotkey == Keys.None && this._modifiers == Keys.None)
                {
                    control.Text = EmptyHotkeyText;
                    return;
                }

                // LWin/RWin don't work as hotkeys...
                // (neither do they work as modifier keys in .NET 2.0).
                if (this._hotkey == Keys.LWin || this._hotkey == Keys.RWin)
                {
                    control.Text = InvalidHotkeyText;

                    return;
                }

                if (this._modifiers == Keys.None)
                {
                    if (this._hotkey == Keys.None)
                    {
                        control.Text = EmptyHotkeyText;

                        return;
                    }
                    else
                    {
                        // We get here if we've got a hotkey that is valid without a modifier,
                        // like F1-F12, Media-keys etc.
                        control.Text = this._hotkey.ToString();

                        return;
                    }
                }
                else
                {
                    // Only validate input if it comes from the user.
                    if (internalCall == false)
                    {
                        // No modifier or shift only, and a hotkey that needs another modifier.
                        if ((this._modifiers == Keys.Shift || this._modifiers == Keys.None) &&
                            this._needNonShiftModifier.Contains((int)this._hotkey))
                        {
                            if (this._modifiers == Keys.None)
                            {
                                // Set Ctrl+Alt as the modifier unless Ctrl+Alt+<key> won't work.
                                if (_needNonAltGrModifier.Contains((int)this._hotkey) == false)
                                {
                                    this._modifiers = Keys.Alt | Keys.Control;
                                }
                                else
                                {
                                    // ...In that case, use Shift+Alt instead.
                                    this._modifiers = Keys.Alt | Keys.Shift;
                                }
                            }
                            else
                            {
                                // User pressed Shift and an invalid key (e.g. a letter or a number), 
                                // that needs another set of modifier keys.
                                this._hotkey = Keys.None;

                                control.Text = this._modifiers.ToString() + $" + {InvalidHotkeyText}";

                                return;
                            }
                        }
                    }
                }

                // Without this code, pressing only Ctrl 
                // will show up as "Control + ControlKey", etc.
                if (this._hotkey == Keys.Menu || /* Alt */
                    this._hotkey == Keys.ShiftKey ||
                    this._hotkey == Keys.Alt ||
                    this._hotkey == Keys.ControlKey ||
                    this._hotkey == Keys.LControlKey ||
                    this._hotkey == Keys.RControlKey ||
                    this._hotkey == Keys.LShiftKey ||
                    this._hotkey == Keys.RShiftKey)
                {
                    this._hotkey = Keys.None;
                }

                // A final compilation of the processed keys in string format.
                if (this._modifiers == Keys.None)
                    parsedHotkey = this._hotkey.ToString();
                else
                    parsedHotkey = this._modifiers.ToString() + " + " + this._hotkey.ToString();

                control.Text = parsedHotkey;

                return;
            }
            catch (Exception) { }
        }

        #endregion

        #endregion

        #region Events

        #region Private

        /// <summary>
        /// Fires when a key is pressed down. Here, we'll want to update the Text  
        /// property to notify the user what key combination is currently pressed.
        /// </summary>
        private void OnKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.Delete || e.Key == (System.Windows.Input.Key.LeftCtrl | System.Windows.Input.Key.RightCtrl | System.Windows.Input.Key.Delete))
                Reset((System.Windows.Controls.TextBox)sender);

            if (e.Key == (System.Windows.Input.Key.LeftShift | System.Windows.Input.Key.RightShift | System.Windows.Input.Key.Insert))
            {
                this._modifiers = Keys.Shift;
                e.Handled = true;
            }

            // Clear the current hotkey.
            if (e.Key == System.Windows.Input.Key.Back || e.Key == System.Windows.Input.Key.Delete)
            {
                Reset((System.Windows.Controls.TextBox)sender);

                return;
            }
            else
            {
                this._modifiers = ToWinforms(e.KeyboardDevice.Modifiers);
                this._hotkey = (Keys)System.Windows.Input.KeyInterop.VirtualKeyFromKey(e.Key);

                Refresh((System.Windows.Controls.TextBox)sender);
            }
        }

        /// <summary>
        /// Source: https://stackoverflow.com/questions/1153009/how-can-i-convert-system-windows-input-key-to-system-windows-forms-keys
        /// </summary>
        /// <param name="modifier"></param>
        /// <returns></returns>
        private System.Windows.Forms.Keys ToWinforms(System.Windows.Input.ModifierKeys modifier)
        {
            var retVal = System.Windows.Forms.Keys.None;
            if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Alt))
            {
                retVal |= System.Windows.Forms.Keys.Alt;
            }
            if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Control))
            {
                retVal |= System.Windows.Forms.Keys.Control;
            }
            if (modifier.HasFlag(System.Windows.Input.ModifierKeys.None))
            {
                // Pointless I know
                retVal |= System.Windows.Forms.Keys.None;
            }
            if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Shift))
            {
                retVal |= System.Windows.Forms.Keys.Shift;
            }
            if (modifier.HasFlag(System.Windows.Input.ModifierKeys.Windows))
            {
                // Not supported lel
            }
            return retVal;
        }

        /// <summary>
        /// Fires when all keys are released. If the current hotkey isn't valid, reset it.
        /// Otherwise, do nothing and keep the Text and hotkey as it was.
        /// </summary>
        private void OnKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {

            if (this._hotkey == Keys.None && e.KeyboardDevice.Modifiers == System.Windows.Input.ModifierKeys.None)
            {
                Reset((System.Windows.Controls.TextBox)sender);

                return;
            }
        }

        #endregion

        #endregion
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.