Remove unused monitor helpers and simplify utilities

Removed obsolete helper methods and the MonitorFeatureHelper class, streamlining monitor feature parsing and value conversion logic. Cleaned up thread-safe dictionary utilities by dropping rarely used methods. Updated application icon path in project file. Documentation comments were clarified for consistency.
This commit is contained in:
Yu Leng
2025-12-10 19:30:17 +08:00
parent 762a6bce0c
commit a05859efc8
8 changed files with 7 additions and 374 deletions

View File

@@ -24,27 +24,6 @@ namespace PowerDisplay.Common.Drivers.DDC
{
}
/// <summary>
/// Get monitor device ID
/// </summary>
public unsafe string GetMonitorDeviceId(IntPtr hMonitor)
{
try
{
var monitorInfo = new MONITORINFOEX { CbSize = (uint)sizeof(MonitorInfoEx) };
if (GetMonitorInfo(hMonitor, ref monitorInfo))
{
return monitorInfo.GetDeviceName() ?? string.Empty;
}
}
catch
{
// Silent failure
}
return string.Empty;
}
/// <summary>
/// Get physical monitors for a logical monitor.
/// Filters out any monitors with NULL handles (Windows API bug workaround).

View File

@@ -150,39 +150,6 @@ namespace PowerDisplay.Common.Drivers
return new string((char*)ptr);
}
}
/// <summary>
/// Helper method to get device string as string
/// </summary>
public readonly string GetDeviceString()
{
fixed (ushort* ptr = DeviceString)
{
return new string((char*)ptr);
}
}
/// <summary>
/// Helper method to get device ID as string
/// </summary>
public readonly string GetDeviceID()
{
fixed (ushort* ptr = DeviceID)
{
return new string((char*)ptr);
}
}
/// <summary>
/// Helper method to get device key as string
/// </summary>
public readonly string GetDeviceKey()
{
fixed (ushort* ptr = DeviceKey)
{
return new string((char*)ptr);
}
}
}
/// <summary>

View File

@@ -13,27 +13,27 @@ namespace PowerDisplay.Common.Models
public readonly struct VcpFeatureValue
{
/// <summary>
/// Current value
/// Gets current value
/// </summary>
public int Current { get; }
/// <summary>
/// Minimum value
/// Gets minimum value
/// </summary>
public int Minimum { get; }
/// <summary>
/// Maximum value
/// Gets maximum value
/// </summary>
public int Maximum { get; }
/// <summary>
/// Whether the value information is valid
/// Gets a value indicating whether whether the value information is valid
/// </summary>
public bool IsValid { get; }
/// <summary>
/// Timestamp when the value information was obtained
/// Gets timestamp when the value information was obtained
/// </summary>
public DateTime Timestamp { get; }
@@ -52,7 +52,7 @@ namespace PowerDisplay.Common.Models
}
/// <summary>
/// Creates invalid value information
/// Gets creates invalid value information
/// </summary>
public static VcpFeatureValue Invalid => new(-1, -1, -1);
@@ -69,20 +69,6 @@ namespace PowerDisplay.Common.Models
return (int)Math.Round((double)(Current - Minimum) * 100 / (Maximum - Minimum));
}
/// <summary>
/// Creates raw value from percentage
/// </summary>
public int FromPercentage(int percentage)
{
if (!IsValid)
{
return -1;
}
percentage = Math.Clamp(percentage, 0, 100);
return Minimum + (int)Math.Round((double)(Maximum - Minimum) * percentage / 100);
}
public override string ToString()
{
return IsValid ? $"{Current}/{Maximum} ({ToPercentage()}%)" : "Invalid";

View File

@@ -22,20 +22,6 @@ namespace PowerDisplay.Common.Utils
private readonly Dictionary<TKey, TValue> _dictionary = new();
private readonly object _lock = new();
/// <summary>
/// Gets the number of key/value pairs in the dictionary.
/// </summary>
public int Count
{
get
{
lock (_lock)
{
return _dictionary.Count;
}
}
}
/// <summary>
/// Tries to get the value associated with the specified key.
/// </summary>
@@ -50,73 +36,6 @@ namespace PowerDisplay.Common.Utils
}
}
/// <summary>
/// Gets the value associated with the specified key, or the default value if not found.
/// </summary>
/// <param name="key">The key to locate.</param>
/// <returns>The value if found; otherwise, the default value.</returns>
public TValue? GetValueOrDefault(TKey key)
{
lock (_lock)
{
return _dictionary.TryGetValue(key, out var value) ? value : default;
}
}
/// <summary>
/// Adds or updates a key/value pair.
/// </summary>
/// <param name="key">The key to add or update.</param>
/// <param name="value">The value to associate with the key.</param>
public void AddOrUpdate(TKey key, TValue value)
{
lock (_lock)
{
_dictionary[key] = value;
}
}
/// <summary>
/// Gets the value for the key if it exists; otherwise, adds the value using the provided factory.
/// </summary>
/// <param name="key">The key to locate or add.</param>
/// <param name="valueFactory">The factory function to create a new value if the key doesn't exist.</param>
/// <returns>The existing or newly created value.</returns>
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
{
lock (_lock)
{
if (_dictionary.TryGetValue(key, out var existingValue))
{
return existingValue;
}
var newValue = valueFactory(key);
_dictionary[key] = newValue;
return newValue;
}
}
/// <summary>
/// Tries to remove the value associated with the specified key.
/// </summary>
/// <param name="key">The key to remove.</param>
/// <param name="value">When this method returns, contains the removed value if found; otherwise, the default value.</param>
/// <returns>True if the key was found and removed; otherwise, false.</returns>
public bool TryRemove(TKey key, out TValue? value)
{
lock (_lock)
{
if (_dictionary.TryGetValue(key, out value))
{
_dictionary.Remove(key);
return true;
}
return false;
}
}
/// <summary>
/// Removes all key/value pairs from the dictionary.
/// </summary>
@@ -128,19 +47,6 @@ namespace PowerDisplay.Common.Utils
}
}
/// <summary>
/// Checks if the dictionary contains the specified key.
/// </summary>
/// <param name="key">The key to check.</param>
/// <returns>True if the key exists; otherwise, false.</returns>
public bool ContainsKey(TKey key)
{
lock (_lock)
{
return _dictionary.ContainsKey(key);
}
}
/// <summary>
/// Gets a snapshot of all values in the dictionary.
/// Returns a copy to ensure thread safety.
@@ -154,32 +60,6 @@ namespace PowerDisplay.Common.Utils
}
}
/// <summary>
/// Gets a snapshot of all keys in the dictionary.
/// Returns a copy to ensure thread safety.
/// </summary>
/// <returns>A list containing copies of all keys.</returns>
public List<TKey> GetKeysSnapshot()
{
lock (_lock)
{
return new List<TKey>(_dictionary.Keys);
}
}
/// <summary>
/// Gets a snapshot of all key/value pairs in the dictionary.
/// Returns a copy to ensure thread safety.
/// </summary>
/// <returns>A dictionary containing copies of all key/value pairs.</returns>
public Dictionary<TKey, TValue> GetSnapshot()
{
lock (_lock)
{
return new Dictionary<TKey, TValue>(_dictionary);
}
}
/// <summary>
/// Executes an action within the lock, providing the internal dictionary for complex operations.
/// Use this for multi-step transactions that need to be atomic.

View File

@@ -1,112 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Globalization;
using PowerDisplay.Common.Drivers;
namespace PowerDisplay.Common.Utils
{
/// <summary>
/// Unified helper class for parsing monitor feature support from VCP capabilities.
/// This eliminates duplicate VCP parsing logic across PowerDisplay.exe and Settings.UI.
/// </summary>
public static class MonitorFeatureHelper
{
/// <summary>
/// Result of parsing monitor feature support from VCP capabilities
/// </summary>
public readonly struct FeatureSupportResult
{
public bool SupportsBrightness { get; init; }
public bool SupportsContrast { get; init; }
public bool SupportsColorTemperature { get; init; }
public bool SupportsVolume { get; init; }
public bool SupportsInputSource { get; init; }
public string CapabilitiesStatus { get; init; }
public static FeatureSupportResult Unavailable => new()
{
SupportsBrightness = false,
SupportsContrast = false,
SupportsColorTemperature = false,
SupportsVolume = false,
SupportsInputSource = false,
CapabilitiesStatus = "unavailable",
};
}
/// <summary>
/// Parse feature support from a list of VCP code strings.
/// This is the single source of truth for determining monitor capabilities.
/// </summary>
/// <param name="vcpCodes">List of VCP codes as strings (e.g., "0x10", "10", "0x12")</param>
/// <param name="capabilitiesRaw">Raw capabilities string, used to determine availability status</param>
/// <returns>Feature support result</returns>
public static FeatureSupportResult ParseFeatureSupport(IReadOnlyList<string>? vcpCodes, string? capabilitiesRaw)
{
// Check capabilities availability
if (string.IsNullOrEmpty(capabilitiesRaw))
{
return FeatureSupportResult.Unavailable;
}
// Convert all VCP codes to integers for comparison
var vcpCodeInts = ParseVcpCodesToIntegers(vcpCodes);
// Determine feature support based on VCP codes
return new FeatureSupportResult
{
SupportsBrightness = vcpCodeInts.Contains(NativeConstants.VcpCodeBrightness),
SupportsContrast = vcpCodeInts.Contains(NativeConstants.VcpCodeContrast),
SupportsColorTemperature = vcpCodeInts.Contains(NativeConstants.VcpCodeSelectColorPreset),
SupportsVolume = vcpCodeInts.Contains(NativeConstants.VcpCodeVolume),
SupportsInputSource = vcpCodeInts.Contains(NativeConstants.VcpCodeInputSource),
CapabilitiesStatus = "available",
};
}
/// <summary>
/// Parse VCP codes from string list to integer set
/// Handles both hex formats: "0x10" and "10"
/// </summary>
private static HashSet<int> ParseVcpCodesToIntegers(IReadOnlyList<string>? vcpCodes)
{
var result = new HashSet<int>();
if (vcpCodes == null)
{
return result;
}
foreach (var code in vcpCodes)
{
if (string.IsNullOrWhiteSpace(code))
{
continue;
}
// Remove "0x" prefix if present and parse as hex
var cleanCode = code.Trim();
if (cleanCode.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
cleanCode = cleanCode.Substring(2);
}
if (int.TryParse(cleanCode, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int codeInt))
{
result.Add(codeInt);
}
}
return result;
}
}
}

View File

@@ -2,9 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using PowerDisplay.Common.Drivers;
namespace PowerDisplay.Common.Utils
{
/// <summary>
@@ -13,49 +10,6 @@ namespace PowerDisplay.Common.Utils
/// </summary>
public static class MonitorValueConverter
{
/// <summary>
/// Standard VCP color temperature preset to Kelvin value mapping.
/// Based on MCCS (Monitor Control Command Set) standard.
/// </summary>
private static readonly Dictionary<int, int> VcpToKelvinMap = new()
{
[0x03] = 4000,
[0x04] = 5000,
[0x05] = 6500,
[0x06] = 7500,
[0x08] = 9300,
[0x09] = 10000,
[0x0A] = 11500,
};
/// <summary>
/// Converts a VCP color temperature preset value to approximate Kelvin temperature.
/// </summary>
/// <param name="vcpValue">The VCP preset value (e.g., 0x05).</param>
/// <returns>The Kelvin temperature (e.g., 6500), or 0 if unknown.</returns>
public static int VcpToKelvin(int vcpValue)
{
return VcpToKelvinMap.TryGetValue(vcpValue, out var kelvin) ? kelvin : 0;
}
/// <summary>
/// Formats a VCP color temperature value as a Kelvin string for display.
/// </summary>
/// <param name="vcpValue">The VCP preset value (e.g., 0x05).</param>
/// <returns>Formatted string like "6500K" or "Unknown (0x05)" if not a standard preset.</returns>
public static string FormatVcpAsKelvin(int vcpValue)
{
var kelvin = VcpToKelvin(vcpValue);
if (kelvin > 0)
{
return $"{kelvin}K";
}
// Use VcpValueNames for special presets like sRGB, User 1, etc.
var name = VcpValueNames.GetName(NativeConstants.VcpCodeSelectColorPreset, vcpValue);
return name ?? $"Unknown (0x{vcpValue:X2})";
}
/// <summary>
/// Formats a VCP color temperature value as a display name with preset name.
/// </summary>
@@ -65,26 +19,5 @@ namespace PowerDisplay.Common.Utils
{
return ColorTemperatureHelper.FormatColorTemperatureDisplayName(vcpValue);
}
/// <summary>
/// Gets the preset name for a VCP color temperature value.
/// </summary>
/// <param name="vcpValue">The VCP preset value (e.g., 0x05).</param>
/// <returns>Preset name like "6500K", "sRGB", or null if unknown.</returns>
public static string? GetColorTemperaturePresetName(int vcpValue)
{
return VcpValueNames.GetName(NativeConstants.VcpCodeSelectColorPreset, vcpValue);
}
/// <summary>
/// Checks if a VCP value represents a known color temperature preset.
/// </summary>
/// <param name="vcpValue">The VCP preset value.</param>
/// <returns>True if the value is a known preset.</returns>
public static bool IsKnownColorTemperaturePreset(int vcpValue)
{
return VcpToKelvinMap.ContainsKey(vcpValue) ||
VcpValueNames.GetName(NativeConstants.VcpCodeSelectColorPreset, vcpValue) != null;
}
}
}

View File

Before

Width:  |  Height:  |  Size: 468 KiB

After

Width:  |  Height:  |  Size: 468 KiB

View File

@@ -7,7 +7,7 @@
<OutputType>WinExe</OutputType>
<RootNamespace>PowerDisplay</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>Assets\PowerDisplay\PowerDisplay.ico</ApplicationIcon>
<ApplicationIcon>Assets\PowerDisplay.ico</ApplicationIcon>
<Platforms>x64;ARM64</Platforms>
<UseWinUI>true</UseWinUI>
<EnableMsixTooling>true</EnableMsixTooling>