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">
<HintPath>..\packages\SixLabors.ImageSharp.1.0.0-beta0006\lib\net472\SixLabors.ImageSharp.dll</HintPath>
</Reference>
<Reference Include="System" />
<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>
</Reference>

@ -4,17 +4,24 @@
namespace ClickableTransparentOverlay
{
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
using ImGuiNET;
/// <summary>
/// This class Hooks the Global Window Mouse/Keyboard events
/// and pass them into ImGui Overlay.
/// This class Hooks the Global Window Keyboard/Mouse events
/// 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>
public class HookController
{
private readonly Stack<HookControllerMessage> messages;
private IKeyboardMouseEvents myHook;
private bool enable;
private int windowX;
@ -31,12 +38,23 @@ namespace ClickableTransparentOverlay
/// </param>
public HookController(int x, int y)
{
this.messages = new Stack<HookControllerMessage>();
this.windowX = x;
this.windowY = y;
this.enable = true;
this.myHook = Hook.GlobalEvents();
}
private enum HookControllerMessageType
{
MouseUpDown,
MouseMove,
MouseWheel,
KeyUp,
KeyDown,
KeyPress,
}
/// <summary>
/// Enable this class functionality ( only call it once ).
/// </summary>
@ -101,9 +119,61 @@ namespace ClickableTransparentOverlay
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();
if (shouldSendToImGui)
{
switch (e.Button)
{
case MouseButtons.Left:
@ -128,36 +198,22 @@ namespace ClickableTransparentOverlay
// TODO: Make a Logger for the whole Overlay
break;
}
if (io.WantCaptureMouse)
{
e.Handled = true;
}
}
private void HookMouseUpExt(object sender, MouseEventExtArgs e)
else
{
if (this.enable)
{
this.MouseButtonFunction(e, false);
}
this.PushMessage(HookControllerMessageType.MouseUpDown, e, isDownEvent);
}
private void HookMouseDownExt(object sender, MouseEventExtArgs e)
{
if (this.enable)
if (io.WantCaptureMouse)
{
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();
io.MousePos = new Vector2(e.X - this.windowX, e.Y - this.windowY);
@ -165,23 +221,33 @@ namespace ClickableTransparentOverlay
// ImGui.GetIO().MouseDrawCursor = true;
// Window32 API ShowCursor(false)
}
private void HookMouseWheelExt(object sender, MouseEventExtArgs e)
else
{
if (!this.enable)
{
return;
this.PushMessage(HookControllerMessageType.MouseMove, e);
}
}
private void ProcessMouseWheel(MouseEventExtArgs e, bool shouldSendToImGui)
{
ImGuiIOPtr io = ImGui.GetIO();
if (io.WantCaptureMouse)
{
if (shouldSendToImGui)
{
io.MouseWheel = e.Delta / SystemInformation.MouseWheelScrollDelta;
}
else
{
this.PushMessage(HookControllerMessageType.MouseWheel, e);
}
e.Handled = true;
}
}
private void HookKeyUp(object sender, KeyEventArgs e)
private void ProcessKeyUp(KeyEventArgs e, bool shouldSendToImGui)
{
if (shouldSendToImGui)
{
var io = ImGui.GetIO();
io.KeysDown[e.KeyValue] = false;
@ -208,37 +274,60 @@ namespace ClickableTransparentOverlay
break;
}
}
private void HookKeyDown(object sender, KeyEventArgs e)
else
{
if (!this.enable)
{
return;
this.PushMessage(HookControllerMessageType.KeyUp, e);
}
}
private void ProcessKeyDown(KeyEventArgs e, bool shouldSendToImGui)
{
var io = ImGui.GetIO();
if (io.WantCaptureKeyboard)
{
if (shouldSendToImGui)
{
io.KeysDown[e.KeyValue] = true;
}
else
{
this.PushMessage(HookControllerMessageType.KeyDown, e);
}
switch (e.KeyCode)
{
case Keys.LWin:
case Keys.RWin:
if (shouldSendToImGui)
{
io.KeySuper = true;
}
break;
case Keys.LControlKey:
case Keys.RControlKey:
if (shouldSendToImGui)
{
io.KeyCtrl = true;
}
e.Handled = true;
break;
case Keys.LMenu: // LAlt is LMenu
case Keys.RMenu: // RAlt is RMenu
if (shouldSendToImGui)
{
io.KeyAlt = true;
}
break;
case Keys.LShiftKey:
case Keys.RShiftKey:
if (shouldSendToImGui)
{
io.KeyShift = true;
}
break;
default:
// 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)
{
if (!this.enable)
private void ProcessKeyPress(KeyPressEventArgs e, bool shouldSendToImGui)
{
return;
}
var io = ImGui.GetIO();
// 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 (shouldSendToImGui)
{
io.AddInputCharacter(e.KeyChar);
}
else
{
this.PushMessage(HookControllerMessageType.KeyPress, e);
}
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;
}
hookController.PopMessages();
if (!window.Exists)
{
break;

Loading…
Cancel
Save