From 4981ee195c81944c5a71f4091009a690e25cf478 Mon Sep 17 00:00:00 2001 From: Mathieu GRENET Date: Mon, 7 Mar 2016 19:30:19 +0100 Subject: [PATCH] Fix Config switch --- LittleBigMouse_Control/MultiScreensView.xaml | 15 ++++- .../Properties/AssemblyInfo.cs | 4 +- LittleBigMouse_Control/app.manifest | 2 +- LittleBigMouse_Daemon/LittleBigMouseDaemon.cs | 37 ++++++++--- LittleBigMouse_Daemon/MouseEngine.cs | 36 ++++++----- LittleBigMouse_Daemon/Notify.cs | 63 ++++++++++++++----- .../Properties/AssemblyInfo.cs | 10 +-- MonitorVcp/Properties/AssemblyInfo.cs | 9 ++- NativeHelpers/PerMonitorDPIWindow.cpp | 2 +- NotifyChange/Properties/AssemblyInfo.cs | 12 ++-- ScreenConfig/Screen.cs | 54 +--------------- ScreenConfig/ScreenConfig.cs | 58 ++++++++++++++++- WindowsMonitors/DisplayAdapter.cs | 14 +++-- WindowsMonitors/DisplayDevice.cs | 51 ++++++++++----- WindowsMonitors/DisplayMonitor.cs | 51 ++++++++++++--- WindowsMonitors/Properties/AssemblyInfo.cs | 9 ++- 16 files changed, 275 insertions(+), 152 deletions(-) diff --git a/LittleBigMouse_Control/MultiScreensView.xaml b/LittleBigMouse_Control/MultiScreensView.xaml index da4115e1..52bf49f7 100644 --- a/LittleBigMouse_Control/MultiScreensView.xaml +++ b/LittleBigMouse_Control/MultiScreensView.xaml @@ -23,6 +23,7 @@ + - + + + + + + + diff --git a/LittleBigMouse_Control/Properties/AssemblyInfo.cs b/LittleBigMouse_Control/Properties/AssemblyInfo.cs index 2b9324a3..148476ab 100644 --- a/LittleBigMouse_Control/Properties/AssemblyInfo.cs +++ b/LittleBigMouse_Control/Properties/AssemblyInfo.cs @@ -11,7 +11,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Mgth")] [assembly: AssemblyProduct("LittleBigMouse_Control")] -[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: DisableDpiAwareness] @@ -51,5 +51,5 @@ // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut // en utilisant '*', comme indiqué ci-dessous : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.*")] +[assembly: AssemblyVersion("3.0.*")] //[assembly: AssemblyFileVersion("2.0.0.0")] diff --git a/LittleBigMouse_Control/app.manifest b/LittleBigMouse_Control/app.manifest index 71e78e88..1264eb43 100644 --- a/LittleBigMouse_Control/app.manifest +++ b/LittleBigMouse_Control/app.manifest @@ -2,7 +2,7 @@ - + True/PM diff --git a/LittleBigMouse_Daemon/LittleBigMouseDaemon.cs b/LittleBigMouse_Daemon/LittleBigMouseDaemon.cs index d641e540..c7d867d4 100644 --- a/LittleBigMouse_Daemon/LittleBigMouseDaemon.cs +++ b/LittleBigMouse_Daemon/LittleBigMouseDaemon.cs @@ -36,6 +36,8 @@ private void OnStartup(object sender, EventArgs exitEventArgs) _notify = new Notify(); _engine = new MouseEngine(); + _engine.ConfigLoaded += _engine_ConfigLoaded; + _engine.StartServer(this); @@ -43,21 +45,38 @@ private void OnStartup(object sender, EventArgs exitEventArgs) if (_notify != null) _notify.Click += OnNotifyClick; + UpdateConfig(); + + //_notify.AddMenu("Brightness", Brightness); + + _notify.AddMenu(-1,"Open", Open); + _notify.AddMenu(-1,"Start", Start); + _notify.AddMenu(-1,"Stop", Stop); + _notify.AddMenu(-1,"Exit", Quit); + + Start(); + } + + private void _engine_ConfigLoaded(object sender, EventArgs e) + { + UpdateConfig(); + } + + public void UpdateConfig() + { + _notify.RemoveMenu("config"); foreach (string configName in ScreenConfig.ConfigsList) { - _notify.AddMenu(configName, MatchConfig); + bool chk = configName==_engine.Config?.Id; + + if (ScreenConfig.IsDoableConfig(configName)) + _notify.AddMenu(0,configName, MatchConfig, "config", chk); } - //_notify.AddMenu("Brightness", Brightness); + } - _notify.AddMenu("Open", Open); - _notify.AddMenu("Start", Start); - _notify.AddMenu("Stop", Stop); - _notify.AddMenu("Exit", Quit); - Start(); - } private void OnNotifyClick(object sender, EventArgs e) { Open(); } private void OnDeactivated(object sender, EventArgs eventArgs) @@ -78,7 +97,7 @@ private void OnExit(object sender, ExitEventArgs exitEventArgs) { Stop(); _engine.StopServer(); - _notify.Dispose(); + _notify.Hide(); } public void CommandLine(IList args) diff --git a/LittleBigMouse_Daemon/MouseEngine.cs b/LittleBigMouse_Daemon/MouseEngine.cs index 28f09bcc..e76a3630 100644 --- a/LittleBigMouse_Daemon/MouseEngine.cs +++ b/LittleBigMouse_Daemon/MouseEngine.cs @@ -18,7 +18,7 @@ namespace LittleBigMouse_Daemon [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class MouseEngine { - private ScreenConfig _config; + public ScreenConfig Config { get; private set; } private double _initMouseSpeed; public readonly MouseHookListener Hook = new MouseHookListener(new GlobalHooker()); private PixelPoint _oldPoint = null; @@ -53,10 +53,10 @@ public void Start() { if (Hook.Enabled) return; - if (_config == null) + if (Config == null) LoadConfig(); - if (_config == null || !_config.Enabled) return; + if (Config == null || !Config.Enabled) return; SystemEvents.DisplaySettingsChanged += OnDisplaySettingsChanged; @@ -96,9 +96,9 @@ public void Stop() Hook.Enabled = false; // LittleBigMouseDaemon.Callback?.OnStateChange(); - if (_config == null) return; + if (Config == null) return; - if (_config.AdjustSpeed) + if (Config.AdjustSpeed) { LbmMouse.MouseSpeed = _initMouseSpeed; using (var key = ScreenConfig.OpenRootRegKey(true)) @@ -107,7 +107,7 @@ public void Stop() } } - if (_config.AdjustPointer) + if (Config.AdjustPointer) { using (var key = ScreenConfig.OpenRootRegKey()) { @@ -126,15 +126,17 @@ public void Stop() public void LoadConfig(ScreenConfig config) { - _config = config; + Config = config; + ConfigLoaded?.Invoke(config,null); } + + public event EventHandler ConfigLoaded; public void LoadConfig() { LoadConfig(new ScreenConfig()); } private void OnDisplaySettingsChanged(object sender, EventArgs e) { - Debug.Print("LoadConfig"); LoadConfig(); } @@ -143,7 +145,7 @@ private void OnMouseMoveExt(object sender, MouseEventExtArgs e) // If first time called just save that point if (_oldPoint == null) { - _oldPoint = new PixelPoint(_config, null, e.X, e.Y); + _oldPoint = new PixelPoint(Config, null, e.X, e.Y); return; } @@ -187,9 +189,9 @@ private void OnMouseMoveExt(object sender, MouseEventExtArgs e) Side side = seg.IntersectSide(_oldPoint.Screen.PhysicalBounds); - foreach (Screen screen in _config.AllScreens.Where(s => s != oldScreen)) + foreach (Screen screen in Config.AllScreens.Where(s => s != oldScreen)) { - if (_config.AllowCornerCrossing) + if (Config.AllowCornerCrossing) { foreach ( Point p in seg.Line.Intersect(screen.PhysicalBounds) ) { @@ -198,7 +200,7 @@ private void OnMouseMoveExt(object sender, MouseEventExtArgs e) if (travel.Size > dist) continue; dist = travel.Size; - pOut = (new PhysicalPoint(_config, screen, p.X, p.Y)).Pixel.Inside; + pOut = (new PhysicalPoint(Config, screen, p.X, p.Y)).Pixel.Inside; screenOut = screen; } } @@ -235,7 +237,7 @@ private void OnMouseMoveExt(object sender, MouseEventExtArgs e) if (offset.Length > 0 && offset.Length < dist) { Point shiftedPoint = pIn.Physical.Point + offset; - PhysicalPoint shifted = new PhysicalPoint(_config, screen, shiftedPoint.X , shiftedPoint.Y); + PhysicalPoint shifted = new PhysicalPoint(Config, screen, shiftedPoint.X , shiftedPoint.Y); if (shifted.TargetScreen == screen) { dist = offset.Length; @@ -262,7 +264,7 @@ private void OnMouseMoveExt(object sender, MouseEventExtArgs e) Debug.Print(">" + LbmMouse.CursorPos.X + "," + LbmMouse.CursorPos.Y); // Adjust pointer size to dpi ratio : should not be usefull if windows screen ratio is used - if (_config.AdjustPointer) + if (Config.AdjustPointer) { if (screenOut.RealDpiAvg > 110) { @@ -273,12 +275,12 @@ private void OnMouseMoveExt(object sender, MouseEventExtArgs e) // Adjust pointer speed to dpi ratio : should not be usefull if windows screen ratio is used - if (_config.AdjustSpeed) + if (Config.AdjustSpeed) { LbmMouse.MouseSpeed = Math.Round((5.0/96.0)*screenOut.RealDpiAvg, 0); } - if (_config.HomeCinema) + if (Config.HomeCinema) { oldScreen.Monitor.Vcp().Power = false; } @@ -290,7 +292,7 @@ private void OnMouseMoveExt(object sender, MouseEventExtArgs e) public void MatchConfig(string configId) { - _config.MatchConfig(configId); + Config.MatchConfig(configId); } } } diff --git a/LittleBigMouse_Daemon/Notify.cs b/LittleBigMouse_Daemon/Notify.cs index 799bac35..49f14d53 100644 --- a/LittleBigMouse_Daemon/Notify.cs +++ b/LittleBigMouse_Daemon/Notify.cs @@ -26,9 +26,9 @@ You should have received a copy of the GNU General Public License namespace LittleBigMouse_Daemon { - public class Notify : IDisposable + public class Notify //: IDisposable { - private System.Windows.Forms.NotifyIcon _notify; + private readonly System.Windows.Forms.NotifyIcon _notify; public Notify() { @@ -52,6 +52,14 @@ public void SetOff() { _notify.Icon = Properties.Resources.lbm_off; } + public void Show() + { + _notify.Visible = true; + } + public void Hide() + { + _notify.Visible = false; + } private void _notify_MouseClick(object sender, MouseEventArgs e) { @@ -64,25 +72,52 @@ private void _notify_MouseClick(object sender, MouseEventArgs e) public event EventHandler Click; - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + //public void Dispose() + //{ + // Dispose(true); + // GC.SuppressFinalize(this); + //} public delegate void Func(); - public void AddMenu(string txt, EventHandler evt) + public void AddMenu(int pos, string txt, EventHandler evt, string tag=null, bool chk = false) { - _notify.ContextMenuStrip.Items.Add(txt, null, evt); + ToolStripMenuItem item = new ToolStripMenuItem(txt, null, evt); + + item.Checked = chk; + + item.Tag = tag; + + if(pos<0 || pos>= _notify.ContextMenuStrip.Items.Count) _notify.ContextMenuStrip.Items.Add(item); + + else _notify.ContextMenuStrip.Items.Insert(pos,item); } - protected virtual void Dispose(bool disposing) + public void RemoveMenu(string tag) { - if (!disposing) return; - - _notify.Visible = false; - _notify.Dispose(); + bool done = false; + while (!done) + { + ToolStripItem[] items = new ToolStripItem[_notify.ContextMenuStrip.Items.Count]; + _notify.ContextMenuStrip.Items.CopyTo(items,0); + done = true; + foreach (ToolStripItem i in items) + { + if (i.Tag == tag) + { + _notify.ContextMenuStrip.Items.Remove(i); + done = false; + } + } + } } + + //protected virtual void Dispose(bool disposing) + //{ + // if (!disposing) return; + + // _notify.Visible = false; + // _notify.Dispose(); + //} } } diff --git a/LittleBigMouse_Daemon/Properties/AssemblyInfo.cs b/LittleBigMouse_Daemon/Properties/AssemblyInfo.cs index 5be84fbb..39602b55 100644 --- a/LittleBigMouse_Daemon/Properties/AssemblyInfo.cs +++ b/LittleBigMouse_Daemon/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ // l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations // associées à un assembly. [assembly: AssemblyTitle("LittleBigMouse_Daemon")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyDescription("Little Big Mouse Service")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("LittleBigMouse_Daemon")] -[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyCompany("Mgth")] +[assembly: AssemblyProduct("LittleBigMouse")] +[assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,6 +31,6 @@ // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut // en utilisant '*', comme indiqué ci-dessous : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.*")] +[assembly: AssemblyVersion("3.0.*")] //[assembly: AssemblyVersion("1.0.0.0")] //[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MonitorVcp/Properties/AssemblyInfo.cs b/MonitorVcp/Properties/AssemblyInfo.cs index d62ef43f..5ed4a19d 100644 --- a/MonitorVcp/Properties/AssemblyInfo.cs +++ b/MonitorVcp/Properties/AssemblyInfo.cs @@ -6,10 +6,10 @@ // l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations // associées à un assembly. [assembly: AssemblyTitle("MonitorVcp")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyDescription("Monitor VCP control")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MonitorVcp")] +[assembly: AssemblyCompany("Mgth")] +[assembly: AssemblyProduct("LittleBigMouse")] [assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,4 @@ // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut // en utilisant '*', comme indiqué ci-dessous : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("3.0.*")] diff --git a/NativeHelpers/PerMonitorDPIWindow.cpp b/NativeHelpers/PerMonitorDPIWindow.cpp index 2544d922..304c1bd2 100644 --- a/NativeHelpers/PerMonitorDPIWindow.cpp +++ b/NativeHelpers/PerMonitorDPIWindow.cpp @@ -21,7 +21,7 @@ namespace NativeHelpers } else { - m_perMonitorEnabled = false; + m_perMonitorEnabled = true; //throw gcnew System::Exception(L"Enabling Per-monitor DPI Failed. Do you have [assembly: DisableDpiAwareness] in your assembly manifest [AssemblyInfo.cs]?"); } diff --git a/NotifyChange/Properties/AssemblyInfo.cs b/NotifyChange/Properties/AssemblyInfo.cs index 7d44dea7..9f912c21 100644 --- a/NotifyChange/Properties/AssemblyInfo.cs +++ b/NotifyChange/Properties/AssemblyInfo.cs @@ -6,11 +6,11 @@ // l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations // associées à un assembly. [assembly: AssemblyTitle("NotifyChange")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyDescription("Take care of IPropertyNotifyChange")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NotifyChange")] -[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyCompany("Mgth")] +[assembly: AssemblyProduct("LittleBigMouse")] +[assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,6 +31,4 @@ // // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut // en utilisant '*', comme indiqué ci-dessous : -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("3.0.*")] diff --git a/ScreenConfig/Screen.cs b/ScreenConfig/Screen.cs index 27c7978b..68f2e151 100644 --- a/ScreenConfig/Screen.cs +++ b/ScreenConfig/Screen.cs @@ -636,6 +636,8 @@ public void Save(RegistryKey baseKey) key.SetKey(PixelSize.Width, "PixelWidth"); key.SetKey(PixelSize.Height, "PixelHeight"); + key.SetKey(Primary?1:0,"Primary"); + key.SetKey(Monitor.DisplayOrientation, "Orientation"); } } } @@ -1311,58 +1313,6 @@ public double MoveDownToTouch(Screen screen) return screen.PhysicalY - PhysicalBounds.Bottom; } - public static void AttachToDesktop(string configId, string monitorId) - { - string id; - using (RegistryKey monkey = OpenMonitorRegKey(monitorId)) - { - id = monkey?.GetValue("DeviceId").ToString(); - if (id == null) return; - } - - double x = 0; - double y = 0; - double width = 0; - double height = 0; - - using (RegistryKey monkey = OpenConfigRegKey(configId, monitorId)) - { - x = double.Parse(monkey.GetValue("PixelX").ToString()); - y = double.Parse(monkey.GetValue("PixelY").ToString()); - width = double.Parse(monkey.GetValue("PixelWidth").ToString()); - height = double.Parse(monkey.GetValue("PixelHeight").ToString()); - } - - DisplayAdapter adapter = DisplayDevice.FromId(id); - if (adapter != null) - { - NativeMethods.DEVMODE devmode = new NativeMethods.DEVMODE(true); - - int idx = 0; - while (true) - { - if (!NativeMethods.EnumDisplaySettings(adapter.DeviceName, idx, ref devmode)) - return; - - if (devmode.PelsHeight == height && devmode.PelsWidth == width && devmode.BitsPerPel == 32) break; - idx++; - } - - - - //devmode.Position = new POINTL { x = (int)x, y = (int)y }; - //devmode.Fields |= DM.Position; - - devmode.DeviceName = adapter.DeviceName /*+ @"\Monitor0"*/; - - NativeMethods.DISP_CHANGE ch = NativeMethods.ChangeDisplaySettingsEx(adapter.DeviceName, ref devmode, - IntPtr.Zero, - NativeMethods.ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | - NativeMethods.ChangeDisplaySettingsFlags.CDS_NORESET, IntPtr.Zero); - if (ch == NativeMethods.DISP_CHANGE.Successful) - ch = NativeMethods.ChangeDisplaySettingsEx(null, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero); - } - } public void PlaceAuto(IEnumerable screens) { diff --git a/ScreenConfig/ScreenConfig.cs b/ScreenConfig/ScreenConfig.cs index ae2c7740..e23c6359 100644 --- a/ScreenConfig/ScreenConfig.cs +++ b/ScreenConfig/ScreenConfig.cs @@ -70,7 +70,7 @@ public static IEnumerable ConfigsList } } - private static ObservableCollection Monitors => DisplayDevice.AllMonitors; + private static ObservableCollection Monitors => DisplayDevice.AttachedMonitors; public ScreenConfig() { MonitorsOnCollectionChanged(Monitors,new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add,Monitors)); @@ -161,20 +161,72 @@ public void MatchConfig(string id) { if (todo.Contains(screen.IdMonitor)) { + AttachToDesktop(id, screen.IdMonitor, false); todo.Remove(screen.IdMonitor); } else { - screen.Monitor.DetachFromDesktop(); + screen.Monitor.DetachFromDesktop(false); } } foreach (string s in todo) { - Screen.AttachToDesktop(id, s); + AttachToDesktop(id, s, false); + } + + DisplayMonitor.ApplyDesktop(); + } + } + } + + public static bool IsDoableConfig(String id) + { + using (RegistryKey rootkey = OpenRootRegKey()) + { + using (RegistryKey key = rootkey.OpenSubKey(@"configs\" + id)) + { + List todo = key.GetSubKeyNames().ToList(); + + // ReSharper disable once LoopCanBeConvertedToQuery + foreach (string s in todo) + { + //string s2 = s.Substring(0, s.Length - 2); + DisplayMonitor m = DisplayDevice.AllMonitors.FirstOrDefault( + d => s == d.ManufacturerCode + d.ProductCode + "_" + d.Serial); + + if (m == null) return false; } } } + return true; + } + public static void AttachToDesktop(string configId, string monitorId, bool apply=true) + { + //using (RegistryKey monkey = Screen.OpenMonitorRegKey(monitorId)) + //{ + // id = monkey?.GetValue("DeviceId").ToString(); + // if (id == null) return; + //} + Rect area = new Rect(); + bool primary = false; + int orientation = 0; + + using (RegistryKey monkey = Screen.OpenConfigRegKey(configId, monitorId)) + { + area.X = double.Parse(monkey.GetValue("PixelX").ToString()); + area.Y = double.Parse(monkey.GetValue("PixelY").ToString()); + area.Width = double.Parse(monkey.GetValue("PixelWidth").ToString()); + area.Height = double.Parse(monkey.GetValue("PixelHeight").ToString()); + + primary = double.Parse(monkey.GetValue("Primary").ToString()) == 1; + orientation = (int)double.Parse(monkey.GetValue("Orientation").ToString()); + } + + DisplayMonitor monitor = DisplayDevice.AllMonitors.FirstOrDefault( + d => monitorId == d.ManufacturerCode + d.ProductCode + "_" + d.Serial); + + monitor?.AttachToDesktop(primary, area, orientation, apply); } public void EnumWMI() diff --git a/WindowsMonitors/DisplayAdapter.cs b/WindowsMonitors/DisplayAdapter.cs index 5b290588..de7a955d 100644 --- a/WindowsMonitors/DisplayAdapter.cs +++ b/WindowsMonitors/DisplayAdapter.cs @@ -23,13 +23,15 @@ public DisplayAdapter(NativeMethods.DISPLAY_DEVICE dev) NativeMethods.DISPLAY_DEVICE mon = new NativeMethods.DISPLAY_DEVICE(true); while (NativeMethods.EnumDisplayDevices(DeviceName, i++, ref mon, 0)) { - DisplayMonitor displayMonitor = AllMonitors.FirstOrDefault(d => d.DeviceId == mon.DeviceID); - if (displayMonitor == null) displayMonitor = new DisplayMonitor(this, mon); - else - displayMonitor.Init(this, mon); + if (TempMonitors.FirstOrDefault(d => d.DeviceId == mon.DeviceID) == null) + { + DisplayMonitor displayMonitor = AllMonitors.FirstOrDefault(d => d.DeviceId == mon.DeviceID); + if (displayMonitor == null) displayMonitor = new DisplayMonitor(this, mon); + else + displayMonitor.Init(this, mon); - if(displayMonitor.AttachedToDesktop) - TempMonitors.Add(displayMonitor); + TempMonitors.Add(displayMonitor); + } } } } diff --git a/WindowsMonitors/DisplayDevice.cs b/WindowsMonitors/DisplayDevice.cs index 8808ddea..146ee4c4 100644 --- a/WindowsMonitors/DisplayDevice.cs +++ b/WindowsMonitors/DisplayDevice.cs @@ -24,23 +24,28 @@ private static void SystemEventsOnDisplaySettingsChanged(object sender, EventArg UpdateDevices(); } - public static ObservableCollection AllMonitors { get; } = new ObservableCollection(); + public static ObservableCollection AttachedMonitors { get; } = new ObservableCollection(); + public static ObservableCollection UnattachedMonitors { get; } = new ObservableCollection(); + + public static IEnumerable AllMonitors => AttachedMonitors.Union(UnattachedMonitors); + public static List TempMonitors { get; private set; } - public static DisplayAdapter FromId(string id) + public static DisplayMonitor FromId(string id) { - return (from monitor in AllMonitors where monitor.DeviceId == id select monitor.Adapter).FirstOrDefault(); + return AllMonitors.FirstOrDefault(m => m.DeviceId == id); } public static void UpdateDevices() { // Todo: try not to clear berore updating, but it's very buggy now - while(AllMonitors.Count>0) AllMonitors.RemoveAt(0); + while(AttachedMonitors.Count>0) AttachedMonitors.RemoveAt(0); TempMonitors = new List(); - IList oldMonitors = AllMonitors.ToList(); + IList oldAttachedMonitors = AttachedMonitors.ToList(); + IList oldUnattachedMonitors = UnattachedMonitors.ToList(); NativeMethods.DISPLAY_DEVICE dev = new NativeMethods.DISPLAY_DEVICE(true); uint i = 0; @@ -58,24 +63,40 @@ public static void UpdateDevices() if (success) { IList monitors = TempMonitors.Where(d => d.Adapter.DeviceName == mi.DeviceName).ToList(); - foreach (DisplayMonitor ddMon in monitors) + foreach (DisplayMonitor monitor in monitors) { - ddMon.Init(hMonitor, mi); - - if (oldMonitors.Contains(ddMon)) - oldMonitors.Remove(ddMon); - - if(!AllMonitors.Contains(ddMon)) AllMonitors.Add(ddMon); + monitor.Init(hMonitor, mi); } - } return true; }, IntPtr.Zero); - foreach (DisplayMonitor monitor in oldMonitors) + foreach (DisplayMonitor monitor in TempMonitors) + { + + if (monitor.AttachedToDesktop) + { + if (!oldAttachedMonitors.Remove(monitor)) + AttachedMonitors.Add(monitor); + oldUnattachedMonitors.Remove(monitor); + } + else + { + if (!oldUnattachedMonitors.Remove(monitor)) + UnattachedMonitors.Add(monitor); + oldAttachedMonitors.Remove(monitor); + } + } + + + foreach (DisplayMonitor monitor in oldAttachedMonitors) + { + AttachedMonitors.Remove(monitor); + } + foreach (DisplayMonitor monitor in oldUnattachedMonitors) { - AllMonitors.Remove(monitor); + UnattachedMonitors.Remove(monitor); } } public static RegistryKey GetKeyFromPath(string path, int parent = 0) diff --git a/WindowsMonitors/DisplayMonitor.cs b/WindowsMonitors/DisplayMonitor.cs index f4d2c354..9c9d3a14 100644 --- a/WindowsMonitors/DisplayMonitor.cs +++ b/WindowsMonitors/DisplayMonitor.cs @@ -50,11 +50,11 @@ public bool Equals(DisplayMonitor other) { if (other == null) return false; return DeviceId == other.DeviceId; - } + } - ~DisplayMonitor() + ~DisplayMonitor() { - //AllMonitors.Remove(this); TODO : this is not thread safe + //AttachedMonitors.Remove(this); TODO : this is not thread safe if (_pPhysicalMonitorArray != null && _pPhysicalMonitorArray.Length > 0) NativeMethods.DestroyPhysicalMonitors((uint)_pPhysicalMonitorArray.Length, ref _pPhysicalMonitorArray); } @@ -166,7 +166,7 @@ public uint Primary // Must remove old primary screen before setting this one if (value == 1) { - foreach (DisplayMonitor monitor in AllMonitors.Where(m => m!=this)) + foreach (DisplayMonitor monitor in AttachedMonitors.Where(m => m != this)) { monitor.Primary = 0; } @@ -366,8 +366,45 @@ public string Block(char code) } return ""; } + public void AttachToDesktop(bool primary, Rect area, int orientation, bool apply = true) + { + + NativeMethods.DEVMODE devmode = new NativeMethods.DEVMODE(true); + + devmode.DeviceName = Adapter.DeviceName /*+ @"\Monitor0"*/; + + devmode.Position = new NativeMethods.POINTL { x = (int)area.X, y = (int)area.Y }; + devmode.Fields |= NativeMethods.DM.Position; + + devmode.PelsWidth = (int)area.Width; + devmode.PelsHeight = (int)area.Height; + devmode.Fields |= NativeMethods.DM.PelsHeight | NativeMethods.DM.PelsWidth; + + devmode.DisplayOrientation = orientation; + devmode.Fields |= NativeMethods.DM.DisplayOrientation; + + devmode.BitsPerPel = 32; + devmode.Fields |= NativeMethods.DM.BitsPerPixel; + + NativeMethods.ChangeDisplaySettingsFlags flag = + NativeMethods.ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | + NativeMethods.ChangeDisplaySettingsFlags.CDS_NORESET; + + if (primary) flag |= NativeMethods.ChangeDisplaySettingsFlags.CDS_SET_PRIMARY; + + + var ch = NativeMethods.ChangeDisplaySettingsEx(Adapter.DeviceName, ref devmode, IntPtr.Zero, flag, IntPtr.Zero); + + if (ch == NativeMethods.DISP_CHANGE.Successful && apply) + ApplyDesktop(); + } + + public static void ApplyDesktop() + { + NativeMethods.ChangeDisplaySettingsEx(null, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero); + } - public void DetachFromDesktop() + public void DetachFromDesktop(bool apply = true) { NativeMethods.DEVMODE devmode = new NativeMethods.DEVMODE(); devmode.Size = (short)Marshal.SizeOf(devmode); @@ -379,8 +416,8 @@ public void DetachFromDesktop() | NativeMethods.DM.DisplayFrequency | NativeMethods.DM.DisplayFlags; NativeMethods.DISP_CHANGE ch = NativeMethods.ChangeDisplaySettingsEx(Adapter.DeviceName, ref devmode, IntPtr.Zero, NativeMethods.ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | NativeMethods.ChangeDisplaySettingsFlags.CDS_NORESET, IntPtr.Zero); - if (ch == NativeMethods.DISP_CHANGE.Successful) - ch = NativeMethods.ChangeDisplaySettingsEx(null, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero); + if (ch == NativeMethods.DISP_CHANGE.Successful && apply) + ApplyDesktop(); } private IntPtr _hPhysical; diff --git a/WindowsMonitors/Properties/AssemblyInfo.cs b/WindowsMonitors/Properties/AssemblyInfo.cs index c385e78f..5cbe249b 100644 --- a/WindowsMonitors/Properties/AssemblyInfo.cs +++ b/WindowsMonitors/Properties/AssemblyInfo.cs @@ -6,10 +6,10 @@ // l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations // associées à un assembly. [assembly: AssemblyTitle("WindowsMonitors")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyDescription("Display Monitors management")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WindowsMonitors")] +[assembly: AssemblyCompany("Mgth")] +[assembly: AssemblyProduct("LittleBigMouse")] [assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,4 @@ // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut // en utilisant '*', comme indiqué ci-dessous : // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("3.0.*")]