Merged in homigoshzur/eve-o-preview-git-shortcuts/feature_keyboard_shortcuts (pull request #1)
Customizable keyboard shortcuts
This commit is contained in:
302
Hotkey.cs
Normal file
302
Hotkey.cs
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace MovablePython
|
||||||
|
{
|
||||||
|
public class Hotkey : IMessageFilter
|
||||||
|
{
|
||||||
|
#region Interop
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
private static extern int RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, Keys vk);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError=true)]
|
||||||
|
private static extern int UnregisterHotKey(IntPtr hWnd, int id);
|
||||||
|
|
||||||
|
private const uint WM_HOTKEY = 0x312;
|
||||||
|
|
||||||
|
private const uint MOD_ALT = 0x1;
|
||||||
|
private const uint MOD_CONTROL = 0x2;
|
||||||
|
private const uint MOD_SHIFT = 0x4;
|
||||||
|
private const uint MOD_WIN = 0x8;
|
||||||
|
|
||||||
|
private const uint ERROR_HOTKEY_ALREADY_REGISTERED = 1409;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private static int currentID;
|
||||||
|
private const int maximumID = 0xBFFF;
|
||||||
|
|
||||||
|
private Keys keyCode;
|
||||||
|
private bool shift;
|
||||||
|
private bool control;
|
||||||
|
private bool alt;
|
||||||
|
private bool windows;
|
||||||
|
|
||||||
|
[XmlIgnore]
|
||||||
|
private int id;
|
||||||
|
[XmlIgnore]
|
||||||
|
private bool registered;
|
||||||
|
[XmlIgnore]
|
||||||
|
private Control windowControl;
|
||||||
|
|
||||||
|
public event HandledEventHandler Pressed;
|
||||||
|
|
||||||
|
public Hotkey() : this(Keys.None, false, false, false, false)
|
||||||
|
{
|
||||||
|
// No work done here!
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hotkey(Keys keyCode, bool shift, bool control, bool alt, bool windows)
|
||||||
|
{
|
||||||
|
// Assign properties
|
||||||
|
this.KeyCode = keyCode;
|
||||||
|
this.Shift = shift;
|
||||||
|
this.Control = control;
|
||||||
|
this.Alt = alt;
|
||||||
|
this.Windows = windows;
|
||||||
|
|
||||||
|
// Register us as a message filter
|
||||||
|
Application.AddMessageFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Hotkey()
|
||||||
|
{
|
||||||
|
// Unregister the hotkey if necessary
|
||||||
|
if (this.Registered)
|
||||||
|
{ this.Unregister(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hotkey Clone()
|
||||||
|
{
|
||||||
|
// Clone the whole object
|
||||||
|
return new Hotkey(this.keyCode, this.shift, this.control, this.alt, this.windows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetCanRegister(Control windowControl)
|
||||||
|
{
|
||||||
|
// Handle any exceptions: they mean "no, you can't register" :)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Attempt to register
|
||||||
|
if (!this.Register(windowControl))
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
// Unregister and say we managed it
|
||||||
|
this.Unregister();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Win32Exception)
|
||||||
|
{ return false; }
|
||||||
|
catch (NotSupportedException)
|
||||||
|
{ return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Register(Control windowControl)
|
||||||
|
{
|
||||||
|
// Check that we have not registered
|
||||||
|
if (this.registered)
|
||||||
|
{ throw new NotSupportedException("You cannot register a hotkey that is already registered"); }
|
||||||
|
|
||||||
|
// We can't register an empty hotkey
|
||||||
|
if (this.Empty)
|
||||||
|
{ throw new NotSupportedException("You cannot register an empty hotkey"); }
|
||||||
|
|
||||||
|
// Get an ID for the hotkey and increase current ID
|
||||||
|
this.id = Hotkey.currentID;
|
||||||
|
Hotkey.currentID = Hotkey.currentID + 1 % Hotkey.maximumID;
|
||||||
|
|
||||||
|
// Translate modifier keys into unmanaged version
|
||||||
|
uint modifiers = (this.Alt ? Hotkey.MOD_ALT : 0) | (this.Control ? Hotkey.MOD_CONTROL : 0) |
|
||||||
|
(this.Shift ? Hotkey.MOD_SHIFT : 0) | (this.Windows ? Hotkey.MOD_WIN : 0);
|
||||||
|
|
||||||
|
// Register the hotkey
|
||||||
|
if (Hotkey.RegisterHotKey(windowControl.Handle, this.id, modifiers, keyCode) == 0)
|
||||||
|
{
|
||||||
|
// Is the error that the hotkey is registered?
|
||||||
|
if (Marshal.GetLastWin32Error() == ERROR_HOTKEY_ALREADY_REGISTERED)
|
||||||
|
{ return false; }
|
||||||
|
else
|
||||||
|
{ throw new Win32Exception(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the control reference and register state
|
||||||
|
this.registered = true;
|
||||||
|
this.windowControl = windowControl;
|
||||||
|
|
||||||
|
// We successfully registered
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unregister()
|
||||||
|
{
|
||||||
|
// Check that we have registered
|
||||||
|
if (!this.registered)
|
||||||
|
{ throw new NotSupportedException("You cannot unregister a hotkey that is not registered"); }
|
||||||
|
|
||||||
|
// It's possible that the control itself has died: in that case, no need to unregister!
|
||||||
|
if (!this.windowControl.IsDisposed)
|
||||||
|
{
|
||||||
|
// Clean up after ourselves
|
||||||
|
if (Hotkey.UnregisterHotKey(this.windowControl.Handle, this.id) == 0)
|
||||||
|
{ throw new Win32Exception(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the control reference and register state
|
||||||
|
this.registered = false;
|
||||||
|
this.windowControl = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Reregister()
|
||||||
|
{
|
||||||
|
// Only do something if the key is already registered
|
||||||
|
if (!this.registered)
|
||||||
|
{ return; }
|
||||||
|
|
||||||
|
// Save control reference
|
||||||
|
Control windowControl = this.windowControl;
|
||||||
|
|
||||||
|
// Unregister and then reregister again
|
||||||
|
this.Unregister();
|
||||||
|
this.Register(windowControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool PreFilterMessage(ref Message message)
|
||||||
|
{
|
||||||
|
// Only process WM_HOTKEY messages
|
||||||
|
if (message.Msg != Hotkey.WM_HOTKEY)
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
// Check that the ID is our key and we are registerd
|
||||||
|
if (this.registered && (message.WParam.ToInt32() == this.id))
|
||||||
|
{
|
||||||
|
// Fire the event and pass on the event if our handlers didn't handle it
|
||||||
|
return this.OnPressed();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool OnPressed()
|
||||||
|
{
|
||||||
|
// Fire the event if we can
|
||||||
|
HandledEventArgs handledEventArgs = new HandledEventArgs(false);
|
||||||
|
if (this.Pressed != null)
|
||||||
|
{ this.Pressed(this, handledEventArgs); }
|
||||||
|
|
||||||
|
// Return whether we handled the event or not
|
||||||
|
return handledEventArgs.Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
// We can be empty
|
||||||
|
if (this.Empty)
|
||||||
|
{ return "(none)"; }
|
||||||
|
|
||||||
|
// Build key name
|
||||||
|
string keyName = Enum.GetName(typeof(Keys), this.keyCode);;
|
||||||
|
switch (this.keyCode)
|
||||||
|
{
|
||||||
|
case Keys.D0:
|
||||||
|
case Keys.D1:
|
||||||
|
case Keys.D2:
|
||||||
|
case Keys.D3:
|
||||||
|
case Keys.D4:
|
||||||
|
case Keys.D5:
|
||||||
|
case Keys.D6:
|
||||||
|
case Keys.D7:
|
||||||
|
case Keys.D8:
|
||||||
|
case Keys.D9:
|
||||||
|
// Strip the first character
|
||||||
|
keyName = keyName.Substring(1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Leave everything alone
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build modifiers
|
||||||
|
string modifiers = "";
|
||||||
|
if (this.shift)
|
||||||
|
{ modifiers += "Shift+"; }
|
||||||
|
if (this.control)
|
||||||
|
{ modifiers += "Control+"; }
|
||||||
|
if (this.alt)
|
||||||
|
{ modifiers += "Alt+"; }
|
||||||
|
if (this.windows)
|
||||||
|
{ modifiers += "Windows+"; }
|
||||||
|
|
||||||
|
// Return result
|
||||||
|
return modifiers + keyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Empty
|
||||||
|
{
|
||||||
|
get { return this.keyCode == Keys.None; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Registered
|
||||||
|
{
|
||||||
|
get { return this.registered; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Keys KeyCode
|
||||||
|
{
|
||||||
|
get { return this.keyCode; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Save and reregister
|
||||||
|
this.keyCode = value;
|
||||||
|
this.Reregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Shift
|
||||||
|
{
|
||||||
|
get { return this.shift; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Save and reregister
|
||||||
|
this.shift = value;
|
||||||
|
this.Reregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Control
|
||||||
|
{
|
||||||
|
get { return this.control; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Save and reregister
|
||||||
|
this.control = value;
|
||||||
|
this.Reregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Alt
|
||||||
|
{
|
||||||
|
get { return this.alt; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Save and reregister
|
||||||
|
this.alt = value;
|
||||||
|
this.Reregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Windows
|
||||||
|
{
|
||||||
|
get { return this.windows; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Save and reregister
|
||||||
|
this.windows = value;
|
||||||
|
this.Reregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Preview.cs
46
Preview.cs
@@ -6,6 +6,7 @@ using System.Text;
|
|||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using MovablePython;
|
||||||
|
|
||||||
namespace PreviewToy
|
namespace PreviewToy
|
||||||
{
|
{
|
||||||
@@ -26,6 +27,7 @@ namespace PreviewToy
|
|||||||
private bool has_been_set_up = false;
|
private bool has_been_set_up = false;
|
||||||
private bool thumbnail_has_been_set_up = false;
|
private bool thumbnail_has_been_set_up = false;
|
||||||
private PreviewToyHandler spawner;
|
private PreviewToyHandler spawner;
|
||||||
|
private Hotkey hotkey;
|
||||||
|
|
||||||
private bool hide = false;
|
private bool hide = false;
|
||||||
|
|
||||||
@@ -41,6 +43,8 @@ namespace PreviewToy
|
|||||||
return this.Text;
|
return this.Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void MakeTopMost(bool topmost)
|
public void MakeTopMost(bool topmost)
|
||||||
{
|
{
|
||||||
this.TopMost = topmost && !(this.hide);
|
this.TopMost = topmost && !(this.hide);
|
||||||
@@ -66,6 +70,8 @@ namespace PreviewToy
|
|||||||
this.old_position = this.Location;
|
this.old_position = this.Location;
|
||||||
|
|
||||||
has_been_set_up = true;
|
has_been_set_up = true;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void preview_MouseHover(object sender, System.EventArgs e)
|
public void preview_MouseHover(object sender, System.EventArgs e)
|
||||||
@@ -84,6 +90,46 @@ namespace PreviewToy
|
|||||||
RefreshPreview();
|
RefreshPreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override CreateParams CreateParams
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var Params = base.CreateParams;
|
||||||
|
Params.ExStyle |= 0x80;
|
||||||
|
return Params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerShortcut(string shortcut)
|
||||||
|
{
|
||||||
|
if (shortcut == "")
|
||||||
|
return;
|
||||||
|
var cvt = new KeysConverter();
|
||||||
|
var key = (Keys)cvt.ConvertFrom(shortcut);
|
||||||
|
|
||||||
|
Hotkey hotkey = new Hotkey();
|
||||||
|
|
||||||
|
if ((key & Keys.Shift) == Keys.Shift)
|
||||||
|
{
|
||||||
|
hotkey.Shift = true;
|
||||||
|
}
|
||||||
|
if ((key & Keys.Alt) == Keys.Alt)
|
||||||
|
{
|
||||||
|
hotkey.Alt = true;
|
||||||
|
}
|
||||||
|
if ((key & Keys.Control) == Keys.Control)
|
||||||
|
{
|
||||||
|
hotkey.Control = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = key & ~Keys.Shift & ~Keys.Alt & ~Keys.Control;
|
||||||
|
hotkey.KeyCode = key;
|
||||||
|
hotkey.Register(this);
|
||||||
|
hotkey.Pressed += delegate { bring_client_to_foreground(); spawner.preview_did_switch(); };
|
||||||
|
|
||||||
|
this.hotkey = hotkey;
|
||||||
|
}
|
||||||
|
|
||||||
public void doZoom()
|
public void doZoom()
|
||||||
{
|
{
|
||||||
if (is_zoomed)
|
if (is_zoomed)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace PreviewToy
|
|||||||
|
|
||||||
private Dictionary<String, Dictionary<String, Point>> unique_layouts;
|
private Dictionary<String, Dictionary<String, Point>> unique_layouts;
|
||||||
private Dictionary<String, Point> flat_layout;
|
private Dictionary<String, Point> flat_layout;
|
||||||
|
private Dictionary<String, String> flat_layout_shortcuts;
|
||||||
private Dictionary<String, ClientLocation> client_layout;
|
private Dictionary<String, ClientLocation> client_layout;
|
||||||
|
|
||||||
private bool is_initialized;
|
private bool is_initialized;
|
||||||
@@ -89,6 +90,7 @@ namespace PreviewToy
|
|||||||
|
|
||||||
unique_layouts = new Dictionary<String, Dictionary<String, Point>>();
|
unique_layouts = new Dictionary<String, Dictionary<String, Point>>();
|
||||||
flat_layout = new Dictionary<String, Point>();
|
flat_layout = new Dictionary<String, Point>();
|
||||||
|
flat_layout_shortcuts = new Dictionary<String, String>();
|
||||||
client_layout = new Dictionary<String, ClientLocation>();
|
client_layout = new Dictionary<String, ClientLocation>();
|
||||||
|
|
||||||
ignoring_size_sync = new Stopwatch();
|
ignoring_size_sync = new Stopwatch();
|
||||||
@@ -197,6 +199,8 @@ namespace PreviewToy
|
|||||||
else if (previews.ContainsKey(process.MainWindowHandle) && process.MainWindowTitle != previews[process.MainWindowHandle].Text) //or update the preview titles
|
else if (previews.ContainsKey(process.MainWindowHandle) && process.MainWindowTitle != previews[process.MainWindowHandle].Text) //or update the preview titles
|
||||||
{
|
{
|
||||||
previews[process.MainWindowHandle].SetLabel(process.MainWindowTitle);
|
previews[process.MainWindowHandle].SetLabel(process.MainWindowTitle);
|
||||||
|
string key = previews[process.MainWindowHandle].Text;
|
||||||
|
previews[process.MainWindowHandle].registerShortcut(flat_layout_shortcuts[key]);
|
||||||
refresh_client_window_locations(process);
|
refresh_client_window_locations(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,6 +303,12 @@ namespace PreviewToy
|
|||||||
foreach (var el in rootElement.Elements())
|
foreach (var el in rootElement.Elements())
|
||||||
{
|
{
|
||||||
flat_layout[ParseXElement(el)] = new Point(Convert.ToInt32(el.Element("x").Value), Convert.ToInt32(el.Element("y").Value));
|
flat_layout[ParseXElement(el)] = new Point(Convert.ToInt32(el.Element("x").Value), Convert.ToInt32(el.Element("y").Value));
|
||||||
|
flat_layout_shortcuts[ParseXElement(el)] = "";
|
||||||
|
|
||||||
|
if (el.Element("shortcut") != null)
|
||||||
|
{
|
||||||
|
flat_layout_shortcuts[ParseXElement(el)] = el.Element("shortcut").Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,6 +365,7 @@ namespace PreviewToy
|
|||||||
XElement layout = MakeXElement(clientKV.Key);
|
XElement layout = MakeXElement(clientKV.Key);
|
||||||
layout.Add(new XElement("x", clientKV.Value.X));
|
layout.Add(new XElement("x", clientKV.Value.X));
|
||||||
layout.Add(new XElement("y", clientKV.Value.Y));
|
layout.Add(new XElement("y", clientKV.Value.Y));
|
||||||
|
layout.Add(new XElement("shortcut", flat_layout_shortcuts[clientKV.Key]));
|
||||||
el2.Add(layout);
|
el2.Add(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,5 +41,15 @@ namespace PreviewToy
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override CreateParams CreateParams
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var Params = base.CreateParams;
|
||||||
|
Params.ExStyle |= 0x80;
|
||||||
|
return Params;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,6 +95,7 @@
|
|||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Hotkey.cs" />
|
||||||
<Compile Include="PreviewHandler.cs">
|
<Compile Include="PreviewHandler.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
Reference in New Issue
Block a user