diff --git a/FsConnector/FsConnector.csproj b/FsConnector/FsConnector.csproj
index f5bc613..6b650b2 100644
--- a/FsConnector/FsConnector.csproj
+++ b/FsConnector/FsConnector.csproj
@@ -5,15 +5,15 @@
FsConnector
MSFS 2020 Popout Panel Manager FsConnector
MSFS 2020 Popout Panel Manager FsConnector
- 3.3.3.0
+ 3.4.0.0
Stanley Kwok
Stanley Kwok
Stanley Kwok 2021
https://github.com/hawkeye-stan/msfs-popout-panel-manager
MSFSPopoutPanelManager.FsConnector
x64;AnyCPU
- 3.3.3.0
- 3.3.3.0
+ 3.4.0.0
+ 3.4.0.0
diff --git a/Model/Model.csproj b/Model/Model.csproj
index 397c4f8..d89c978 100644
--- a/Model/Model.csproj
+++ b/Model/Model.csproj
@@ -5,15 +5,15 @@
MSFSPopoutPanelManager.Model
Model
MSFS 2020 Popout Panel Manager Model
- 3.3.3.0
+ 3.4.0.0
Stanley Kwok
Stanley Kwok
Stanley Kwok 2021
MSFS 2020 Popout Panel Manager Model
https://github.com/hawkeye-stan/msfs-popout-panel-manager
x64;AnyCPU
- 3.3.3.0
- 3.3.3.0
+ 3.4.0.0
+ 3.4.0.0
diff --git a/Model/PanelConfig.cs b/Model/PanelConfig.cs
index dae8d13..1fcfcd8 100644
--- a/Model/PanelConfig.cs
+++ b/Model/PanelConfig.cs
@@ -28,10 +28,45 @@ namespace MSFSPopoutPanelManager.Model
public bool FullScreen { get; set; }
+ public bool TouchEnabled { get; set; }
+
[JsonIgnore]
public bool IsCustomPopout { get { return PanelType == PanelType.CustomPopout; } }
[JsonIgnore]
public IntPtr PanelHandle { get; set; }
+
+ [JsonIgnore]
+ public bool IsLockable
+ {
+ get
+ {
+ switch (PanelType)
+ {
+ case PanelType.CustomPopout:
+ case PanelType.BuiltInPopout:
+ case PanelType.MSFSTouchPanel:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+
+ [JsonIgnore]
+ public bool HasTouchableEvent
+ {
+ get
+ {
+ switch (PanelType)
+ {
+ case PanelType.CustomPopout:
+ case PanelType.BuiltInPopout:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
}
}
diff --git a/Model/PanelConfigPropertyName.cs b/Model/PanelConfigPropertyName.cs
index 5c95694..43606c2 100644
--- a/Model/PanelConfigPropertyName.cs
+++ b/Model/PanelConfigPropertyName.cs
@@ -12,6 +12,7 @@ namespace MSFSPopoutPanelManager.Model
AlwaysOnTop,
HideTitlebar,
FullScreen,
+ TouchEnabled,
Invalid
}
diff --git a/Provider/InputEmulationManager.cs b/Provider/InputEmulationManager.cs
index fee2b07..9ea3fa4 100644
--- a/Provider/InputEmulationManager.cs
+++ b/Provider/InputEmulationManager.cs
@@ -28,6 +28,13 @@ namespace MSFSPopoutPanelManager.Provider
PInvoke.mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
}
+ 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);
+ }
+
public static void PopOutPanel(int x, int y)
{
LeftClick(x, y);
diff --git a/Provider/PInvoke.cs b/Provider/PInvoke.cs
index 39cf50d..cbfd721 100644
--- a/Provider/PInvoke.cs
+++ b/Provider/PInvoke.cs
@@ -16,6 +16,9 @@ namespace MSFSPopoutPanelManager.Provider
public const int SW_MINIMIZE = 6;
public const int SW_RESTORE = 9;
+ public const uint EVENT_SYSTEM_CAPTURESTART = 0x0008;
+ public const uint EVENT_SYSTEM_CAPTUREEND = 0x0009;
+ public const uint EVENT_SYSTEM_MOVESIZESTART = 0x000A;
public const uint EVENT_SYSTEM_MOVESIZEEND = 0x000B;
public const uint EVENT_OBJECT_LOCATIONCHANGE = 0x800B;
diff --git a/Provider/PanelConfigurationManager.cs b/Provider/PanelConfigurationManager.cs
index a344e4f..69ece4c 100644
--- a/Provider/PanelConfigurationManager.cs
+++ b/Provider/PanelConfigurationManager.cs
@@ -1,7 +1,10 @@
using MSFSPopoutPanelManager.Model;
using System;
+using System.Diagnostics;
using System.Drawing;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
namespace MSFSPopoutPanelManager.Provider
{
@@ -11,6 +14,8 @@ namespace MSFSPopoutPanelManager.Provider
private IntPtr _winEventHook;
private static PInvoke.WinEventProc _winEvent; // keep this as static to prevent garbage collect or the app will crash
private Rectangle _lastWindowRectangle;
+ private uint _prevWinEvent = PInvokeConstant.EVENT_SYSTEM_CAPTUREEND;
+ private int _winEventClickLock = 0;
public UserProfile UserProfile { get; set; }
@@ -26,7 +31,7 @@ namespace MSFSPopoutPanelManager.Provider
public void HookWinEvent()
{
// Setup panel config event hooks
- _winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, DiagnosticManager.GetApplicationProcess().Handle, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT);
+ _winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_CAPTURESTART, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, DiagnosticManager.GetApplicationProcess().Handle, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT);
}
public void UnhookWinEvent()
@@ -173,34 +178,46 @@ namespace MSFSPopoutPanelManager.Provider
private void EventCallback(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime)
{
- PanelConfig panelConfig;
-
- // check by priority to minimize escaping constraint
- if (hWnd == IntPtr.Zero
- || idObject != 0
- || hWinEventHook != _winEventHook
- || !AllowEdit
- || !(iEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE || iEvent == PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND)
- || UserProfile.PanelConfigs == null || UserProfile.PanelConfigs.Count == 0)
+ switch(iEvent)
{
- return;
- }
-
- if(UserProfile.IsLocked)
- {
- panelConfig = UserProfile.PanelConfigs.FirstOrDefault(panel => panel.PanelHandle == hWnd);
-
- if (panelConfig != null && panelConfig.PanelType == PanelType.CustomPopout)
- {
- // Move window back to original location if user profile is locked
- if (iEvent == PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND)
+ case PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE:
+ case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
+ case PInvokeConstant.EVENT_SYSTEM_CAPTURESTART:
+ case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
+ // check by priority to speed up comparing of escaping constraints
+ if (hWnd == IntPtr.Zero
+ || idObject != 0
+ || hWinEventHook != _winEventHook
+ || !AllowEdit
+ || UserProfile.PanelConfigs == null
+ || UserProfile.PanelConfigs.Count == 0)
{
- PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
return;
}
- if (iEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE)
- {
+ HandleEventCallback(hWnd, iEvent);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void HandleEventCallback(IntPtr hWnd, uint iEvent)
+ {
+ var panelConfig = UserProfile.PanelConfigs.FirstOrDefault(panel => panel.PanelHandle == hWnd);
+
+ if (panelConfig == null)
+ return;
+
+ if (panelConfig.IsLockable && UserProfile.IsLocked)
+ {
+ switch (iEvent)
+ {
+ case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
+ // Move window back to original location
+ PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
+ break;
+ case PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE:
// Detect if window is maximized, if so, save settings
WINDOWPLACEMENT wp = new WINDOWPLACEMENT();
wp.length = System.Runtime.InteropServices.Marshal.SizeOf(wp);
@@ -209,16 +226,19 @@ namespace MSFSPopoutPanelManager.Provider
{
PInvoke.ShowWindow(hWnd, PInvokeConstant.SW_RESTORE);
}
- return;
- }
+ break;
+ case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
+ if (!panelConfig.TouchEnabled || _prevWinEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE)
+ break;
+
+ if (!panelConfig.HasTouchableEvent || _prevWinEvent == PInvokeConstant.EVENT_SYSTEM_CAPTUREEND)
+ break;
+
+ HandleTouchEvent(panelConfig);
+ break;
}
-
- return;
}
-
- panelConfig = UserProfile.PanelConfigs.FirstOrDefault(panel => panel.PanelHandle == hWnd);
-
- if (panelConfig != null)
+ else
{
switch (iEvent)
{
@@ -260,8 +280,54 @@ namespace MSFSPopoutPanelManager.Provider
case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
_userProfileManager.WriteUserProfiles();
break;
+ case PInvokeConstant.EVENT_SYSTEM_CAPTUREEND:
+ if (!panelConfig.TouchEnabled || _prevWinEvent == PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE)
+ break;
+
+ if (!panelConfig.HasTouchableEvent || _prevWinEvent == PInvokeConstant.EVENT_SYSTEM_CAPTUREEND)
+ break;
+
+ HandleTouchEvent(panelConfig);
+ break;
}
}
+
+ _prevWinEvent = iEvent;
+ }
+
+ private void HandleTouchEvent(PanelConfig panelConfig)
+ {
+ Point point;
+ PInvoke.GetCursorPos(out point);
+
+ // Disable left clicking if user is touching the title bar area
+ if (point.Y - panelConfig.Top > (panelConfig.HideTitlebar ? 5 : 31))
+ {
+ var prevWinEventClickLock = ++_winEventClickLock;
+
+ UnhookWinEvent();
+ InputEmulationManager.LeftClickFast(point.X, point.Y);
+ HookWinEvent();
+
+ if (prevWinEventClickLock == _winEventClickLock)
+ {
+ Task.Run(() => RefocusMsfs(prevWinEventClickLock));
+ }
+ }
+ }
+
+ private async Task RefocusMsfs(int prevWinEventClickLock)
+ {
+ Thread.Sleep(1000);
+
+ if (prevWinEventClickLock == _winEventClickLock)
+ {
+ var simulatorProcess = DiagnosticManager.GetSimulatorProcess();
+
+ Rectangle rectangle;
+ PInvoke.GetWindowRect(simulatorProcess.Handle, out rectangle);
+ PInvoke.SetCursorPos(rectangle.X + 18, rectangle.Y + 80);
+ }
}
}
}
diff --git a/Provider/PanelPopoutManager.cs b/Provider/PanelPopoutManager.cs
index 1465688..2739302 100644
--- a/Provider/PanelPopoutManager.cs
+++ b/Provider/PanelPopoutManager.cs
@@ -215,13 +215,13 @@ namespace MSFSPopoutPanelManager.Provider
});
// Remove pop out that do not exist for this pop out iteration
- foreach(var panelConfig in UserProfile.PanelConfigs.ToList())
- {
- if(panelConfig.PanelHandle == IntPtr.Zero)
- {
- UserProfile.PanelConfigs.Remove(panelConfig);
- }
- }
+ //foreach(var panelConfig in UserProfile.PanelConfigs.ToList())
+ //{
+ // if(panelConfig.PanelHandle == IntPtr.Zero)
+ // {
+ // UserProfile.PanelConfigs.Remove(panelConfig);
+ // }
+ //}
Parallel.ForEach(UserProfile.PanelConfigs, panel =>
{
@@ -254,6 +254,14 @@ namespace MSFSPopoutPanelManager.Provider
PInvoke.MoveWindow(panel.PanelHandle, panel.Left, panel.Top, panel.Width, panel.Height, false);
Thread.Sleep(1000);
+ // Built-in panels (ie. Checklist, ATC) needs another window resize since there is a bug where when move between
+ // monitors, it changes its size
+ if(panel.PanelType == PanelType.BuiltInPopout)
+ {
+ PInvoke.MoveWindow(panel.PanelHandle, panel.Left, panel.Top, panel.Width, panel.Height, false);
+ Thread.Sleep(1000);
+ }
+
// Apply always on top
if (panel.AlwaysOnTop)
{
diff --git a/Provider/Provider.csproj b/Provider/Provider.csproj
index 5de1d98..8173c39 100644
--- a/Provider/Provider.csproj
+++ b/Provider/Provider.csproj
@@ -7,7 +7,7 @@
MSFSPopoutPanelManager.Provider
MSFS 2020 Popout Panel Manager Provider
MSFS 2020 Popout Panel Manager Provider
- 3.3.3.0
+ 3.4.0.0
Stanley Kwok
Stanley Kwok 2021
https://github.com/hawkeye-stan/msfs-popout-panel-manager
diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj
index 9d161e7..bfdb97f 100644
--- a/Shared/Shared.csproj
+++ b/Shared/Shared.csproj
@@ -9,10 +9,10 @@
Stanley Kwok
Stanley Kwok 2021
https://github.com/hawkeye-stan/msfs-popout-panel-manager
- 3.3.3.0
+ 3.4.0.0
AnyCPU;x64
true
- 3.3.3.0
+ 3.4.0.0
diff --git a/WpfApp/UserControlPanelConfiguration.xaml b/WpfApp/UserControlPanelConfiguration.xaml
index d31165f..e9694b3 100644
--- a/WpfApp/UserControlPanelConfiguration.xaml
+++ b/WpfApp/UserControlPanelConfiguration.xaml
@@ -91,10 +91,10 @@
-
+
-