diff --git a/Blish HUD/Common/Gw2/GuildWarsControls.cs b/Blish HUD/Common/Gw2/GuildWarsControls.cs
new file mode 100644
index 000000000..357e796d4
--- /dev/null
+++ b/Blish HUD/Common/Gw2/GuildWarsControls.cs
@@ -0,0 +1,22 @@
+namespace Blish_HUD.Common.Gw2 {
+ public enum GuildWarsControls {
+ None,
+ SwapWeapons,
+ WeaponSkill1,
+ WeaponSkill2,
+ WeaponSkill3,
+ WeaponSkill4,
+ WeaponSkill5,
+ HealingSkill,
+ UtilitySkill1,
+ UtilitySkill2,
+ UtilitySkill3,
+ EliteSkill,
+ ProfessionSkill1,
+ ProfessionSkill2,
+ ProfessionSkill3,
+ ProfessionSkill4,
+ ProfessionSkill5,
+ SpecialAction
+ }
+}
diff --git a/Blish HUD/Controls/Extern/HardwareInput.cs b/Blish HUD/Controls/Extern/HardwareInput.cs
index 8e1cde8a0..ee7867a78 100644
--- a/Blish HUD/Controls/Extern/HardwareInput.cs
+++ b/Blish HUD/Controls/Extern/HardwareInput.cs
@@ -1,7 +1,9 @@
+using System;
using System.Runtime.InteropServices;
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("HardwareInput is obsolete.", true)]
[StructLayout(LayoutKind.Sequential)]
internal struct HardwareInput
{
diff --git a/Blish HUD/Controls/Extern/Input.cs b/Blish HUD/Controls/Extern/Input.cs
index 725b13d9f..6e43bf459 100644
--- a/Blish HUD/Controls/Extern/Input.cs
+++ b/Blish HUD/Controls/Extern/Input.cs
@@ -1,7 +1,9 @@
+using System;
using System.Runtime.InteropServices;
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("Input is obsolete.", true)]
[StructLayout(LayoutKind.Sequential)]
internal struct Input
{
diff --git a/Blish HUD/Controls/Extern/InputType.cs b/Blish HUD/Controls/Extern/InputType.cs
index 1a1f62bb9..6387a147c 100644
--- a/Blish HUD/Controls/Extern/InputType.cs
+++ b/Blish HUD/Controls/Extern/InputType.cs
@@ -1,5 +1,8 @@
+using System;
+
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("InputType is obsolete.", true)]
internal enum InputType : uint
{
MOUSE = 0,
diff --git a/Blish HUD/Controls/Extern/InputUnion.cs b/Blish HUD/Controls/Extern/InputUnion.cs
index 98f0e8e6d..3bdaeec7d 100644
--- a/Blish HUD/Controls/Extern/InputUnion.cs
+++ b/Blish HUD/Controls/Extern/InputUnion.cs
@@ -1,7 +1,9 @@
+using System;
using System.Runtime.InteropServices;
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("InputUnion is obsolete.", true)]
[StructLayout(LayoutKind.Explicit)]
internal struct InputUnion
{
diff --git a/Blish HUD/Controls/Extern/KeyEventF.cs b/Blish HUD/Controls/Extern/KeyEventF.cs
index a67fee9d4..4219b8c2f 100644
--- a/Blish HUD/Controls/Extern/KeyEventF.cs
+++ b/Blish HUD/Controls/Extern/KeyEventF.cs
@@ -2,6 +2,7 @@
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("KeyEventF is obsolete.", true)]
[Flags]
internal enum KeyEventF : uint
{
diff --git a/Blish HUD/Controls/Extern/KeybdInput.cs b/Blish HUD/Controls/Extern/KeybdInput.cs
index 210869522..4521f1965 100644
--- a/Blish HUD/Controls/Extern/KeybdInput.cs
+++ b/Blish HUD/Controls/Extern/KeybdInput.cs
@@ -3,6 +3,7 @@
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("KeybdInput is obsolete.", true)]
[StructLayout(LayoutKind.Sequential)]
internal struct KeybdInput
{
diff --git a/Blish HUD/Controls/Extern/MouseEventF.cs b/Blish HUD/Controls/Extern/MouseEventF.cs
index 12fa652bd..e59262ff2 100644
--- a/Blish HUD/Controls/Extern/MouseEventF.cs
+++ b/Blish HUD/Controls/Extern/MouseEventF.cs
@@ -2,6 +2,7 @@
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("MouseEventF is obsolete.", true)]
[Flags]
internal enum MouseEventF : uint
{
diff --git a/Blish HUD/Controls/Extern/MouseInput.cs b/Blish HUD/Controls/Extern/MouseInput.cs
index f78710cf7..643b730f1 100644
--- a/Blish HUD/Controls/Extern/MouseInput.cs
+++ b/Blish HUD/Controls/Extern/MouseInput.cs
@@ -3,6 +3,7 @@
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("MouseInput is obsolete.", true)]
[StructLayout(LayoutKind.Sequential)]
internal struct MouseInput
{
diff --git a/Blish HUD/Controls/Extern/PInvoke.cs b/Blish HUD/Controls/Extern/PInvoke.cs
index fcec25d84..9fae08d7f 100644
--- a/Blish HUD/Controls/Extern/PInvoke.cs
+++ b/Blish HUD/Controls/Extern/PInvoke.cs
@@ -4,6 +4,7 @@
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("POINT is obsolete.", true)]
///
/// Struct representing a point.
///
@@ -16,7 +17,7 @@ public static implicit operator Point(POINT point) {
return new Point(point.X, point.Y);
}
}
-
+ [Obsolete("PInvoke is obsolete.", true)]
internal static class PInvoke {
[DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] Input[] pInputs, int cbSize);
diff --git a/Blish HUD/Controls/Extern/ScanCodeShort.cs b/Blish HUD/Controls/Extern/ScanCodeShort.cs
index 23650a3e6..882524bd2 100644
--- a/Blish HUD/Controls/Extern/ScanCodeShort.cs
+++ b/Blish HUD/Controls/Extern/ScanCodeShort.cs
@@ -1,5 +1,8 @@
+using System;
+
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("ScanCodeShort is obsolete.", true)]
internal enum ScanCodeShort : short
{
LBUTTON = 0,
diff --git a/Blish HUD/Controls/Extern/VirtualKeyShort.cs b/Blish HUD/Controls/Extern/VirtualKeyShort.cs
index 9a8ac9652..5e98e24ec 100644
--- a/Blish HUD/Controls/Extern/VirtualKeyShort.cs
+++ b/Blish HUD/Controls/Extern/VirtualKeyShort.cs
@@ -1,5 +1,8 @@
+using System;
+
namespace Blish_HUD.Controls.Extern
{
+ [Obsolete("VirtualKeyShort is obsolete. Please use Keys instead.", true)]
public enum VirtualKeyShort : short
{
///
diff --git a/Blish HUD/Controls/Intern/GuildWarsControls.cs b/Blish HUD/Controls/Intern/GuildWarsControls.cs
index f87b3fc38..f44a5d308 100644
--- a/Blish HUD/Controls/Intern/GuildWarsControls.cs
+++ b/Blish HUD/Controls/Intern/GuildWarsControls.cs
@@ -1,5 +1,8 @@
-namespace Blish_HUD.Controls.Intern
+using System;
+
+namespace Blish_HUD.Controls.Intern
{
+ [Obsolete("Controls.Intern.GuildWarsControls is obsolete. Please use Common.Gw2.GuildWarsControls instead.", true)]
public enum GuildWarsControls
{
None,
diff --git a/Blish HUD/Controls/Intern/Keyboard.cs b/Blish HUD/Controls/Intern/Keyboard.cs
index 512b422d4..203ba66d4 100644
--- a/Blish HUD/Controls/Intern/Keyboard.cs
+++ b/Blish HUD/Controls/Intern/Keyboard.cs
@@ -3,6 +3,7 @@
using Blish_HUD.Controls.Extern;
namespace Blish_HUD.Controls.Intern
{
+ [Obsolete("Keyboard is obsolete. Please use KeyboardUtil instead.", true)]
public static class Keyboard
{
private const uint WM_KEYDOWN = 0x0100;
@@ -179,6 +180,7 @@ public static void Stroke(VirtualKeyShort key, bool sendToSystem = false)
Release(key, sendToSystem);
}
}
+ [Obsolete("Controls.Intern.ExtraKeyInfo is obsolete. Please use ExtraKeyInfo instead.", true)]
class ExtraKeyInfo
{
public ushort repeatCount;
diff --git a/Blish HUD/Controls/Intern/Mouse.cs b/Blish HUD/Controls/Intern/Mouse.cs
index 951bab83a..a7d8c881a 100644
--- a/Blish HUD/Controls/Intern/Mouse.cs
+++ b/Blish HUD/Controls/Intern/Mouse.cs
@@ -4,6 +4,7 @@
using Blish_HUD.Controls.Extern;
namespace Blish_HUD.Controls.Intern
{
+ [Obsolete("Controls.Intern.MouseButton is obsolete. Please use MouseButton instead.", true)]
public enum MouseButton
{
LEFT,
@@ -11,6 +12,7 @@ public enum MouseButton
MIDDLE,
XBUTTON
}
+ [Obsolete("Mouse is obsolete. Please use MouseUtil instead.", true)]
public static class Mouse
{
private const uint WM_MOUSEWHEEL = 0x020A;
diff --git a/Blish HUD/GameServices/GameIntegrationService.cs b/Blish HUD/GameServices/GameIntegrationService.cs
index 4a0c1c790..24764657c 100644
--- a/Blish HUD/GameServices/GameIntegrationService.cs
+++ b/Blish HUD/GameServices/GameIntegrationService.cs
@@ -2,8 +2,6 @@
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
-using Blish_HUD.Controls.Extern;
-using Blish_HUD.Controls.Intern;
using Blish_HUD.GameIntegration;
using Blish_HUD.Settings;
using Microsoft.Xna.Framework;
@@ -164,11 +162,11 @@ await ClipboardUtil.WindowsClipboardService.SetTextAsync(message)
else
Task.Run(() => {
Focus();
- Keyboard.Press(VirtualKeyShort.LCONTROL, true);
- Keyboard.Stroke(VirtualKeyShort.KEY_V, true);
+ KeyboardUtil.Press(0xA2, true);
+ KeyboardUtil.Stroke(0x56, true);
Thread.Sleep(50);
- Keyboard.Release(VirtualKeyShort.LCONTROL, true);
- Keyboard.Stroke(VirtualKeyShort.RETURN);
+ KeyboardUtil.Release(0xA2, true);
+ KeyboardUtil.Stroke(0x0D);
}).ContinueWith(result => {
if (result.IsFaulted) {
Logger.Warn(result.Exception, "Failed to send message {message}", message);
@@ -191,10 +189,10 @@ await ClipboardUtil.WindowsClipboardService.SetTextAsync(text)
else
Task.Run(() => {
Focus();
- Keyboard.Press(VirtualKeyShort.LCONTROL, true);
- Keyboard.Stroke(VirtualKeyShort.KEY_V, true);
+ KeyboardUtil.Press(0xA2, true);
+ KeyboardUtil.Stroke(0x56, true);
Thread.Sleep(50);
- Keyboard.Release(VirtualKeyShort.LCONTROL, true);
+ KeyboardUtil.Release(0xA2, true);
}).ContinueWith(result => {
if (result.IsFaulted) {
Logger.Warn(result.Exception, "Failed to paste {text}", text);
@@ -210,11 +208,11 @@ public async Task GetInputText() {
byte[] prevClipboardContent = await ClipboardUtil.WindowsClipboardService.GetAsUnicodeBytesAsync();
await Task.Run(() => {
Focus();
- Keyboard.Press(VirtualKeyShort.LCONTROL, true);
- Keyboard.Stroke(VirtualKeyShort.KEY_A, true);
- Keyboard.Stroke(VirtualKeyShort.KEY_C, true);
+ KeyboardUtil.Press(0xA2, true);
+ KeyboardUtil.Stroke(0x41, true);
+ KeyboardUtil.Stroke(0x43, true);
Thread.Sleep(50);
- Keyboard.Release(VirtualKeyShort.LCONTROL, true);
+ KeyboardUtil.Release(0xA2, true);
Unfocus();
});
string inputText = await ClipboardUtil.WindowsClipboardService.GetTextAsync()
@@ -231,22 +229,22 @@ public void Clear() {
if (IsBusy()) return;
Task.Run(() => {
Focus();
- Keyboard.Press(VirtualKeyShort.LCONTROL, true);
- Keyboard.Stroke(VirtualKeyShort.KEY_A, true);
+ KeyboardUtil.Press(0xA2, true);
+ KeyboardUtil.Stroke(0x41, true);
Thread.Sleep(50);
- Keyboard.Release(VirtualKeyShort.LCONTROL, true);
- Keyboard.Stroke(VirtualKeyShort.BACK);
+ KeyboardUtil.Release(0xA2, true);
+ KeyboardUtil.Stroke(0x08);
Unfocus();
});
}
private void Focus() {
Unfocus();
- Keyboard.Stroke(VirtualKeyShort.RETURN);
+ KeyboardUtil.Stroke(0x0D);
}
private void Unfocus() {
- Mouse.Click(MouseButton.LEFT, Graphics.GraphicsDevice.Viewport.Width / 2, 0);
+ MouseUtil.Click(0, Graphics.GraphicsDevice.Viewport.Width / 2, 0);
}
private bool IsTextValid(string text) {
diff --git a/Blish HUD/GameServices/Input/WinApi/Input.cs b/Blish HUD/GameServices/Input/WinApi/Input.cs
new file mode 100644
index 000000000..ed0432578
--- /dev/null
+++ b/Blish HUD/GameServices/Input/WinApi/Input.cs
@@ -0,0 +1,32 @@
+using System.Runtime.InteropServices;
+namespace Blish_HUD.Input.WinApi {
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct Input {
+ internal InputType type;
+ internal InputUnion U;
+ internal static int Size => Marshal.SizeOf(typeof(Input));
+ }
+
+ internal enum InputType : uint {
+ MOUSE = 0,
+ KEYBOARD = 1,
+ HARDWARE = 2
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct InputUnion {
+ [FieldOffset(0)]
+ internal MouseUtil.MouseInput mi;
+ [FieldOffset(0)]
+ internal KeyboardUtil.KeybdInput ki;
+ [FieldOffset(0)]
+ internal HardwareInput hi;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct HardwareInput {
+ internal int uMsg;
+ internal short wParamL;
+ internal short wParamH;
+ }
+}
\ No newline at end of file
diff --git a/Blish HUD/_Utils/KeyboardUtil.cs b/Blish HUD/_Utils/KeyboardUtil.cs
new file mode 100644
index 000000000..cd6e8c119
--- /dev/null
+++ b/Blish HUD/_Utils/KeyboardUtil.cs
@@ -0,0 +1,211 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using InputType = Blish_HUD.Input.WinApi.InputType;
+using InputUnion = Blish_HUD.Input.WinApi.InputUnion;
+namespace Blish_HUD {
+ public static class KeyboardUtil {
+ private const uint WM_KEYDOWN = 0x0100;
+ private const uint WM_KEYUP = 0x0101;
+ private const uint WM_CHAR = 0x0102;
+ private const uint MAPVK_VK_TO_VSC = 0x00;
+ private const uint MAPVK_VSC_TO_VK = 0x01;
+ private const uint MAPVK_VK_TO_CHAR = 0x02;
+ private const uint MAPVK_VSC_TO_VK_EX = 0x03;
+ private const uint MAPVK_VK_TO_VSC_EX = 0x04;
+
+ [Flags]
+ internal enum KeyEventF : uint {
+ EXTENDEDKEY = 0x0001,
+ KEYUP = 0x0002,
+ SCANCODE = 0x0008,
+ UNICODE = 0x0004
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct KeybdInput {
+ internal short wVk;
+ internal short wScan;
+ internal KeyEventF dwFlags;
+ internal int time;
+ internal UIntPtr dwExtraInfo;
+ }
+
+ private static List ExtendedKeys = new List {
+ 0x2D, 0x24, 0x22,
+ 0x2E, 0x23, 0x21,
+ 0xA5, 0xA1, 0xA3,
+ 0x26, 0x28, 0x25,
+ 0x27, 0x90, 0x2A
+ };
+
+ [DllImport("user32.dll")]
+ private static extern uint MapVirtualKey(uint uCode, uint uMapType);
+
+ [DllImport("user32.dll")]
+ private static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] Input.WinApi.Input[] pInputs, int cbSize);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern bool PostMessage(IntPtr hWnd, uint msg, uint wParam, int lParam); // sends a message asynchronously.
+ ///
+ /// Presses a key.
+ ///
+ /// Virtual key code of the key to press.
+ /// Set if key message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void Press(int keyCode, bool sendToSystem = false) {
+ if (!GameService.GameIntegration.Gw2Instance.Gw2IsRunning || sendToSystem) {
+ Input.WinApi.Input[] nInputs;
+ if (ExtendedKeys.Contains(keyCode)) {
+ nInputs = new[]
+ {
+ new Input.WinApi.Input
+ {
+ type = InputType.KEYBOARD,
+ U = new InputUnion
+ {
+ ki = new KeybdInput
+ {
+ wScan = 224,
+ wVk = 0,
+ dwFlags = 0
+ }
+ }
+ },
+ new Input.WinApi.Input
+ {
+ type = InputType.KEYBOARD,
+ U = new InputUnion
+ {
+ ki = new KeybdInput
+ {
+ wScan = (short)MapVirtualKey((uint)keyCode, MAPVK_VK_TO_VSC),
+ wVk = (short)keyCode,
+ dwFlags = KeyEventF.EXTENDEDKEY
+ }
+ }
+ }
+ };
+ } else {
+ nInputs = new[]
+ {
+ new Input.WinApi.Input
+ {
+ type = InputType.KEYBOARD,
+ U = new InputUnion
+ {
+ ki = new KeybdInput
+ {
+ wScan = (short)MapVirtualKey((uint)keyCode, MAPVK_VK_TO_VSC),
+ wVk = (short)keyCode
+ }
+ }
+ }
+ };
+ }
+ SendInput((uint)nInputs.Length, nInputs, Input.WinApi.Input.Size);
+ } else {
+ uint vkCode = (uint)keyCode;
+ ExtraKeyInfo lParam = new ExtraKeyInfo {
+ scanCode = (char)MapVirtualKey(vkCode, MAPVK_VK_TO_VSC)
+ };
+
+ if (ExtendedKeys.Contains(keyCode))
+ lParam.extendedKey = 1;
+ PostMessage(GameService.GameIntegration.Gw2Instance.Gw2WindowHandle, WM_KEYDOWN, vkCode, lParam.GetInt());
+ }
+ }
+
+ ///
+ /// Releases a key.
+ ///
+ /// Virtual key code of the key to release.
+ /// Set if key message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void Release(int keyCode, bool sendToSystem = false) {
+ if (!GameService.GameIntegration.Gw2Instance.Gw2IsRunning || sendToSystem) {
+ Input.WinApi.Input[] nInputs;
+ if (ExtendedKeys.Contains(keyCode)) {
+ nInputs = new[]
+ {
+ new Input.WinApi.Input
+ {
+ type = InputType.KEYBOARD,
+ U = new InputUnion
+ {
+ ki = new KeybdInput
+ {
+ wScan = 224,
+ wVk = 0,
+ dwFlags = 0
+ }
+ }
+ },
+ new Input.WinApi.Input
+ {
+ type = InputType.KEYBOARD,
+ U = new InputUnion
+ {
+ ki = new KeybdInput
+ {
+ wScan = (short)MapVirtualKey((uint)keyCode, MAPVK_VK_TO_VSC),
+ wVk = (short)keyCode,
+ dwFlags = KeyEventF.EXTENDEDKEY | KeyEventF.KEYUP
+ }
+ }
+ }
+ };
+ } else {
+ nInputs = new[]
+ {
+ new Input.WinApi.Input
+ {
+ type = InputType.KEYBOARD,
+ U = new InputUnion
+ {
+ ki = new KeybdInput
+ {
+ wScan = (short)MapVirtualKey((uint)keyCode, MAPVK_VK_TO_VSC),
+ wVk = (short)keyCode,
+ dwFlags = KeyEventF.KEYUP
+ }
+ }
+ }
+ };
+ }
+ SendInput((uint)nInputs.Length, nInputs, Input.WinApi.Input.Size);
+ } else {
+ uint vkCode = (uint)keyCode;
+ ExtraKeyInfo lParam = new ExtraKeyInfo {
+ scanCode = (char)MapVirtualKey(vkCode, MAPVK_VK_TO_VSC),
+ repeatCount = 1,
+ prevKeyState = 1,
+ transitionState = 1
+ };
+
+ if (ExtendedKeys.Contains(keyCode))
+ lParam.extendedKey = 1;
+ PostMessage(GameService.GameIntegration.Gw2Instance.Gw2WindowHandle, WM_KEYUP, vkCode, lParam.GetInt());
+ }
+ }
+
+ ///
+ /// Performs a keystroke inwhich a key is pressed and immediately released once.
+ ///
+ /// Virtual key code of the key to stroke.
+ /// Set if key message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void Stroke(int keyCode, bool sendToSystem = false) {
+ Press(keyCode, sendToSystem);
+ Release(keyCode, sendToSystem);
+ }
+
+ private class ExtraKeyInfo {
+ public ushort repeatCount;
+ public char scanCode;
+ public ushort extendedKey, prevKeyState, transitionState;
+
+ public int GetInt() {
+ return repeatCount | (scanCode << 16) | (extendedKey << 24) |
+ (prevKeyState << 30) | (transitionState << 31);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blish HUD/_Utils/MouseUtil.cs b/Blish HUD/_Utils/MouseUtil.cs
new file mode 100644
index 000000000..14e69832a
--- /dev/null
+++ b/Blish HUD/_Utils/MouseUtil.cs
@@ -0,0 +1,307 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using Blish_HUD.Input.WinApi;
+namespace Blish_HUD {
+ public static class MouseUtil {
+ public enum MouseButton {
+ LEFT,
+ RIGHT,
+ MIDDLE,
+ XBUTTON
+ }
+
+ [Flags]
+ internal enum MouseEventF : uint {
+ ABSOLUTE = 0x8000,
+ HWHEEL = 0x01000,
+ MOVE = 0x0001,
+ MOVE_NOCOALESCE = 0x2000,
+ LEFTDOWN = 0x0002,
+ LEFTUP = 0x0004,
+ RIGHTDOWN = 0x0008,
+ RIGHTUP = 0x0010,
+ MIDDLEDOWN = 0x0020,
+ MIDDLEUP = 0x0040,
+ VIRTUALDESK = 0x4000,
+ WHEEL = 0x0800,
+ XDOWN = 0x0080,
+ XUP = 0x0100
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct MouseInput {
+ internal int dx;
+ internal int dy;
+ internal int mouseData;
+ internal MouseEventF dwFlags;
+ internal uint time;
+ internal UIntPtr dwExtraInfo;
+ }
+
+ private const uint WM_MOUSEWHEEL = 0x020A;
+ private const uint WM_MOUSEHWHEEL = 0x020E;
+ private const int WHEEL_DELTA = 120;
+ private const uint WM_MOUSEMOVE = 0x0200;
+
+ private static Dictionary ButtonPress = new Dictionary()
+ {
+ { MouseButton.LEFT, MouseEventF.LEFTDOWN },
+ { MouseButton.RIGHT, MouseEventF.RIGHTDOWN },
+ { MouseButton.MIDDLE, MouseEventF.MIDDLEDOWN },
+ { MouseButton.XBUTTON, MouseEventF.XDOWN }
+ };
+
+ private static Dictionary ButtonRelease = new Dictionary()
+ {
+ { MouseButton.LEFT, MouseEventF.LEFTUP },
+ { MouseButton.RIGHT, MouseEventF.RIGHTUP },
+ { MouseButton.MIDDLE, MouseEventF.MIDDLEUP },
+ { MouseButton.XBUTTON, MouseEventF.XUP }
+ };
+
+ private static Dictionary VirtualButtonShort = new Dictionary()
+ {
+ { MouseButton.LEFT, 0x01 },
+ { MouseButton.RIGHT, 0x02 },
+ { MouseButton.MIDDLE, 0x04 },
+ { MouseButton.XBUTTON, 0x05 }
+ };
+
+ private static Dictionary WM_BUTTONDOWN = new Dictionary()
+ {
+ { MouseButton.LEFT, 0x0201 },
+ { MouseButton.RIGHT, 0x0204 },
+ { MouseButton.MIDDLE, 0x0207 },
+ { MouseButton.XBUTTON, 0x020B }
+ };
+
+ private static Dictionary WM_BUTTONUP = new Dictionary()
+ {
+ { MouseButton.LEFT, 0x0202 },
+ { MouseButton.RIGHT, 0x0205 },
+ { MouseButton.MIDDLE, 0x0208 },
+ { MouseButton.XBUTTON, 0x020C }
+ };
+
+ private static Dictionary WM_BUTTONDBLCLK = new Dictionary()
+ {
+ { MouseButton.LEFT, 0x0203 },
+ { MouseButton.RIGHT, 0x0206 },
+ { MouseButton.MIDDLE, 0x0209 },
+ { MouseButton.XBUTTON, 0x020D }
+ };
+
+ ///
+ /// Struct representing a point.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ private struct POINT {
+ public int X;
+ public int Y;
+
+ public static implicit operator Point(POINT point) {
+ return new Point(point.X, point.Y);
+ }
+ }
+
+ [DllImport("user32.Dll", SetLastError = true)]
+ private static extern long SetCursorPos(int x, int y);
+
+ [DllImport("user32.dll")]
+ private static extern bool GetCursorPos(out POINT lpPoint);
+
+ [DllImport("user32.dll")]
+ private static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] Input.WinApi.Input[] pInputs, int cbSize);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern bool PostMessage(IntPtr hWnd, uint msg, uint wParam, int lParam); // sends a message asynchronously.
+
+ ///
+ /// Presses a mouse button.
+ ///
+ /// The mouse button to press.
+ /// The X coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current X coordinate.
+ /// The Y coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current Y coordinate.
+ /// Set if button message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void Press(MouseButton button, int xPos = -1, int yPos = -1, bool sendToSystem = false) {
+ if (xPos == -1 || yPos == -1) {
+ var pos = GetPosition();
+ xPos = pos.X;
+ yPos = pos.Y;
+ }
+
+ if (!GameService.GameIntegration.Gw2Instance.Gw2IsRunning || sendToSystem) {
+ var nInputs = new[]
+ {
+ new Input.WinApi.Input
+ {
+ type = InputType.MOUSE,
+ U = new InputUnion
+ {
+ mi = new MouseInput
+ {
+ dx = xPos,
+ dy = yPos,
+ mouseData = 0,
+ dwFlags = ButtonPress[button],
+ time = 0
+ }
+ }
+ }
+ };
+ SendInput((uint)nInputs.Length, nInputs, Input.WinApi.Input.Size);
+ } else {
+ uint wParam = (uint)VirtualButtonShort[button];
+ int lParam = xPos | (yPos << 16);
+ PostMessage(GameService.GameIntegration.Gw2Instance.Gw2WindowHandle, WM_BUTTONDOWN[button], wParam, lParam);
+ }
+ }
+
+ ///
+ /// Releases a mouse button.
+ ///
+ /// The mouse button to release.
+ /// The X coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current X coordinate.
+ /// The Y coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current Y coordinate.
+ /// Set if button message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void Release(MouseButton button, int xPos = -1, int yPos = -1, bool sendToSystem = false) {
+ if (xPos == -1 || yPos == -1) {
+ var pos = GetPosition();
+ xPos = pos.X;
+ yPos = pos.Y;
+ }
+ if (!GameService.GameIntegration.Gw2Instance.Gw2IsRunning || sendToSystem) {
+ var nInputs = new[]
+ {
+ new Input.WinApi.Input
+ {
+ type = InputType.MOUSE,
+ U = new InputUnion
+ {
+ mi = new MouseInput
+ {
+ dx = xPos,
+ dy = yPos,
+ mouseData = 0,
+ dwFlags = ButtonRelease[button],
+ time = 0
+ }
+ }
+ }
+ };
+ SendInput((uint)nInputs.Length, nInputs, Input.WinApi.Input.Size);
+ } else {
+ uint wParam = (uint)VirtualButtonShort[button];
+ int lParam = xPos | (yPos << 16);
+ PostMessage(GameService.GameIntegration.Gw2Instance.Gw2WindowHandle, WM_BUTTONUP[button], wParam, lParam);
+ }
+ }
+
+ ///
+ /// Rotates the mouse wheel.
+ ///
+ /// Distance of movement by multiples or divisions of 120 (WHEEL_DELTA). A positive value indicates the wheel to rotate forward, away from the user; a negative value indicates the wheel to rotate backward, toward the user.
+ /// Indicates the wheel to rotate horizontally.
+ /// The X coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current X coordinate.
+ /// The Y coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current Y coordinate.
+ /// Set if button message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void RotateWheel(int wheelDistance, bool horizontalWheel = false, int xPos = -1, int yPos = -1, bool sendToSystem = false) {
+ wheelDistance = wheelDistance % WHEEL_DELTA;
+ if (wheelDistance == 0) return;
+
+ if (xPos == -1 || yPos == -1) {
+ var pos = GetPosition();
+ xPos = pos.X;
+ yPos = pos.Y;
+ }
+ if (!GameService.GameIntegration.Gw2Instance.Gw2IsRunning || sendToSystem) {
+ var nInputs = new[]
+ {
+ new Input.WinApi.Input
+ {
+ type = InputType.MOUSE,
+ U = new InputUnion
+ {
+ mi = new MouseInput
+ {
+ dx = xPos,
+ dy = yPos,
+ mouseData = wheelDistance,
+ dwFlags = horizontalWheel ? MouseEventF.HWHEEL : MouseEventF.WHEEL,
+ time = 0
+ }
+ }
+ }
+ };
+ SendInput((uint)nInputs.Length, nInputs, Input.WinApi.Input.Size);
+ } else {
+ uint wParam = (uint)(0 | wheelDistance << 16);
+ int lParam = xPos | (yPos << 16);
+ PostMessage(GameService.GameIntegration.Gw2Instance.Gw2WindowHandle, horizontalWheel ? WM_MOUSEHWHEEL : WM_MOUSEWHEEL, wParam, lParam);
+ }
+ }
+
+ ///
+ /// Sets the cursors absolute screen position.
+ ///
+ /// The X coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current X coordinate.
+ /// The Y coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current Y coordinate.
+ /// Set if button message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void SetPosition(int xPos, int yPos, bool sendToSystem = false) {
+ if (!GameService.GameIntegration.Gw2Instance.Gw2IsRunning || sendToSystem) {
+ SetCursorPos(xPos, yPos);
+ } else {
+ int lParam = xPos | (yPos << 16);
+ PostMessage(GameService.GameIntegration.Gw2Instance.Gw2WindowHandle, WM_MOUSEMOVE, 0, lParam);
+ }
+ }
+
+ ///
+ /// Gets the cursors absolute screen position.
+ ///
+ public static Point GetPosition() {
+ POINT lpPoint;
+ GetCursorPos(out lpPoint);
+ return lpPoint;
+ }
+
+ ///
+ /// Presses and immediately releases a mouse button ONCE.
+ ///
+ /// The mouse button to click.
+ /// The X coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current X coordinate.
+ /// The Y coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current Y coordinate.
+ /// Set if button message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void Click(MouseButton button, int xPos = -1, int yPos = -1, bool sendToSystem = false) {
+ Press(button, xPos, yPos, sendToSystem);
+ Release(button, xPos, yPos, sendToSystem);
+ }
+
+ ///
+ /// Performs a double click of a mouse button.
+ ///
+ /// The mouse button to click.
+ /// The X coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current X coordinate.
+ /// The Y coodinate where this action takes place. Relative to the game client window if sendToSystem is not set. Default: current Y coordinate.
+ /// Set if button message (or a combination of such) cannot be correctly interpreted by the game client.
+ public static void DoubleClick(MouseButton button, int xPos = -1, int yPos = -1, bool sendToSystem = false) {
+ if (!GameService.GameIntegration.Gw2Instance.Gw2IsRunning || sendToSystem) {
+ for (int i = 0; i <= 1; i++) {
+ Press(button, xPos, yPos, sendToSystem);
+ Release(button, xPos, yPos, sendToSystem);
+ }
+ } else {
+ if (xPos == -1 || yPos == -1) {
+ var pos = GetPosition();
+ xPos = pos.X;
+ yPos = pos.Y;
+ }
+ uint wParam = (uint)VirtualButtonShort[button];
+ int lParam = xPos | (yPos << 16);
+ PostMessage(GameService.GameIntegration.Gw2Instance.Gw2WindowHandle, WM_BUTTONDBLCLK[button], wParam, lParam);
+ }
+ }
+ }
+}
\ No newline at end of file