Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c6cc15281 | |||
| ce3402f1a9 | |||
| 0e530238f6 |
@@ -15,9 +15,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.1.2</Version>
|
||||
<AssemblyVersion>1.1.2.0</AssemblyVersion>
|
||||
<FileVersion>1.1.2.0</FileVersion>
|
||||
<Version>1.1.5</Version>
|
||||
<AssemblyVersion>1.1.5.0</AssemblyVersion>
|
||||
<FileVersion>1.1.5.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -187,9 +187,26 @@
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Background="#444" CornerRadius="8,8,0,0" Padding="12,10">
|
||||
<Grid>
|
||||
<TextBlock Text="Monitor Control" Foreground="White" FontSize="14" FontWeight="SemiBold" VerticalAlignment="Center"/>
|
||||
<Button Content="Exit" HorizontalAlignment="Right" Click="ExitButton_Click"
|
||||
Style="{StaticResource DarkButton}" FontSize="11"/>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<TextBlock Text="Monitor Control" Foreground="White" FontSize="14" FontWeight="SemiBold" VerticalAlignment="Center"/>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="About" Margin="0,0,6,0" Click="AboutButton_Click"
|
||||
Style="{StaticResource DarkButton}" FontSize="11"/>
|
||||
<Button Content="Exit" Click="ExitButton_Click"
|
||||
Style="{StaticResource DarkButton}" FontSize="11"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<!-- Update Banner -->
|
||||
<Border Name="updateBanner" Grid.Row="1" Background="#0078D4" CornerRadius="3"
|
||||
Padding="8,4" Margin="0,8,0,0" Visibility="Collapsed" Cursor="Hand"
|
||||
MouseLeftButtonUp="UpdateBanner_Click">
|
||||
<TextBlock Name="updateText" Text="Update available!" Foreground="White"
|
||||
FontSize="11" HorizontalAlignment="Center"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ public partial class MainWindow : Window
|
||||
private List<(XMonitor Monitor, List<InputSourceOption> Options)> _loadedMonitors = new();
|
||||
private Storyboard? _spinnerStoryboard;
|
||||
private DispatcherTimer? _showLogButtonTimer;
|
||||
private UpdateInfo? _pendingUpdate;
|
||||
private DateTime _lastUpdateCheck = DateTime.MinValue;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
@@ -53,12 +55,50 @@ public partial class MainWindow : Window
|
||||
};
|
||||
_showLogButtonTimer.Start();
|
||||
|
||||
// Check for updates in background (max once per hour)
|
||||
if ((DateTime.Now - _lastUpdateCheck).TotalMinutes > 60)
|
||||
{
|
||||
_lastUpdateCheck = DateTime.Now;
|
||||
_ = CheckForUpdatesAsync();
|
||||
}
|
||||
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
Top = workArea.Bottom - ActualHeight - 10;
|
||||
}), DispatcherPriority.Loaded);
|
||||
}
|
||||
|
||||
private async Task CheckForUpdatesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var update = await UpdateChecker.CheckForUpdateAsync();
|
||||
if (update != null)
|
||||
{
|
||||
_pendingUpdate = update;
|
||||
await Dispatcher.InvokeAsync(() => ShowUpdateBanner(update));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Silently ignore update check failures
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowUpdateBanner(UpdateInfo update)
|
||||
{
|
||||
updateBanner.Visibility = Visibility.Visible;
|
||||
updateText.Text = $"v{update.LatestVersion} available - Click to update";
|
||||
}
|
||||
|
||||
private void UpdateBanner_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (_pendingUpdate != null && !string.IsNullOrEmpty(_pendingUpdate.DownloadUrl))
|
||||
{
|
||||
UpdateChecker.OpenDownloadPage(_pendingUpdate.DownloadUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Deactivated(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
@@ -70,6 +110,85 @@ public partial class MainWindow : Window
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
private void AboutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
var versionStr = $"{version?.Major}.{version?.Minor}.{version?.Build}";
|
||||
|
||||
var aboutWindow = new Window
|
||||
{
|
||||
Title = "About Monitor Control",
|
||||
Width = 300,
|
||||
Height = 180,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
ResizeMode = ResizeMode.NoResize,
|
||||
WindowStyle = WindowStyle.None,
|
||||
AllowsTransparency = true,
|
||||
Background = Brushes.Transparent
|
||||
};
|
||||
|
||||
var border = new Border
|
||||
{
|
||||
Background = new SolidColorBrush(Color.FromArgb(0xF0, 0x33, 0x33, 0x33)),
|
||||
CornerRadius = new CornerRadius(8),
|
||||
BorderBrush = new SolidColorBrush(Color.FromRgb(0x55, 0x55, 0x55)),
|
||||
BorderThickness = new Thickness(1),
|
||||
Padding = new Thickness(20)
|
||||
};
|
||||
|
||||
var stack = new StackPanel { VerticalAlignment = VerticalAlignment.Center };
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "Monitor Control",
|
||||
Foreground = Brushes.White,
|
||||
FontSize = 18,
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
Margin = new Thickness(0, 0, 0, 5)
|
||||
});
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = $"Version {versionStr}",
|
||||
Foreground = Brushes.LightGray,
|
||||
FontSize = 12,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
Margin = new Thickness(0, 0, 0, 10)
|
||||
});
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "by David H. Friedel Jr",
|
||||
Foreground = Brushes.Gray,
|
||||
FontSize = 11,
|
||||
HorizontalAlignment = HorizontalAlignment.Center
|
||||
});
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "MarketAlly",
|
||||
Foreground = Brushes.Gray,
|
||||
FontSize = 11,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
Margin = new Thickness(0, 0, 0, 15)
|
||||
});
|
||||
|
||||
var closeBtn = new Button
|
||||
{
|
||||
Content = "OK",
|
||||
Width = 80,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
Style = (Style)FindResource("DarkButton")
|
||||
};
|
||||
closeBtn.Click += (s, args) => aboutWindow.Close();
|
||||
stack.Children.Add(closeBtn);
|
||||
|
||||
border.Child = stack;
|
||||
aboutWindow.Content = border;
|
||||
aboutWindow.ShowDialog();
|
||||
}
|
||||
|
||||
private void ShowLogButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var logWindow = new Window
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define MyAppName "Monitor Control"
|
||||
#define MyAppVersion "1.1.2"
|
||||
#define MyAppVersion "1.1.5"
|
||||
#define MyAppPublisher "MarketAlly"
|
||||
#define MyAppExeName "DellMonitorControl.exe"
|
||||
#define MyAppIcon "MonitorIcon.ico"
|
||||
|
||||
@@ -25,13 +25,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resource\ControlMyMonitor.exe" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resource\ControlMyMonitor.exe">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<Content Include="Resource\ControlMyMonitor.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<Link>ControlMyMonitor.exe</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -10,13 +10,14 @@ namespace CMM.Library.Method;
|
||||
/// </summary>
|
||||
public static class CMMCommand
|
||||
{
|
||||
static readonly string CMMTmpFolder = Path.Combine(Path.GetTempPath(), $"CMM");
|
||||
static readonly string CMMexe = Path.Combine(CMMTmpFolder, "ControlMyMonitor.exe");
|
||||
static readonly string CMMTmpFolder = Path.Combine(Path.GetTempPath(), "CMM");
|
||||
static readonly string CMMexe = Path.Combine(AppContext.BaseDirectory, "ControlMyMonitor.exe");
|
||||
static readonly string CMMsMonitors = Path.Combine(CMMTmpFolder, "smonitors.tmp");
|
||||
|
||||
public static async Task ScanMonitor()
|
||||
{
|
||||
await BytesToFileAsync(new(CMMexe));
|
||||
// Ensure temp folder exists for output files
|
||||
Directory.CreateDirectory(CMMTmpFolder);
|
||||
await ConsoleHelper.ExecuteExeAsync(CMMexe, $"/smonitors {CMMsMonitors}");
|
||||
}
|
||||
|
||||
@@ -279,22 +280,4 @@ public static class CMMCommand
|
||||
return monitors;
|
||||
}
|
||||
|
||||
static void BytesToFile(FileInfo fi)
|
||||
{
|
||||
fi.Refresh();
|
||||
if (fi.Exists) return;
|
||||
if (!fi.Directory.Exists) fi.Directory.Create();
|
||||
|
||||
File.WriteAllBytes(fi.FullName, fi.Name.ResourceToByteArray());
|
||||
}
|
||||
|
||||
static async Task BytesToFileAsync(FileInfo fi)
|
||||
{
|
||||
fi.Refresh();
|
||||
if (fi.Exists) return;
|
||||
if (!fi.Directory.Exists) fi.Directory.Create();
|
||||
|
||||
await File.WriteAllBytesAsync(fi.FullName, fi.Name.ResourceToByteArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user