2
0

Add brightness/contrast sliders, input source switching, and 9-language localization

- Add VCP commands for brightness (10), contrast (12), input source (60)
- Fix UTF-16 encoding for monitor data parsing
- Add system tray app with monitor controls
- Add localization for en, es, fr, de, zh, ja, pt, it, hi
- Update to .NET 9.0
- Add LICENSE and README

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-03 22:11:35 -05:00
parent 6b656ead2d
commit 0352c6b755
34 changed files with 1640 additions and 158 deletions

View File

@@ -54,12 +54,48 @@ namespace CMM.Language
var Languages = new List<string>();
string uriPath = ResourceLocalPath + "/" + LanguageFileName;
Languages.Add(uriPath + ".en-US.xaml");
Languages.Add(uriPath + ".zh-TW.xaml");
Languages.Add(uriPath + ".en.xaml");
Languages.Add(uriPath + ".es.xaml");
Languages.Add(uriPath + ".fr.xaml");
Languages.Add(uriPath + ".de.xaml");
Languages.Add(uriPath + ".zh.xaml");
Languages.Add(uriPath + ".ja.xaml");
Languages.Add(uriPath + ".pt.xaml");
Languages.Add(uriPath + ".it.xaml");
Languages.Add(uriPath + ".hi.xaml");
return Languages;
}
/// <summary>
/// Auto-detect and apply system language
/// </summary>
public void ApplySystemLanguage()
{
var systemCulture = CultureInfo.CurrentUICulture;
var matchedCulture = FindBestMatchingCulture(systemCulture);
ChangeCulture(matchedCulture);
}
/// <summary>
/// Find the best matching supported culture for the given culture
/// </summary>
private CultureInfo FindBestMatchingCulture(CultureInfo culture)
{
// Try exact match first
var exactMatch = SupportedCultures.FirstOrDefault(c =>
c.Name.Equals(culture.Name, StringComparison.OrdinalIgnoreCase));
if (exactMatch != null) return exactMatch;
// Try matching by two-letter ISO language name
var languageMatch = SupportedCultures.FirstOrDefault(c =>
c.TwoLetterISOLanguageName.Equals(culture.TwoLetterISOLanguageName, StringComparison.OrdinalIgnoreCase));
if (languageMatch != null) return languageMatch;
// Default to English
return SupportedCultures.FirstOrDefault(c => c.Name == "en") ?? SupportedCultures.First();
}
public void ChangeCulture(string cultureName)
{
var cultureInfo = CultureInfo.GetCultureInfo(cultureName);

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<TargetFramework>net9.0-windows</TargetFramework>
<RootNamespace>CMM.Language</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
@@ -22,13 +22,34 @@
</PropertyGroup>
<ItemGroup>
<None Update="StringResources.en-US.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.zh-TW.xam">
<None Update="StringResources.en.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.es.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.fr.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.de.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.zh.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.ja.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.pt.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.it.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="StringResources.hi.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
</ItemGroup>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">Monitorsteuerung</sys:String>
<sys:String x:Key="ScreenSwitch">Bildschirmschalter</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">Helligkeit</sys:String>
<sys:String x:Key="Contrast">Kontrast</sys:String>
<sys:String x:Key="InputSource">Eingangsquelle</sys:String>
<sys:String x:Key="Power">Stromversorgung</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">Einschalten</sys:String>
<sys:String x:Key="Sleep">Ruhezustand</sys:String>
<sys:String x:Key="PowerOff">Ausschalten</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">Minimieren</sys:String>
<sys:String x:Key="Exit">Beenden</sys:String>
<sys:String x:Key="Loading">Laden...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">Fehler beim Laden der Konfiguration: </sys:String>
<sys:String x:Key="SaveConfigErr">Fehler beim Speichern der Konfiguration: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">Monitor Control Management</sys:String>
<sys:String x:Key="ScreenSwitch">Screen Switch</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">Brightness</sys:String>
<sys:String x:Key="Contrast">Contrast</sys:String>
<sys:String x:Key="InputSource">Input Source</sys:String>
<sys:String x:Key="Power">Power</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">Power On</sys:String>
<sys:String x:Key="Sleep">Sleep</sys:String>
<sys:String x:Key="PowerOff">Power Off</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">Minimize</sys:String>
<sys:String x:Key="Exit">Exit</sys:String>
<sys:String x:Key="Loading">Loading...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">Failed to load configuration: </sys:String>
<sys:String x:Key="SaveConfigErr">Failed to save configuration: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">Control de Monitor</sys:String>
<sys:String x:Key="ScreenSwitch">Interruptor de Pantalla</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">Brillo</sys:String>
<sys:String x:Key="Contrast">Contraste</sys:String>
<sys:String x:Key="InputSource">Fuente de Entrada</sys:String>
<sys:String x:Key="Power">Encendido</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">Encender</sys:String>
<sys:String x:Key="Sleep">Suspender</sys:String>
<sys:String x:Key="PowerOff">Apagar</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">Minimizar</sys:String>
<sys:String x:Key="Exit">Salir</sys:String>
<sys:String x:Key="Loading">Cargando...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">Error al cargar la configuración: </sys:String>
<sys:String x:Key="SaveConfigErr">Error al guardar la configuración: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">Gestion du Moniteur</sys:String>
<sys:String x:Key="ScreenSwitch">Interrupteur d'Écran</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">Luminosité</sys:String>
<sys:String x:Key="Contrast">Contraste</sys:String>
<sys:String x:Key="InputSource">Source d'Entrée</sys:String>
<sys:String x:Key="Power">Alimentation</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">Allumer</sys:String>
<sys:String x:Key="Sleep">Veille</sys:String>
<sys:String x:Key="PowerOff">Éteindre</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">Réduire</sys:String>
<sys:String x:Key="Exit">Quitter</sys:String>
<sys:String x:Key="Loading">Chargement...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">Échec du chargement de la configuration: </sys:String>
<sys:String x:Key="SaveConfigErr">Échec de la sauvegarde de la configuration: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">मॉनिटर नियंत्रण प्रबंधन</sys:String>
<sys:String x:Key="ScreenSwitch">स्क्रीन स्विच</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">चमक</sys:String>
<sys:String x:Key="Contrast">कंट्रास्ट</sys:String>
<sys:String x:Key="InputSource">इनपुट स्रोत</sys:String>
<sys:String x:Key="Power">पावर</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">चालू करें</sys:String>
<sys:String x:Key="Sleep">स्लीप</sys:String>
<sys:String x:Key="PowerOff">बंद करें</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">छोटा करें</sys:String>
<sys:String x:Key="Exit">बाहर निकलें</sys:String>
<sys:String x:Key="Loading">लोड हो रहा है...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">कॉन्फ़िगरेशन लोड करने में विफल: </sys:String>
<sys:String x:Key="SaveConfigErr">कॉन्फ़िगरेशन सहेजने में विफल: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">Gestione Monitor</sys:String>
<sys:String x:Key="ScreenSwitch">Interruttore Schermo</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">Luminosità</sys:String>
<sys:String x:Key="Contrast">Contrasto</sys:String>
<sys:String x:Key="InputSource">Sorgente di Ingresso</sys:String>
<sys:String x:Key="Power">Alimentazione</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">Accendi</sys:String>
<sys:String x:Key="Sleep">Sospendi</sys:String>
<sys:String x:Key="PowerOff">Spegni</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">Riduci a icona</sys:String>
<sys:String x:Key="Exit">Esci</sys:String>
<sys:String x:Key="Loading">Caricamento...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">Impossibile caricare la configurazione: </sys:String>
<sys:String x:Key="SaveConfigErr">Impossibile salvare la configurazione: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">モニター制御管理</sys:String>
<sys:String x:Key="ScreenSwitch">画面スイッチ</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">輝度</sys:String>
<sys:String x:Key="Contrast">コントラスト</sys:String>
<sys:String x:Key="InputSource">入力ソース</sys:String>
<sys:String x:Key="Power">電源</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">電源オン</sys:String>
<sys:String x:Key="Sleep">スリープ</sys:String>
<sys:String x:Key="PowerOff">電源オフ</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">最小化</sys:String>
<sys:String x:Key="Exit">終了</sys:String>
<sys:String x:Key="Loading">読み込み中...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">設定の読み込みに失敗しました: </sys:String>
<sys:String x:Key="SaveConfigErr">設定の保存に失敗しました: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">Controle de Monitor</sys:String>
<sys:String x:Key="ScreenSwitch">Interruptor de Tela</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">Brilho</sys:String>
<sys:String x:Key="Contrast">Contraste</sys:String>
<sys:String x:Key="InputSource">Fonte de Entrada</sys:String>
<sys:String x:Key="Power">Energia</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">Ligar</sys:String>
<sys:String x:Key="Sleep">Suspender</sys:String>
<sys:String x:Key="PowerOff">Desligar</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">Minimizar</sys:String>
<sys:String x:Key="Exit">Sair</sys:String>
<sys:String x:Key="Loading">Carregando...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">Falha ao carregar a configuração: </sys:String>
<sys:String x:Key="SaveConfigErr">Falha ao salvar a configuração: </sys:String>
</ResourceDictionary>

View File

@@ -1,5 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
</ResourceDictionary>
<!-- Application (Default: English) -->
<sys:String x:Key="AppTitle">Monitor Control Management</sys:String>
<sys:String x:Key="ScreenSwitch">Screen Switch</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">Brightness</sys:String>
<sys:String x:Key="Contrast">Contrast</sys:String>
<sys:String x:Key="InputSource">Input Source</sys:String>
<sys:String x:Key="Power">Power</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">Power On</sys:String>
<sys:String x:Key="Sleep">Sleep</sys:String>
<sys:String x:Key="PowerOff">Power Off</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">Minimize</sys:String>
<sys:String x:Key="Exit">Exit</sys:String>
<sys:String x:Key="Loading">Loading...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">Failed to load configuration: </sys:String>
<sys:String x:Key="SaveConfigErr">Failed to save configuration: </sys:String>
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Application -->
<sys:String x:Key="AppTitle">螢幕控制管理</sys:String>
<sys:String x:Key="ScreenSwitch">螢幕開關</sys:String>
<!-- Controls -->
<sys:String x:Key="Brightness">亮度</sys:String>
<sys:String x:Key="Contrast">對比度</sys:String>
<sys:String x:Key="InputSource">輸入源</sys:String>
<sys:String x:Key="Power">電源</sys:String>
<!-- Power States -->
<sys:String x:Key="PowerOn">開啟</sys:String>
<sys:String x:Key="Sleep">休眠</sys:String>
<sys:String x:Key="PowerOff">關閉</sys:String>
<!-- Window Controls -->
<sys:String x:Key="Minimize">最小化</sys:String>
<sys:String x:Key="Exit">結束</sys:String>
<sys:String x:Key="Loading">載入中...</sys:String>
<!-- Error Messages -->
<sys:String x:Key="LoadConfigErr">載入設定檔失敗: </sys:String>
<sys:String x:Key="SaveConfigErr">保存設定檔失敗: </sys:String>
</ResourceDictionary>