1
0
Fork 0
mirror of https://github.com/hawkeye-stan/msfs-popout-panel-manager.git synced 2024-10-16 06:00:45 +00:00

Clean up and reformat code

This commit is contained in:
Stanley 2022-06-30 19:53:08 -04:00
parent 4bd472f1d9
commit 93442a0150
52 changed files with 469 additions and 462 deletions

View file

@ -1,5 +1,4 @@

namespace MSFSPopoutPanelManager.FsConnector
namespace MSFSPopoutPanelManager.FsConnector
{
public enum SimConnectDefinition
{
@ -8,7 +7,7 @@ namespace MSFSPopoutPanelManager.FsConnector
public enum NotificationGroup
{
GROUP0,
GROUP0
}
public enum DataRequest
@ -23,7 +22,7 @@ namespace MSFSPopoutPanelManager.FsConnector
SIMSTOP,
FLIGHTLOADED,
VIEW,
PAUSED,
PAUSED,
NONE
};
}

View file

@ -11,7 +11,7 @@
<Copyright>Stanley Kwok 2021</Copyright>
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<RootNamespace>MSFSPopoutPanelManager.FsConnector</RootNamespace>
<Platforms>x64;AnyCPU</Platforms>
<Platforms>x64</Platforms>
<AssemblyVersion>3.3.4.0</AssemblyVersion>
<FileVersion>3.3.4.0</FileVersion>
</PropertyGroup>

View file

@ -1,5 +1,4 @@

using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
namespace MSFSPopoutPanelManager.FsConnector
{

View file

@ -6,7 +6,6 @@ using System.Diagnostics;
using System.Dynamic;
using System.Runtime.InteropServices;
namespace MSFSPopoutPanelManager.FsConnector
{
public class SimConnector
@ -34,7 +33,7 @@ namespace MSFSPopoutPanelManager.FsConnector
{
if (_simConnect == null)
{
_simConnect = new SimConnect("MSFS Pop Out Panel Manager", Process.GetCurrentProcess().MainWindowHandle, WM_USER_SIMCONNECT, null, 0);
_simConnect = new SimConnect("MSFS Pop Out Panel Manager", Process.GetCurrentProcess().MainWindowHandle, WM_USER_SIMCONNECT, null, 0);
_simConnect.OnRecvQuit += HandleOnRecvQuit;
_simConnect.OnRecvException += HandleOnRecvException;
@ -162,7 +161,7 @@ namespace MSFSPopoutPanelManager.FsConnector
{
var exception = (SIMCONNECT_EXCEPTION)data.dwException;
switch(exception)
switch (exception)
{
case SIMCONNECT_EXCEPTION.DATA_ERROR:
case SIMCONNECT_EXCEPTION.NAME_UNRECOGNIZED:

View file

@ -23,23 +23,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
VERSION.md = VERSION.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{D8938324-934B-4602-B30E-66B60365B426}"
ProjectSection(SolutionItems) = preProject
images\logo.png = images\logo.png
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{E2AF3E4D-F5B6-44C0-8E15-528206E9F3C7}"
ProjectSection(SolutionItems) = preProject
images\doc\frameworkdownload.png = images\doc\frameworkdownload.png
images\doc\screenshot_1.png = images\doc\screenshot_1.png
images\doc\screenshot_2.png = images\doc\screenshot_2.png
images\doc\screenshot_3.png = images\doc\screenshot_3.png
images\doc\screenshot_4.png = images\doc\screenshot_4.png
images\doc\screenshot_5.png = images\doc\screenshot_5.png
images\doc\screenshot_6.png = images\doc\screenshot_6.png
images\doc\screenshot_7.png = images\doc\screenshot_7.png
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64

View file

@ -25,7 +25,7 @@ namespace MSFSPopoutPanelManager.Model
}
SimBaseDocument data;
using (Stream stream = new FileStream(filePath, FileMode.Open))
{
data = (SimBaseDocument)serializer.Deserialize(stream);

View file

@ -1,20 +1,16 @@
using MSFSPopoutPanelManager.Shared;
using CommunityToolkit.Mvvm.ComponentModel;
using MSFSPopoutPanelManager.Shared;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
using System.IO;
namespace MSFSPopoutPanelManager.Model
{
public class AppSetting : INotifyPropertyChanged
public class AppSetting : ObservableObject
{
private const string APP_SETTING_DATA_FILENAME = "appsettingdata.json";
private bool _saveEnabled;
// Using PropertyChanged.Fody
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler<EventArgs<bool>> AlwaysOnTopChanged;
public event EventHandler<EventArgs<bool>> AutoPopOutPanelsChanged;
@ -100,7 +96,7 @@ namespace MSFSPopoutPanelManager.Model
{
return AppAutoStart.CheckIsAutoStart();
}
set
set
{
if (value)
AppAutoStart.Activate();
@ -148,12 +144,9 @@ namespace MSFSPopoutPanelManager.Model
}
}
public class AutoPopOutPanelsWaitDelay : INotifyPropertyChanged
public class AutoPopOutPanelsWaitDelay : ObservableObject
{
// Using PropertyChanged.Fody
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler DataChanged;
public event EventHandler<EventArgs<string>> DataChanged;
public AutoPopOutPanelsWaitDelay()
{
@ -170,7 +163,7 @@ namespace MSFSPopoutPanelManager.Model
public void OnPropertyChanged(string propertyName, object before, object after)
{
DataChanged?.Invoke(this, null);
DataChanged?.Invoke(this, new EventArgs<string>(propertyName));
}
}
}

View file

@ -11,18 +11,15 @@
<Copyright>Stanley Kwok 2021</Copyright>
<Product>MSFS 2020 Popout Panel Manager Model</Product>
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<Platforms>x64;AnyCPU</Platforms>
<Platforms>x64</Platforms>
<AssemblyVersion>3.3.4.0</AssemblyVersion>
<FileVersion>3.3.4.0</FileVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Fody" Version="6.6.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="7.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.1" />
</ItemGroup>
<ItemGroup>

View file

@ -1,13 +1,11 @@
using Newtonsoft.Json;
using CommunityToolkit.Mvvm.ComponentModel;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
namespace MSFSPopoutPanelManager.Model
{
public class PanelConfig : INotifyPropertyChanged
public class PanelConfig : ObservableObject
{
public event PropertyChangedEventHandler PropertyChanged;
public int PanelIndex { get; set; }
public string PanelName { get; set; }

View file

@ -1,6 +1,4 @@
using System;
namespace MSFSPopoutPanelManager.Model
namespace MSFSPopoutPanelManager.Model
{
public enum PanelConfigPropertyName
{

View file

@ -1,13 +1,11 @@
using Newtonsoft.Json;
using CommunityToolkit.Mvvm.ComponentModel;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
namespace MSFSPopoutPanelManager.Model
{
public class PanelSourceCoordinate : INotifyPropertyChanged
public class PanelSourceCoordinate : ObservableObject
{
public event PropertyChangedEventHandler PropertyChanged;
public int PanelIndex { get; set; }
public int X { get; set; }

View file

@ -5,6 +5,7 @@
FlightSimMainWindow,
BuiltInPopout,
CustomPopout,
MSFSTouchPanel
MSFSTouchPanel,
WPFWindow
}
}

View file

@ -1,14 +1,12 @@
using Newtonsoft.Json;
using CommunityToolkit.Mvvm.ComponentModel;
using Newtonsoft.Json;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace MSFSPopoutPanelManager.Model
{
public class UserProfile : INotifyPropertyChanged
public class UserProfile : ObservableObject
{
public event PropertyChangedEventHandler PropertyChanged;
public UserProfile()
{
PanelSourceCoordinates = new ObservableCollection<PanelSourceCoordinate>();
@ -71,16 +69,16 @@ namespace MSFSPopoutPanelManager.Model
{
object val = new object();
if(reader.TokenType == JsonToken.String)
if (reader.TokenType == JsonToken.String)
{
var instance = (string)serializer.Deserialize(reader, typeof(string));
val = new ObservableCollection<string>() { instance };
}
else if(reader.TokenType == JsonToken.StartArray)
else if (reader.TokenType == JsonToken.StartArray)
{
val = serializer.Deserialize(reader, objectType);
}
else if(reader.TokenType == JsonToken.Null)
else if (reader.TokenType == JsonToken.Null)
{
val = new ObservableCollection<string>();
}

View file

@ -26,7 +26,7 @@ namespace MSFSPopoutPanelManager.Provider
// Take a screen shot by removing the titlebar of the window
var left = rectangle.Left;
var top = rectangle.Top + (rectangle.Height - clientRectangle.Height) - 8; // 8 pixels adjustments
var bmp = new Bitmap(clientRectangle.Width, clientRectangle.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(bmp))
@ -37,10 +37,12 @@ namespace MSFSPopoutPanelManager.Provider
// Place the above image in the same canvas size as before
Bitmap backingImage = new Bitmap(rectangle.Width, rectangle.Height);
using (Graphics gfx = Graphics.FromImage(backingImage))
using (SolidBrush brush = new SolidBrush(Color.FromArgb(255, 0, 0)))
{
gfx.FillRectangle(brush, 0, 0, rectangle.Width, rectangle.Height);
gfx.DrawImage(bmp, new Point(0, top));
using (SolidBrush brush = new SolidBrush(Color.FromArgb(255, 0, 0)))
{
gfx.FillRectangle(brush, 0, 0, rectangle.Width, rectangle.Height);
gfx.DrawImage(bmp, new Point(0, top));
}
}
return backingImage;

View file

@ -58,7 +58,7 @@ namespace MSFSPopoutPanelManager.Provider
Rectangle clientRectangle;
PInvoke.GetClientRect(hwnd, out clientRectangle);
var x = Convert.ToInt32(rectangle.X + (clientRectangle.Width) * 0.5);
var x = Convert.ToInt32(rectangle.X + (clientRectangle.Width) * 0.5);
var y = Convert.ToInt32(rectangle.Y + (clientRectangle.Height) * 0.5);
PInvoke.SetForegroundWindow(hwnd);
@ -75,7 +75,7 @@ namespace MSFSPopoutPanelManager.Provider
public static void SaveCustomView(IntPtr hwnd, string keybinding)
{
uint customViewKey = (uint) (Convert.ToInt32(keybinding) + KEY_0);
uint customViewKey = (uint)(Convert.ToInt32(keybinding) + KEY_0);
PInvoke.SetForegroundWindow(hwnd);
Thread.Sleep(500);
@ -117,7 +117,6 @@ namespace MSFSPopoutPanelManager.Provider
Thread.Sleep(200);
PInvoke.keybd_event(Convert.ToByte(customViewKey), 0, KEYEVENTF_KEYUP, 0);
PInvoke.keybd_event(Convert.ToByte(VK_LMENU), 0, KEYEVENTF_KEYUP, 0);
}
public static void ToggleFullScreenPanel(IntPtr hwnd)
@ -157,11 +156,11 @@ namespace MSFSPopoutPanelManager.Provider
// set focus to game app
var x = Convert.ToInt32(rectangle.X + (clientRectangle.Width) * 0.947);
var y = Convert.ToInt32(rectangle.Y + (clientRectangle.Height) * 0.9);
LeftClick(x, y);
LeftClick(x, y);
Thread.Sleep(250);
LeftClick(x, y);
Thread.Sleep(250);
for (var top = y; top < y + 100; top = top + 20)
{
LeftClick(x, Convert.ToInt32(top));

View file

@ -38,6 +38,8 @@ namespace MSFSPopoutPanelManager.Provider
public const uint WS_POPUP = 0x80000000;
public const uint WS_EX_DLGMODALFRAME = 0x00000001;
public const uint WS_THICKFRAME = 0x00040000;
public const uint WS_MAXIMIZEBOX = 0x10000;
public const uint WS_MINIMIZEBOX = 0x20000;
public const int HWND_TOPMOST = -1;
public const int HWND_NOTOPMOST = -2;
@ -57,6 +59,8 @@ namespace MSFSPopoutPanelManager.Provider
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
public static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder strPtrClassName, Int32 nMaxCount);

View file

@ -1,6 +1,5 @@
using MSFSPopoutPanelManager.Model;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
@ -30,7 +29,7 @@ namespace MSFSPopoutPanelManager.Provider
public void HookWinEvent()
{
// Setup panel config event hooks
// Setup panel config event hooks
_winEventHook = PInvoke.SetWinEventHook(PInvokeConstant.EVENT_SYSTEM_CAPTURESTART, PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE, DiagnosticManager.GetApplicationProcess().Handle, _winEvent, 0, 0, PInvokeConstant.WINEVENT_OUTOFCONTEXT);
}
@ -68,29 +67,27 @@ namespace MSFSPopoutPanelManager.Provider
name = name + " (Custom)";
PInvoke.SetWindowText(panelConfig.PanelHandle, name);
}
else if(!panelConfig.FullScreen)
else if (!panelConfig.FullScreen)
{
switch (panelConfigItem.PanelConfigProperty)
{
case PanelConfigPropertyName.Left:
case PanelConfigPropertyName.Top:
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, true);
WindowManager.MoveWindow(panelConfig.PanelHandle, panelConfig.PanelType, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height);
break;
case PanelConfigPropertyName.Width:
case PanelConfigPropertyName.Height:
if (panelConfig.HideTitlebar)
WindowManager.ApplyHidePanelTitleBar(panelConfig.PanelHandle, false);
int orignalLeft = panelConfig.Left;
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, true);
MSFSBugPanelShiftWorkaround(panelConfig.PanelHandle, orignalLeft, panelConfig.Top, panelConfig.Width, panelConfig.Height);
WindowManager.MoveWindowWithMsfsBugOverrirde(panelConfig.PanelHandle, panelConfig.PanelType, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height);
if (panelConfig.HideTitlebar)
WindowManager.ApplyHidePanelTitleBar(panelConfig.PanelHandle, true);
break;
case PanelConfigPropertyName.AlwaysOnTop:
WindowManager.ApplyAlwaysOnTop(panelConfig.PanelHandle, panelConfig.AlwaysOnTop, new Rectangle(panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height));
WindowManager.ApplyAlwaysOnTop(panelConfig.PanelHandle, panelConfig.PanelType, panelConfig.AlwaysOnTop, new Rectangle(panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height));
break;
case PanelConfigPropertyName.HideTitlebar:
WindowManager.ApplyHidePanelTitleBar(panelConfig.PanelHandle, panelConfig.HideTitlebar);
@ -123,11 +120,11 @@ namespace MSFSPopoutPanelManager.Provider
{
case PanelConfigPropertyName.Left:
panelConfig.Left += changeAmount;
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
WindowManager.MoveWindow(panelConfig.PanelHandle, panelConfig.PanelType, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height);
break;
case PanelConfigPropertyName.Top:
panelConfig.Top += changeAmount;
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
WindowManager.MoveWindow(panelConfig.PanelHandle, panelConfig.PanelType, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height);
break;
case PanelConfigPropertyName.Width:
panelConfig.Width += changeAmount;
@ -135,8 +132,7 @@ namespace MSFSPopoutPanelManager.Provider
if (panelConfig.HideTitlebar)
WindowManager.ApplyHidePanelTitleBar(panelConfig.PanelHandle, false);
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
MSFSBugPanelShiftWorkaround(panelConfig.PanelHandle, orignalLeft, panelConfig.Top, panelConfig.Width, panelConfig.Height);
WindowManager.MoveWindowWithMsfsBugOverrirde(panelConfig.PanelHandle, panelConfig.PanelType, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height);
if (panelConfig.HideTitlebar)
WindowManager.ApplyHidePanelTitleBar(panelConfig.PanelHandle, true);
@ -148,8 +144,7 @@ namespace MSFSPopoutPanelManager.Provider
if (panelConfig.HideTitlebar)
WindowManager.ApplyHidePanelTitleBar(panelConfig.PanelHandle, false);
PInvoke.MoveWindow(panelConfig.PanelHandle, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height, false);
MSFSBugPanelShiftWorkaround(panelConfig.PanelHandle, orignalLeft, panelConfig.Top, panelConfig.Width, panelConfig.Height);
WindowManager.MoveWindowWithMsfsBugOverrirde(panelConfig.PanelHandle, panelConfig.PanelType, panelConfig.Left, panelConfig.Top, panelConfig.Width, panelConfig.Height);
if (panelConfig.HideTitlebar)
WindowManager.ApplyHidePanelTitleBar(panelConfig.PanelHandle, true);
@ -163,22 +158,9 @@ namespace MSFSPopoutPanelManager.Provider
}
}
private void MSFSBugPanelShiftWorkaround(IntPtr handle, int originalLeft, int top, int width, int height)
{
// Fixed MSFS bug, create workaround where on 2nd or later instance of width adjustment, the panel shift to the left by itself
// Wait for system to catch up on panel coordinate that were just applied
System.Threading.Thread.Sleep(200);
Rectangle rectangle;
PInvoke.GetWindowRect(handle, out rectangle);
if (rectangle.Left != originalLeft)
PInvoke.MoveWindow(handle, originalLeft, top, width, height, false);
}
private void EventCallback(IntPtr hWinEventHook, uint iEvent, IntPtr hWnd, int idObject, int idChild, int dwEventThread, int dwmsEventTime)
{
switch(iEvent)
switch (iEvent)
{
case PInvokeConstant.EVENT_OBJECT_LOCATIONCHANGE:
case PInvokeConstant.EVENT_SYSTEM_MOVESIZEEND:
@ -316,7 +298,7 @@ namespace MSFSPopoutPanelManager.Provider
}
}
private async Task RefocusMsfs(int prevWinEventClickLock)
private void RefocusMsfs(int prevWinEventClickLock)
{
Thread.Sleep(1000);

View file

@ -38,13 +38,13 @@ namespace MSFSPopoutPanelManager.Provider
{
var simulatorProcess = DiagnosticManager.GetSimulatorProcess();
if(simulatorProcess != null)
if (simulatorProcess != null)
_simulatorHandle = simulatorProcess.Handle;
_panels = new List<PanelConfig>();
OnPopOutStarted?.Invoke(this, null);
// If enable, load the current viewport into custom view by Ctrl-Alt-0
if (AppSetting.UseAutoPanning)
{
@ -82,7 +82,7 @@ namespace MSFSPopoutPanelManager.Provider
// Recenter the view port by Ctrl-Space, needs to click on game window
var simualatorProcess = DiagnosticManager.GetSimulatorProcess();
if (simualatorProcess != null && UserProfile.PanelSourceCoordinates.Count > 0)
if (simualatorProcess != null)
{
InputEmulationManager.CenterView(simualatorProcess.Handle);
}
@ -91,7 +91,7 @@ namespace MSFSPopoutPanelManager.Provider
OnPopOutCompleted?.Invoke(this, new EventArgs<bool>(true));
}
else
else
{
OnPopOutCompleted?.Invoke(this, new EventArgs<bool>(false));
}
@ -143,7 +143,7 @@ namespace MSFSPopoutPanelManager.Provider
PInvoke.SetWindowText(panelInfo.PanelHandle, panelInfo.PanelName + " (Custom)");
if (i > 1)
PInvoke.MoveWindow(panelInfo.PanelHandle, 0, 0, 800, 600, true);
WindowManager.MoveWindow(panelInfo.PanelHandle, panelInfo.PanelType, 0, 0, 800, 600);
}
_currentPanelIndex = _panels.Count;
@ -173,7 +173,7 @@ namespace MSFSPopoutPanelManager.Provider
_panels[i].Width = 800;
_panels[i].Height = 600;
PInvoke.MoveWindow(_panels[i].PanelHandle, _panels[i].Top, _panels[i].Left, _panels[i].Width, _panels[i].Height, true);
WindowManager.MoveWindow(_panels[i].PanelHandle, _panels[i].PanelType, _panels[i].Top, _panels[i].Left, _panels[i].Width, _panels[i].Height);
PInvoke.SetForegroundWindow(_panels[i].PanelHandle);
Thread.Sleep(200);
}
@ -238,7 +238,7 @@ namespace MSFSPopoutPanelManager.Provider
Thread.Sleep(500);
}
// Apply full screen (cannot combine with always on top or hide title bar
// Apply full screen (cannot combine with always on top or hide title bar)
if (panel.FullScreen)
{
WindowManager.MoveWindow(panel.PanelHandle, panel.Left, panel.Top);
@ -246,17 +246,17 @@ namespace MSFSPopoutPanelManager.Provider
InputEmulationManager.ToggleFullScreenPanel(panel.PanelHandle);
Thread.Sleep(1000);
}
else
else
{
// Apply locations
PInvoke.ShowWindow(panel.PanelHandle, PInvokeConstant.SW_RESTORE);
Thread.Sleep(250);
PInvoke.MoveWindow(panel.PanelHandle, panel.Left, panel.Top, panel.Width, panel.Height, false);
WindowManager.MoveWindow(panel.PanelHandle, panel.PanelType, panel.Left, panel.Top, panel.Width, panel.Height);
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)
if (panel.PanelType == PanelType.BuiltInPopout)
{
PInvoke.MoveWindow(panel.PanelHandle, panel.Left, panel.Top, panel.Width, panel.Height, false);
Thread.Sleep(1000);
@ -265,7 +265,7 @@ namespace MSFSPopoutPanelManager.Provider
// Apply always on top
if (panel.AlwaysOnTop)
{
WindowManager.ApplyAlwaysOnTop(panel.PanelHandle, true, new Rectangle(panel.Left, panel.Top, panel.Width, panel.Height));
WindowManager.ApplyAlwaysOnTop(panel.PanelHandle, panel.PanelType, true, new Rectangle(panel.Left, panel.Top, panel.Width, panel.Height));
Thread.Sleep(1000);
}
@ -300,7 +300,7 @@ namespace MSFSPopoutPanelManager.Provider
{
// Resize all windows to 800x600 when separating and shimmy the panel
// MSFS draws popout panel differently at different time for same panel
PInvoke.MoveWindow(hwnd, -8, 0, 800, 600, true);
WindowManager.MoveWindow(hwnd, PanelType.CustomPopout, -8, 0, 800, 600);
PInvoke.SetForegroundWindow(hwnd);
Thread.Sleep(500);
@ -319,7 +319,7 @@ namespace MSFSPopoutPanelManager.Provider
if (!_panels.Exists(x => x.PanelHandle == hwnd))
{
Interlocked.Increment(ref _currentPanelIndex);
panelInfo.PanelIndex = _currentPanelIndex;
panelInfo.PanelIndex = _currentPanelIndex;
_panels.Add(panelInfo);
}
}
@ -357,7 +357,7 @@ namespace MSFSPopoutPanelManager.Provider
_panels.Add(panelInfo);
// Apply always on top to these panels
WindowManager.ApplyAlwaysOnTop(panelInfo.PanelHandle, true);
//WindowManager.ApplyAlwaysOnTop(panelInfo.PanelHandle, true);
}
}
@ -400,7 +400,7 @@ namespace MSFSPopoutPanelManager.Provider
panelInfo.PanelHandle = hwnd;
panelInfo.PanelName = caption;
if (caption.IndexOf("MSFS Touch Panel |") > -1)
if (caption.IndexOf("Touch Panel |") > -1)
{
panelInfo.PanelType = PanelType.MSFSTouchPanel;
return panelInfo;
@ -408,8 +408,6 @@ namespace MSFSPopoutPanelManager.Provider
else
return null;
}
return null;
}
private Point AnalyzeMergedWindows(IntPtr hwnd)
@ -432,7 +430,7 @@ namespace MSFSPopoutPanelManager.Provider
var panelsStartingLeft = GetPanelMenubarStartingLeft(sourceImage, rectangle, panelMenubarTop + 5);
// The center of magnifying glass icon is around (2.7 x height of menubar) to the right of the panel menubar starting left
// The center of magnifying glass icon is around (3.2 x height of menubar) to the right of the panel menubar starting left
// But need to use higher number here to click the left side of magnifying glass icon because on some panel, the ratio is smaller
var menubarHeight = panelMenubarBottom - panelMenubarTop;
var magnifyingIconXCoor = panelsStartingLeft - Convert.ToInt32(menubarHeight * 3.2); // ToDo: play around with this multiplier to find the best for all resolutions

View file

@ -69,7 +69,7 @@ namespace MSFSPopoutPanelManager.Provider
private void HandleOnPanelSelectionRemoved(object sender, EventArgs e)
{
if(_panelCoordinates.Count > 0)
if (_panelCoordinates.Count > 0)
{
_panelCoordinates.RemoveAt(_panelCoordinates.Count - 1);
_panelIndex--;

View file

@ -14,14 +14,11 @@
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon />
<StartupObject />
<Platforms>AnyCPU;x64</Platforms>
<Platforms>x64</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
@ -29,9 +26,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MouseKeyHook" Version="5.6.0" />

View file

@ -9,15 +9,14 @@ using System.Timers;
namespace MSFSPopoutPanelManager.Provider
{
public class SimConnectManager
{
public class SimConnectManager
{
private const int MSFS_DATA_REFRESH_TIMEOUT = 1000;
private SimConnector _simConnector;
private dynamic _simData;
private System.Timers.Timer _requestDataTimer;
private SimConnectSystemEvent _lastSystemEvent;
private bool _isPowerOnForPopOut;
private bool _isTrackIRManaged;
@ -75,7 +74,7 @@ namespace MSFSPopoutPanelManager.Provider
public void TurnOffpower()
{
if(_isPowerOnForPopOut)
if (_isPowerOnForPopOut)
{
_simConnector.TransmitActionEvent(ActionEvent.KEY_AVIONICS_MASTER_2_SET, 0);
Thread.Sleep(100);
@ -91,7 +90,7 @@ namespace MSFSPopoutPanelManager.Provider
public void TurnOffTrackIR()
{
if(_simData != null && _simData.TrackIREnable)
if (_simData != null && _simData.TrackIREnable)
{
SetTrackIREnable(false);
_isTrackIRManaged = true;
@ -114,10 +113,10 @@ namespace MSFSPopoutPanelManager.Provider
// It is prop3 in SimConnectStruct (by DataDefinitions.cs)
SimConnectStruct simConnectStruct = new SimConnectStruct();
simConnectStruct.Prop01 = _simData.Title; // must set "Title" for TrackIR variable to write correctly
simConnectStruct.Prop02 = _simData.ElectricalMasterBattery ? Convert.ToDouble(1) : Convert.ToDouble(0); // must set "ElectricalMasterBattery" for TrackIR variable to write correctly
simConnectStruct.Prop03 = enable ? Convert.ToDouble(1): Convert.ToDouble(0); // this is the TrackIR variable
simConnectStruct.Prop03 = enable ? Convert.ToDouble(1) : Convert.ToDouble(0); // this is the TrackIR variable
_simConnector.SetDataObject(simConnectStruct);
}

View file

@ -4,7 +4,6 @@ using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -90,8 +89,6 @@ namespace MSFSPopoutPanelManager.Provider
public void WriteUserProfiles()
{
Debug.WriteLine("saving profile....");
if (UserProfiles == null)
throw new Exception("User Profiles is null.");

View file

@ -1,4 +1,5 @@
using System;
using MSFSPopoutPanelManager.Model;
using System;
using System.Drawing;
using System.Runtime.InteropServices;
@ -16,12 +17,16 @@ namespace MSFSPopoutPanelManager.Provider
PInvoke.SetWindowLong(handle, PInvokeConstant.GWL_STYLE, (uint)(currentStyle | (PInvokeConstant.WS_CAPTION | PInvokeConstant.WS_SIZEBOX)));
}
public static void ApplyAlwaysOnTop(IntPtr handle, bool alwaysOnTop, Rectangle panelRectangle)
public static void ApplyAlwaysOnTop(IntPtr handle, PanelType panelType, bool alwaysOnTop, Rectangle panelRectangle)
{
// Override weird size adjustment for Touch Panel WPF window
int newWidth = panelType == PanelType.MSFSTouchPanel ? panelRectangle.Width - 16 : panelRectangle.Width;
int newHeight = panelType == PanelType.MSFSTouchPanel ? panelRectangle.Height - 39 : panelRectangle.Height;
if (alwaysOnTop)
PInvoke.SetWindowPos(handle, new IntPtr(PInvokeConstant.HWND_TOPMOST), panelRectangle.Left, panelRectangle.Top, panelRectangle.Width, panelRectangle.Height, PInvokeConstant.SWP_ALWAYS_ON_TOP);
PInvoke.SetWindowPos(handle, new IntPtr(PInvokeConstant.HWND_TOPMOST), panelRectangle.Left, panelRectangle.Top, newWidth, newHeight, PInvokeConstant.SWP_ALWAYS_ON_TOP);
else
PInvoke.SetWindowPos(handle, new IntPtr(PInvokeConstant.HWND_NOTOPMOST), panelRectangle.Left, panelRectangle.Top, panelRectangle.Width, panelRectangle.Height, 0);
PInvoke.SetWindowPos(handle, new IntPtr(PInvokeConstant.HWND_NOTOPMOST), panelRectangle.Left, panelRectangle.Top, newWidth, newHeight, 0);
}
public static void ApplyAlwaysOnTop(IntPtr handle, bool alwaysOnTop)
@ -32,7 +37,7 @@ namespace MSFSPopoutPanelManager.Provider
Rectangle clientRectangle;
PInvoke.GetClientRect(handle, out clientRectangle);
ApplyAlwaysOnTop(handle, alwaysOnTop, new Rectangle(rect.X, rect.Y, clientRectangle.Width, clientRectangle.Height));
ApplyAlwaysOnTop(handle, PanelType.WPFWindow, alwaysOnTop, new Rectangle(rect.X, rect.Y, clientRectangle.Width, clientRectangle.Height));
}
public static void CloseWindow(IntPtr handle)
@ -47,6 +52,36 @@ namespace MSFSPopoutPanelManager.Provider
PInvoke.MoveWindow(handle, x, y, rectangle.Width, rectangle.Height, true);
}
public static void MoveWindow(IntPtr handle, PanelType panelType, int x, int y, int width, int height)
{
// Override weird size adjustment for Touch Panel WPF window
int newWidth = panelType == PanelType.MSFSTouchPanel ? width - 16 : width;
int newHeight = panelType == PanelType.MSFSTouchPanel ? height - 39 : height;
PInvoke.MoveWindow(handle, x, y, newWidth, newHeight, true);
}
public static void MoveWindowWithMsfsBugOverrirde(IntPtr handle, PanelType panelType, int x, int y, int width, int height)
{
int originalX = x;
// Override weird size adjustment for Touch Panel WPF window
int newWidth = panelType == PanelType.MSFSTouchPanel ? width - 16 : width;
int newHeight = panelType == PanelType.MSFSTouchPanel ? height - 39 : height;
PInvoke.MoveWindow(handle, x, y, newWidth, newHeight, true);
// Fixed MSFS bug, create workaround where on 2nd or later instance of width adjustment, the panel shift to the left by itself
// Wait for system to catch up on panel coordinate that were just applied
System.Threading.Thread.Sleep(200);
Rectangle rectangle;
PInvoke.GetWindowRect(handle, out rectangle);
if (rectangle.Left != originalX)
PInvoke.MoveWindow(handle, originalX, y, newWidth, newHeight, false);
}
public static void MinimizeWindow(IntPtr handle)
{
PInvoke.ShowWindow(handle, PInvokeConstant.SW_MINIMIZE);
@ -75,6 +110,11 @@ namespace MSFSPopoutPanelManager.Provider
}
}
public static IntPtr FindWindowByCaption(string caption)
{
return PInvoke.FindWindowByCaption(IntPtr.Zero, caption);
}
private static bool EnumToMinimizePopoutPanels(IntPtr hwnd, int index)
{
var className = PInvoke.GetClassName(hwnd);

View file

@ -4,7 +4,7 @@
<img src="images/doc/panel_selection.png" width="600" hspace="10"/>
</p>
MSFS Pop Out Panel Manager is an application for MSFS 2020 which helps pop out, save and re-position pop out panels to be used by utilities such as Sim Innovations Air Manager or to place pop out panels onto your screen or another monitor at predetermined locations automatically.
MSFS Pop Out Panel Manager is an application for MSFS 2020 which helps pop out, save and position pop out panels to be used by utilities such as Sim Innovations Air Manager or to place pop out panels onto your screen or another monitor at predetermined locations automatically.
Please follow [FlightSimulator.com](https://forums.flightsimulator.com/t/msfs-pop-out-panel-manager-automatically-pop-out-and-save-panel-position/460613) forum thread regarding this project
@ -15,18 +15,19 @@ Please follow [FlightSimulator.com](https://forums.flightsimulator.com/t/msfs-po
<hr>
## Application Features
* Display resolution independent. Supports 1080p/1440p/4k display.
* Display resolution independent. Supports 1080p/1440p/4k display and ultrawide displays.
* Support multiple user defined aircraft profiles to save panel locations to be recalled later.
* Intuitive user interface to defined location of panels to be popped out.
* [Auto Pop Out](#auto-pop-out-feature) feature. The application will detect active aircraft by livery and activate the corresponding profile on start of new flight session.
* [Cold Start feature](#auto-pop-out-feature). Instrumentation panels can be popped out even when they're not powered on (for G1000 planes only).
* [Cold Start feature](#auto-pop-out-feature). Instrumentation panels can be popped out even when they're not powered on (for G1000 / / G1000 NXi planes only).
* Auto Panning feature remembers the cockpit camera angle when you first define the pop out panels. You can now pan, zoom in, and zoom out to identify offscreen panels and the camera angle will be saved and reused. This feature requires the use of Ctrl-Alt-0 keyboard binding to save custom camera view per plane configuration. (Can be configured to use 0 through 9). If the keyboard binding is currently being used. The auto-panning feature will overwrite the saved camera view if enabled.
* Fine-grain control in positioning of panels down to pixel level.
* Panels can also be configured to be always on top, with title bar hidden, or stretch to full screen mode.
* Panels can be configured to appear always on top, with title bar hidden, or stretch to full screen mode.
* Auto disable Track IR when pop out starts.
* User-friendly features such as application always on top, auto start, minimized to tray with keyboard shortcuts.
* Auto save feature. All profile and panel changes are saved automatically.
* **Experimental Feature**: Enable touch support for pop outs on touch enable display. Please see [Touch Enable Pop Out Feature](#touch-enable-pop-out-feature) for more information.
* Auto update feature. Application can auto-update itself when new version becomes available.
* **Experimental Feature**: Enable touch support for pop outs on touch capable display. Please see [Touch Enable Pop Out Feature](#touch-enable-pop-out-feature) for more information.
<hr>

View file

@ -19,13 +19,22 @@ namespace MSFSPopoutPanelManager.Shared
{
return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
}
private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
{
if (originalObject == null) return null;
if (originalObject == null)
return null;
var typeToReflect = originalObject.GetType();
if (IsPrimitive(typeToReflect)) return originalObject;
if (visited.ContainsKey(originalObject)) return visited[originalObject];
if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null;
if (IsPrimitive(typeToReflect))
return originalObject;
if (visited.ContainsKey(originalObject))
return visited[originalObject];
if (typeof(Delegate).IsAssignableFrom(typeToReflect))
return null;
var cloneObject = CloneMethod.Invoke(originalObject, null);
if (typeToReflect.IsArray)
{
@ -35,7 +44,6 @@ namespace MSFSPopoutPanelManager.Shared
Array clonedArray = (Array)cloneObject;
clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
}
}
visited.Add(originalObject, cloneObject);
CopyFields(originalObject, visited, cloneObject, typeToReflect);
@ -63,6 +71,7 @@ namespace MSFSPopoutPanelManager.Shared
fieldInfo.SetValue(cloneObject, clonedFieldValue);
}
}
public static T Copy<T>(this T original)
{
return (T)Copy((Object)original);
@ -75,6 +84,7 @@ namespace MSFSPopoutPanelManager.Shared
{
return ReferenceEquals(x, y);
}
public override int GetHashCode(object obj)
{
if (obj == null) return 0;

View file

@ -10,7 +10,7 @@
<Copyright>Stanley Kwok 2021</Copyright>
<PackageProjectUrl>https://github.com/hawkeye-stan/msfs-popout-panel-manager</PackageProjectUrl>
<Version>3.3.4.0</Version>
<Platforms>AnyCPU;x64</Platforms>
<Platforms>x64</Platforms>
<UseWPF>true</UseWPF>
<AssemblyVersion>3.3.4.0</AssemblyVersion>
</PropertyGroup>

View file

@ -1,12 +1,11 @@
<mah:MetroWindow x:Class="MSFSPopoutPanelManager.WpfApp.AddProfileDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
mc:Ignorable="d"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
mc:Ignorable="d"
Title="Add Profile"
Height="220"
Width="600"

View file

@ -9,9 +9,6 @@ using System.Windows.Input;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for AddProfileDialog.xaml
/// </summary>
public partial class AddProfileDialog : MetroWindow
{
public List<UserProfile> UserProfiles { get; set; }
@ -66,4 +63,4 @@ namespace MSFSPopoutPanelManager.WpfApp
btnDialogOk.IsEnabled = txtProfileName.Text.Length > 0;
}
}
}
}

View file

@ -1,9 +1,7 @@
<Application x:Class="MSFSPopoutPanelManager.WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="ApplicationWindow.xaml">
<Application.Resources>
<ResourceDictionary>

View file

@ -11,9 +11,6 @@ using System.Windows;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private static Mutex _mutex = null;
@ -59,8 +56,11 @@ namespace MSFSPopoutPanelManager.WpfApp
private void HandleDispatcherException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
Log.Error(e.Exception.Message, e.Exception);
ShowExceptionDialog();
if (e.Exception.Message != "E_INVALIDARG") // Ignore this error
{
Log.Error(e.Exception.Message, e.Exception);
ShowExceptionDialog();
}
}
private void HandledDomainException(object sender, UnhandledExceptionEventArgs e)
@ -78,7 +78,11 @@ namespace MSFSPopoutPanelManager.WpfApp
if (MessageBox.Show(messageBoxMessage, messageBoxTitle, messageBoxButtons) == MessageBoxResult.OK)
{
Application.Current.Shutdown();
try
{
Application.Current.Shutdown();
}
catch { }
}
}
}
@ -138,4 +142,4 @@ namespace MSFSPopoutPanelManager.WpfApp
[DllImport("SHCore.dll", SetLastError = true)]
internal static extern void GetProcessDpiAwareness(IntPtr hprocess, out PROCESS_DPI_AWARENESS awareness);
}
}
}

View file

@ -1,14 +1,13 @@
<mah:MetroWindow x:Class="MSFSPopoutPanelManager.WpfApp.ApplicationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:tb="http://www.hardcodet.net/taskbar"
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
xmlns:shared="clr-namespace:MSFSPopoutPanelManager.Shared;assembly=Shared"
mc:Ignorable="d"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tb="http://www.hardcodet.net/taskbar"
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:shared="clr-namespace:MSFSPopoutPanelManager.Shared;assembly=Shared"
mc:Ignorable="d"
Title="MSFS Pop Out Panel Manager"
Height="670"
Width="920"
@ -19,14 +18,14 @@
WindowState="{Binding InitialWindowState, Mode=OneWay}"
Loaded="Window_Loaded"
Closing="Window_Closing">
<Window.InputBindings>
<KeyBinding Command="{Binding Path=MinimizeAllPanelsCommand}" Modifiers="Ctrl" Key="M" />
<Window.InputBindings>
<KeyBinding Command="{Binding Path=MinimizeAllPanelsCommand}" Modifiers="Ctrl+Alt" Key="M" />
</Window.InputBindings>
<Grid>
<tb:TaskbarIcon Name="notifyIcon"
ToolTipText="MSFS Pop Out Panel Manager"
IconSource="logo.ico"
MenuActivation="RightClick"
MenuActivation="LeftOrRightClick"
Visibility="Visible">
<tb:TaskbarIcon.ContextMenu>
<ContextMenu>
@ -58,7 +57,7 @@
<MenuItem Name="menuItem_Exit" Header="Exit" Command="{Binding Path=ExitCommand}"/>
</MenuItem>
<MenuItem Header="View">
<MenuItem Name="menuItem_MinimizeAllPanels" Header="Minimize All Panels " InputGestureText="Ctrl+M" Command="{Binding Path=MinimizeAllPanelsCommand}" IsChecked="{Binding Path=IsMinimizedAllPanels, Mode=TwoWay}" IsEnabled="{c:Binding Path='IsShownPanelConfigurationScreen'}"/>
<MenuItem Name="menuItem_MinimizeAllPanels" Header="Minimize All Panels " InputGestureText="Ctrl+Alt+M" Command="{Binding Path=MinimizeAllPanelsCommand}" IsChecked="{Binding Path=IsMinimizedAllPanels, Mode=TwoWay}" IsEnabled="{c:Binding Path='IsShownPanelConfigurationScreen'}"/>
</MenuItem>
<MenuItem Header="Help">
<MenuItem Name="menuItem_UserGuide" Header="User Guide" Command="{Binding Path=UserGuideCommand}"/>
@ -102,7 +101,6 @@
<Label Name="lblVersion" Margin="0, 0, 0, 5" FontSize="14" Content="{Binding Path = ApplicationVersion, Mode=OneWay}" />
</WrapPanel>
</DockPanel>
</DockPanel>
</Grid>
</mah:MetroWindow>

View file

@ -10,9 +10,6 @@ using System.Windows.Interop;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for ApplicationWindow.xaml
/// </summary>
public partial class ApplicationWindow : MetroWindow
{
private ApplicationViewModel _viewModel;
@ -97,12 +94,12 @@ namespace MSFSPopoutPanelManager.WpfApp
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
_viewModel.ExitCommand.Execute(null);
_viewModel.Exit();
}
private void EditPreferences_Click(object sender, RoutedEventArgs e)
{
PreferencesDialog dialog = new PreferencesDialog(_viewModel.DataStore.AppSetting);
PreferencesDialog dialog = new PreferencesDialog(_viewModel.PreferencesViewModel);
dialog.Owner = Application.Current.MainWindow;
dialog.Topmost = true;
dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner;

View file

@ -1,11 +1,10 @@
<mah:MetroWindow x:Class="MSFSPopoutPanelManager.WpfApp.ConfirmationDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
mc:Ignorable="d"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="Confirmation"
ResizeMode="NoResize"
Height="180"

View file

@ -1,23 +1,8 @@
using MahApps.Metro.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for ConfirmationDialog.xaml
/// </summary>
public partial class ConfirmationDialog : MetroWindow
{
public ConfirmationDialog(string title, string message)

View file

@ -1,11 +1,11 @@
<mah:MetroWindow x:Class="MSFSPopoutPanelManager.WpfApp.OnScreenMessageDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
mc:Ignorable="d"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
mc:Ignorable="d"
Height="Auto"
Width="Auto"
SizeToContent="WidthAndHeight"

View file

@ -1,16 +1,13 @@
using MahApps.Metro.Controls;
using MSFSPopoutPanelManager.Model;
using MSFSPopoutPanelManager.Provider;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for OnScreenMessageDialog.xaml
/// </summary>
public partial class OnScreenMessageDialog : MetroWindow
{
public MessageIcon MessageIcon { get; set; }
@ -40,17 +37,20 @@ namespace MSFSPopoutPanelManager.WpfApp
if (window != null)
{
var dialogHandle = window.Handle;
var simulatorProcessHandle = DiagnosticManager.GetSimulatorProcess().Handle;
var simulatorProcess = DiagnosticManager.GetSimulatorProcess();
Rectangle rectangle;
PInvoke.GetWindowRect(DiagnosticManager.GetSimulatorProcess().Handle, out rectangle);
Rectangle clientRectangle;
PInvoke.GetClientRect(DiagnosticManager.GetSimulatorProcess().Handle, out clientRectangle);
if (simulatorProcess != null)
{
Rectangle rectangle;
PInvoke.GetWindowRect(simulatorProcess.Handle, out rectangle);
Rectangle clientRectangle;
PInvoke.GetClientRect(simulatorProcess.Handle, out clientRectangle);
var x = Convert.ToInt32(rectangle.X + clientRectangle.Width / 2 - this.Width / 2);
var y = Convert.ToInt32(rectangle.Y + clientRectangle.Height / 2 - this.Height / 2);
var x = Convert.ToInt32(rectangle.X + clientRectangle.Width / 2 - this.Width / 2);
var y = Convert.ToInt32(rectangle.Y + clientRectangle.Height / 2 - this.Height / 2);
PInvoke.MoveWindow(dialogHandle, x, y, Convert.ToInt32(this.Width), Convert.ToInt32(this.Height), false);
WindowManager.MoveWindow(dialogHandle, PanelType.WPFWindow, x, y, Convert.ToInt32(this.Width), Convert.ToInt32(this.Height));
}
}
}
};
@ -63,7 +63,7 @@ namespace MSFSPopoutPanelManager.WpfApp
this.Close(); timer.Enabled = false;
});
};
timer.Interval = duration * 1000;
timer.Interval = duration * 1000;
timer.Enabled = true;
}
}

View file

@ -1,9 +1,8 @@
<Window x:Class="MSFSPopoutPanelManager.WpfApp.PanelCoorOverlay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
mc:Ignorable="d"
Title="PanelCoorOverlay"
ResizeMode="NoResize"

View file

@ -1,12 +1,8 @@
using System;
using System.Windows;
using System.Windows.Interop;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for PanelCoorOverlay.xaml
/// </summary>
public partial class PanelCoorOverlay : Window
{
public bool IsEditingPanelLocation { get; set; }
@ -23,9 +19,7 @@ namespace MSFSPopoutPanelManager.WpfApp
private void Window_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (IsEditingPanelLocation && e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
{
this.DragMove();
}
}
}
}

View file

@ -1,13 +1,10 @@
<mah:MetroWindow x:Class="MSFSPopoutPanelManager.WpfApp.PreferencesDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
mc:Ignorable="d"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d"
Title="Preferences"
Height="580"
Width="800"
@ -25,6 +22,7 @@
<Setter Property="Width" Value="Auto"/>
<Setter Property="Margin" Value="24,5,0,10"/>
</Style>
<BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />
</Window.Resources>
<Grid>
<DockPanel>
@ -48,26 +46,26 @@
<TreeViewItem Header="Track IR Settings" Selected="TreeViewItem_Selected" Margin="0,0,0,10"></TreeViewItem>
</TreeView>
<WrapPanel DockPanel.Dock="Right" Margin="20,15,20,0" Width="Auto" >
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=ApplicationSettingsVisibility, Mode=TwoWay}">
<CheckBox IsChecked="{Binding Path=AppSetting.AlwaysOnTop, Mode=TwoWay}" Content="Always on Top"></CheckBox>
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=ApplicationSettingsVisible, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}">
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.AlwaysOnTop, Mode=TwoWay}" Content="Always on Top"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">
Pin the application on top of all open windows.
</TextBlock>
<CheckBox IsChecked="{Binding Path=AppSetting.AutoStart, Mode=TwoWay}" Content="Auto Start"></CheckBox>
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.AutoStart, Mode=TwoWay}" Content="Auto Start"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">
Enable auto start the application when MSFS starts. This adds a XML config entry in EXE.xml file.
</TextBlock>
<CheckBox IsChecked="{Binding Path=AppSetting.MinimizeToTray, Mode=TwoWay}" Content="Minimize to Tray"></CheckBox>
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.MinimizeToTray, Mode=TwoWay}" Content="Minimize to Tray"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">
Minimize the application to system tray.
</TextBlock>
<CheckBox IsChecked="{Binding Path=AppSetting.StartMinimized, Mode=TwoWay}" Content="Start Minimized"></CheckBox>
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.StartMinimized, Mode=TwoWay}" Content="Start Minimized"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">
Start the application in minimized mode in system tray.
</TextBlock>
</WrapPanel>
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=PopOutSettingsVisibility, Mode=TwoWay}">
<CheckBox IsChecked="{Binding Path=AppSetting.UseAutoPanning, Mode=TwoWay}" Content="Enable Auto Panning"></CheckBox>
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=PopOutSettingsVisible, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}">
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.UseAutoPanning, Mode=TwoWay}" Content="Enable Auto Panning"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">
Enable automatic panning of cockpit view when popping out panels. Auto Panning remembers the custom cockpit camera angle you used when defining the locations of pop out panel.
</TextBlock>
@ -83,7 +81,7 @@
VerticalAlignment="Center"
Width="60"
SelectedValuePath="Tag"
SelectedValue="{Binding Path=AppSetting.AutoPanningKeyBinding, Mode=TwoWay}" >
SelectedValue="{Binding Path=DataStore.AppSetting.AutoPanningKeyBinding, Mode=TwoWay}" >
<ComboBoxItem Content="0" Tag="0"></ComboBoxItem>
<ComboBoxItem Content="1" Tag="1"></ComboBoxItem>
<ComboBoxItem Content="2" Tag="2"></ComboBoxItem>
@ -96,11 +94,11 @@
<ComboBoxItem Content="9" Tag="9"></ComboBoxItem>
</ComboBox>
</WrapPanel>
<CheckBox IsChecked="{Binding Path=AppSetting.IncludeBuiltInPanel, Mode=TwoWay}" Content="Include Built-in Panels"></CheckBox>
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.IncludeBuiltInPanel, Mode=TwoWay}" Content="Include Built-in Panels"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">Enable saving and recalling of MSFS built-in panels (ie. ATC, VFR Map, Checklist, etc) as part of profile definition.</TextBlock>
</WrapPanel>
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=AutoPopOutSettingsVisibility, Mode=TwoWay}">
<CheckBox IsChecked="{Binding Path=AppSetting.AutoPopOutPanels, Mode=TwoWay}" Content="Enable Auto Pop Out Panels"></CheckBox>
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=AutoPopOutSettingsVisible, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}">
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.AutoPopOutPanels, Mode=TwoWay}" Content="Enable Auto Pop Out Panels"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">
Automatic pop out panels when an aircraft livery is bound to a profile. The following steps will be performed.
</TextBlock>
@ -116,33 +114,35 @@
<TextBlock Style="{StaticResource TextBlockDescription}">
4. If configured for a profile on cold start, wait for instrumentation power on before executing pop out panel sequence.
</TextBlock>
<TextBlock Style="{StaticResource TextBlockHeading}">Wait delay for each step during auto pop out process (in seconds)</TextBlock>
<WrapPanel Orientation="Horizontal" Margin="24,0,0,0" >
<mah:NumericUpDown Width="80" Minimum="1" Maximum="30" FontSize="16" Value="{Binding Path=AppSetting.AutoPopOutPanelsWaitDelay.ReadyToFlyButton, Mode=TwoWay}"></mah:NumericUpDown>
<Label Margin="10,0,0,0">Ready to Fly</Label>
<WrapPanel Visibility="{Binding Path=DataStore.IsEnableAutoPopOutPanel, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}">
<TextBlock Style="{StaticResource TextBlockHeading}">Wait delay for each step during auto pop out process (in seconds)</TextBlock>
<WrapPanel Orientation="Horizontal" Margin="24,0,0,0" >
<mah:NumericUpDown Width="80" Minimum="1" Maximum="30" FontSize="16" Value="{Binding Path=DataStore.AppSetting.AutoPopOutPanelsWaitDelay.ReadyToFlyButton, Mode=TwoWay}"></mah:NumericUpDown>
<Label Margin="10,0,0,0">Ready to Fly</Label>
</WrapPanel>
<TextBlock Margin="119,0,10,10" Style="{StaticResource TextBlockDescription}">Amount of time to wait for 'Ready to Fly' button to appear.<LineBreak/>(Default: 6 seconds)</TextBlock>
<WrapPanel Orientation="Horizontal" Margin="24,0,0,0" >
<mah:NumericUpDown Width="80" Minimum="1" Maximum="30" FontSize="16" Value="{Binding Path=DataStore.AppSetting.AutoPopOutPanelsWaitDelay.InitialCockpitView, Mode=TwoWay}"></mah:NumericUpDown>
<Label Margin="10,0,0,0">Initial Cockpit View</Label>
</WrapPanel>
<TextBlock Margin="119,0,10,10" Style="{StaticResource TextBlockDescription}">Amount of time to wait for the cockpit to appear.<LineBreak/>(Default: 2 seconds)</TextBlock>
<WrapPanel Orientation="Horizontal" Margin="24,0,0,0" >
<mah:NumericUpDown Width="80" Minimum="1" Maximum="30" FontSize="16" Value="{Binding Path=DataStore.AppSetting.AutoPopOutPanelsWaitDelay.InstrumentationPowerOn, Mode=TwoWay}"></mah:NumericUpDown>
<Label Margin="10,0,0,0">Instrumentation Power On</Label>
</WrapPanel>
<TextBlock Margin="119,0,10,10" Style="{StaticResource TextBlockDescription}">Amount of time to wait for cold start instrumentation power on to complete.<LineBreak/>(Default: 2 seconds)</TextBlock>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</WrapPanel>
<TextBlock Margin="119,0,10,10" Style="{StaticResource TextBlockDescription}">Amount of time to wait for 'Ready to Fly' button to appear.<LineBreak/>(Default: 6 seconds)</TextBlock>
<WrapPanel Orientation="Horizontal" Margin="24,0,0,0" >
<mah:NumericUpDown Width="80" Minimum="1" Maximum="30" FontSize="16" Value="{Binding Path=AppSetting.AutoPopOutPanelsWaitDelay.InitialCockpitView, Mode=TwoWay}"></mah:NumericUpDown>
<Label Margin="10,0,0,0">Initial Cockpit View</Label>
</WrapPanel>
<TextBlock Margin="119,0,10,10" Style="{StaticResource TextBlockDescription}">Amount of time to wait for the cockpit to appear.<LineBreak/>(Default: 2 seconds)</TextBlock>
<WrapPanel Orientation="Horizontal" Margin="24,0,0,00" >
<mah:NumericUpDown Width="80" Minimum="1" Maximum="30" FontSize="16" Value="{Binding Path=AppSetting.AutoPopOutPanelsWaitDelay.InstrumentationPowerOn, Mode=TwoWay}"></mah:NumericUpDown>
<Label Margin="10,0,0,0">Instrumentation Power On</Label>
</WrapPanel>
<TextBlock Margin="119,0,10,10" Style="{StaticResource TextBlockDescription}">Amount of time to wait for cold start instrumentation power on to complete.<LineBreak/>(Default: 2 seconds)</TextBlock>
<WrapPanel Orientation="Horizontal"></WrapPanel>
</WrapPanel>
<WrapPanel Orientation="Vertical" Visibility="Visible">
</WrapPanel>
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=TrackIRSettingsVisibility, Mode=TwoWay}">
<CheckBox IsChecked="{Binding Path=AppSetting.AutoDisableTrackIR, Mode=TwoWay}" Content="Auto Disable Track IR"></CheckBox>
<WrapPanel Orientation="Vertical" Width="Auto" Visibility="{Binding Path=TrackIRSettingsVisible, Converter={StaticResource VisibleIfTrueConverter}, Mode=OneWay}">
<CheckBox IsChecked="{Binding Path=DataStore.AppSetting.AutoDisableTrackIR, Mode=TwoWay}" Content="Auto Disable Track IR"></CheckBox>
<TextBlock Style="{StaticResource TextBlockDescription}">
Automactically disable Track IR during panel selections and pop out process. Track IR will be re-enable once these processes are completed.
</TextBlock>
</WrapPanel>
<WrapPanel Orientation="Vertical" Visibility="Visible">
</WrapPanel>
</WrapPanel>
</DockPanel>
</Grid>
</mah:MetroWindow>
</mah:MetroWindow>

View file

@ -1,66 +1,37 @@
using MahApps.Metro.Controls;
using MSFSPopoutPanelManager.Model;
using System.ComponentModel;
using MSFSPopoutPanelManager.WpfApp.ViewModel;
using System.Windows;
using System.Windows.Controls;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for AddProfileDialog.xaml
/// </summary>
public partial class PreferencesDialog : MetroWindow, INotifyPropertyChanged
public partial class PreferencesDialog : MetroWindow
{
public event PropertyChangedEventHandler PropertyChanged;
private PreferencesViewModel _preferencesViewModel;
public PreferencesDialog(AppSetting appSetting)
public PreferencesDialog(PreferencesViewModel preferencesViewModel)
{
_preferencesViewModel = preferencesViewModel;
InitializeComponent();
AppSetting = appSetting;
this.DataContext = this;
ApplicationSettingsVisibility = Visibility.Visible;
PopOutSettingsVisibility = Visibility.Collapsed;
AutoPopOutSettingsVisibility = Visibility.Collapsed;
TrackIRSettingsVisibility = Visibility.Collapsed;
this.DataContext = preferencesViewModel;
}
public AppSetting AppSetting { get; set; }
public Visibility ApplicationSettingsVisibility { get; set; }
public bool ApplicationSettingsVisible { get; set; }
public Visibility PopOutSettingsVisibility { get; set; }
public bool PopOutSettingsVisible { get; set; }
public Visibility AutoPopOutSettingsVisibility { get; set; }
public bool AutoPopOutSettingsVisible { get; set; }
public Visibility TrackIRSettingsVisibility { get; set; }
public bool TrackIRSettingsVisible { get; set; }
private void TreeViewItem_Selected(object sender, RoutedEventArgs e)
{
var treeViewItem = (TreeViewItem)e.Source;
ApplicationSettingsVisibility = Visibility.Collapsed;
PopOutSettingsVisibility = Visibility.Collapsed;
AutoPopOutSettingsVisibility = Visibility.Collapsed;
TrackIRSettingsVisibility = Visibility.Collapsed;
if (treeViewItem.Header.ToString() == "Application Settings")
{
ApplicationSettingsVisibility = Visibility.Visible;
}
else if(treeViewItem.Header.ToString() == "Pop Out Settings")
{
PopOutSettingsVisibility = Visibility.Visible;
}
else if (treeViewItem.Header.ToString() == "Auto Pop Out Panel Settings")
{
AutoPopOutSettingsVisibility = Visibility.Visible;
}
else if (treeViewItem.Header.ToString() == "Track IR Settings")
{
TrackIRSettingsVisibility = Visibility.Visible;
}
_preferencesViewModel.SectionSelectCommand.Execute(treeViewItem.Header.ToString());
}
}
}

View file

@ -1,10 +1,9 @@
<UserControl x:Class="MSFSPopoutPanelManager.WpfApp.UserControlPanelConfiguration"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
mc:Ignorable="d"
Height="505"
@ -125,7 +124,8 @@
SourceUpdated="GridData_SourceUpdated"
Style="{StaticResource TextBoxColumnFocus}"
IsReadOnly="{c:Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid, AncestorLevel=1}, Path='DataContext.DataStore.ActiveUserProfile.IsLocked or !DataContext.DataStore.AllowEdit'}"
IsHitTestVisible="{c:Binding Path='!FullScreen'}"/> </DataTemplate>
IsHitTestVisible="{c:Binding Path='!FullScreen'}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Y-Pos" Width="80">
@ -228,7 +228,6 @@
</Button.Style>
</Button>
</WrapPanel>
</DockPanel>
</Grid>
</UserControl>

View file

@ -9,9 +9,6 @@ using System.Windows.Media;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for UserControlPanelConfiguration.xaml
/// </summary>
public partial class UserControlPanelConfiguration : UserControl
{
private PanelConfigurationViewModel _panelConfigurationViewModel;
@ -25,9 +22,9 @@ namespace MSFSPopoutPanelManager.WpfApp
private void GridData_SourceUpdated(object sender, DataTransferEventArgs e)
{
var container = VisualTreeHelper.GetParent((Control) sender) as ContentPresenter;
var container = VisualTreeHelper.GetParent((Control)sender) as ContentPresenter;
var panelConfig = container.Content as PanelConfig;
var propertyName = (PanelConfigPropertyName) Enum.Parse(typeof(PanelConfigPropertyName), ((Control)sender).Name);
var propertyName = (PanelConfigPropertyName)Enum.Parse(typeof(PanelConfigPropertyName), ((Control)sender).Name);
var panelConfigItem = new PanelConfigItem() { PanelIndex = panelConfig.PanelIndex, PanelConfigProperty = propertyName };
_panelConfigurationViewModel.PanelConfigUpdatedCommand.Execute(panelConfigItem);
@ -42,7 +39,7 @@ namespace MSFSPopoutPanelManager.WpfApp
PanelConfigPropertyName selectedProperty = PanelConfigPropertyName.Invalid;
switch(cell.Column.Header)
switch (cell.Column.Header)
{
case "Panel Name":
selectedProperty = PanelConfigPropertyName.PanelName;
@ -73,13 +70,13 @@ namespace MSFSPopoutPanelManager.WpfApp
break;
}
_panelConfigurationViewModel.SelectedPanelConfigItem = new PanelConfigItem() { PanelIndex = panelConfig.PanelIndex, PanelConfigProperty = selectedProperty };
_panelConfigurationViewModel.SelectedPanelConfigItem = new PanelConfigItem() { PanelIndex = panelConfig.PanelIndex, PanelConfigProperty = selectedProperty };
}
}
private void LockPanels_Click(object sender, RoutedEventArgs e)
{
if(_panelConfigurationViewModel.DataStore.ActiveUserProfile.IsLocked)
if (_panelConfigurationViewModel.DataStore.ActiveUserProfile.IsLocked)
{
ConfirmationDialog dialog = new ConfirmationDialog("Confirm Unlock Panels", "Are you sure you want to unlock all panels to make changes?");
dialog.Owner = Application.Current.MainWindow;

View file

@ -1,12 +1,11 @@
<UserControl x:Class="MSFSPopoutPanelManager.WpfApp.UserControlPanelSelection"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
xmlns:local="clr-namespace:MSFSPopoutPanelManager.WpfApp"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
mc:Ignorable="d"
Height="505"
Width="920"
@ -43,6 +42,7 @@
</DataTrigger>
</Style.Triggers>
</Style>
<BooleanToVisibilityConverter x:Key="VisibleIfTrueConverter" />
</UserControl.Resources>
<Grid>
<DockPanel>
@ -95,30 +95,34 @@
<TextBlock Text="Power on required to pop out panels on cold start (G1000 / NXi Only)" TextWrapping="Wrap" Margin="5,0,0,3"/>
</CheckBox>
</WrapPanel>
<Separator Margin="5,10,5,5"/>
<Label Content="3. Identify pop out panel locations in the game by clicking on them." Margin="0,0,0,0" />
<WrapPanel Orientation="Vertical" Margin="20,0,0,0" HorizontalAlignment="Left">
<WrapPanel Orientation="Horizontal">
<Label Content="LEFT CLICK" Foreground="AntiqueWhite"/>
<Label Content="to add a new panel."/>
</WrapPanel>
<WrapPanel Orientation="Horizontal">
<Label Content="CTRL + LEFT CLICK" Foreground="AntiqueWhite" />
<Label Content="when all panels have been selected or to cancel selections." />
</WrapPanel>
<WrapPanel Orientation="Horizontal">
<Label Content="SHIFT + LEFT CLICK" Foreground="AntiqueWhite" />
<Label Content="to remove the most recently added panel."/>
</WrapPanel>
<WrapPanel Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Left">
<Button Content="Start Panel Selection" HorizontalAlignment="Left" Margin="0,0,0,0" Width="165" Click="StartPanelSelection_Click" Style="{StaticResource ProfileSelectedDependency}"/>
<Button Content="Save Auto Panning Camera" HorizontalAlignment="Left" Margin="20,0,0,0" IsEnabled="{c:Binding Path='DataStore.HasActiveUserProfileId and DataStore.IsFlightActive'}" Width="215" Click="SaveAutoPanningCamera_Click" Style="{StaticResource ProfileSelectedDependency}"/>
<WrapPanel Orientation="Vertical">
<Label Content="3. Identify pop out panel locations in the game by clicking on them." Margin="0,0,0,0" />
<WrapPanel Orientation="Vertical" Margin="20,0,0,0" HorizontalAlignment="Left">
<WrapPanel Orientation="Horizontal">
<Label Content="LEFT CLICK" Foreground="AntiqueWhite"/>
<Label Content="to add a new panel."/>
</WrapPanel>
<WrapPanel Orientation="Horizontal">
<Label Content="CTRL + LEFT CLICK" Foreground="AntiqueWhite" />
<Label Content="when all panels have been selected or to cancel selections." />
</WrapPanel>
<WrapPanel Orientation="Horizontal">
<Label Content="SHIFT + LEFT CLICK" Foreground="AntiqueWhite" />
<Label Content="to remove the most recently added panel."/>
</WrapPanel>
<WrapPanel Orientation="Horizontal" Margin="0,5,0,0" HorizontalAlignment="Left">
<Button Content="Start Panel Selection" HorizontalAlignment="Left" Margin="0,0,0,0" Width="165" Click="StartPanelSelection_Click" Style="{StaticResource ProfileSelectedDependency}"/>
<Button Content="Save Auto Panning Camera" HorizontalAlignment="Left" Margin="20,0,0,0" IsEnabled="{c:Binding Path='DataStore.HasActiveUserProfileId and DataStore.IsFlightActive'}" Width="215" Click="SaveAutoPanningCamera_Click" Style="{StaticResource ProfileSelectedDependency}"/>
</WrapPanel>
</WrapPanel>
<Separator Margin="5,10,5,5"/>
</WrapPanel>
<WrapPanel Orientation="Vertical" >
<Label Content="4. Start the pop out process for selected panels." Margin="0,0,0,0" />
<Button Content="Start Pop Out" HorizontalAlignment="Left" Margin="20,5,0,0" Width="130" IsEnabled="{c:Binding Path='DataStore.HasActiveUserProfileId and DataStore.IsFlightActive'}" Command="{Binding Path=StartPopOutCommand}" Style="{StaticResource ProfileSelectedDependency}"/>
</WrapPanel>
<WrapPanel Orientation="Vertical" Visibility="Visible">
</WrapPanel>
<Separator Margin="5,10,5,5"/>
<Label Content="4. Start the pop out process for selected panels." Margin="0,0,0,0" />
<Button Content="Start Pop Out" HorizontalAlignment="Left" Margin="20,5,0,0" Width="130" IsEnabled="{c:Binding Path='DataStore.HasActiveUserProfileId and DataStore.IsFlightActive'}" Command="{Binding Path=StartPopOutCommand}" Style="{StaticResource ProfileSelectedDependency}"/>
</WrapPanel>
<DockPanel DockPanel.Dock="Right" Width="325" HorizontalAlignment="Center">
<Label DockPanel.Dock="Top" Content="Panel Locations" HorizontalAlignment="Center" Margin="0,10,0,0"/>

View file

@ -4,9 +4,6 @@ using System.Windows.Controls;
namespace MSFSPopoutPanelManager.WpfApp
{
/// <summary>
/// Interaction logic for UserControlPanelSelection.xaml
/// </summary>
public partial class UserControlPanelSelection : UserControl
{
private PanelSelectionViewModel _panelSelectionViewModel;
@ -94,16 +91,6 @@ namespace MSFSPopoutPanelManager.WpfApp
private void AddBinding_Click(object sender, RoutedEventArgs e)
{
//ConfirmationDialog dialog = new ConfirmationDialog("Confirm Add Binding", $"Are you sure you want to bind the aircraft livery below to the active profile? \n{_panelSelectionViewModel.DataStore.CurrentMsfsPlaneTitle}");
//dialog.Owner = Application.Current.MainWindow;
//dialog.Topmost = true;
//dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner;
//if ((bool)dialog.ShowDialog())
//{
// _panelSelectionViewModel.AddProfileBindingCommand.Execute(null);
//}
_panelSelectionViewModel.AddProfileBindingCommand.Execute(null);
}

View file

@ -1,10 +1,9 @@
using AutoUpdaterDotNET;
using CommunityToolkit.Mvvm.ComponentModel;
using MSFSPopoutPanelManager.Model;
using MSFSPopoutPanelManager.Provider;
using MSFSPopoutPanelManager.Shared;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
@ -12,21 +11,20 @@ using System.Windows;
namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
public class ApplicationViewModel : INotifyPropertyChanged
public class ApplicationViewModel : ObservableObject
{
private UserProfileManager _userProfileManager;
private PanelPopOutManager _panelPopoutManager;
private SimConnectManager _simConnectManager;
// Using PropertyChanged.Fody
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler<EventArgs<StatusMessage>> ShowContextMenuBalloonTip;
public PanelSelectionViewModel PanelSelectionViewModel { get; private set; }
public PanelConfigurationViewModel PanelConfigurationViewModel { get; private set; }
public PreferencesViewModel PreferencesViewModel { get; private set; }
public DataStore DataStore { get; set; }
public int ActiveUserProfileId { get; set; }
@ -43,6 +41,8 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
public bool IsMinimizedAllPanels { get; set; }
public IntPtr WindowHandle { get; set; }
public DelegateCommand RestartCommand => new DelegateCommand(OnRestart, CanExecute);
public DelegateCommand MinimizeAllPanelsCommand => new DelegateCommand(OnMinimizeAllPanels, CanExecute);
public DelegateCommand ExitCommand => new DelegateCommand(OnExit, CanExecute);
@ -61,15 +61,15 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
_userProfileManager = new UserProfileManager();
_simConnectManager = new SimConnectManager();
_simConnectManager.OnSimConnectDataRefreshed += (sender, e) =>
{
_simConnectManager.OnSimConnectDataRefreshed += (sender, e) =>
{
// Automatic switching of active profile when SimConnect active aircraft livery changes
if(DataStore.CurrentMsfsPlaneTitle != e.Value.Title)
if (DataStore.CurrentMsfsPlaneTitle != e.Value.Title)
{
DataStore.CurrentMsfsPlaneTitle = e.Value.Title;
AutoSwitchProfile(e.Value.Title);
}
DataStore.ElectricalMasterBatteryStatus = e.Value.ElectricalMasterBattery;
};
_simConnectManager.OnConnected += (sender, e) => { DataStore.IsSimulatorStarted = true; };
@ -95,9 +95,9 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
PanelSelectionViewModel = new PanelSelectionViewModel(DataStore, _userProfileManager, _panelPopoutManager, _simConnectManager);
PanelSelectionViewModel.OnPopOutCompleted += (sender, e) => { ShowPanelSelection(false); PanelConfigurationViewModel.Initialize(); };
PanelConfigurationViewModel = new PanelConfigurationViewModel(DataStore, _userProfileManager);
PreferencesViewModel = new PreferencesViewModel(DataStore);
InputHookManager.OnStartPopout += (source, e) => { OnStartPopOut(null); };
}
@ -141,10 +141,17 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
InputHookManager.StartHook();
}
public void Exit()
{
// This method gets call on Windows_Closing
InputHookManager.EndHook();
_simConnectManager.Stop();
}
private void OnRestart(object commandParameter)
{
// Un-minimize all panels if applicable
if(IsMinimizedAllPanels)
if (IsMinimizedAllPanels)
{
DataStore.AllowEdit = true;
IsMinimizedAllPanels = false;
@ -167,10 +174,14 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
private void OnExit(object commandParameter)
{
InputHookManager.EndHook();
_simConnectManager.Stop();
if (Application.Current != null)
Application.Current.Dispatcher.Invoke(() => Application.Current.Shutdown());
}
Application.Current.Shutdown();
private void ShutDownApplication()
{
if (Application.Current != null)
Application.Current.Shutdown();
}
private void OnMinimizeAllPanels(object commandParameter)
@ -306,4 +317,4 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
}
}
}
}
}

View file

@ -1,17 +1,16 @@
using MSFSPopoutPanelManager.Model;
using CommunityToolkit.Mvvm.ComponentModel;
using MSFSPopoutPanelManager.Model;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
public class DataStore : INotifyPropertyChanged
public class DataStore : ObservableObject
{
private int _activeProfileId;
public event PropertyChangedEventHandler PropertyChanged;
private AppSetting _appSetting;
public event EventHandler OnActiveUserProfileChanged;
public event EventHandler OnAllowEditChanged;
@ -23,21 +22,45 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
IsFlightActive = true; // ToDo: temporary for testing
}
public AppSetting AppSetting { get; set; }
public AppSetting AppSetting
{
get
{
return _appSetting;
}
set
{
_appSetting = value;
if (_appSetting != null)
{
IsEnableAutoPopOutPanel = _appSetting.AutoPopOutPanels;
}
// bubble event up to this 'DataStore' level
_appSetting.AutoPopOutPanelsChanged += (sender, e) =>
{
IsEnableAutoPopOutPanel = e.Value;
};
}
}
public ObservableCollection<UserProfile> UserProfiles { get; set; }
public ObservableCollection<PanelSourceCoordinate> ActiveProfilePanelCoordinates
{
get
public ObservableCollection<PanelSourceCoordinate> ActiveProfilePanelCoordinates
{
get
{
if (ActiveUserProfile == null)
return new ObservableCollection<PanelSourceCoordinate>();
else
return ActiveUserProfile.PanelSourceCoordinates;
}
return ActiveUserProfile.PanelSourceCoordinates;
}
}
public ObservableCollection<PanelConfig> ActiveProfilePanelConfigs
{
get
@ -69,14 +92,10 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
}
set
{
if(value != _allowEdit)
if (value != _allowEdit)
{
_allowEdit = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("AllowEdit"));
OnAllowEditChanged?.Invoke(this, null);
}
OnAllowEditChanged?.Invoke(this, null);
}
}
}
@ -98,7 +117,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
// Set active profile flag
UserProfiles.ToList().ForEach(p => p.IsActive = false);
var profile = UserProfiles.ToList().Find(p => p.ProfileId == value);
if(profile != null)
if (profile != null)
profile.IsActive = true;
OnActiveUserProfileChanged?.Invoke(this, null);
@ -112,7 +131,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
public string CurrentMsfsPlaneTitle { get; set; }
public bool HasCurrentMsfsPlaneTitle
public bool HasCurrentMsfsPlaneTitle
{
get { return !String.IsNullOrEmpty(CurrentMsfsPlaneTitle); }
}
@ -123,7 +142,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
if (ActiveUserProfile == null)
return false;
return ActiveUserProfile.BindingAircraftLiveries.ToList().Exists(p => p == CurrentMsfsPlaneTitle);
}
}
@ -165,5 +184,6 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
public bool IsEnteredFlight { get; set; }
public bool IsFlightActive { get; set; }
public bool IsEnableAutoPopOutPanel { get; set; }
}
}
}

View file

@ -22,4 +22,4 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
public void InvokeCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
}

View file

@ -1,20 +1,15 @@
using MSFSPopoutPanelManager.Model;
using CommunityToolkit.Mvvm.ComponentModel;
using MSFSPopoutPanelManager.Model;
using MSFSPopoutPanelManager.Provider;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
public class PanelConfigurationViewModel
public class PanelConfigurationViewModel : ObservableObject
{
private UserProfileManager _userProfileManager;
private PanelConfigurationManager _panelConfigurationManager;
// Using PropertyChanged.Fody
public event PropertyChangedEventHandler PropertyChanged;
public DataStore DataStore { get; set; }
public PanelConfigItem SelectedPanelConfigItem { get; set; }
@ -39,9 +34,9 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
_panelConfigurationManager.UserProfile = DataStore.ActiveUserProfile;
_panelConfigurationManager.AllowEdit = DataStore.AllowEdit;
_panelConfigurationManager.HookWinEvent();
DataStore.OnAllowEditChanged += (sender, e) =>
DataStore.OnAllowEditChanged += (sender, e) =>
{
_panelConfigurationManager.AllowEdit = DataStore.AllowEdit;
_panelConfigurationManager.AllowEdit = DataStore.AllowEdit;
};
}
@ -57,7 +52,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
private void OnPanelConfigUpdated(object panelConfigItem)
{
if(DataStore.AllowEdit)
if (DataStore.AllowEdit)
_panelConfigurationManager.PanelConfigPropertyUpdated(panelConfigItem as PanelConfigItem);
}
@ -71,5 +66,5 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
return true;
}
}
}
}
}

View file

@ -1,8 +1,8 @@
using MSFSPopoutPanelManager.Model;
using CommunityToolkit.Mvvm.ComponentModel;
using MSFSPopoutPanelManager.Model;
using MSFSPopoutPanelManager.Provider;
using MSFSPopoutPanelManager.Shared;
using System;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Windows;
@ -10,7 +10,7 @@ using System.Windows.Interop;
namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
public class PanelSelectionViewModel : INotifyPropertyChanged
public class PanelSelectionViewModel : ObservableObject
{
private UserProfileManager _userProfileManager;
private PanelSelectionManager _panelSelectionManager;
@ -18,14 +18,11 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
private SimConnectManager _simConnectManager;
private bool _minimizeForPopOut;
// Using PropertyChanged.Fody
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler OnPopOutStarted;
public event EventHandler OnPopOutCompleted;
public event EventHandler OnShowPrePopOutMessage;
public event EventHandler OnUserProfileChanged;
public DataStore DataStore { get; set; }
public DataStore DataStore { get; private set; }
public bool IsEditingPanelCoorOverlay { get; set; }
@ -43,8 +40,9 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
public PanelSelectionViewModel(DataStore dataStore, UserProfileManager userProfileManager, PanelPopOutManager panelPopoutManager, SimConnectManager simConnectManager)
{
DataStore = dataStore;
DataStore.OnActiveUserProfileChanged += (sender, e) => {
IsEditingPanelCoorOverlay = false;
DataStore.OnActiveUserProfileChanged += (sender, e) =>
{
IsEditingPanelCoorOverlay = false;
RemoveAllPanelCoorOverlay();
};
@ -95,6 +93,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
private void OnChangeProfile(object commandParameter)
{
DataStore.AppSetting.LastUsedProfileId = DataStore.ActiveUserProfileId;
OnUserProfileChanged?.Invoke(this, null);
}
private void OnAddProfileBinding(object commandParameter)
@ -178,7 +177,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
// Turn off TrackIR if TrackIR is started
if (commandParameter == null && DataStore.AppSetting.AutoDisableTrackIR)
{
if(IsEditingPanelCoorOverlay)
if (IsEditingPanelCoorOverlay)
_simConnectManager.TurnOffTrackIR();
else
_simConnectManager.TurnOnTrackIR();
@ -209,7 +208,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
var overlay = (Window)sender;
var handle = new WindowInteropHelper(Window.GetWindow(overlay)).Handle;
panelSourceCoordinate.PanelHandle = handle;
PInvoke.MoveWindow(handle, (int)overlay.Left, (int)overlay.Top, (int)overlay.Width, (int)overlay.Height, false);
WindowManager.MoveWindow(handle, PanelType.WPFWindow, (int)overlay.Left, (int)overlay.Top, (int)overlay.Width, (int)overlay.Height);
};
overlay.WindowStartupLocation = System.Windows.WindowStartupLocation.Manual;
overlay.Left = panelSourceCoordinate.X - overlay.Width / 2;
@ -276,7 +275,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
OnPopOutCompleted?.Invoke(this, null);
}
// Turn off TrackIR if TrackIR is started
if (DataStore.AppSetting.AutoDisableTrackIR)
_simConnectManager.TurnOnTrackIR();
}
@ -294,7 +293,7 @@ namespace MSFSPopoutPanelManager.WpfApp.ViewModel
else
Logger.LogStatus("Panels selection is completed. No panel has been selected.", StatusMessageType.Info);
// Turn off TrackIR if TrackIR is started
if (DataStore.AppSetting.AutoDisableTrackIR)
_simConnectManager.TurnOnTrackIR();
}

View file

@ -0,0 +1,58 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace MSFSPopoutPanelManager.WpfApp.ViewModel
{
public class PreferencesViewModel : ObservableObject
{
public PreferencesViewModel(DataStore dataStore)
{
DataStore = dataStore;
ApplicationSettingsVisible = true;
PopOutSettingsVisible = false;
AutoPopOutSettingsVisible = false;
TrackIRSettingsVisible = false;
}
public DelegateCommand SectionSelectCommand => new DelegateCommand(OnSectionSelected, CanExecute);
public DataStore DataStore { get; private set; }
public bool ApplicationSettingsVisible { get; private set; }
public bool PopOutSettingsVisible { get; private set; }
public bool AutoPopOutSettingsVisible { get; private set; }
public bool TrackIRSettingsVisible { get; private set; }
private bool CanExecute(object commandParameter)
{
return true;
}
private void OnSectionSelected(object commandParameter)
{
ApplicationSettingsVisible = false;
PopOutSettingsVisible = false;
AutoPopOutSettingsVisible = false;
TrackIRSettingsVisible = false;
switch (commandParameter.ToString())
{
case "Application Settings":
ApplicationSettingsVisible = true;
break;
case "Pop Out Settings":
PopOutSettingsVisible = true;
break;
case "Auto Pop Out Panel Settings":
AutoPopOutSettingsVisible = true;
break;
case "Track IR Settings":
TrackIRSettingsVisible = true;
break;
}
}
}
}

View file

@ -17,6 +17,10 @@
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
</PropertyGroup>
<ItemGroup>
<None Remove="resources\logo.png" />
</ItemGroup>
<ItemGroup>
<Content Include="log4net.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@ -30,6 +34,9 @@
<Content Include="Resources\info.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="resources\logo.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\msfsconnected.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@ -42,18 +49,15 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autoupdater.NET.Official" Version="1.7.0" />
<PackageReference Include="Autoupdater.NET.Official" Version="1.7.3" />
<PackageReference Include="CalcBinding" Version="2.5.2" />
<PackageReference Include="Fody" Version="6.6.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="CommunityToolkit.Mvvm" Version="7.1.2" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf" Version="1.1.0" />
<PackageReference Include="log4net" Version="2.0.14" />
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
<PackageReference Include="MouseKeyHook" Version="5.6.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
<PackageReference Include="PropertyChanged.Fody" Version="3.4.1" />
</ItemGroup>
<ItemGroup>

BIN
WpfApp/resources/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB