2022-01-27 13:40:04 +00:00
using System ;
2022-07-06 18:09:10 +00:00
using System.Diagnostics ;
2022-01-27 13:40:04 +00:00
using System.Drawing ;
2021-12-14 05:40:07 +00:00
using System.Threading ;
2022-07-06 18:09:10 +00:00
using System.Threading.Tasks ;
2021-12-14 05:40:07 +00:00
namespace MSFSPopoutPanelManager.Provider
{
public class InputEmulationManager
{
const uint MOUSEEVENTF_LEFTDOWN = 0x02 ;
const uint MOUSEEVENTF_LEFTUP = 0x04 ;
const uint KEYEVENTF_EXTENDEDKEY = 0x01 ;
const uint KEYEVENTF_KEYDOWN = 0x0 ;
const uint KEYEVENTF_KEYUP = 0x2 ;
const uint VK_RMENU = 0xA5 ;
const uint VK_LMENU = 0xA4 ;
const uint VK_LCONTROL = 0xA2 ;
const uint VK_SPACE = 0x20 ;
2022-04-18 19:52:39 +00:00
const uint VK_ENT = 0x0D ;
2021-12-14 05:40:07 +00:00
const uint KEY_0 = 0x30 ;
public static void LeftClick ( int x , int y )
{
2022-07-10 23:58:54 +00:00
PInvoke . SetCursorPos ( x , y ) ;
2021-12-14 05:40:07 +00:00
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 ) ;
}
2022-06-13 03:49:56 +00:00
public static void LeftClickFast ( int x , int y )
{
PInvoke . mouse_event ( MOUSEEVENTF_LEFTDOWN , x , y , 0 , 0 ) ;
Thread . Sleep ( 50 ) ;
PInvoke . mouse_event ( MOUSEEVENTF_LEFTUP , x , y , 0 , 0 ) ;
}
2021-12-14 05:40:07 +00:00
public static void PopOutPanel ( int x , int y )
{
2022-02-07 03:05:05 +00:00
LeftClick ( x , y ) ;
Thread . Sleep ( 300 ) ;
2022-07-10 23:58:54 +00:00
PInvoke . SetCursorPos ( x , y ) ;
2021-12-14 05:40:07 +00:00
PInvoke . SetCursorPos ( x , y ) ;
Thread . Sleep ( 300 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_RMENU ) , 0 , KEYEVENTF_EXTENDEDKEY , 0 ) ;
PInvoke . mouse_event ( MOUSEEVENTF_LEFTDOWN , x , y , 0 , 0 ) ;
Thread . Sleep ( 200 ) ;
PInvoke . mouse_event ( MOUSEEVENTF_LEFTUP , x , y , 0 , 0 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_RMENU ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
}
2022-05-31 15:45:35 +00:00
public static void CenterView ( IntPtr hwnd )
2021-12-14 05:40:07 +00:00
{
2022-05-31 15:45:35 +00:00
Rectangle rectangle ;
PInvoke . GetWindowRect ( hwnd , out rectangle ) ;
Rectangle clientRectangle ;
PInvoke . GetClientRect ( hwnd , out clientRectangle ) ;
2022-06-30 23:53:08 +00:00
var x = Convert . ToInt32 ( rectangle . X + ( clientRectangle . Width ) * 0.5 ) ;
2022-05-31 15:45:35 +00:00
var y = Convert . ToInt32 ( rectangle . Y + ( clientRectangle . Height ) * 0.5 ) ;
2021-12-14 05:40:07 +00:00
PInvoke . SetForegroundWindow ( hwnd ) ;
2022-01-27 13:40:04 +00:00
LeftClick ( x , y ) ;
2021-12-14 05:40:07 +00:00
// First center view using Ctrl-Space
PInvoke . keybd_event ( Convert . ToByte ( VK_LCONTROL ) , 0 , KEYEVENTF_KEYDOWN , 0 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_SPACE ) , 0 , KEYEVENTF_KEYDOWN , 0 ) ;
Thread . Sleep ( 200 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_SPACE ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_LCONTROL ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
Thread . Sleep ( 200 ) ;
}
2022-04-18 03:38:33 +00:00
public static void SaveCustomView ( IntPtr hwnd , string keybinding )
2021-12-14 05:40:07 +00:00
{
2022-06-30 23:53:08 +00:00
uint customViewKey = ( uint ) ( Convert . ToInt32 ( keybinding ) + KEY_0 ) ;
2022-04-18 03:38:33 +00:00
2021-12-14 05:40:07 +00:00
PInvoke . SetForegroundWindow ( hwnd ) ;
Thread . Sleep ( 500 ) ;
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 ) ;
2022-04-18 03:38:33 +00:00
PInvoke . keybd_event ( Convert . ToByte ( customViewKey ) , 0 , KEYEVENTF_KEYDOWN , 0 ) ;
2021-12-14 05:40:07 +00:00
Thread . Sleep ( 200 ) ;
2022-04-18 03:38:33 +00:00
PInvoke . keybd_event ( Convert . ToByte ( customViewKey ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
2021-12-14 05:40:07 +00:00
PInvoke . keybd_event ( Convert . ToByte ( VK_LMENU ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_LCONTROL ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
}
2022-07-06 18:09:10 +00:00
public static void LoadCustomView ( string keybinding )
2021-12-14 05:40:07 +00:00
{
2022-07-06 18:09:10 +00:00
var simualatorProcess = DiagnosticManager . GetSimulatorProcess ( ) ;
if ( simualatorProcess ! = null )
{
// First center view to make sure recalling custom camera works on the first press
InputEmulationManager . CenterView ( simualatorProcess . Handle ) ;
2022-04-18 03:38:33 +00:00
2022-07-06 18:09:10 +00:00
uint customViewKey = ( uint ) ( Convert . ToInt32 ( keybinding ) + KEY_0 ) ;
2021-12-14 05:40:07 +00:00
2022-07-06 18:09:10 +00:00
PInvoke . SetForegroundWindow ( simualatorProcess . Handle ) ;
Thread . Sleep ( 300 ) ;
2021-12-14 05:40:07 +00:00
2022-07-06 18:09:10 +00:00
PInvoke . SetFocus ( simualatorProcess . Handle ) ;
Thread . Sleep ( 300 ) ;
2021-12-14 05:40:07 +00:00
2022-07-06 18:09:10 +00:00
// First center view using Ctrl-Space
PInvoke . keybd_event ( Convert . ToByte ( VK_LCONTROL ) , 0 , KEYEVENTF_KEYDOWN , 0 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_SPACE ) , 0 , KEYEVENTF_KEYDOWN , 0 ) ;
Thread . Sleep ( 200 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_SPACE ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_LCONTROL ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
Thread . Sleep ( 200 ) ;
// 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 ( 500 ) ;
}
2021-12-14 05:40:07 +00:00
}
2022-01-27 13:40:04 +00:00
2022-04-18 19:52:39 +00:00
public static void ToggleFullScreenPanel ( IntPtr hwnd )
{
PInvoke . SetForegroundWindow ( hwnd ) ;
Thread . Sleep ( 500 ) ;
PInvoke . SetFocus ( hwnd ) ;
Thread . Sleep ( 300 ) ;
PInvoke . keybd_event ( Convert . ToByte ( VK_RMENU ) , 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_RMENU ) , 0 , KEYEVENTF_KEYUP , 0 ) ;
}
2022-01-27 13:40:04 +00:00
public static void LeftClickReadyToFly ( )
{
var simualatorProcess = DiagnosticManager . GetSimulatorProcess ( ) ;
if ( simualatorProcess ! = null )
{
var hwnd = simualatorProcess . Handle ;
PInvoke . SetForegroundWindow ( hwnd ) ;
2022-06-24 14:24:31 +00:00
Thread . Sleep ( 250 ) ;
2022-01-27 13:40:04 +00:00
Rectangle rectangle ;
PInvoke . GetWindowRect ( hwnd , out rectangle ) ;
Rectangle clientRectangle ;
PInvoke . GetClientRect ( hwnd , out clientRectangle ) ;
2022-07-06 18:09:10 +00:00
// The "Ready to Fly" button is at about 94.7% width, 84% to 96.25% height (91.3% default) with interface scaling of 70 at the lower right corner of game window
2022-06-22 12:12:46 +00:00
// Try to click the area a few times to hit that button for both full screen and windows mode
2022-01-27 13:40:04 +00:00
2022-06-22 12:12:46 +00:00
var x = Convert . ToInt32 ( rectangle . X + ( clientRectangle . Width ) * 0.947 ) ;
2022-07-06 18:09:10 +00:00
var y = Convert . ToInt32 ( rectangle . Y + ( clientRectangle . Height ) * 0.84 ) ;
2022-06-30 23:53:08 +00:00
LeftClick ( x , y ) ;
2022-01-27 13:40:04 +00:00
LeftClick ( x , y ) ;
2022-06-30 23:53:08 +00:00
2022-07-06 18:09:10 +00:00
for ( var top = y ; top < y + ( clientRectangle . Height ) * 0.125 ; top = top + 10 )
2022-06-22 12:12:46 +00:00
{
2022-07-06 18:09:10 +00:00
Debug . WriteLine ( $"Trying to click at x: {x} y: {Convert.ToInt32(top)}" ) ;
PInvoke . SetCursorPos ( x , Convert . ToInt32 ( top ) ) ;
2022-06-22 12:12:46 +00:00
Thread . Sleep ( 100 ) ;
2022-07-06 18:09:10 +00:00
PInvoke . mouse_event ( MOUSEEVENTF_LEFTDOWN , x , Convert . ToInt32 ( top ) , 0 , 0 ) ;
Thread . Sleep ( 200 ) ;
PInvoke . mouse_event ( MOUSEEVENTF_LEFTUP , x , Convert . ToInt32 ( top ) , 0 , 0 ) ;
Thread . Sleep ( 200 ) ;
PInvoke . mouse_event ( MOUSEEVENTF_LEFTDOWN , x , Convert . ToInt32 ( top ) , 0 , 0 ) ;
Thread . Sleep ( 200 ) ;
PInvoke . mouse_event ( MOUSEEVENTF_LEFTUP , x , Convert . ToInt32 ( top ) , 0 , 0 ) ;
2022-06-22 12:12:46 +00:00
}
2022-01-27 13:40:04 +00:00
}
}
2021-12-14 05:40:07 +00:00
}
}