Added Support for queueing the Keyboard/Mouse events

before sending them to the ImGui

This featured can be turned on/off per event basis.
Currently, it is turned off for the Key Up/Down
and turned on for Key press, mouse Up/Down/Move
master
Zaafar Ahmed 6 years ago
parent 0d3f689f40
commit 0a4fc113f6
  1. 1
      ClickableTransparentOverlay/ClickableTransparentOverlay.csproj
  2. 242
      ClickableTransparentOverlay/HookController.cs
  3. 1
      ClickableTransparentOverlay/Overlay.cs

@ -86,6 +86,7 @@
<Reference Include="SixLabors.ImageSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="SixLabors.ImageSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SixLabors.ImageSharp.1.0.0-beta0006\lib\net472\SixLabors.ImageSharp.dll</HintPath> <HintPath>..\packages\SixLabors.ImageSharp.1.0.0-beta0006\lib\net472\SixLabors.ImageSharp.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath> <HintPath>..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference> </Reference>

@ -4,17 +4,24 @@
namespace ClickableTransparentOverlay namespace ClickableTransparentOverlay
{ {
using System;
using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using System.Windows.Forms; using System.Windows.Forms;
using Gma.System.MouseKeyHook; using Gma.System.MouseKeyHook;
using ImGuiNET; using ImGuiNET;
/// <summary> /// <summary>
/// This class Hooks the Global Window Mouse/Keyboard events /// This class Hooks the Global Window Keyboard/Mouse events
/// and pass them into ImGui Overlay. /// and pass them into the ImGui Overlay.
///
/// NOTE: This class might miss/skip a Keyboard/Mouse event
/// if ImGui render function takes a lot of time. Report on GitHub
/// if that happens.
/// </summary> /// </summary>
public class HookController public class HookController
{ {
private readonly Stack<HookControllerMessage> messages;
private IKeyboardMouseEvents myHook; private IKeyboardMouseEvents myHook;
private bool enable; private bool enable;
private int windowX; private int windowX;
@ -31,12 +38,23 @@ namespace ClickableTransparentOverlay
/// </param> /// </param>
public HookController(int x, int y) public HookController(int x, int y)
{ {
this.messages = new Stack<HookControllerMessage>();
this.windowX = x; this.windowX = x;
this.windowY = y; this.windowY = y;
this.enable = true; this.enable = true;
this.myHook = Hook.GlobalEvents(); this.myHook = Hook.GlobalEvents();
} }
private enum HookControllerMessageType
{
MouseUpDown,
MouseMove,
MouseWheel,
KeyUp,
KeyDown,
KeyPress,
}
/// <summary> /// <summary>
/// Enable this class functionality ( only call it once ). /// Enable this class functionality ( only call it once ).
/// </summary> /// </summary>
@ -101,9 +119,61 @@ namespace ClickableTransparentOverlay
this.myHook.Dispose(); this.myHook.Dispose();
} }
private void MouseButtonFunction(MouseEventExtArgs e, bool isDownEvent) /// <summary>
/// Tells the HookController if the ImGui is ready to accept keyboard/mouse messages.
/// </summary>
public void PopMessages()
{
int counter = 0;
int maxCounter = 10;
while (counter < maxCounter && this.messages.Count > 0)
{
var message = this.messages.Pop();
switch (message.Type)
{
case HookControllerMessageType.MouseUpDown:
this.ProcessMouseUpDown((MouseEventExtArgs)message.E, message.MiscArg, true);
break;
case HookControllerMessageType.MouseMove:
this.ProcessMouseMove((MouseEventArgs)message.E, true);
break;
case HookControllerMessageType.MouseWheel:
this.ProcessMouseWheel((MouseEventExtArgs)message.E, true);
break;
case HookControllerMessageType.KeyUp:
this.ProcessKeyUp((KeyEventArgs)message.E, true);
break;
case HookControllerMessageType.KeyDown:
this.ProcessKeyDown((KeyEventArgs)message.E, true);
break;
case HookControllerMessageType.KeyPress:
this.ProcessKeyPress((KeyPressEventArgs)message.E, true);
break;
default:
break;
}
counter++;
}
}
private void PushMessage(HookControllerMessageType type, EventArgs e, bool miscArg = false)
{
var message = new HookControllerMessage()
{
Type = type,
E = e,
MiscArg = miscArg,
};
this.messages.Push(message);
}
private void ProcessMouseUpDown(MouseEventExtArgs e, bool isDownEvent, bool shouldSendToImGui)
{ {
ImGuiIOPtr io = ImGui.GetIO(); ImGuiIOPtr io = ImGui.GetIO();
if (shouldSendToImGui)
{
switch (e.Button) switch (e.Button)
{ {
case MouseButtons.Left: case MouseButtons.Left:
@ -128,36 +198,22 @@ namespace ClickableTransparentOverlay
// TODO: Make a Logger for the whole Overlay // TODO: Make a Logger for the whole Overlay
break; break;
} }
if (io.WantCaptureMouse)
{
e.Handled = true;
}
} }
else
private void HookMouseUpExt(object sender, MouseEventExtArgs e)
{ {
if (this.enable) this.PushMessage(HookControllerMessageType.MouseUpDown, e, isDownEvent);
{
this.MouseButtonFunction(e, false);
}
} }
private void HookMouseDownExt(object sender, MouseEventExtArgs e) if (io.WantCaptureMouse)
{
if (this.enable)
{ {
this.MouseButtonFunction(e, true); e.Handled = true;
} }
} }
private void HookMouseMove(object sender, MouseEventArgs e) private void ProcessMouseMove(MouseEventArgs e, bool shouldSendToImGui)
{ {
if (!this.enable) if (shouldSendToImGui)
{ {
return;
}
ImGuiIOPtr io = ImGui.GetIO(); ImGuiIOPtr io = ImGui.GetIO();
io.MousePos = new Vector2(e.X - this.windowX, e.Y - this.windowY); io.MousePos = new Vector2(e.X - this.windowX, e.Y - this.windowY);
@ -165,23 +221,33 @@ namespace ClickableTransparentOverlay
// ImGui.GetIO().MouseDrawCursor = true; // ImGui.GetIO().MouseDrawCursor = true;
// Window32 API ShowCursor(false) // Window32 API ShowCursor(false)
} }
else
private void HookMouseWheelExt(object sender, MouseEventExtArgs e)
{ {
if (!this.enable) this.PushMessage(HookControllerMessageType.MouseMove, e);
{ }
return;
} }
private void ProcessMouseWheel(MouseEventExtArgs e, bool shouldSendToImGui)
{
ImGuiIOPtr io = ImGui.GetIO(); ImGuiIOPtr io = ImGui.GetIO();
if (io.WantCaptureMouse) if (io.WantCaptureMouse)
{
if (shouldSendToImGui)
{ {
io.MouseWheel = e.Delta / SystemInformation.MouseWheelScrollDelta; io.MouseWheel = e.Delta / SystemInformation.MouseWheelScrollDelta;
}
else
{
this.PushMessage(HookControllerMessageType.MouseWheel, e);
}
e.Handled = true; e.Handled = true;
} }
} }
private void HookKeyUp(object sender, KeyEventArgs e) private void ProcessKeyUp(KeyEventArgs e, bool shouldSendToImGui)
{
if (shouldSendToImGui)
{ {
var io = ImGui.GetIO(); var io = ImGui.GetIO();
io.KeysDown[e.KeyValue] = false; io.KeysDown[e.KeyValue] = false;
@ -208,37 +274,60 @@ namespace ClickableTransparentOverlay
break; break;
} }
} }
else
private void HookKeyDown(object sender, KeyEventArgs e)
{ {
if (!this.enable) this.PushMessage(HookControllerMessageType.KeyUp, e);
{ }
return;
} }
private void ProcessKeyDown(KeyEventArgs e, bool shouldSendToImGui)
{
var io = ImGui.GetIO(); var io = ImGui.GetIO();
if (io.WantCaptureKeyboard) if (io.WantCaptureKeyboard)
{
if (shouldSendToImGui)
{ {
io.KeysDown[e.KeyValue] = true; io.KeysDown[e.KeyValue] = true;
}
else
{
this.PushMessage(HookControllerMessageType.KeyDown, e);
}
switch (e.KeyCode) switch (e.KeyCode)
{ {
case Keys.LWin: case Keys.LWin:
case Keys.RWin: case Keys.RWin:
if (shouldSendToImGui)
{
io.KeySuper = true; io.KeySuper = true;
}
break; break;
case Keys.LControlKey: case Keys.LControlKey:
case Keys.RControlKey: case Keys.RControlKey:
if (shouldSendToImGui)
{
io.KeyCtrl = true; io.KeyCtrl = true;
}
e.Handled = true; e.Handled = true;
break; break;
case Keys.LMenu: // LAlt is LMenu case Keys.LMenu: // LAlt is LMenu
case Keys.RMenu: // RAlt is RMenu case Keys.RMenu: // RAlt is RMenu
if (shouldSendToImGui)
{
io.KeyAlt = true; io.KeyAlt = true;
}
break; break;
case Keys.LShiftKey: case Keys.LShiftKey:
case Keys.RShiftKey: case Keys.RShiftKey:
if (shouldSendToImGui)
{
io.KeyShift = true; io.KeyShift = true;
}
break; break;
default: default:
// Ignoring ALT key so we can do ALT+TAB or ALT+F4 etc. // Ignoring ALT key so we can do ALT+TAB or ALT+F4 etc.
@ -257,13 +346,8 @@ namespace ClickableTransparentOverlay
} }
} }
private void HookKeyPress(object sender, KeyPressEventArgs e) private void ProcessKeyPress(KeyPressEventArgs e, bool shouldSendToImGui)
{
if (!this.enable)
{ {
return;
}
var io = ImGui.GetIO(); var io = ImGui.GetIO();
// Ignoring Win/Super key so we can do Win+D or other stuff // Ignoring Win/Super key so we can do Win+D or other stuff
@ -275,10 +359,88 @@ namespace ClickableTransparentOverlay
} }
if (io.WantTextInput || io.WantCaptureKeyboard) if (io.WantTextInput || io.WantCaptureKeyboard)
{
if (shouldSendToImGui)
{ {
io.AddInputCharacter(e.KeyChar); io.AddInputCharacter(e.KeyChar);
}
else
{
this.PushMessage(HookControllerMessageType.KeyPress, e);
}
e.Handled = true; e.Handled = true;
} }
} }
private void HookMouseUpExt(object sender, MouseEventExtArgs e)
{
if (this.enable)
{
this.ProcessMouseUpDown(e, false, false);
}
}
private void HookMouseDownExt(object sender, MouseEventExtArgs e)
{
if (this.enable)
{
this.ProcessMouseUpDown(e, true, false);
}
}
private void HookMouseMove(object sender, MouseEventArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessMouseMove(e, false);
}
private void HookMouseWheelExt(object sender, MouseEventExtArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessMouseWheel(e, false);
}
private void HookKeyUp(object sender, KeyEventArgs e)
{
this.ProcessKeyUp(e, true);
}
private void HookKeyDown(object sender, KeyEventArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessKeyDown(e, true);
}
private void HookKeyPress(object sender, KeyPressEventArgs e)
{
if (!this.enable)
{
return;
}
this.ProcessKeyPress(e, false);
}
private struct HookControllerMessage
{
public HookControllerMessageType Type { get; set; }
public EventArgs E { get; set; }
public bool MiscArg { get; set; }
}
} }
} }

@ -245,6 +245,7 @@ namespace ClickableTransparentOverlay
continue; continue;
} }
hookController.PopMessages();
if (!window.Exists) if (!window.Exists)
{ {
break; break;

Loading…
Cancel
Save