1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-10-16 14:10:45 +00:00
msfs-popout-panel-manager/WindowsAgent/InputEmulationManager.cs
2024-02-27 21:44:21 -05:00

255 lines
No EOL
9.4 KiB
C#

using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using WindowsInput;
namespace MSFSPopoutPanelManager.WindowsAgent
{
public class InputEmulationManager
{
private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
private const uint MOUSEEVENTF_LEFTUP = 0x04;
private const uint KEYEVENTF_KEYDOWN = 0x0;
private const uint KEYEVENTF_KEYUP = 0x2;
private const uint VK_LMENU = 0xA4;
private const uint VK_LCONTROL = 0xA2;
private const uint VK_ENT = 0x0D;
private const uint KEY_0 = 0x30;
private const uint NUMPAD_0 = 0x60;
private const uint NUMPAD_1 = 0x61;
private const uint NUMPAD_2 = 0x62;
private const uint NUMPAD_3 = 0x63;
private const uint NUMPAD_4 = 0x64;
private const uint NUMPAD_5 = 0x65;
private const uint NUMPAD_6 = 0x66;
private const uint NUMPAD_7 = 0x67;
private const uint NUMPAD_8 = 0x68;
private const uint NUMPAD_9 = 0x69;
private const uint NUMPAD_DECIMAL = 0x6E;
private const uint NUMPAD_ADD = 0x6B;
private const uint NUMPAD_SUBTRACT = 0x6D;
private const uint NUMPAD_DIVIDE = 0x6F;
private const uint NUMPAD_MULTIPLY = 0x6A;
private const uint NUMPAD_ENTER = 0x0D;
private const uint NUMPAD_TAB = 0x09;
private static readonly InputSimulator InputSimulator = new ();
public static void LeftClick(int x, int y)
{
PInvoke.SetCursorPos(x, y);
Thread.Sleep(300);
PInvoke.mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
Thread.Sleep(200);
PInvoke.mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
Thread.Sleep(200);
}
public static void PrepareToPopOutPanel(int x, int y, bool isTurboMode)
{
PInvoke.SetForegroundWindow(WindowProcessManager.SimulatorProcess.Handle);
Thread.Sleep(isTurboMode ? 0 : 250);
MoveAppWindowFromLeftClickPoint(x, y);
LeftClick(x + 30, y); // Left click outside the circle area to focus game window
// Force cursor reset and focus
PInvoke.SetCursorPos(x, y);
Thread.Sleep(isTurboMode ? 50 : 500);
}
public static void PopOutPanel(int x, int y, bool useSecondaryKeys, bool isTurbo)
{
if (useSecondaryKeys)
{
InputSimulator.Keyboard.KeyDown(WindowsInput.Native.VirtualKeyCode.LCONTROL);
InputSimulator.Keyboard.KeyDown(WindowsInput.Native.VirtualKeyCode.RCONTROL);
Thread.Sleep(isTurbo ? 0: 500);
PInvoke.mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
Thread.Sleep(200);
PInvoke.mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
InputSimulator.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.RCONTROL);
InputSimulator.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.LCONTROL);
Thread.Sleep(100);
InputSimulator.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.RCONTROL); // resend to make sure Ctrl key is up
InputSimulator.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.LCONTROL);
}
else
{
InputSimulator.Keyboard.KeyDown(WindowsInput.Native.VirtualKeyCode.RMENU);
Thread.Sleep(isTurbo ? 0 : 500);
PInvoke.mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
Thread.Sleep(200);
PInvoke.mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
InputSimulator.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.RMENU);
Thread.Sleep(100);
InputSimulator.Keyboard.KeyUp(WindowsInput.Native.VirtualKeyCode.RMENU); // resend to make sure Alt key is up
}
}
public static void SaveCustomView(string keyBinding)
{
Debug.WriteLine("Saving custom view...");
if (WindowProcessManager.SimulatorProcess == null)
return;
var hWnd = WindowProcessManager.SimulatorProcess.Handle;
var customViewKey = (uint)(Convert.ToInt32(keyBinding) + KEY_0);
PInvoke.SetForegroundWindow(hWnd);
Thread.Sleep(200);
PInvoke.SetFocus(hWnd);
Thread.Sleep(300);
// Set view using Ctrl-Alt-0
PInvoke.keybd_event(Convert.ToByte(VK_LCONTROL), 0, KEYEVENTF_KEYDOWN, 0);
PInvoke.keybd_event(Convert.ToByte(VK_LMENU), 0, KEYEVENTF_KEYDOWN, 0);
PInvoke.keybd_event(Convert.ToByte(customViewKey), 0, KEYEVENTF_KEYDOWN, 0);
Thread.Sleep(200);
PInvoke.keybd_event(Convert.ToByte(customViewKey), 0, KEYEVENTF_KEYUP, 0);
PInvoke.keybd_event(Convert.ToByte(VK_LMENU), 0, KEYEVENTF_KEYUP, 0);
PInvoke.keybd_event(Convert.ToByte(VK_LCONTROL), 0, KEYEVENTF_KEYUP, 0);
Thread.Sleep(200);
}
public static void LoadCustomView(string keyBinding)
{
Debug.WriteLine("Loading custom view...");
if (WindowProcessManager.SimulatorProcess == null)
return;
var hWnd = WindowProcessManager.SimulatorProcess.Handle;
PInvoke.SetForegroundWindow(hWnd);
Thread.Sleep(200);
var customViewKey = (uint)(Convert.ToInt32(keyBinding) + KEY_0);
// Then load view using Alt-0
PInvoke.keybd_event(Convert.ToByte(VK_LMENU), 0, KEYEVENTF_KEYDOWN, 0);
PInvoke.keybd_event(Convert.ToByte(customViewKey), 0, KEYEVENTF_KEYDOWN, 0);
Thread.Sleep(200);
PInvoke.keybd_event(Convert.ToByte(customViewKey), 0, KEYEVENTF_KEYUP, 0);
PInvoke.keybd_event(Convert.ToByte(VK_LMENU), 0, KEYEVENTF_KEYUP, 0);
Thread.Sleep(200);
}
public static void ToggleFullScreenPanel(IntPtr hWnd)
{
PInvoke.SetForegroundWindow(hWnd);
Thread.Sleep(200);
PInvoke.SetFocus(hWnd);
Thread.Sleep(300);
PInvoke.keybd_event(Convert.ToByte(VK_LMENU), 0, KEYEVENTF_KEYDOWN, 0);
PInvoke.keybd_event(Convert.ToByte(VK_ENT), 0, KEYEVENTF_KEYDOWN, 0);
Thread.Sleep(200);
PInvoke.keybd_event(Convert.ToByte(VK_ENT), 0, KEYEVENTF_KEYUP, 0);
PInvoke.keybd_event(Convert.ToByte(VK_LMENU), 0, KEYEVENTF_KEYUP, 0);
Thread.Sleep(200);
}
public static void NumPadClick(string numPadKey)
{
var hWnd = WindowProcessManager.SimulatorProcess.Handle;
PInvoke.SetForegroundWindow(hWnd);
Thread.Sleep(200);
var key = NUMPAD_DECIMAL;
switch (numPadKey.ToUpper())
{
case "0":
key = NUMPAD_0;
break;
case "1":
key = NUMPAD_1;
break;
case "2":
key = NUMPAD_2;
break;
case "3":
key = NUMPAD_3;
break;
case "4":
key = NUMPAD_4;
break;
case "5":
key = NUMPAD_5;
break;
case "6":
key = NUMPAD_6;
break;
case "7":
key = NUMPAD_7;
break;
case "8":
key = NUMPAD_8;
break;
case "9":
key = NUMPAD_9;
break;
case "DECIMAL":
key = NUMPAD_DECIMAL;
break;
case "ADD":
key = NUMPAD_ADD;
break;
case "SUBTRACT":
key = NUMPAD_SUBTRACT;
break;
case "DIVIDE":
key = NUMPAD_DIVIDE;
break;
case "MULTIPLY":
key = NUMPAD_MULTIPLY;
break;
case "TAB":
key = NUMPAD_TAB;
break;
case "ENTER":
key = NUMPAD_ENTER;
break;
}
PInvoke.keybd_event(Convert.ToByte(key), 0, KEYEVENTF_KEYDOWN, 0);
Thread.Sleep(200);
PInvoke.keybd_event(Convert.ToByte(key), 0, KEYEVENTF_KEYUP, 0);
}
private static void MoveAppWindowFromLeftClickPoint(int x, int y)
{
var appHandle = WindowProcessManager.GetApplicationProcess().Handle;
var applicationRectangle = WindowActionManager.GetWindowRectangle(appHandle);
if (IsPointWithinRectangle(x, y, applicationRectangle))
{
var top = y - applicationRectangle.Height - 50;
WindowActionManager.MoveWindow(appHandle, applicationRectangle.X, top, applicationRectangle.Width, applicationRectangle.Height);
Thread.Sleep(1000);
}
}
private static bool IsPointWithinRectangle(int x, int y, Rectangle rect)
{
var rightEdge = rect.X + rect.Width;
var bottomEdge = rect.Y + rect.Height;
return x >= rect.X && x <= rightEdge && y >= rect.Y && y <= bottomEdge;
}
}
}