2023-07-12 22:41:31 +00:00
using MSFSPopoutPanelManager.DomainModel.Profile ;
using MSFSPopoutPanelManager.DomainModel.Setting ;
using System ;
using System.Diagnostics ;
using System.Linq ;
using System.Threading ;
namespace MSFSPopoutPanelManager.WindowsAgent
{
public class WindowEventManager
{
private static PInvoke . WinEventProc _winEvent ; // keep this as static to prevent garbage collect or the app will crash
private static IntPtr _winEventHook ;
private static int? _prevShowWinCmd ;
public static UserProfile ActiveProfile { private get ; set ; }
public static ApplicationSetting ApplicationSetting { private get ; set ; }
public static void HookWinEvent ( )
{
if ( ActiveProfile = = null | | ActiveProfile . PanelConfigs = = null )
return ;
UnhookWinEvent ( ) ;
Debug . WriteLine ( "Executing HookWinEvent()..." ) ;
bool isRequiredPanelConfiguration = false ;
bool isUsedNontouchPanelRefocusLogic = false ;
if ( ( ! ActiveProfile . IsLocked | | ( ActiveProfile . IsLocked & & ApplicationSetting . PopOutSetting . EnablePanelResetWhenLocked ) )
& & ActiveProfile . PanelConfigs . Any ( p = > p . IsPopOutSuccess ! = null & & ( bool ) p . IsPopOutSuccess ) )
isRequiredPanelConfiguration = true ;
if ( ActiveProfile . PanelConfigs . Any ( p = > p . AutoGameRefocus & & ! p . TouchEnabled & & p . IsPopOutSuccess ! = null & & ( bool ) p . IsPopOutSuccess )
& & ! ActiveProfile . PanelConfigs . All ( p = > p . TouchEnabled )
& & ApplicationSetting . RefocusSetting . RefocusGameWindow . IsEnabled )
isUsedNontouchPanelRefocusLogic = true ;
uint winEventMin , winEventMax ;
if ( isRequiredPanelConfiguration & & isUsedNontouchPanelRefocusLogic )
{
winEventMin = PInvokeConstant . EVENT_SYSTEM_CAPTURESTART ;
winEventMax = PInvokeConstant . EVENT_OBJECT_STATECHANGE ;
}
else if ( isRequiredPanelConfiguration )
{
winEventMin = PInvokeConstant . EVENT_SYSTEM_MOVESIZEEND ;
winEventMax = PInvokeConstant . EVENT_OBJECT_STATECHANGE ;
}
else if ( isUsedNontouchPanelRefocusLogic )
{
winEventMin = PInvokeConstant . EVENT_SYSTEM_CAPTURESTART ;
winEventMax = PInvokeConstant . EVENT_SYSTEM_CAPTUREEND ;
}
else
{
return ;
}
_winEvent = new PInvoke . WinEventProc ( EventCallback ) ;
_winEventHook = PInvoke . SetWinEventHook ( winEventMin , winEventMax , IntPtr . Zero , _winEvent , 0 , 0 , PInvokeConstant . WINEVENT_OUTOFCONTEXT ) ;
Debug . WriteLine ( $"WinEventMin: {winEventMin} WinEventMax: {winEventMax}" ) ;
}
public static void UnhookWinEvent ( )
{
_prevShowWinCmd = null ;
// Unhook all Win API events
if ( _winEventHook ! = IntPtr . Zero )
{
Debug . WriteLine ( "Executing UnhookWinEvent()..." ) ;
PInvoke . UnhookWinEvent ( _winEventHook ) ;
}
}
private static void EventCallback ( IntPtr hWinEventHook , uint iEvent , IntPtr hwnd , int idObject , int idChild , int dwEventThread , int dwmsEventTime )
{
switch ( iEvent )
{
case PInvokeConstant . EVENT_SYSTEM_MOVESIZEEND :
case PInvokeConstant . EVENT_SYSTEM_CAPTURESTART :
case PInvokeConstant . EVENT_SYSTEM_CAPTUREEND :
if ( hwnd = = IntPtr . Zero | | idObject ! = 0 | | hWinEventHook ! = _winEventHook ) // check by priority to speed up comparing of escaping constraints
return ;
HandleEventCallback ( hwnd , iEvent ) ;
break ;
case PInvokeConstant . EVENT_OBJECT_STATECHANGE :
if ( hwnd = = IntPtr . Zero | | hWinEventHook ! = _winEventHook )
return ;
HandleEventCallback ( hwnd , iEvent ) ;
break ;
default :
break ;
}
}
private static void HandleEventCallback ( IntPtr hwnd , uint iEvent )
{
var panelConfig = ActiveProfile . PanelConfigs . FirstOrDefault ( panel = > panel . PanelHandle = = hwnd ) ;
if ( panelConfig = = null ) // Should not apply any other settings if panel is full screen mode
return ;
switch ( iEvent )
{
case PInvokeConstant . EVENT_OBJECT_STATECHANGE :
if ( ! ActiveProfile . IsLocked )
{
Thread . Sleep ( 300 ) ;
UpdatePanelCoordinates ( panelConfig ) ;
}
else
{
WINDOWPLACEMENT wp = new WINDOWPLACEMENT ( ) ;
wp . length = System . Runtime . InteropServices . Marshal . SizeOf ( wp ) ;
PInvoke . GetWindowPlacement ( hwnd , ref wp ) ;
if ( _prevShowWinCmd = = null )
{
_prevShowWinCmd = wp . showCmd ;
Thread . Sleep ( 250 ) ;
break ;
}
if ( wp . showCmd = = PInvokeConstant . SW_SHOWMAXIMIZED & & _prevShowWinCmd = = PInvokeConstant . SW_SHOWNORMAL )
PInvoke . ShowWindow ( hwnd , PInvokeConstant . SW_RESTORE ) ;
else if ( wp . showCmd = = PInvokeConstant . SW_SHOWMAXIMIZED & & _prevShowWinCmd = = PInvokeConstant . SW_SHOWMINIMIZED )
PInvoke . ShowWindow ( hwnd , PInvokeConstant . SW_SHOWMINIMIZED ) ;
else if ( wp . showCmd = = PInvokeConstant . SW_SHOWMINIMIZED & & _prevShowWinCmd = = PInvokeConstant . SW_SHOWNORMAL )
PInvoke . ShowWindow ( hwnd , PInvokeConstant . SW_RESTORE ) ;
else if ( wp . showCmd = = PInvokeConstant . SW_SHOWMINIMIZED & & _prevShowWinCmd = = PInvokeConstant . SW_SHOWMAXIMIZED )
PInvoke . ShowWindow ( hwnd , PInvokeConstant . SW_SHOWMAXIMIZED ) ;
else if ( wp . showCmd = = PInvokeConstant . SW_SHOWNORMAL & & _prevShowWinCmd = = PInvokeConstant . SW_SHOWMAXIMIZED )
PInvoke . ShowWindow ( hwnd , PInvokeConstant . SW_SHOWMAXIMIZED ) ;
else if ( wp . showCmd = = PInvokeConstant . SW_SHOWNORMAL & & _prevShowWinCmd = = PInvokeConstant . SW_SHOWMINIMIZED )
PInvoke . ShowWindow ( hwnd , PInvokeConstant . SW_SHOWMINIMIZED ) ;
else if ( wp . showCmd = = PInvokeConstant . SW_SHOWNORMAL & & _prevShowWinCmd = = PInvokeConstant . SW_SHOWNORMAL )
WindowActionManager . MoveWindow ( panelConfig . PanelHandle , panelConfig . Left , panelConfig . Top , panelConfig . Width , panelConfig . Height ) ;
_prevShowWinCmd = null ;
}
break ;
case PInvokeConstant . EVENT_SYSTEM_MOVESIZEEND :
if ( ActiveProfile . IsLocked )
WindowActionManager . MoveWindow ( panelConfig . PanelHandle , panelConfig . Left , panelConfig . Top , panelConfig . Width , panelConfig . Height ) ; // Move window back to original location
else
UpdatePanelCoordinates ( panelConfig ) ;
break ;
case PInvokeConstant . EVENT_SYSTEM_CAPTURESTART :
GameRefocusManager . HandleMouseDownEvent ( panelConfig ) ;
break ;
case PInvokeConstant . EVENT_SYSTEM_CAPTUREEND :
GameRefocusManager . HandleMouseUpEvent ( panelConfig ) ;
break ;
}
}
private static void UpdatePanelCoordinates ( PanelConfig panelConfig )
{
var rect = WindowActionManager . GetWindowRectangle ( panelConfig . PanelHandle ) ;
panelConfig . Left = rect . Left ;
panelConfig . Top = rect . Top ;
2023-07-21 21:45:16 +00:00
if ( panelConfig . PanelType = = PanelType . HudBarWindow )
return ;
2023-07-12 22:41:31 +00:00
panelConfig . Width = rect . Width ;
panelConfig . Height = rect . Height ;
}
}
}