From 6f3c6fa75e399a3c5f1d419fe6393829f0aedc76 Mon Sep 17 00:00:00 2001 From: jrhodnik Date: Sat, 25 May 2019 23:42:59 -0400 Subject: [PATCH] Started implementing GUI. --- VDash/ConfigManager.cs | 12 +++ VDash/MainWindow.xaml | 27 ++++- VDash/MainWindow.xaml.cs | 50 ++++++---- .../Actions/BringWindowToFrontAction.cs | 2 +- VDash/Overlay/Actions/MaximizeWindowAction.cs | 2 +- VDash/Overlay/Actions/ResizeWindowAction.cs | 2 +- VDash/Overlay/Actions/RestoreWindowAction.cs | 2 +- VDash/Overlay/Config/IOverlayConfig.cs | 14 +++ VDash/Overlay/Config/MonitorOverlayConfig.cs | 15 +++ VDash/Overlay/Config/WindowOverlayConfig.cs | 29 ++++++ VDash/Overlay/IOverlay.cs | 6 +- VDash/Overlay/MonitorOverlay.cs | 33 ++++--- VDash/Overlay/WindowOverlay.cs | 55 ++++++----- VDash/OverlayManager.cs | 17 ++++ VDash/UI/CreateNewOverlay.xaml | 30 ++++++ VDash/UI/CreateNewOverlay.xaml.cs | 99 +++++++++++++++++++ VDash/UI/IOverlayEditor.cs | 14 +++ VDash/UI/MonitorOverlayEditor.xaml | 30 ++++++ VDash/UI/MonitorOverlayEditor.xaml.cs | 48 +++++++++ VDash/UI/ProcessSelectorEditor.xaml | 22 +++++ VDash/UI/ProcessSelectorEditor.xaml.cs | 32 ++++++ VDash/UI/WindowOverlayEditor.xaml | 46 +++++++++ VDash/UI/WindowOverlayEditor.xaml.cs | 96 ++++++++++++++++++ VDash/UI/WindowSelectorEditor.xaml | 26 +++++ VDash/UI/WindowSelectorEditor.xaml.cs | 39 ++++++++ VDash/Utilities/User32.cs | 18 ++-- VDash/VDash.csproj | 42 +++++++- VDash/WindowSelectors/FromProcessName.cs | 15 ++- .../{FromWindowName.cs => FromWindowTitle.cs} | 25 +++-- 29 files changed, 751 insertions(+), 97 deletions(-) create mode 100644 VDash/ConfigManager.cs create mode 100644 VDash/Overlay/Config/IOverlayConfig.cs create mode 100644 VDash/Overlay/Config/MonitorOverlayConfig.cs create mode 100644 VDash/Overlay/Config/WindowOverlayConfig.cs create mode 100644 VDash/OverlayManager.cs create mode 100644 VDash/UI/CreateNewOverlay.xaml create mode 100644 VDash/UI/CreateNewOverlay.xaml.cs create mode 100644 VDash/UI/IOverlayEditor.cs create mode 100644 VDash/UI/MonitorOverlayEditor.xaml create mode 100644 VDash/UI/MonitorOverlayEditor.xaml.cs create mode 100644 VDash/UI/ProcessSelectorEditor.xaml create mode 100644 VDash/UI/ProcessSelectorEditor.xaml.cs create mode 100644 VDash/UI/WindowOverlayEditor.xaml create mode 100644 VDash/UI/WindowOverlayEditor.xaml.cs create mode 100644 VDash/UI/WindowSelectorEditor.xaml create mode 100644 VDash/UI/WindowSelectorEditor.xaml.cs rename VDash/WindowSelectors/{FromWindowName.cs => FromWindowTitle.cs} (87%) diff --git a/VDash/ConfigManager.cs b/VDash/ConfigManager.cs new file mode 100644 index 0000000..c75b815 --- /dev/null +++ b/VDash/ConfigManager.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VDash +{ + class ConfigManager + { + } +} diff --git a/VDash/MainWindow.xaml b/VDash/MainWindow.xaml index 9200877..f545546 100644 --- a/VDash/MainWindow.xaml +++ b/VDash/MainWindow.xaml @@ -7,9 +7,28 @@ mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VDash/MainWindow.xaml.cs b/VDash/MainWindow.xaml.cs index 43cd4d4..bbaa829 100644 --- a/VDash/MainWindow.xaml.cs +++ b/VDash/MainWindow.xaml.cs @@ -23,11 +23,12 @@ namespace VDash /// public partial class MainWindow : Window { + public static OverlayManager OverlayManager = new OverlayManager(); public MainWindow() { InitializeComponent(); - // Connect to VR runtime... + //Connect to VR runtime... EVRInitError initError = EVRInitError.None; var ret = OpenVR.Init(ref initError, EVRApplicationType.VRApplication_Overlay); @@ -37,6 +38,10 @@ namespace VDash throw new Exception($"Error connecting to VR: {initError.ToString()}"); } + lvOverlays.ItemsSource = OverlayManager.Overlays; + + #region Debug + //StartOverlayWindow("Discord"); @@ -54,29 +59,34 @@ namespace VDash //var bringWindow = new Overlay.Actions.BringWindowToFrontAction(true); //obsoverlay.OverlayShownActions.Add(bringWindow); - var displays = User32.GetDisplays(); - MonitorOverlay mo0 = new MonitorOverlay("left", "Left Monitor", displays[0]); - mo0.Create(); - MonitorOverlay mo1 = new MonitorOverlay("center", "Center Monitor", displays[1]); - mo1.Create(); - MonitorOverlay mo2= new MonitorOverlay("right", "Right Monitor", displays[2]); - mo2.Create(); + //var displays = User32.GetDisplays(); + //MonitorOverlay mo0 = new MonitorOverlay("left", "Left Monitor", displays[0]); + //mo0.Create(); + //MonitorOverlay mo1 = new MonitorOverlay("center", "Center Monitor", displays[1]); + //mo1.Create(); + //MonitorOverlay mo2= new MonitorOverlay("right", "Right Monitor", displays[2]); + //mo2.Create(); + #endregion } - - - //This is just for debugging I swear - int count = 0; - IOverlay StartOverlayWindow(string windowFilter) + private void btnAdd_Click(object sender, RoutedEventArgs e) { - var ws = new WindowSelectors.FromWindowTitle(windowFilter, WindowSelectors.FromWindowTitle.TitleSearchType.Contains); - Overlay.WindowOverlay overlay = new Overlay.WindowOverlay($"ws{count}", "Loading...", ws, true); - overlay.Create(); + Window w = new Window(); + var uc = new UI.CreateNewOverlay(); + uc.Created += (x, y) => { w.Close(); }; + w.Content = uc; + w.Width = 500; + w.Height = 400; + w.SizeToContent = System.Windows.SizeToContent.Height; + w.Show(); + } - var bringWindow = new Overlay.Actions.BringWindowToFrontAction(true); - overlay.OverlayShownActions.Add(bringWindow); - count++; - return overlay; + private void btnRemove_Click(object sender, RoutedEventArgs e) + { + if(lvOverlays.SelectedItem == null) { return; } + IOverlay overlay = (IOverlay)lvOverlays.SelectedItem; + overlay.Dispose(); + OverlayManager.Overlays.Remove(overlay); } } } diff --git a/VDash/Overlay/Actions/BringWindowToFrontAction.cs b/VDash/Overlay/Actions/BringWindowToFrontAction.cs index 8907c6b..d216c3c 100644 --- a/VDash/Overlay/Actions/BringWindowToFrontAction.cs +++ b/VDash/Overlay/Actions/BringWindowToFrontAction.cs @@ -32,7 +32,7 @@ namespace VDash.Overlay.Actions } WindowOverlay overlay = (WindowOverlay)intOverlay; - IntPtr handle = overlay.Selector.GetWindowHandle(); + IntPtr handle = overlay.Config.Selector.GetWindowHandle(); PreformAction(handle); } diff --git a/VDash/Overlay/Actions/MaximizeWindowAction.cs b/VDash/Overlay/Actions/MaximizeWindowAction.cs index 507cde2..8edfbf0 100644 --- a/VDash/Overlay/Actions/MaximizeWindowAction.cs +++ b/VDash/Overlay/Actions/MaximizeWindowAction.cs @@ -22,7 +22,7 @@ namespace VDash.Overlay.Actions } WindowOverlay overlay = (WindowOverlay)intOverlay; - IntPtr handle = overlay.Selector.GetWindowHandle(); + IntPtr handle = overlay.Config.Selector.GetWindowHandle(); PreformAction(handle); } diff --git a/VDash/Overlay/Actions/ResizeWindowAction.cs b/VDash/Overlay/Actions/ResizeWindowAction.cs index 444023f..dd47984 100644 --- a/VDash/Overlay/Actions/ResizeWindowAction.cs +++ b/VDash/Overlay/Actions/ResizeWindowAction.cs @@ -29,7 +29,7 @@ namespace VDash.Overlay.Actions } WindowOverlay overlay = (WindowOverlay)intOverlay; - IntPtr handle = overlay.Selector.GetWindowHandle(); + IntPtr handle = overlay.Config.Selector.GetWindowHandle(); PreformAction(handle); } diff --git a/VDash/Overlay/Actions/RestoreWindowAction.cs b/VDash/Overlay/Actions/RestoreWindowAction.cs index 7e9e2e8..5173bca 100644 --- a/VDash/Overlay/Actions/RestoreWindowAction.cs +++ b/VDash/Overlay/Actions/RestoreWindowAction.cs @@ -22,7 +22,7 @@ namespace VDash.Overlay.Actions } WindowOverlay overlay = (WindowOverlay)intOverlay; - IntPtr handle = overlay.Selector.GetWindowHandle(); + IntPtr handle = overlay.Config.Selector.GetWindowHandle(); PreformAction(handle); } diff --git a/VDash/Overlay/Config/IOverlayConfig.cs b/VDash/Overlay/Config/IOverlayConfig.cs new file mode 100644 index 0000000..0dc7ba2 --- /dev/null +++ b/VDash/Overlay/Config/IOverlayConfig.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VDash.Overlay.Config +{ + public interface IOverlayConfig + { + string Name { get; set; } + string Key { get; set; } + } +} diff --git a/VDash/Overlay/Config/MonitorOverlayConfig.cs b/VDash/Overlay/Config/MonitorOverlayConfig.cs new file mode 100644 index 0000000..63e1027 --- /dev/null +++ b/VDash/Overlay/Config/MonitorOverlayConfig.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace VDash.Overlay.Config +{ + public class MonitorOverlayConfig : IOverlayConfig + { + public string Name { get; set; } + public string Key { get; set; } + public string MonitorName { get; set; } + } +} diff --git a/VDash/Overlay/Config/WindowOverlayConfig.cs b/VDash/Overlay/Config/WindowOverlayConfig.cs new file mode 100644 index 0000000..cef802a --- /dev/null +++ b/VDash/Overlay/Config/WindowOverlayConfig.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VDash.WindowSelectors; + +namespace VDash.Overlay.Config +{ + public class WindowOverlayConfig : IOverlayConfig + { + public WindowOverlayConfig(string name, string key, IWindowSelector selector, bool updateDashboardName, bool destroyOnNoWindowFound) + { + Name = name; + Key = key; + Selector = selector; + UpdateDashboardName = updateDashboardName; + DestroyOnNoWindowFound = destroyOnNoWindowFound; + } + public WindowOverlayConfig() { } + + public string Name { get; set; } + public string Key { get; set; } + + public IWindowSelector Selector {get; set; } + public bool UpdateDashboardName { get; set; } = false; + public bool DestroyOnNoWindowFound { get; set; } = false; + } +} diff --git a/VDash/Overlay/IOverlay.cs b/VDash/Overlay/IOverlay.cs index 4a3a34a..9f387ef 100644 --- a/VDash/Overlay/IOverlay.cs +++ b/VDash/Overlay/IOverlay.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using VDash.Overlay.Actions; +using VDash.Overlay.Config; namespace VDash.Overlay { @@ -13,8 +14,7 @@ namespace VDash.Overlay List OverlayHiddenActions { get; } ulong OverlayHandle { get; } - string Name { get; } - string Key { get; } + IOverlayConfig OverlayConfig { get; } void Create(); void Destroy(); @@ -22,5 +22,7 @@ namespace VDash.Overlay float GetOverlayWidth(); void SetOverlayWidth(float width); void SetOverlayName(string newName); + + int CurrentFPS { get; } } } diff --git a/VDash/Overlay/MonitorOverlay.cs b/VDash/Overlay/MonitorOverlay.cs index 5f120a3..9d805e6 100644 --- a/VDash/Overlay/MonitorOverlay.cs +++ b/VDash/Overlay/MonitorOverlay.cs @@ -17,6 +17,7 @@ using VDash.Utilities; using VDash.WindowSelectors; using System.Linq; using static VDash.Utilities.User32; +using VDash.Overlay.Config; namespace VDash.Overlay { @@ -35,30 +36,29 @@ namespace VDash.Overlay bool m_Created = false; bool m_Running = true; - public DisplayInfo DisplayInfo { get; private set; } + public DisplayInfo DisplayInfo { get + { + return User32.GetDisplays().Single(x => x.MonitorInfo.DeviceName == Config.MonitorName); + } + } internal ulong m_OverlayHandle; public ulong OverlayHandle { get { return m_OverlayHandle; } } internal ulong m_ThumbnailIcon; public ulong ThumbnailIcon { get { return m_ThumbnailIcon; } } - - internal string m_Key; - public string Key { get { return m_Key; } } - - internal string m_Name; - public string Name { get { return m_Name; } } public List OverlayShownActions { get; private set; } = new List(); public List OverlayHiddenActions { get; private set; } = new List(); + public IOverlayConfig OverlayConfig { get { return Config; } } + public MonitorOverlayConfig Config { get; set; } + char[] specialKeys = { '+', '^', '%', '~', '(', ')', '{', '}', '[', ']' }; - public MonitorOverlay(string key, string name, DisplayInfo display) + public MonitorOverlay(MonitorOverlayConfig config) { - m_Key = key; - m_Name = name; - DisplayInfo = display; + Config = config; } @@ -74,7 +74,7 @@ namespace VDash.Overlay //Actually create the overlay var overlay = OpenVR.Overlay; - EVROverlayError err = overlay.CreateDashboardOverlay(m_Key, m_Name, ref m_OverlayHandle, ref m_ThumbnailIcon); + EVROverlayError err = overlay.CreateDashboardOverlay(Config.Key, Config.Name, ref m_OverlayHandle, ref m_ThumbnailIcon); if (err != EVROverlayError.None) { @@ -351,8 +351,7 @@ namespace VDash.Overlay int width = rect.right - rect.left; int height = rect.bottom - rect.top; - - //Make sure the coords are actually valid. Could be minimized or something. + if (width > 0 && height > 0) { using (var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb)) @@ -542,7 +541,6 @@ namespace VDash.Overlay public void SetOverlayName(string newName) { OpenVR.Overlay.SetOverlayName(m_OverlayHandle, newName); - m_Name = newName; } public float GetOverlayWidth() @@ -556,5 +554,10 @@ namespace VDash.Overlay { OpenVR.Overlay.SetOverlayWidthInMeters(m_OverlayHandle, width); } + + public override string ToString() + { + return Config.Name; + } } } diff --git a/VDash/Overlay/WindowOverlay.cs b/VDash/Overlay/WindowOverlay.cs index c668fad..df2b4e7 100644 --- a/VDash/Overlay/WindowOverlay.cs +++ b/VDash/Overlay/WindowOverlay.cs @@ -16,19 +16,16 @@ using VDash.Overlay.Actions; using VDash.Utilities; using VDash.WindowSelectors; using System.Linq; +using VDash.Overlay.Config; namespace VDash.Overlay { public class WindowOverlay : IOverlay { - public event EventHandler OverlayShown; public event EventHandler OverlayHidden; - - public bool UpdateDashboardName { get; set; } = false; - public bool DestroyOnNoWindowFound { get; set; } = false; public int CurrentFPS { get; private set; } - + private Task m_EventPumpTask = null; /// /// Tracks whether or not this overlay is actually created. @@ -40,27 +37,26 @@ namespace VDash.Overlay public ulong OverlayHandle { get { return m_OverlayHandle; } } internal ulong m_ThumbnailIcon; public ulong ThumbnailIcon { get { return m_ThumbnailIcon; } } + public IOverlayConfig OverlayConfig { get { return Config; } } - internal string m_Key; - public string Key { get { return m_Key; } } + public WindowOverlayConfig Config { get; set; } - internal string m_Name; - public string Name { get { return m_Name; } } + //internal string m_Key; + + //internal string m_Name; - public IWindowSelector Selector { get; private set; } = null; + //public IWindowSelector Selector { get; private set; } = null; public List OverlayShownActions { get; private set; } = new List(); public List OverlayHiddenActions { get; private set; } = new List(); char[] specialKeys = { '+', '^', '%', '~', '(', ')', '{', '}', '[', ']' }; - public WindowOverlay(string key, string name, IWindowSelector selector, bool updateDashboardName) + public WindowOverlay(WindowOverlayConfig config) { - m_Key = key; - m_Name = name; - Selector = selector; - UpdateDashboardName = updateDashboardName; + //Selector = selector; + Config = config; } /// @@ -82,7 +78,7 @@ namespace VDash.Overlay //Actually create the overlay var overlay = OpenVR.Overlay; - EVROverlayError err = overlay.CreateDashboardOverlay(m_Key, m_Name, ref m_OverlayHandle, ref m_ThumbnailIcon); + EVROverlayError err = overlay.CreateDashboardOverlay(Config.Key, Config.Name, ref m_OverlayHandle, ref m_ThumbnailIcon); if (err != EVROverlayError.None) { @@ -161,21 +157,21 @@ namespace VDash.Overlay while (m_Running) { - if (DestroyOnNoWindowFound) + if (Config.DestroyOnNoWindowFound) { //Check to see if the window actually exists. Act accordingly. - if (!Selector.WindowExists()) + if (!Config.Selector.WindowExists()) { if (IsCreated()) { destroyInternal(); - Console.WriteLine($"Destroyed {m_Key} because it's window does not exist."); + Console.WriteLine($"Destroyed {Config.Key} because it's window does not exist."); } Thread.Sleep(100); continue; } - else if(Selector.WindowExists() && !m_Created && !m_Destroyed) + else if(Config.Selector.WindowExists() && !m_Created && !m_Destroyed) { createInternal(); } @@ -185,16 +181,16 @@ namespace VDash.Overlay IntPtr windowHandle = IntPtr.Zero; try { - windowHandle = Selector.GetWindowHandle(); + windowHandle = Config.Selector.GetWindowHandle(); } catch (WindowNotFoundException) { } //Update the SteamVR dash name if necessary, only once a second. - if (Selector.WindowExists() && UpdateDashboardName && DateTime.Now.Subtract(lastNameCheck).TotalMilliseconds >= 1000) + if (Config.Selector.WindowExists() && Config.UpdateDashboardName && DateTime.Now.Subtract(lastNameCheck).TotalMilliseconds >= 1000) { - var window = Selector.GetWindowInfo(); + var window = Config.Selector.GetWindowInfo(); if(GetOverlayName() != window.Title) { SetOverlayName(window.Title); @@ -339,7 +335,7 @@ namespace VDash.Overlay { OverlayShown?.Invoke(this, new EventArgs()); - if (Selector.WindowExists()) + if (Config.Selector.WindowExists()) { foreach (var action in OverlayShownActions) { @@ -352,7 +348,7 @@ namespace VDash.Overlay { OverlayHidden?.Invoke(this, new EventArgs()); - if (Selector.WindowExists()) + if (Config.Selector.WindowExists()) { foreach (var action in OverlayHiddenActions) { @@ -418,7 +414,7 @@ namespace VDash.Overlay #region Acutally Render //Redundant check, but w/e - if (Selector.WindowExists() && windowHandle != IntPtr.Zero) + if (Config.Selector.WindowExists() && windowHandle != IntPtr.Zero) { var rect = new User32.Rect(); User32.GetClientRect(windowHandle, ref rect); @@ -621,7 +617,7 @@ namespace VDash.Overlay public void SetOverlayName(string newName) { OpenVR.Overlay.SetOverlayName(m_OverlayHandle, newName); - m_Name = newName; + //Config.Name = newName; } public float GetOverlayWidth() @@ -635,5 +631,10 @@ namespace VDash.Overlay { OpenVR.Overlay.SetOverlayWidthInMeters(m_OverlayHandle, width); } + + public override string ToString() + { + return Config.Name; + } } } diff --git a/VDash/OverlayManager.cs b/VDash/OverlayManager.cs new file mode 100644 index 0000000..bdbf1be --- /dev/null +++ b/VDash/OverlayManager.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VDash.Overlay; + +namespace VDash +{ + public class OverlayManager + { + public ObservableCollection Overlays { get; internal set; } = new ObservableCollection(); + } +} diff --git a/VDash/UI/CreateNewOverlay.xaml b/VDash/UI/CreateNewOverlay.xaml new file mode 100644 index 0000000..7c3cd73 --- /dev/null +++ b/VDash/UI/CreateNewOverlay.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + New Overlay Type: + + + + + + + + diff --git a/VDash/UI/CreateNewOverlay.xaml.cs b/VDash/UI/CreateNewOverlay.xaml.cs new file mode 100644 index 0000000..0f55d27 --- /dev/null +++ b/VDash/UI/CreateNewOverlay.xaml.cs @@ -0,0 +1,99 @@ +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.Navigation; +using System.Windows.Shapes; +using VDash.Overlay; + +namespace VDash.UI +{ + /// + /// Interaction logic for CreateNewOverlay.xaml + /// + public partial class CreateNewOverlay : UserControl + { + public event EventHandler Created; + + public OverlayTypeWrapper[] EligibleOverlays { get; private set; } = { + new OverlayTypeWrapper("Window Overlay", typeof(WindowOverlay), new WindowOverlayEditor()), + new OverlayTypeWrapper("Monitor Overlay", typeof(MonitorOverlay), new MonitorOverlayEditor()) + }; + + public CreateNewOverlay() + { + InitializeComponent(); + DataContext = this; + } + + private void cbOverlayType_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + bdrContent.Child = ((OverlayTypeWrapper)cbOverlayType.SelectedItem).Control; + } + + private void btnCreate_Click(object sender, RoutedEventArgs e) + { + var wrapper = ((OverlayTypeWrapper)cbOverlayType.SelectedItem); + var config = wrapper.Editor.Config; + if (String.IsNullOrWhiteSpace(config.Key)) + { + config.Key = RandomString(8, true); + } + + IOverlay overlay = (IOverlay)Activator.CreateInstance(wrapper.OverlayType, new object[] { config }); + overlay.Create(); + + MainWindow.OverlayManager.Overlays.Add(overlay); + + Created?.Invoke(this, null); + } + + // Generate a random string with a given size + public string RandomString(int size, bool lowerCase) + { + StringBuilder builder = new StringBuilder(); + Random random = new Random(); + char ch; + for (int i = 0; i < size; i++) + { + ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))); + builder.Append(ch); + } + if (lowerCase) + return builder.ToString().ToLower(); + return builder.ToString(); + } + } + + + public class OverlayTypeWrapper + { + public Type OverlayType { get; private set; } + public string FriendlyName { get; private set; } + public UserControl Control { get; private set; } + //this is a bit messy... + public IOverlayEditor Editor { get { return (IOverlayEditor)Control; } } + public OverlayTypeWrapper(string friendlyName, Type overlayType, UserControl control) + { + if (!typeof(IOverlay).IsAssignableFrom(overlayType)) + { + throw new Exception("The type must be based on IOverlay."); + } + OverlayType = overlayType; + FriendlyName = friendlyName; + Control = control; + } + public override string ToString() + { + return FriendlyName; + } + } +} diff --git a/VDash/UI/IOverlayEditor.cs b/VDash/UI/IOverlayEditor.cs new file mode 100644 index 0000000..bc87bff --- /dev/null +++ b/VDash/UI/IOverlayEditor.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using VDash.Overlay.Config; + +namespace VDash.UI +{ + public interface IOverlayEditor + { + IOverlayConfig Config { get; } + } +} diff --git a/VDash/UI/MonitorOverlayEditor.xaml b/VDash/UI/MonitorOverlayEditor.xaml new file mode 100644 index 0000000..c98830e --- /dev/null +++ b/VDash/UI/MonitorOverlayEditor.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + Name: + + Monitor: + + + + + + + diff --git a/VDash/UI/MonitorOverlayEditor.xaml.cs b/VDash/UI/MonitorOverlayEditor.xaml.cs new file mode 100644 index 0000000..e9ea159 --- /dev/null +++ b/VDash/UI/MonitorOverlayEditor.xaml.cs @@ -0,0 +1,48 @@ +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.Navigation; +using System.Windows.Shapes; +using VDash.Overlay.Config; +using static VDash.Utilities.User32; + +namespace VDash.UI +{ + /// + /// Interaction logic for MonitorOverlayEditor.xaml + /// + public partial class MonitorOverlayEditor : UserControl,IOverlayEditor + { + public IOverlayConfig Config { get { return OverlayConfig; } } + public MonitorOverlayConfig OverlayConfig { get; set; } = new MonitorOverlayConfig(); + + public MonitorOverlayEditor(ref MonitorOverlayConfig config) + { + InitializeComponent(); + OverlayConfig = config; + DataContext = OverlayConfig; + cbMontitor.ItemsSource = GetDisplays(); + } + + public MonitorOverlayEditor() + { + InitializeComponent(); + DataContext = OverlayConfig; + cbMontitor.ItemsSource = GetDisplays(); + } + + private void cbMontitor_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + OverlayConfig.MonitorName = ((DisplayInfo)cbMontitor.SelectedItem).MonitorInfo.DeviceName; + } + } +} diff --git a/VDash/UI/ProcessSelectorEditor.xaml b/VDash/UI/ProcessSelectorEditor.xaml new file mode 100644 index 0000000..7205f1b --- /dev/null +++ b/VDash/UI/ProcessSelectorEditor.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + Process Name: + + + diff --git a/VDash/UI/ProcessSelectorEditor.xaml.cs b/VDash/UI/ProcessSelectorEditor.xaml.cs new file mode 100644 index 0000000..9bdcdee --- /dev/null +++ b/VDash/UI/ProcessSelectorEditor.xaml.cs @@ -0,0 +1,32 @@ +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.Navigation; +using System.Windows.Shapes; +using VDash.WindowSelectors; + +namespace VDash.UI +{ + /// + /// Interaction logic for ProcessSelectorEditor.xaml + /// + public partial class ProcessSelectorEditor : UserControl + { + public FromProcessName Selector { get; private set; } + public ProcessSelectorEditor(ref FromProcessName selector) + { + InitializeComponent(); + Selector = selector; + DataContext = Selector; + } + } +} diff --git a/VDash/UI/WindowOverlayEditor.xaml b/VDash/UI/WindowOverlayEditor.xaml new file mode 100644 index 0000000..e510d9d --- /dev/null +++ b/VDash/UI/WindowOverlayEditor.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + Name: + + Window Selector: + + Auto dashboard name: + + Hide when no window found: + + + + + + + + + + diff --git a/VDash/UI/WindowOverlayEditor.xaml.cs b/VDash/UI/WindowOverlayEditor.xaml.cs new file mode 100644 index 0000000..ae65b4b --- /dev/null +++ b/VDash/UI/WindowOverlayEditor.xaml.cs @@ -0,0 +1,96 @@ +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.Navigation; +using System.Windows.Shapes; +using VDash.Overlay.Config; +using VDash.WindowSelectors; + +namespace VDash.UI +{ + /// + /// Interaction logic for CreateWindowOverlay.xaml + /// + public partial class WindowOverlayEditor : UserControl,IOverlayEditor + { + public WindowOverlayConfig OverlayConfig { get; set; } = new WindowOverlayConfig(); + + public SelectorWrapper[] Selectors { get; private set; } = + { + new SelectorWrapper("By Process Name", typeof(FromProcessName), typeof(ProcessSelectorEditor)), + new SelectorWrapper("By Window Title", typeof(FromWindowTitle), typeof(WindowSelectorEditor)) + }; + + + + public IOverlayConfig Config { get { return OverlayConfig; } } + + + public WindowOverlayEditor() + { + InitializeComponent(); + DataContext = OverlayConfig; + + if (OverlayConfig.Selector != null) + { + SelectorWrapper wrapper = Selectors.Single(x => x.SelectorType == OverlayConfig.Selector.GetType()); + IWindowSelector selector = OverlayConfig.Selector; + UserControl editor = (UserControl)Activator.CreateInstance(wrapper.EditorType, OverlayConfig); + wrapper.Editor = editor; + } + cbSelector.ItemsSource = Selectors; + } + + public WindowOverlayEditor(ref WindowOverlayConfig config) + { + InitializeComponent(); + OverlayConfig = config; + DataContext = OverlayConfig; + cbSelector.ItemsSource = Selectors; + } + + public class SelectorWrapper + { + public string FriendlyName { get; set; } + //public IWindowSelector Selector{ get; private set; } + public Type SelectorType { get; set; } + //public UserControl Control { get; set; } + public Type EditorType { get; set; } + + public IWindowSelector Selector { get; set; } + + public UserControl Editor { get; set; } = null; + + public SelectorWrapper(string friendlyName, Type selectorType, Type editorType) + { + FriendlyName = friendlyName; + SelectorType = selectorType; + EditorType = editorType; + + Selector = (IWindowSelector)Activator.CreateInstance(selectorType); + Editor = (UserControl)Activator.CreateInstance(EditorType, new object[] { Selector }); + } + + public override string ToString() + { + return FriendlyName; + } + } + + private void cbSelector_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + var wrapper = (SelectorWrapper)cbSelector.SelectedItem; + OverlayConfig.Selector = wrapper.Selector; + bdrSelector.Child = wrapper.Editor; + } + } +} diff --git a/VDash/UI/WindowSelectorEditor.xaml b/VDash/UI/WindowSelectorEditor.xaml new file mode 100644 index 0000000..e60dea8 --- /dev/null +++ b/VDash/UI/WindowSelectorEditor.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + Search Type: + Search Text: + + + + + diff --git a/VDash/UI/WindowSelectorEditor.xaml.cs b/VDash/UI/WindowSelectorEditor.xaml.cs new file mode 100644 index 0000000..8f1ae5f --- /dev/null +++ b/VDash/UI/WindowSelectorEditor.xaml.cs @@ -0,0 +1,39 @@ +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.Navigation; +using System.Windows.Shapes; +using VDash.WindowSelectors; + +namespace VDash.UI +{ + /// + /// Interaction logic for WindowSelectorEditor.xaml + /// + public partial class WindowSelectorEditor : UserControl + { + public FromWindowTitle Selector { get; set; } + + public WindowSelectorEditor(ref FromWindowTitle selector) + { + InitializeComponent(); + Selector = selector; + cbSearchType.ItemsSource = Enum.GetValues(typeof(FromWindowTitle.TitleSearchType)); + DataContext = selector; + } + + private void cbSearchType_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + Selector.SearchType = (FromWindowTitle.TitleSearchType)cbSearchType.SelectedItem; + } + } +} diff --git a/VDash/Utilities/User32.cs b/VDash/Utilities/User32.cs index dfb0fba..f7f6d57 100644 --- a/VDash/Utilities/User32.cs +++ b/VDash/Utilities/User32.cs @@ -642,6 +642,11 @@ namespace VDash.Utilities public Rect MonitorArea { get; set; } public Rect WorkArea { get; set; } public MonitorInfoEx MonitorInfo { get; set; } + + public override string ToString() + { + return MonitorInfo.DeviceName + (Primary ? "(Primary)" : ""); + } } // size of a device name string private const int CCHDEVICENAME = 32; @@ -699,20 +704,13 @@ namespace VDash.Utilities } } - /// - /// Collection of display information - /// - public class DisplayInfoCollection : List - { - } - /// /// Returns the number of Displays using the Win32 functions /// /// Collection of Display Info - public static DisplayInfoCollection GetDisplays() + public static DisplayInfo[] GetDisplays() { - DisplayInfoCollection col = new DisplayInfoCollection(); + List col = new List(); EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, delegate (IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData) @@ -733,7 +731,7 @@ namespace VDash.Utilities } return true; }, IntPtr.Zero); - return col; + return col.ToArray(); } #endregion diff --git a/VDash/VDash.csproj b/VDash/VDash.csproj index 32f7105..81d20df 100644 --- a/VDash/VDash.csproj +++ b/VDash/VDash.csproj @@ -85,16 +85,36 @@ MSBuild:Compile Designer + + + + + + CreateNewOverlay.xaml + + + + MonitorOverlayEditor.xaml + + + ProcessSelectorEditor.xaml + + + WindowOverlayEditor.xaml + + + WindowSelectorEditor.xaml + - + MSBuild:Compile @@ -109,6 +129,26 @@ MainWindow.xaml Code + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + diff --git a/VDash/WindowSelectors/FromProcessName.cs b/VDash/WindowSelectors/FromProcessName.cs index abc0290..241a511 100644 --- a/VDash/WindowSelectors/FromProcessName.cs +++ b/VDash/WindowSelectors/FromProcessName.cs @@ -7,7 +7,7 @@ namespace VDash.WindowSelectors { public class FromProcessName : IWindowSelector { - string m_ProcName = ""; + public string ProcessName { get; set; } = ""; public FromProcessName(string procName) { if (string.IsNullOrWhiteSpace(procName)) @@ -15,7 +15,12 @@ namespace VDash.WindowSelectors throw new ArgumentNullException("procName", "procName must not be null, whitespace, or empty."); } - m_ProcName = procName; + ProcessName = procName; + } + + public FromProcessName() + { + } Process[] processes = null; @@ -23,7 +28,7 @@ namespace VDash.WindowSelectors { if(processes == null) { - processes = Process.GetProcessesByName(m_ProcName); + processes = Process.GetProcessesByName(ProcessName); } return processes; @@ -35,7 +40,7 @@ namespace VDash.WindowSelectors if (procs.Count() <= 0) { - throw new WindowNotFoundException($"No process found with name {m_ProcName}."); + throw new WindowNotFoundException($"No process found with name {ProcessName}."); } return procs.First(); } @@ -49,7 +54,7 @@ namespace VDash.WindowSelectors var ret = WindowInfo.GetWindowList().SingleOrDefault(x => x.hWnd == GetWindowHandle()); if(ret == null) { - throw new WindowNotFoundException($"Unable to locate window for process {m_ProcName}."); + throw new WindowNotFoundException($"Unable to locate window for process {ProcessName}."); } return ret; } diff --git a/VDash/WindowSelectors/FromWindowName.cs b/VDash/WindowSelectors/FromWindowTitle.cs similarity index 87% rename from VDash/WindowSelectors/FromWindowName.cs rename to VDash/WindowSelectors/FromWindowTitle.cs index dba5b31..db0a074 100644 --- a/VDash/WindowSelectors/FromWindowName.cs +++ b/VDash/WindowSelectors/FromWindowTitle.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Text.RegularExpressions; +using VDash.Utilities; namespace VDash.WindowSelectors { @@ -42,6 +43,10 @@ namespace VDash.WindowSelectors SearchType = searchType; } + public FromWindowTitle() + { + } + internal WindowInfo GetWindowUsingFilter() { var windows = WindowInfo.GetWindowList(); @@ -82,15 +87,17 @@ namespace VDash.WindowSelectors public bool WindowExists() { - try - { - var window = Window; - } - catch (WindowNotFoundException) - { - return false; - } - return true; + //try + //{ + // var window = Window; + //} + //catch (WindowNotFoundException) + //{ + // return false; + //} + //return true; + + return User32.IsWindow(GetWindowHandle()); } public enum TitleSearchType