Clean up and polish release
- 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>
This commit is contained in:
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Bash(dir \"C:\\\\Users\\\\logik\\\\source\\\\repos\\\\ControlMyMonitorManagement\\\\Language\")",
|
|
||||||
"Bash(find:*)",
|
|
||||||
"Bash(dir \"C:\\\\Users\\\\logik\\\\source\\\\repos\\\\ControlMyMonitorManagement\\\\Language\" /S)",
|
|
||||||
"Bash(cat:*)",
|
|
||||||
"Bash(dotnet build:*)",
|
|
||||||
"Bash(dotnet --list-sdks:*)",
|
|
||||||
"Bash(dotnet:*)",
|
|
||||||
"Bash(timeout /t 5 /nobreak)",
|
|
||||||
"Bash(taskkill:*)",
|
|
||||||
"Bash(start \"\" \"C:\\\\Users\\\\logik\\\\source\\\\repos\\\\ControlMyMonitorManagement\\\\DellMonitorControl\\\\bin\\\\Debug\\\\net9.0-windows\\\\DellMonitorControl.exe\")",
|
|
||||||
"Bash(ping:*)",
|
|
||||||
"Bash(git remote:*)"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -361,3 +361,9 @@ MigrationBackup/
|
|||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
# Claude Code
|
||||||
|
.claude/
|
||||||
|
|
||||||
|
# Windows special files
|
||||||
|
nul
|
||||||
@@ -14,19 +14,20 @@ namespace DellMonitorControl
|
|||||||
_trayIcon.TrayLeftMouseUp += TrayIcon_Click;
|
_trayIcon.TrayLeftMouseUp += TrayIcon_Click;
|
||||||
|
|
||||||
_mainWindow = new MainWindow();
|
_mainWindow = new MainWindow();
|
||||||
_mainWindow.Show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TrayIcon_Click(object sender, RoutedEventArgs e)
|
private async void TrayIcon_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_mainWindow == null) return;
|
if (_mainWindow == null) return;
|
||||||
|
|
||||||
if (_mainWindow.IsVisible)
|
if (_mainWindow.IsVisible)
|
||||||
|
{
|
||||||
_mainWindow.Hide();
|
_mainWindow.Hide();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_mainWindow.Show();
|
_mainWindow.ShowNearTray();
|
||||||
_mainWindow.Activate();
|
await _mainWindow.LoadMonitors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,40 @@
|
|||||||
<Window x:Class="DellMonitorControl.MainWindow"
|
<Window x:Class="DellMonitorControl.MainWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="Monitor Control" Height="400" Width="320"
|
Title="Monitor Control"
|
||||||
WindowStyle="ToolWindow"
|
Width="300" MinHeight="200" MaxHeight="500"
|
||||||
ResizeMode="CanResize"
|
SizeToContent="Height"
|
||||||
Background="#333333">
|
WindowStyle="None"
|
||||||
|
AllowsTransparency="True"
|
||||||
|
Background="Transparent"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
ShowInTaskbar="False"
|
||||||
|
Topmost="True"
|
||||||
|
Deactivated="Window_Deactivated">
|
||||||
|
|
||||||
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="10">
|
<Border Background="#F0333333" CornerRadius="8" BorderBrush="#555" BorderThickness="1" Margin="5">
|
||||||
<StackPanel Name="sp">
|
<Border.Effect>
|
||||||
<TextBlock Text="Monitor Control" Foreground="White" FontSize="16" FontWeight="Bold"/>
|
<DropShadowEffect BlurRadius="10" ShadowDepth="2" Opacity="0.5"/>
|
||||||
<TextBlock Text="Loading..." Foreground="LightGray" FontSize="12" Margin="0,10,0,0"/>
|
</Border.Effect>
|
||||||
|
|
||||||
|
<Grid MinHeight="180">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<Border Grid.Row="0" Background="#444" CornerRadius="8,8,0,0" Padding="12,10">
|
||||||
|
<TextBlock Text="Monitor Control" Foreground="White" FontSize="14" FontWeight="SemiBold"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" Padding="12">
|
||||||
|
<StackPanel Name="sp" VerticalAlignment="Center">
|
||||||
|
<TextBlock Name="loadingText" Text="Loading..." Foreground="LightGray" FontSize="12"
|
||||||
|
HorizontalAlignment="Center" Margin="0,40,0,40"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -15,70 +15,67 @@ public partial class MainWindow : Window
|
|||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
PositionWindowNearTray();
|
|
||||||
Loaded += async (s, e) => await LoadMonitors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PositionWindowNearTray()
|
public void ShowNearTray()
|
||||||
{
|
{
|
||||||
var workArea = SystemParameters.WorkArea;
|
var workArea = SystemParameters.WorkArea;
|
||||||
Left = workArea.Right - Width - 10;
|
Left = workArea.Right - Width - 10;
|
||||||
Top = workArea.Bottom - Height - 10;
|
// Use estimated height since ActualHeight is 0 before render
|
||||||
}
|
Top = workArea.Bottom - 350;
|
||||||
|
Show();
|
||||||
|
Activate();
|
||||||
|
|
||||||
private static readonly string LogFile = System.IO.Path.Combine(
|
// Reposition after layout is complete
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "MonitorControl.log");
|
Dispatcher.BeginInvoke(new Action(() =>
|
||||||
|
|
||||||
private static void Log(string msg)
|
|
||||||
{
|
{
|
||||||
try { System.IO.File.AppendAllText(LogFile, $"{DateTime.Now:HH:mm:ss.fff} {msg}\n"); }
|
Top = workArea.Bottom - ActualHeight - 10;
|
||||||
catch { }
|
}), System.Windows.Threading.DispatcherPriority.Loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadMonitors()
|
private void Window_Deactivated(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadMonitors()
|
||||||
{
|
{
|
||||||
var newChildren = new List<UIElement>();
|
var newChildren = new List<UIElement>();
|
||||||
Log("LoadMonitors started");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Log("Calling ScanMonitor...");
|
|
||||||
await CMMCommand.ScanMonitor();
|
await CMMCommand.ScanMonitor();
|
||||||
Log("ScanMonitor complete");
|
|
||||||
|
|
||||||
Log("Calling ReadMonitorsData...");
|
|
||||||
var monitors = (await CMMCommand.ReadMonitorsData()).ToList();
|
var monitors = (await CMMCommand.ReadMonitorsData()).ToList();
|
||||||
Log($"ReadMonitorsData complete, found {monitors.Count} monitors");
|
|
||||||
|
|
||||||
if (!monitors.Any())
|
if (!monitors.Any())
|
||||||
{
|
{
|
||||||
Log("No monitors found");
|
newChildren.Add(new TextBlock
|
||||||
newChildren.Add(new TextBlock { Text = "No DDC/CI monitors detected", Foreground = Brushes.White, FontSize = 14 });
|
{
|
||||||
|
Text = "No DDC/CI monitors detected",
|
||||||
|
Foreground = Brushes.LightGray,
|
||||||
|
FontSize = 12,
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
|
Margin = new Thickness(0, 30, 0, 30)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var m in monitors)
|
foreach (var m in monitors)
|
||||||
{
|
{
|
||||||
Log($"Processing monitor: {m.MonitorName} ({m.SerialNumber})");
|
|
||||||
|
|
||||||
var brightness = await CMMCommand.GetBrightness(m.SerialNumber) ?? 50;
|
var brightness = await CMMCommand.GetBrightness(m.SerialNumber) ?? 50;
|
||||||
Log($" Brightness: {brightness}");
|
|
||||||
var contrast = await CMMCommand.GetContrast(m.SerialNumber) ?? 50;
|
var contrast = await CMMCommand.GetContrast(m.SerialNumber) ?? 50;
|
||||||
Log($" Contrast: {contrast}");
|
|
||||||
var inputSource = await CMMCommand.GetInputSource(m.SerialNumber);
|
var inputSource = await CMMCommand.GetInputSource(m.SerialNumber);
|
||||||
Log($" InputSource: {inputSource}");
|
|
||||||
var inputOptions = await CMMCommand.GetInputSourceOptions(m.SerialNumber);
|
var inputOptions = await CMMCommand.GetInputSourceOptions(m.SerialNumber);
|
||||||
Log($" InputOptions count: {inputOptions.Count}");
|
|
||||||
var powerStatus = await CMMCommand.GetMonPowerStatus(m.SerialNumber) ?? "Unknown";
|
var powerStatus = await CMMCommand.GetMonPowerStatus(m.SerialNumber) ?? "Unknown";
|
||||||
Log($" PowerStatus: {powerStatus}");
|
|
||||||
|
|
||||||
|
// Monitor name header
|
||||||
newChildren.Add(new TextBlock
|
newChildren.Add(new TextBlock
|
||||||
{
|
{
|
||||||
Text = m.MonitorName,
|
Text = m.MonitorName,
|
||||||
Foreground = Brushes.White,
|
Foreground = Brushes.White,
|
||||||
FontSize = 14,
|
FontSize = 13,
|
||||||
FontWeight = FontWeights.Bold,
|
FontWeight = FontWeights.SemiBold,
|
||||||
Margin = new Thickness(0, 10, 0, 5)
|
Margin = new Thickness(0, 8, 0, 6)
|
||||||
});
|
});
|
||||||
|
|
||||||
newChildren.Add(CreateSliderRow("Brightness", brightness, m.SerialNumber, CMMCommand.SetBrightness));
|
newChildren.Add(CreateSliderRow("Brightness", brightness, m.SerialNumber, CMMCommand.SetBrightness));
|
||||||
@@ -88,22 +85,33 @@ public partial class MainWindow : Window
|
|||||||
newChildren.Add(CreateInputRow(inputSource, inputOptions, m.SerialNumber));
|
newChildren.Add(CreateInputRow(inputSource, inputOptions, m.SerialNumber));
|
||||||
|
|
||||||
newChildren.Add(CreatePowerRow(powerStatus, 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);
|
||||||
}
|
}
|
||||||
Log($"Built {newChildren.Count} UI elements");
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"ERROR: {ex.GetType().Name}: {ex.Message}\n{ex.StackTrace}");
|
|
||||||
newChildren.Clear();
|
newChildren.Clear();
|
||||||
newChildren.Add(new TextBlock { Text = $"Error: {ex.Message}", Foreground = Brushes.Red, FontSize = 12, TextWrapping = TextWrapping.Wrap });
|
newChildren.Add(new TextBlock { Text = $"Error: {ex.Message}", Foreground = Brushes.OrangeRed, FontSize = 11, TextWrapping = TextWrapping.Wrap });
|
||||||
}
|
}
|
||||||
|
|
||||||
Log("Updating UI...");
|
sp.VerticalAlignment = VerticalAlignment.Top;
|
||||||
sp.Children.Clear();
|
sp.Children.Clear();
|
||||||
foreach (var child in newChildren)
|
foreach (var child in newChildren)
|
||||||
sp.Children.Add(child);
|
sp.Children.Add(child);
|
||||||
Log($"UI updated with {sp.Children.Count} children");
|
|
||||||
|
// 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)
|
private StackPanel CreateSliderRow(string label, int value, string serialNumber, Func<string, int, Task> setCommand)
|
||||||
|
|||||||
@@ -220,9 +220,6 @@ public static class CMMCommand
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string DebugLog = Path.Combine(
|
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "MonitorParse.log");
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 取得螢幕清單
|
/// 取得螢幕清單
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -232,27 +229,19 @@ public static class CMMCommand
|
|||||||
|
|
||||||
if (!File.Exists(CMMsMonitors)) return monitors;
|
if (!File.Exists(CMMsMonitors)) return monitors;
|
||||||
|
|
||||||
// Try reading raw bytes to understand encoding
|
// Read with UTF-16 LE encoding (ControlMyMonitor outputs UTF-16)
|
||||||
var rawBytes = await File.ReadAllBytesAsync(CMMsMonitors);
|
var rawBytes = await File.ReadAllBytesAsync(CMMsMonitors);
|
||||||
File.WriteAllText(DebugLog, $"File size: {rawBytes.Length} bytes\nFirst 20 bytes: {BitConverter.ToString(rawBytes.Take(20).ToArray())}\n\n");
|
|
||||||
|
|
||||||
// Try UTF-16 LE (common Windows Unicode)
|
|
||||||
var content = System.Text.Encoding.Unicode.GetString(rawBytes);
|
var content = System.Text.Encoding.Unicode.GetString(rawBytes);
|
||||||
File.AppendAllText(DebugLog, $"Content preview:\n{content.Substring(0, Math.Min(500, content.Length))}\n\n");
|
|
||||||
|
|
||||||
XMonitor? mon = null;
|
XMonitor? mon = null;
|
||||||
foreach (var line in content.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (var line in content.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
File.AppendAllText(DebugLog, $"LINE: [{line}]\n");
|
|
||||||
|
|
||||||
var colonIdx = line.IndexOf(':');
|
var colonIdx = line.IndexOf(':');
|
||||||
if (colonIdx < 0) continue;
|
if (colonIdx < 0) continue;
|
||||||
|
|
||||||
var key = line.Substring(0, colonIdx).Trim();
|
var key = line.Substring(0, colonIdx).Trim();
|
||||||
var val = line.Substring(colonIdx + 1).Trim().Trim('"');
|
var val = line.Substring(colonIdx + 1).Trim().Trim('"');
|
||||||
|
|
||||||
File.AppendAllText(DebugLog, $" KEY=[{key}] VAL=[{val}]\n");
|
|
||||||
|
|
||||||
if (key.Contains("Monitor Device Name"))
|
if (key.Contains("Monitor Device Name"))
|
||||||
{
|
{
|
||||||
mon = new XMonitor { MonitorDeviceName = val };
|
mon = new XMonitor { MonitorDeviceName = val };
|
||||||
@@ -272,14 +261,12 @@ public static class CMMCommand
|
|||||||
else if (mon != null && key.Contains("Monitor ID"))
|
else if (mon != null && key.Contains("Monitor ID"))
|
||||||
{
|
{
|
||||||
mon.MonitorID = val;
|
mon.MonitorID = val;
|
||||||
File.AppendAllText(DebugLog, $" -> Adding monitor: Name=[{mon.MonitorName}] SN=[{mon.SerialNumber}]\n");
|
|
||||||
if (!string.IsNullOrEmpty(mon.SerialNumber))
|
if (!string.IsNullOrEmpty(mon.SerialNumber))
|
||||||
monitors.Add(mon);
|
monitors.Add(mon);
|
||||||
mon = null;
|
mon = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File.AppendAllText(DebugLog, $"\nTotal monitors with serial: {monitors.Count}\n");
|
|
||||||
return monitors;
|
return monitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
102
README.md
102
README.md
@@ -1,74 +1,82 @@
|
|||||||
# ControlMyMonitorManagement
|
# Monitor Control Manager
|
||||||
|
|
||||||
A Windows desktop application for controlling monitor settings via DDC/CI (Display Data Channel/Command Interface). Adjust brightness, contrast, power state, and other display parameters across multiple monitors.
|
A lightweight Windows utility for controlling monitor settings via DDC/CI. Adjust brightness, contrast, input source, and power settings directly from your system tray.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Multi-Monitor Support** - Detect and control multiple connected displays
|
- **System Tray Integration** - Clean popup interface accessible from taskbar
|
||||||
- **Brightness & Contrast Sliders** - Easy adjustment with real-time feedback
|
- **Multi-Monitor Support** - Control all DDC/CI compatible displays
|
||||||
- **Input Source Switching** - Switch between VGA, DVI, HDMI, DisplayPort (auto-detected from monitor)
|
- **Brightness & Contrast** - Slider controls with real-time feedback
|
||||||
- **Power Management** - Turn monitors on, off, or into sleep mode
|
- **Input Source Switching** - Auto-detects available inputs (HDMI, DisplayPort, DVI, VGA)
|
||||||
- **System Tray Integration** - DellMonitorControl app with taskbar tray popup
|
- **Power Management** - On, Sleep, and Off controls
|
||||||
- **9 Languages** - Auto-detects system language (en, es, fr, de, zh, ja, pt, it, hi)
|
- **Multi-Language** - Auto-detects system language (English, Spanish, French, German, Chinese, Japanese, Portuguese, Italian, Hindi)
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Windows OS
|
- Windows 10/11
|
||||||
- .NET 7.0 SDK
|
- .NET 9.0 Runtime
|
||||||
- DDC/CI compatible monitor(s)
|
- DDC/CI compatible monitor(s)
|
||||||
|
|
||||||
## Build
|
> **Note:** Most external monitors support DDC/CI, but some laptop internal displays and certain monitors may not support this protocol.
|
||||||
|
|
||||||
```bash
|
## Installation
|
||||||
# Clone the repository
|
|
||||||
git clone https://github.com/yourusername/ControlMyMonitorManagement.git
|
### From Release
|
||||||
|
Download the latest release and run the executable. The app will appear in your system tray.
|
||||||
|
|
||||||
|
### Build from Source
|
||||||
|
```powershell
|
||||||
|
git clone https://git.marketally.com/misc/ControlMyMonitorManagement.git
|
||||||
cd ControlMyMonitorManagement
|
cd ControlMyMonitorManagement
|
||||||
|
dotnet build
|
||||||
# Build the solution
|
dotnet run --project DellMonitorControl
|
||||||
dotnet build ControlMyMonitorManagement.sln
|
|
||||||
|
|
||||||
# Run the main application
|
|
||||||
dotnet run --project ControlMyMonitorManagement/ControlMyMonitorManagement.csproj
|
|
||||||
|
|
||||||
# Run the Dell-specific application (with system tray)
|
|
||||||
dotnet run --project DellMonitorControl/DellMonitorControl.csproj
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Launch the application - it minimizes to system tray
|
||||||
|
2. Click the tray icon to open the control panel
|
||||||
|
3. Adjust brightness/contrast with sliders
|
||||||
|
4. Select input source from dropdown (if multiple available)
|
||||||
|
5. Toggle power state with the power button
|
||||||
|
6. Click outside the popup to close
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
| Project | Description |
|
| Project | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| **ControlMyMonitorManagement** | Main WPF application with full UI |
|
| `DellMonitorControl` | System tray application with popup UI |
|
||||||
| **DellMonitorControl** | Lightweight app with system tray integration |
|
| `ControlMyMonitorManagement` | Full WPF application (alternative) |
|
||||||
| **Library** | Core business logic and DDC/CI operations |
|
| `Library` | Core DDC/CI operations via ControlMyMonitor.exe |
|
||||||
| **CMMModel** | Data models for monitor status |
|
| `Language` | Localization resources (9 languages) |
|
||||||
| **CMMService** | Service layer interfaces |
|
| `CMMModel` | Data models |
|
||||||
| **Language** | Localization support |
|
| `Tester` | Unit tests |
|
||||||
| **Tester** | NUnit test project |
|
|
||||||
|
|
||||||
## Common VCP Codes
|
## Technical Details
|
||||||
|
|
||||||
| Code | Name | Values |
|
### DDC/CI Protocol
|
||||||
|------|------|--------|
|
The application uses DDC/CI (Display Data Channel/Command Interface) to communicate with monitors through the display cable. This allows software control of settings normally accessed via physical monitor buttons.
|
||||||
| D6 | Power Mode | 1=On, 4=Sleep, 5=Off |
|
|
||||||
| 10 | Brightness | 0-100 |
|
|
||||||
| 12 | Contrast | 0-100 |
|
|
||||||
| 60 | Input Source | 1=VGA, 3=DVI, 15=DisplayPort, 17=HDMI |
|
|
||||||
|
|
||||||
## How It Works
|
### VCP Codes Used
|
||||||
|
| Code | Function | Values |
|
||||||
This application uses DDC/CI protocol to communicate with monitors through the display cable (HDMI, DisplayPort, DVI, VGA). DDC/CI allows software to send commands directly to the monitor's firmware to adjust settings that would normally require using the monitor's physical buttons.
|
|------|----------|--------|
|
||||||
|
| `10` | Brightness | 0-100 |
|
||||||
|
| `12` | Contrast | 0-100 |
|
||||||
|
| `60` | Input Source | 1=VGA, 15=DP, 17=HDMI |
|
||||||
|
| `D6` | Power Mode | 1=On, 4=Sleep, 5=Off |
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- **Original Project**: [DangWang](https://github.com/poyingHAHA) - ControlMyMonitorManagement
|
- **Original Project**: [rictirse](https://github.com/rictirse) - ControlMyMonitorManagement base
|
||||||
- **DDC/CI Tool**: [Nir Sofer](https://www.nirsoft.net) - ControlMyMonitor.exe (freeware)
|
- **DDC/CI Engine**: [Nir Sofer](https://www.nirsoft.net/utils/control_my_monitor.html) - ControlMyMonitor (freeware)
|
||||||
- **Enhancements by David H Friedel Jr**: Brightness/contrast sliders, input source switching, 9-language localization
|
- **Enhancements**: David H Friedel Jr - UI improvements, input switching, localization
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project contains multiple components with different terms:
|
MIT License - See [LICENSE](LICENSE) for details.
|
||||||
|
|
||||||
- **Original code by DangWang**: No explicit license provided
|
Note: ControlMyMonitor.exe is freeware by Nir Sofer (free distribution, no modification).
|
||||||
- **ControlMyMonitor.exe**: Freeware by Nir Sofer - free distribution allowed, no commercial use, no modification
|
|
||||||
- **New contributions (sliders, localization, etc.)**: MIT License
|
|
||||||
|
|||||||
Reference in New Issue
Block a user