- Nice popup UI with proper positioning - Professional README with badges - Remove debug logging - Add .claude/ to .gitignore 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
180 lines
7.0 KiB
C#
180 lines
7.0 KiB
C#
using CMM.Library.Method;
|
|
using CMM.Library.ViewModel;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Media;
|
|
|
|
namespace DellMonitorControl;
|
|
|
|
public partial class MainWindow : Window
|
|
{
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
public void ShowNearTray()
|
|
{
|
|
var workArea = SystemParameters.WorkArea;
|
|
Left = workArea.Right - Width - 10;
|
|
// Use estimated height since ActualHeight is 0 before render
|
|
Top = workArea.Bottom - 350;
|
|
Show();
|
|
Activate();
|
|
|
|
// Reposition after layout is complete
|
|
Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
Top = workArea.Bottom - ActualHeight - 10;
|
|
}), System.Windows.Threading.DispatcherPriority.Loaded);
|
|
}
|
|
|
|
private void Window_Deactivated(object sender, EventArgs e)
|
|
{
|
|
Hide();
|
|
}
|
|
|
|
public async Task LoadMonitors()
|
|
{
|
|
var newChildren = new List<UIElement>();
|
|
|
|
try
|
|
{
|
|
await CMMCommand.ScanMonitor();
|
|
var monitors = (await CMMCommand.ReadMonitorsData()).ToList();
|
|
|
|
if (!monitors.Any())
|
|
{
|
|
newChildren.Add(new TextBlock
|
|
{
|
|
Text = "No DDC/CI monitors detected",
|
|
Foreground = Brushes.LightGray,
|
|
FontSize = 12,
|
|
HorizontalAlignment = HorizontalAlignment.Center,
|
|
Margin = new Thickness(0, 30, 0, 30)
|
|
});
|
|
}
|
|
else
|
|
{
|
|
foreach (var m in monitors)
|
|
{
|
|
var brightness = await CMMCommand.GetBrightness(m.SerialNumber) ?? 50;
|
|
var contrast = await CMMCommand.GetContrast(m.SerialNumber) ?? 50;
|
|
var inputSource = await CMMCommand.GetInputSource(m.SerialNumber);
|
|
var inputOptions = await CMMCommand.GetInputSourceOptions(m.SerialNumber);
|
|
var powerStatus = await CMMCommand.GetMonPowerStatus(m.SerialNumber) ?? "Unknown";
|
|
|
|
// Monitor name header
|
|
newChildren.Add(new TextBlock
|
|
{
|
|
Text = m.MonitorName,
|
|
Foreground = Brushes.White,
|
|
FontSize = 13,
|
|
FontWeight = FontWeights.SemiBold,
|
|
Margin = new Thickness(0, 8, 0, 6)
|
|
});
|
|
|
|
newChildren.Add(CreateSliderRow("Brightness", brightness, m.SerialNumber, CMMCommand.SetBrightness));
|
|
newChildren.Add(CreateSliderRow("Contrast", contrast, m.SerialNumber, CMMCommand.SetContrast));
|
|
|
|
if (inputOptions.Count > 0)
|
|
newChildren.Add(CreateInputRow(inputSource, inputOptions, m.SerialNumber));
|
|
|
|
newChildren.Add(CreatePowerRow(powerStatus, m.SerialNumber));
|
|
|
|
// Separator
|
|
newChildren.Add(new Border { Height = 1, Background = new SolidColorBrush(Color.FromRgb(80, 80, 80)), Margin = new Thickness(0, 10, 0, 2) });
|
|
}
|
|
|
|
// Remove last separator
|
|
if (newChildren.Count > 0 && newChildren.Last() is Border)
|
|
newChildren.RemoveAt(newChildren.Count - 1);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
newChildren.Clear();
|
|
newChildren.Add(new TextBlock { Text = $"Error: {ex.Message}", Foreground = Brushes.OrangeRed, FontSize = 11, TextWrapping = TextWrapping.Wrap });
|
|
}
|
|
|
|
sp.VerticalAlignment = VerticalAlignment.Top;
|
|
sp.Children.Clear();
|
|
foreach (var child in newChildren)
|
|
sp.Children.Add(child);
|
|
|
|
// Reposition after content changes
|
|
Dispatcher.BeginInvoke(new Action(() =>
|
|
{
|
|
var workArea = SystemParameters.WorkArea;
|
|
Top = workArea.Bottom - ActualHeight - 10;
|
|
}), System.Windows.Threading.DispatcherPriority.Loaded);
|
|
}
|
|
|
|
private StackPanel CreateSliderRow(string label, int value, string serialNumber, Func<string, int, Task> setCommand)
|
|
{
|
|
var row = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 3, 0, 3) };
|
|
row.Children.Add(new TextBlock { Text = label, Foreground = Brushes.LightGray, Width = 70, FontSize = 12, VerticalAlignment = VerticalAlignment.Center });
|
|
|
|
var slider = new Slider { Minimum = 0, Maximum = 100, Value = value, Width = 140, Tag = serialNumber };
|
|
var valueText = new TextBlock { Text = value.ToString(), Foreground = Brushes.White, Width = 30, FontSize = 12, Margin = new Thickness(5, 0, 0, 0) };
|
|
|
|
slider.ValueChanged += (s, e) => valueText.Text = ((int)e.NewValue).ToString();
|
|
slider.PreviewMouseUp += async (s, e) =>
|
|
{
|
|
if (s is Slider sl && sl.Tag is string sn)
|
|
await setCommand(sn, (int)sl.Value);
|
|
};
|
|
|
|
row.Children.Add(slider);
|
|
row.Children.Add(valueText);
|
|
return row;
|
|
}
|
|
|
|
private StackPanel CreateInputRow(int? currentInput, List<InputSourceOption> options, string serialNumber)
|
|
{
|
|
var row = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 3, 0, 3) };
|
|
row.Children.Add(new TextBlock { Text = "Input", Foreground = Brushes.LightGray, Width = 70, FontSize = 12, VerticalAlignment = VerticalAlignment.Center });
|
|
|
|
var combo = new ComboBox { Width = 170, ItemsSource = options, DisplayMemberPath = "Name", Tag = serialNumber };
|
|
if (currentInput.HasValue)
|
|
combo.SelectedItem = options.Find(o => o.Value == currentInput.Value);
|
|
|
|
combo.SelectionChanged += async (s, e) =>
|
|
{
|
|
if (s is ComboBox cb && cb.Tag is string sn && cb.SelectedItem is InputSourceOption opt)
|
|
await CMMCommand.SetInputSource(sn, opt.Value);
|
|
};
|
|
|
|
row.Children.Add(combo);
|
|
return row;
|
|
}
|
|
|
|
private StackPanel CreatePowerRow(string status, string serialNumber)
|
|
{
|
|
var row = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 3, 0, 3) };
|
|
row.Children.Add(new TextBlock { Text = "Power", Foreground = Brushes.LightGray, Width = 70, FontSize = 12, VerticalAlignment = VerticalAlignment.Center });
|
|
|
|
var btn = new Button { Content = status, Width = 170, Tag = serialNumber };
|
|
btn.Click += async (s, e) =>
|
|
{
|
|
if (s is Button b && b.Tag is string sn)
|
|
{
|
|
var current = await CMMCommand.GetMonPowerStatus(sn);
|
|
if (current == "Sleep" || current == "PowerOff")
|
|
await CMMCommand.PowerOn(sn);
|
|
else
|
|
await CMMCommand.Sleep(sn);
|
|
await Task.Delay(1000);
|
|
b.Content = await CMMCommand.GetMonPowerStatus(sn);
|
|
}
|
|
};
|
|
|
|
row.Children.Add(btn);
|
|
return row;
|
|
}
|
|
}
|