mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
Add NHotkey library.
This commit is contained in:
@@ -35,7 +35,7 @@ namespace Wox.Helper
|
||||
/// Listens keyboard globally.
|
||||
/// <remarks>Uses WH_KEYBOARD_LL.</remarks>
|
||||
/// </summary>
|
||||
public class KeyboardListener : IDisposable
|
||||
public class GloablHotkey : IDisposable
|
||||
{
|
||||
private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc;
|
||||
private IntPtr hookId = IntPtr.Zero;
|
||||
@@ -48,7 +48,7 @@ namespace Wox.Helper
|
||||
private const int VK_ALT = 0x12;
|
||||
private const int VK_WIN = 91;
|
||||
|
||||
public KeyboardListener()
|
||||
public GloablHotkey()
|
||||
{
|
||||
// We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime
|
||||
hookedLowLevelKeyboardProc = LowLevelKeyboardProc;
|
||||
@@ -107,7 +107,7 @@ namespace Wox.Helper
|
||||
return (IntPtr)1;
|
||||
}
|
||||
|
||||
~KeyboardListener()
|
||||
~GloablHotkey()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Wox.Helper
|
||||
{
|
||||
public sealed class KeyboardHook : IDisposable
|
||||
{
|
||||
// Registers a hot key with Windows.
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
|
||||
// Unregisters the hot key with Windows.
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||
/// <summary>
|
||||
/// Represents the window that is used internally to get the messages.
|
||||
/// </summary>
|
||||
private class Window : NativeWindow, IDisposable
|
||||
{
|
||||
private static int wmHotkey = 0x0312;
|
||||
|
||||
public Window()
|
||||
{
|
||||
// create the handle for the window.
|
||||
CreateHandle(new CreateParams());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to get the notifications.
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
base.WndProc(ref m);
|
||||
|
||||
// check if we got a hot key pressed.
|
||||
if (m.Msg == wmHotkey)
|
||||
{
|
||||
// get the keys.
|
||||
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
|
||||
XModifierKeys xModifier = (XModifierKeys)((int)m.LParam & 0xFFFF);
|
||||
|
||||
// invoke the event to notify the parent.
|
||||
if (KeyPressed != null)
|
||||
KeyPressed(this, new KeyPressedEventArgs(xModifier, key));
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<KeyPressedEventArgs> KeyPressed;
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DestroyHandle();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
private Window window = new Window();
|
||||
private int currentId;
|
||||
|
||||
public KeyboardHook()
|
||||
{
|
||||
// register the event of the inner native window.
|
||||
window.KeyPressed += delegate(object sender, KeyPressedEventArgs args)
|
||||
{
|
||||
if (KeyPressed != null)
|
||||
KeyPressed(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a hot key in the system.
|
||||
/// </summary>
|
||||
/// <param name="xModifier">The modifiers that are associated with the hot key.</param>
|
||||
/// <param name="key">The key itself that is associated with the hot key.</param>
|
||||
public void RegisterHotKey(XModifierKeys xModifier, Keys key)
|
||||
{
|
||||
// increment the counter.
|
||||
currentId = currentId + 1;
|
||||
|
||||
// register the hot key.
|
||||
if (!RegisterHotKey(window.Handle, currentId, (uint)xModifier, (uint)key))
|
||||
{
|
||||
Log.Error("Couldn’t register the hot key.");
|
||||
MessageBox.Show("Couldn’t register the hot key.");
|
||||
#if (DEBUG)
|
||||
{
|
||||
throw new InvalidOperationException("Couldn’t register the hot key.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A hot key has been pressed.
|
||||
/// </summary>
|
||||
public event EventHandler<KeyPressedEventArgs> KeyPressed;
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// unregister all the registered hot keys.
|
||||
for (int i = currentId; i > 0; i--)
|
||||
{
|
||||
UnregisterHotKey(window.Handle, i);
|
||||
}
|
||||
|
||||
// dispose the inner native window.
|
||||
window.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event Args for the event that is fired after the hot key has been pressed.
|
||||
/// </summary>
|
||||
public class KeyPressedEventArgs : EventArgs
|
||||
{
|
||||
private XModifierKeys xModifier;
|
||||
private Keys key;
|
||||
|
||||
internal KeyPressedEventArgs(XModifierKeys xModifier, Keys key)
|
||||
{
|
||||
this.xModifier = xModifier;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public XModifierKeys XModifier
|
||||
{
|
||||
get { return xModifier; }
|
||||
}
|
||||
|
||||
public Keys Key
|
||||
{
|
||||
get { return key; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The enumeration of possible modifiers.
|
||||
/// </summary>
|
||||
public enum XModifierKeys : uint
|
||||
{
|
||||
Alt = 1,
|
||||
Control = 2,
|
||||
Shift = 4,
|
||||
Win = 8
|
||||
}
|
||||
}
|
||||
13
Wox/HotkeyControl.xaml
Normal file
13
Wox/HotkeyControl.xaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="Wox.HotkeyControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
Height="50"
|
||||
Width="300"
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
<Grid >
|
||||
<TextBox x:Name="tbHotkey" PreviewKeyDown="TbHotkey_OnPreviewKeyDown"></TextBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
68
Wox/HotkeyControl.xaml.cs
Normal file
68
Wox/HotkeyControl.xaml.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Wox.Helper;
|
||||
using Wox.Plugin;
|
||||
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
|
||||
namespace Wox
|
||||
{
|
||||
public partial class HotkeyControl : UserControl
|
||||
{
|
||||
public HotkeyControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
//when alt is pressed, the real key should be e.SystemKey
|
||||
Key key = (e.Key == Key.System ? e.SystemKey : e.Key);
|
||||
|
||||
string text = string.Empty;
|
||||
SpecialKeyState specialKeyState = new GloablHotkey().CheckModifiers();
|
||||
if (specialKeyState.AltPressed)
|
||||
{
|
||||
text += "Alt ";
|
||||
}
|
||||
if (specialKeyState.CtrlPressed)
|
||||
{
|
||||
text += "Ctrl ";
|
||||
}
|
||||
if (specialKeyState.ShiftPressed)
|
||||
{
|
||||
text += "Shift ";
|
||||
}
|
||||
if (specialKeyState.WinPressed)
|
||||
{
|
||||
text += "Win ";
|
||||
}
|
||||
if(IsKeyAChar(key))
|
||||
{
|
||||
text += e.Key.ToString();
|
||||
}
|
||||
if (key == Key.Space)
|
||||
{
|
||||
text += "Space";
|
||||
}
|
||||
|
||||
tbHotkey.Text = text;
|
||||
}
|
||||
|
||||
private static bool IsKeyAChar(Key key)
|
||||
{
|
||||
return key >= Key.A && key <= Key.Z;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Threading;
|
||||
using NHotkey;
|
||||
using NHotkey.Wpf;
|
||||
using Wox.Commands;
|
||||
using Wox.Helper;
|
||||
using Wox.Infrastructure;
|
||||
@@ -18,19 +17,16 @@ using Wox.Plugin;
|
||||
using Wox.PluginLoader;
|
||||
using Application = System.Windows.Application;
|
||||
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
|
||||
using MessageBox = System.Windows.MessageBox;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
|
||||
namespace Wox
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
private KeyboardHook hook = new KeyboardHook();
|
||||
private NotifyIcon notifyIcon;
|
||||
Storyboard progressBarStoryboard = new Storyboard();
|
||||
private bool queryHasReturn = false;
|
||||
|
||||
private KeyboardListener keyboardListener = new KeyboardListener();
|
||||
private GloablHotkey globalHotkey = new GloablHotkey();
|
||||
private bool WinRStroked = false;
|
||||
private static object locker = new object();
|
||||
|
||||
@@ -41,8 +37,6 @@ namespace Wox
|
||||
InitializeComponent();
|
||||
|
||||
InitialTray();
|
||||
hook.KeyPressed += OnHotKey;
|
||||
hook.RegisterHotKey(XModifierKeys.Alt, Keys.Space);
|
||||
resultCtrl.resultItemChangedEvent += resultCtrl_resultItemChangedEvent;
|
||||
ThreadPool.SetMaxThreads(30, 10);
|
||||
InitProgressbarAnimation();
|
||||
@@ -55,9 +49,23 @@ namespace Wox
|
||||
SetTheme(CommonStorage.Instance.UserSetting.Theme = "Default");
|
||||
}
|
||||
|
||||
HotkeyManager.Current.AddOrReplace("ShowHideWox", Key.W, ModifierKeys.Windows, OnHotkey);
|
||||
this.Closing += MainWindow_Closing;
|
||||
}
|
||||
|
||||
private void OnHotkey(object sender, HotkeyEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
ShowWox();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideWox();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
@@ -114,18 +122,6 @@ namespace Wox
|
||||
resultCtrl.Margin = resultCtrl.GetCurrentResultCount() > 0 ? new Thickness { Top = grid.Margin.Top } : new Thickness { Top = 0 };
|
||||
}
|
||||
|
||||
private void OnHotKey(object sender, KeyPressedEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
ShowWox();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideWox();
|
||||
}
|
||||
}
|
||||
|
||||
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
resultCtrl.Dirty = true;
|
||||
@@ -215,7 +211,7 @@ namespace Wox
|
||||
WakeupApp();
|
||||
Plugins.Init();
|
||||
|
||||
keyboardListener.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
|
||||
globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback;
|
||||
}
|
||||
|
||||
private bool KListener_hookedKeyboardCallback(KeyEvent keyevent, int vkcode, SpecialKeyState state)
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Wox
|
||||
if (Result.Action != null)
|
||||
Result.Action(new ActionContext()
|
||||
{
|
||||
SpecialKeyState = new KeyboardListener().CheckModifiers()
|
||||
SpecialKeyState = new GloablHotkey().CheckModifiers()
|
||||
});
|
||||
|
||||
CommonStorage.Instance.UserSelectedRecords.Add(result);
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace Wox
|
||||
{
|
||||
resultItemControl.Result.Action(new ActionContext()
|
||||
{
|
||||
SpecialKeyState = new KeyboardListener().CheckModifiers()
|
||||
SpecialKeyState = new GloablHotkey().CheckModifiers()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<Window x:Class="Wox.SettingWidow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:wox="clr-namespace:Wox"
|
||||
Icon="Images\app.png"
|
||||
Title="Wox Setting"
|
||||
ResizeMode="NoResize"
|
||||
@@ -22,6 +23,9 @@
|
||||
<TextBlock Text="Theme:" />
|
||||
<ComboBox x:Name="themeComboBox" SelectionChanged="ThemeComboBox_OnSelectionChanged" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" Margin="10">
|
||||
<wox:HotkeyControl />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TabItem>
|
||||
<TabItem Header="Web Search">
|
||||
|
||||
@@ -89,6 +89,12 @@
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net35\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NHotkey">
|
||||
<HintPath>..\packages\NHotkey.1.1.0.0\lib\NHotkey.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NHotkey.Wpf">
|
||||
<HintPath>..\packages\NHotkey.Wpf.1.1.0.0\lib\NHotkey.Wpf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PresentationUI, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="ReachFramework" />
|
||||
<Reference Include="System" />
|
||||
@@ -120,11 +126,13 @@
|
||||
<Compile Include="Commands\PluginCommand.cs" />
|
||||
<Compile Include="Commands\SystemCommand.cs" />
|
||||
<Compile Include="DispatcherExtensions.cs" />
|
||||
<Compile Include="Helper\KeyboardHook.cs" />
|
||||
<Compile Include="Helper\Log.cs" />
|
||||
<Compile Include="Helper\PluginInstaller.cs" />
|
||||
<Compile Include="Helper\WoxException.cs" />
|
||||
<Compile Include="Helper\KeyboardListener.cs" />
|
||||
<Compile Include="Helper\GloablHotkey.cs" />
|
||||
<Compile Include="HotkeyControl.xaml.cs">
|
||||
<DependentUpon>HotkeyControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Msg.xaml.cs">
|
||||
<DependentUpon>Msg.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -140,15 +148,16 @@
|
||||
<Compile Include="ResultItem.xaml.cs">
|
||||
<DependentUpon>ResultItem.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ResultWindow.xaml.cs">
|
||||
<DependentUpon>ResultWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="SettingWindow.xaml.cs">
|
||||
<DependentUpon>SettingWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WebSearchSetting.xaml.cs">
|
||||
<DependentUpon>WebSearchSetting.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="HotkeyControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@@ -173,10 +182,6 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="ResultWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="SettingWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
<package id="InputSimulator" version="1.0.4.0" targetFramework="net35" />
|
||||
<package id="log4net" version="2.0.3" targetFramework="net35" />
|
||||
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="net35" />
|
||||
<package id="NHotkey" version="1.1.0.0" targetFramework="net35" />
|
||||
<package id="NHotkey.Wpf" version="1.1.0.0" targetFramework="net35" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net35" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user