Add project files.
This commit is contained in:
70
Library/Base/ObservableRangeCollection.cs
Normal file
70
Library/Base/ObservableRangeCollection.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace CMM.Library.Base
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ObservableRangeCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the elements of the specified collection to the end of the ObservableCollection(Of T).
|
||||
/// </summary>
|
||||
public void AddRange(IEnumerable<T> collection)
|
||||
{
|
||||
if (collection == null) throw new ArgumentNullException("collection");
|
||||
|
||||
foreach (var i in collection) Items.Add(i);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T).
|
||||
/// </summary>
|
||||
public void RemoveRange(IEnumerable<T> collection)
|
||||
{
|
||||
if (collection == null) throw new ArgumentNullException("collection");
|
||||
|
||||
foreach (var i in collection) Items.Remove(i);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the current collection and replaces it with the specified item.
|
||||
/// </summary>
|
||||
public void Replace(T item)
|
||||
{
|
||||
ReplaceRange(new T[] { item });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the current collection and replaces it with the specified collection.
|
||||
/// </summary>
|
||||
public void ReplaceRange(IEnumerable<T> collection)
|
||||
{
|
||||
if (collection == null) throw new ArgumentNullException("collection");
|
||||
|
||||
Items.Clear();
|
||||
foreach (var i in collection) Items.Add(i);
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class.
|
||||
/// </summary>
|
||||
public ObservableRangeCollection()
|
||||
: base() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collection">collection: The collection from which the elements are copied.</param>
|
||||
/// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception>
|
||||
public ObservableRangeCollection(IEnumerable<T> collection)
|
||||
: base(collection) { }
|
||||
}
|
||||
}
|
||||
31
Library/Base/PropertyBase.cs
Normal file
31
Library/Base/PropertyBase.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace CMM.Library.Base
|
||||
{
|
||||
public class PropertyBase : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
virtual internal protected void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
if (this.PropertyChanged != null)
|
||||
{
|
||||
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
protected void SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (object.Equals(storage, value)) return;
|
||||
|
||||
storage = value;
|
||||
this.OnPropertyChanged(propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
76
Library/Config/Config.cs
Normal file
76
Library/Config/Config.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using CMM.Language;
|
||||
using CMM.Library.Base;
|
||||
using CMM.Library.Helpers;
|
||||
using CMM.Library.Method;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace CMM.Library.Config
|
||||
{
|
||||
public class XConfig : PropertyBase
|
||||
{
|
||||
[JsonIgnore]
|
||||
public string Version { get; private set; }
|
||||
|
||||
public static string ConfigFileName => Path.Combine(AssemblyData.Path, "Config.cfg");
|
||||
|
||||
#region Language
|
||||
[JsonIgnore]
|
||||
public CultureInfo Culture
|
||||
{
|
||||
get => _Culture;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _Culture, value);
|
||||
LoadCultures();
|
||||
}
|
||||
}
|
||||
CultureInfo _Culture;
|
||||
public string Language { get; set; } = null;
|
||||
CulturesHelper CulturesHelper { get; init; } = new();
|
||||
public void LoadCultures()
|
||||
{
|
||||
if (CulturesHelper == null) return;
|
||||
|
||||
CulturesHelper.ChangeCulture(Culture);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public virtual void Load()
|
||||
{
|
||||
XConfig _base = null;
|
||||
if (new FileInfo(ConfigFileName).Exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
_base = ConfigFileName.JsonFormFile<XConfig>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"{Lang.Find("LoadConfigErr")}{ex.Message}", "failed", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
this.Culture = _base?.Culture ?? new CultureInfo(_base?.Language ?? "en-US", false);
|
||||
this.Version = $"{AssemblyData.AppName} {AssemblyData.AppVersion}";
|
||||
}
|
||||
|
||||
public virtual void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.FileToJson(ConfigFileName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"{Lang.Find("SaveConfigErr")}{ex.Message}", "failed", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Library/Extensions/MonitorExtension.cs
Normal file
13
Library/Extensions/MonitorExtension.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.Extensions
|
||||
{
|
||||
public static class MonitorExtension
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
71
Library/Helpers/ConsoleHelper.cs
Normal file
71
Library/Helpers/ConsoleHelper.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.Helpers
|
||||
{
|
||||
internal class ConsoleHelper
|
||||
{
|
||||
const string cmdFileName = "cmd.exe";
|
||||
private static Process CreatProcess(string fileName) =>
|
||||
new Process()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
UseShellExecute = false,
|
||||
RedirectStandardInput = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true,
|
||||
}
|
||||
};
|
||||
|
||||
public static async Task<string> CmdCommandAsync(params string[] cmds) =>
|
||||
await CommandAsync(cmdFileName, cmds);
|
||||
|
||||
public static string CmdCommand(params string[] cmds) =>
|
||||
Command(cmdFileName, cmds);
|
||||
|
||||
public static async Task<string> CommandAsync(string fileName, params string[] cmds)
|
||||
{
|
||||
var p = CreatProcess(fileName);
|
||||
p.Start();
|
||||
foreach (var cmd in cmds)
|
||||
{
|
||||
p.StandardInput.WriteLine(cmd);
|
||||
}
|
||||
p.StandardInput.WriteLine("exit");
|
||||
var result = await p.StandardOutput.ReadToEndAsync();
|
||||
var error = await p.StandardError.ReadToEndAsync();
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
result = result + "\r\n<Error Message>:\r\n" + error;
|
||||
await p.WaitForExitAsync();
|
||||
p.Close();
|
||||
Debug.WriteLine(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string Command(string fileName, params string[] cmds)
|
||||
{
|
||||
var p = CreatProcess(fileName);
|
||||
p.Start();
|
||||
foreach (var cmd in cmds)
|
||||
{
|
||||
p.StandardInput.WriteLine(cmd);
|
||||
}
|
||||
p.StandardInput.WriteLine("exit");
|
||||
var result = p.StandardOutput.ReadToEnd();
|
||||
var error = p.StandardError.ReadToEnd();
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
result = result + "\r\n<Error Message>:\r\n" + error;
|
||||
p.WaitForExit();
|
||||
p.Close();
|
||||
Debug.WriteLine(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Library/Helpers/FileHelper.cs
Normal file
29
Library/Helpers/FileHelper.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.Helpers
|
||||
{
|
||||
internal static class FileHelper
|
||||
{
|
||||
public static byte[] ResourceToByteArray(this string fileName)
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName =
|
||||
assembly.GetManifestResourceNames().
|
||||
Where(str => str.Contains(fileName)).FirstOrDefault();
|
||||
if (resourceName == null) return null;
|
||||
|
||||
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
stream.CopyTo(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
131
Library/Helpers/JsonHelper.cs
Normal file
131
Library/Helpers/JsonHelper.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.Helpers
|
||||
{
|
||||
static class JsonSerializerExtensions
|
||||
{
|
||||
public static JsonSerializerOptions defaultSettings = new JsonSerializerOptions()
|
||||
{
|
||||
WriteIndented = true,
|
||||
IgnoreNullValues = true,
|
||||
PropertyNamingPolicy = null,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
};
|
||||
}
|
||||
|
||||
internal static class JsonHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 複製整個obj全部結構
|
||||
/// </summary>
|
||||
public static T DeepCopy<T>(T RealObject) =>
|
||||
JsonSerializer.Deserialize<T>(JsonSerializer.Serialize(RealObject, JsonSerializerExtensions.defaultSettings));
|
||||
|
||||
public static string JsonFormResource(this string fileName)
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName =
|
||||
assembly.GetManifestResourceNames().
|
||||
Where(str => str.Contains(fileName)).FirstOrDefault();
|
||||
if (resourceName == null) return "";
|
||||
|
||||
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (var reader = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public static T JsonFormResource<T>(this string fileName) =>
|
||||
JsonFormString<T>(JsonFormResource(fileName));
|
||||
|
||||
public static T JsonFormFile<T>(this string fileName) =>
|
||||
JsonFormString<T>(Load(fileName));
|
||||
|
||||
public static T JsonFormString<T>(this string json) =>
|
||||
JsonSerializer.Deserialize<T>(json);
|
||||
|
||||
public static void FileToJson<T>(this T payload, string savePath) =>
|
||||
Save(savePath, payload.ToJson());
|
||||
|
||||
public static string ToJson<T>(this T payload) =>
|
||||
JsonSerializer.Serialize(payload, JsonSerializerExtensions.defaultSettings);
|
||||
|
||||
/// <summary>
|
||||
/// 從Embedded resource讀string
|
||||
/// </summary>
|
||||
/// <param name="aFileName">resource位置,不含副檔名</param>
|
||||
public static string GetResource(this Assembly assembly, string aFileName)
|
||||
{
|
||||
var resourceName = assembly
|
||||
.GetManifestResourceNames()
|
||||
.Where(str => str.Contains(aFileName))
|
||||
.FirstOrDefault();
|
||||
if (resourceName == null) return "";
|
||||
|
||||
using (var stream = assembly.GetManifestResourceStream(resourceName))
|
||||
using (var sr = new StreamReader(stream, Encoding.UTF8))
|
||||
{
|
||||
return sr.ReadToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public static string Load(string aFileName) =>
|
||||
Load(new FileInfo(aFileName));
|
||||
|
||||
public static string Load(FileInfo aFi)
|
||||
{
|
||||
if (aFi.Exists)
|
||||
{
|
||||
string _Json = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
var sr = new StreamReader(aFi.FullName);
|
||||
_Json = sr.ReadToEnd();
|
||||
sr.Close();
|
||||
}
|
||||
catch (IOException) { throw; }
|
||||
catch (Exception) { throw; }
|
||||
|
||||
return _Json;
|
||||
}
|
||||
|
||||
throw new Exception("開檔失敗。");
|
||||
}
|
||||
|
||||
public static void Save(string filePath, string content) =>
|
||||
Save(new FileInfo(filePath), content);
|
||||
|
||||
public static void Save(FileInfo aFi, string aContent)
|
||||
{
|
||||
if (!aFi.Directory.Exists)
|
||||
{
|
||||
aFi.Directory.Create();
|
||||
}
|
||||
|
||||
if (aFi.Exists)
|
||||
{
|
||||
aFi.Delete();
|
||||
}
|
||||
|
||||
aFi.Refresh();
|
||||
if (aFi.Exists) throw new Exception("寫檔失敗,檔案已存在或已開啟。");
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllText(aFi.FullName, aContent);
|
||||
}
|
||||
catch (IOException) { throw; }
|
||||
catch (Exception) { throw; }
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Library/Helpers/UAC.cs
Normal file
18
Library/Helpers/UAC.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace CMM.Library.Helpers
|
||||
{
|
||||
public class UAC
|
||||
{
|
||||
public static void Check()
|
||||
{
|
||||
var identity = WindowsIdentity.GetCurrent();
|
||||
var principal = new WindowsPrincipal(identity);
|
||||
if (!principal.IsInRole(WindowsBuiltInRole.Administrator))
|
||||
throw new Exception($"Cannot delete task with your current identity '{identity.Name}' permissions level." +
|
||||
"You likely need to run this application 'as administrator' even if you are using an administrator account.");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Library/Library.csproj
Normal file
40
Library/Library.csproj
Normal file
@@ -0,0 +1,40 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RootNamespace>CMM.Library</RootNamespace>
|
||||
<Product>ControlMyMonitorManagement</Product>
|
||||
<UseWPF>true</UseWPF>
|
||||
<Company>Dang</Company>
|
||||
<Copyright>Copyright © DangWang $([System.DateTime]::Now.ToString(yyyy))</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<Major>1</Major>
|
||||
<Minor>0</Minor>
|
||||
<ProjectStartedDate>$([System.DateTime]::op_Subtraction($([System.DateTime]::get_Now().get_Date()),$([System.DateTime]::new(2017,9,17))).get_TotalDays())</ProjectStartedDate>
|
||||
<DaysSinceProjectStarted>$([System.DateTime]::Now.ToString(Hmm))</DaysSinceProjectStarted>
|
||||
<DateTimeSuffix>$([System.DateTime]::Now.ToString(yyyyMMdd))</DateTimeSuffix>
|
||||
<VersionSuffix>$(Major).$(Minor).$(ProjectStartedDate).$(DaysSinceProjectStarted)</VersionSuffix>
|
||||
<AssemblyVersion Condition=" '$(DateTimeSuffix)' == '' ">0.0.0.1</AssemblyVersion>
|
||||
<AssemblyVersion Condition=" '$(DateTimeSuffix)' != '' ">$(VersionSuffix)</AssemblyVersion>
|
||||
<Version Condition=" '$(DateTimeSuffix)' == '' ">0.0.0.1</Version>
|
||||
<Version Condition=" '$(DateTimeSuffix)' != '' ">$(DateTimeSuffix)</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resource\ControlMyMonitor.exe" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resource\ControlMyMonitor.exe">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Language\Language.csproj" />
|
||||
<ProjectReference Include="..\Tester\Tester.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
48
Library/Method/AssemblyData.cs
Normal file
48
Library/Method/AssemblyData.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.Method
|
||||
{
|
||||
public static class AssemblyData
|
||||
{
|
||||
/// <summary>
|
||||
/// 當下Assembly名稱
|
||||
/// </summary>
|
||||
public static string AssemblyName => System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
|
||||
|
||||
public static string AppName => AppDomain.CurrentDomain.FriendlyName;
|
||||
|
||||
/// <summary>
|
||||
/// 程式根目錄,無視工作目錄
|
||||
/// </summary>
|
||||
public static string Path => AppDomain.CurrentDomain.BaseDirectory;
|
||||
/// <summary>
|
||||
/// 版本
|
||||
/// </summary>
|
||||
public static string AssemblyVersion => GetAssemblyVersion();
|
||||
public static string AppVersion => GetFileVersion(Process.GetCurrentProcess().MainModule.FileName);
|
||||
/// <summary>
|
||||
/// CCM 輸出
|
||||
/// </summary>
|
||||
public static string smonitors => System.IO.Path.Combine(Path, "smonitors.tmp");
|
||||
|
||||
static string GetAssemblyVersion()
|
||||
{
|
||||
var fi = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase.Replace(@"file:///", "");
|
||||
return GetFileVersion(fi);
|
||||
}
|
||||
|
||||
public static string GetFileVersion(string filePath)
|
||||
{
|
||||
var fvi = FileVersionInfo.GetVersionInfo(filePath);
|
||||
return $"{fvi.FileMajorPart}." +
|
||||
$"{fvi.FileMinorPart}." +
|
||||
$"{fvi.FileBuildPart}." +
|
||||
$"{fvi.FilePrivatePart}";
|
||||
}
|
||||
}
|
||||
}
|
||||
177
Library/Method/CMMCommand.cs
Normal file
177
Library/Method/CMMCommand.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using CMM.Library.Base;
|
||||
using CMM.Library.Helpers;
|
||||
using CMM.Library.ViewModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.Method
|
||||
{
|
||||
/// <summary>
|
||||
/// Control My Monitor Management Command
|
||||
/// </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 CMMsMonitors = Path.Combine(CMMTmpFolder, "smonitors.tmp");
|
||||
static readonly string CMMcfg = Path.Combine(CMMTmpFolder, "ControlMyMonitor.cfg");
|
||||
|
||||
public static async Task ScanMonitor()
|
||||
{
|
||||
await BytesToFileAsync(new(CMMexe));
|
||||
await ConsoleHelper.CmdCommandAsync($"{CMMexe} /smonitors {CMMsMonitors}");
|
||||
}
|
||||
|
||||
public static async Task ScanMonitorInterfaces(IEnumerable<XMonitor> monitors)
|
||||
{
|
||||
var taskList = new List<Task>();
|
||||
foreach (var mon in monitors)
|
||||
{
|
||||
taskList.Add(Task.Run(async () => await
|
||||
ScanMonitorInterfaces($"{CMMTmpFolder}\\{mon.SerialNumber}.tmp", mon)));
|
||||
}
|
||||
|
||||
await Task.WhenAll(taskList.ToArray());
|
||||
}
|
||||
|
||||
static async Task ScanMonitorInterfaces(string savePath, XMonitor mon)
|
||||
{
|
||||
//await ConsoleHelper.CmdCommandAsync($"{CMMexe} /scomma {savePath} {mon.MonitorID}");
|
||||
await mon.ReadMonitorStatus(savePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取得螢幕狀態
|
||||
/// </summary>
|
||||
public static async Task ReadMonitorStatus(this XMonitor @this, string filePath)
|
||||
{
|
||||
var statusColle = new ObservableRangeCollection<XMonitorStatus>();
|
||||
|
||||
if (!File.Exists(filePath)) return;
|
||||
|
||||
foreach (var line in await File.ReadAllLinesAsync(filePath))
|
||||
{
|
||||
var sp = line.Split(",");
|
||||
if (sp.Length < 6) continue;
|
||||
|
||||
statusColle.Add(new XMonitorStatus
|
||||
{
|
||||
VCP_Code = StrTrim(sp[0]),
|
||||
VCPCodeName = StrTrim(sp[1]),
|
||||
Read_Write = StrTrim(sp[2]),
|
||||
CurrentValue = TryGetInt(sp[3]),
|
||||
MaximumValue = TryGetInt(sp[4]),
|
||||
PossibleValues = TryGetArrStr(sp),
|
||||
});
|
||||
}
|
||||
|
||||
@this.Status = statusColle;
|
||||
|
||||
string StrTrim(string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str)) return null;
|
||||
return str;
|
||||
}
|
||||
|
||||
string TryGetArrStr(string[] strArr)
|
||||
{
|
||||
if (strArr.Length < 7) return null;
|
||||
|
||||
var outStr = string.Join(",", strArr[5..]);
|
||||
outStr = outStr.Substring(1, outStr.Length - 2);
|
||||
return outStr;
|
||||
}
|
||||
|
||||
int? TryGetInt(string str)
|
||||
{
|
||||
if (int.TryParse(str, out var value)) return value;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取得螢幕清單
|
||||
/// </summary>
|
||||
public static async Task<IEnumerable<XMonitor>> ReadMonitorsData()
|
||||
{
|
||||
var monitors = new List<XMonitor>();
|
||||
|
||||
if (!File.Exists(CMMsMonitors)) return monitors;
|
||||
|
||||
XMonitor mon = null;
|
||||
string context;
|
||||
foreach (var line in await File.ReadAllLinesAsync(CMMsMonitors))
|
||||
{
|
||||
var sp = line.Split(":", StringSplitOptions.RemoveEmptyEntries);
|
||||
try
|
||||
{
|
||||
if (sp.Length != 2 || string.IsNullOrEmpty(sp[1])) continue;
|
||||
|
||||
context = sp[1].Substring(2, sp[1].Length - 3);
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sp[0].StartsWith("Monitor Device Name"))
|
||||
{
|
||||
mon = new XMonitor();
|
||||
mon.MonitorDeviceName = context;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sp[0].StartsWith("Monitor Name"))
|
||||
{
|
||||
mon.MonitorName = context;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sp[0].StartsWith("Serial Number"))
|
||||
{
|
||||
mon.SerialNumber = context;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sp[0].StartsWith("Adapter Name"))
|
||||
{
|
||||
mon.AdapterName = context;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sp[0].StartsWith("Monitor ID"))
|
||||
{
|
||||
mon.MonitorID = context;
|
||||
monitors.Add(mon);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
29
Library/Method/CMMMgr.cs
Normal file
29
Library/Method/CMMMgr.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using CMM.Library.Base;
|
||||
using CMM.Library.ViewModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.Method
|
||||
{
|
||||
public class CMMMgr : PropertyBase
|
||||
{
|
||||
public ObservableRangeCollection<XMonitor> Monitors
|
||||
{
|
||||
get => _Monitors;
|
||||
set { SetProperty(ref _Monitors, value); }
|
||||
}
|
||||
ObservableRangeCollection<XMonitor> _Monitors = new ();
|
||||
|
||||
public async Task Init()
|
||||
{
|
||||
await CMMCommand.ScanMonitor();
|
||||
var monColle = new ObservableRangeCollection<XMonitor>();
|
||||
monColle.AddRange(await CMMCommand.ReadMonitorsData());
|
||||
Monitors = monColle;
|
||||
await CMMCommand.ScanMonitorInterfaces(monColle);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Library/Resource/ControlMyMonitor.chm
Normal file
BIN
Library/Resource/ControlMyMonitor.chm
Normal file
Binary file not shown.
BIN
Library/Resource/ControlMyMonitor.exe
Normal file
BIN
Library/Resource/ControlMyMonitor.exe
Normal file
Binary file not shown.
393
Library/Resource/readme.txt
Normal file
393
Library/Resource/readme.txt
Normal file
@@ -0,0 +1,393 @@
|
||||
|
||||
|
||||
|
||||
ControlMyMonitor v1.35
|
||||
Copyright (c) 2017 - 2022 Nir Sofer
|
||||
Web site: https://www.nirsoft.net
|
||||
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
ControlMyMonitor allows you view and modify the settings of your monitor
|
||||
(Also known as 'VCP Features'), like brightness, contrast, sharpness,
|
||||
red/green/blue color balance, OSD Language, Input Port (VGA , DVI , HDMI
|
||||
) and more... You can modify the monitor settings from the GUI and from
|
||||
command-line. You can also export all settings of your monitor into a
|
||||
configuration file and then later load the same configuration back into
|
||||
your monitor.
|
||||
|
||||
|
||||
|
||||
System Requirements
|
||||
===================
|
||||
|
||||
|
||||
* Any version of Windows, starting from Windows Vista and up to Windows
|
||||
11.
|
||||
* Hardware that supports DDC/CI.
|
||||
|
||||
|
||||
|
||||
Versions History
|
||||
================
|
||||
|
||||
|
||||
* Version 1.35:
|
||||
o Added 4 display filter options: Display Read+Write, Display Read
|
||||
Only, Display Write Only, Display Manufacturer Specific.
|
||||
|
||||
* Version 1.31:
|
||||
o you can now use 'Secondary' as the monitor string in all
|
||||
command-line options in order to specify the secondary monitor.
|
||||
|
||||
* Version 1.30:
|
||||
o When there is a DDC/CI error (Error codes like 0xC0262582,
|
||||
0xC0262583), the error description is now displayed in the status bar
|
||||
in addition to the error code.
|
||||
o You can also click the error code with the mouse in order to copy
|
||||
the error code and error description to the clipboard.
|
||||
|
||||
* Version 1.29:
|
||||
o Added option to choose another font (name and size) to display in
|
||||
the main window.
|
||||
|
||||
* Version 1.28:
|
||||
o Fixed some display issues in high DPI mode (Toolbar and status
|
||||
bar).
|
||||
|
||||
* Version 1.27:
|
||||
o Added /TurnOff command-line option to turn off the specified
|
||||
monitor.
|
||||
o Added /TurnOn command-line option to turn on the specified
|
||||
monitor.
|
||||
o Added /SwitchOffOn command-line option to switch the specified
|
||||
monitor between on and off state.
|
||||
|
||||
* Version 1.26:
|
||||
o When ControlMyMonitor fails to get the current monitor settings,
|
||||
error code is now displayed in the status bar.
|
||||
|
||||
* Version 1.25:
|
||||
o Added 'Put Icon On Tray' option.
|
||||
|
||||
* Version 1.20:
|
||||
o Added /SwitchValue command-line option, which allows you to
|
||||
switch between multiple values.
|
||||
o For example, in order to switch the monitor off when it's turned
|
||||
on and switch it on when it's turned off, use the following command:
|
||||
(On some monitors you should use 4 instead of 5)
|
||||
ControlMyMonitor.exe /SwitchValue "\\.\DISPLAY1\Monitor0" D6 1 5
|
||||
|
||||
* Version 1.17:
|
||||
o When pressing F5 (Refresh) the refresh process is smoother,
|
||||
keeping the last selected item.
|
||||
o Added 'Load Selected Monitor On Start' option.
|
||||
|
||||
* Version 1.16:
|
||||
o Added /GetValue command-line option, which returns the current
|
||||
value of the specified VCP Code, for example:
|
||||
ControlMyMonitor.exe /GetValue "\\.\DISPLAY1\Monitor0" 10
|
||||
echo %errorlevel%
|
||||
|
||||
* Version 1.15:
|
||||
o Added /SetValueIfNeeded command-line option, which sets a value
|
||||
only if the current value is different from the value you want to set.
|
||||
|
||||
* Version 1.12:
|
||||
o Added 'Add Header Line To CSV/Tab-Delimited File' option (Turned
|
||||
on by default).
|
||||
|
||||
* Version 1.11:
|
||||
o Added /smonitors command-line option to save the monitors list
|
||||
into a text file.
|
||||
o Added 'Save All Items' option (Shift+Ctrl+S).
|
||||
|
||||
* Version 1.10:
|
||||
o Added save command-line options (/scomma, /stab , /shtml, and so
|
||||
on...) to export the current monitor settings into a file.
|
||||
o Added support for JSON file in 'Save Selected Items' option.
|
||||
|
||||
* Version 1.05:
|
||||
o Added 'Refresh Monitors List' option (Ctrl+F5).
|
||||
|
||||
* Version 1.00 - First release.
|
||||
|
||||
|
||||
|
||||
Start Using ControlMyMonitor
|
||||
============================
|
||||
|
||||
ControlMyMonitor doesn't require any installation process or additional
|
||||
DLL files. In order to start using it simply run the executable file -
|
||||
ControlMyMonitor.exe
|
||||
|
||||
After running ControlMyMonitor, the current settings of your monitor are
|
||||
displayed in the main window. If you have multiple monitors, you can
|
||||
choose another monitor from the monitor combo-box below the toolbar.
|
||||
In order to modify a single item, select the item that you want to
|
||||
change, and then double click the item (or press the F6 key). You can
|
||||
also increase or decrease the current value by using the 'Increase Value'
|
||||
or 'Decrease Value' options (Under the Action menu). You can also
|
||||
increase/decrease values by using the mouse wheel, according to the
|
||||
selected option in Options -> Change Value With Mouse Wheel. By default,
|
||||
the mouse wheel feature is active when you hold down the Ctrl key.
|
||||
|
||||
|
||||
|
||||
Restore Factory Defaults
|
||||
========================
|
||||
|
||||
There are some write-only items that allow you to restore the factory
|
||||
defaults of the monitor. In order to activate these items, you have to
|
||||
set the value to 1.
|
||||
|
||||
|
||||
|
||||
Save/Load Config
|
||||
================
|
||||
|
||||
ControlMyMonitor allows you to export all read/write properties into a
|
||||
simple text file and then later load these properties back to the
|
||||
monitor. You can find the save/load config feature under the File menu
|
||||
('Save Monitor Config' and 'Load Monitor Config').
|
||||
|
||||
|
||||
|
||||
Error 0xc0262582, 0xc0262583 and similar codes
|
||||
==============================================
|
||||
|
||||
If you get error 0xc0262582 (or similar codes) and the main window of
|
||||
ControlMyMonitor is empty, it means that Windows operating system cannot
|
||||
connect your monitor using DDC/CI.
|
||||
Here's what you can do in order to try to solve the problem:
|
||||
* Update the driver of your graphics card.
|
||||
* Try to plug your monitor using different type of cable/connector
|
||||
(VGA, DVI, HDMI, DisplayPort).
|
||||
* If you use a KVM switch, try to plug your monitor directly to the
|
||||
computer, without the KVM switch.
|
||||
|
||||
|
||||
|
||||
|
||||
Before you report a bug...
|
||||
==========================
|
||||
|
||||
Be aware that if you have a specific setting that ControlMyMonitor fails
|
||||
to set properly or ControlMyMonitor fails to connect your monitor
|
||||
completely with error code (usually begins with 0xc02625 ), It's not a
|
||||
bug or problem in ControlMyMonitor tool, but in your hardware.
|
||||
It might be a bug with the chip of your monitor or with the driver of
|
||||
your graphics card or a problem with the cable/connector you use. As a
|
||||
programmer of ControlMyMonitor, I cannot help you to debug or fix these
|
||||
hardware problems. You can try to contact the manufacturers of your
|
||||
hardware and ask them to solve the problem.
|
||||
|
||||
|
||||
|
||||
Command-Line Options
|
||||
====================
|
||||
|
||||
You can use 'Primary' as your monitor string in all command-line options
|
||||
in order to specify the primary monitor. You can also use 'Secondary' as
|
||||
your monitor string in all command-line options in order to specify the
|
||||
secondary monitor.
|
||||
If you have multiple monitors, you have to find a string that uniquely
|
||||
identifies your monitor. Open ControlMyMonitor , select the desired
|
||||
monitor and then press Ctrl+M (Copy Monitor Settings). Paste the string
|
||||
from the clipboard into notepad or other text editor. You'll see
|
||||
something like this:
|
||||
|
||||
Monitor Device Name: "\\.\DISPLAY1\Monitor0"
|
||||
Monitor Name: "22EA53"
|
||||
Serial Number: "402CFEZE1200"
|
||||
Adapter Name: "Intel(R) HD Graphics"
|
||||
Monitor ID: "MONITOR\GSM59A4\{4d36e96e-e325-11ce-bfc1-08002be10318}\0012"
|
||||
|
||||
You can use any string from this list as long as the other monitors on
|
||||
your system have different values for the same property.
|
||||
|
||||
|
||||
|
||||
/SetValue <Monitor String> <VCP Code> <Value>
|
||||
Sets the value of the specified VCP Code for the specified monitor.
|
||||
|
||||
Here's some examples:
|
||||
|
||||
Set the brightness of primary monitor to 70:
|
||||
ControlMyMonitor.exe /SetValue Primary 10 70
|
||||
|
||||
Set the contrast of the monitor with serial number 102ABC335 to 65:
|
||||
ControlMyMonitor.exe /SetValue "102ABC335" 12 65
|
||||
|
||||
Restore factory defaults to the \\.\DISPLAY1\Monitor0 monitor:
|
||||
ControlMyMonitor.exe /SetValue "\\.\DISPLAY1\Monitor0" 04 1
|
||||
|
||||
Turn on the \\.\DISPLAY2\Monitor0 monitor:
|
||||
ControlMyMonitor.exe /SetValue "\\.\DISPLAY2\Monitor0" D6 1
|
||||
|
||||
Turn off the \\.\DISPLAY2\Monitor0 monitor: (On some monitors you should
|
||||
set the value to 4 instead of 5)
|
||||
ControlMyMonitor.exe /SetValue "\\.\DISPLAY2\Monitor0" D6 5
|
||||
|
||||
Change the input source of \\.\DISPLAY3\Monitor0 monitor:
|
||||
ControlMyMonitor.exe /SetValue "\\.\DISPLAY3\Monitor0" 60 3
|
||||
|
||||
/SetValueIfNeeded <Monitor String> <VCP Code> <Value>
|
||||
This command is similar to /SetValue , but it actually sets the value
|
||||
only if the current value is different from the specified value.
|
||||
|
||||
/ChangeValue <Monitor String> <VCP Code> <Value>
|
||||
Increases/decreases the value of the specified VCP Code for the specified
|
||||
monitor.
|
||||
|
||||
Here's some examples:
|
||||
|
||||
Increase the brightness of the secondary monitor by 5%:
|
||||
ControlMyMonitor.exe /ChangeValue Secondary 10 5
|
||||
|
||||
Decrease the contrast of the \\.\DISPLAY1\Monitor0 monitor by 5%:
|
||||
ControlMyMonitor.exe /ChangeValue "\\.\DISPLAY1\Monitor0" 12 -5
|
||||
|
||||
/SwitchValue <Monitor String> <VCP Code> <Value1> <Value2> <Value3>...
|
||||
Switch between the specified 2 or more values.
|
||||
|
||||
For example, this command switches the monitor between off (5) and on (1)
|
||||
state:
|
||||
ControlMyMonitor.exe /SwitchValue "\\.\DISPLAY1\Monitor0" D6 1 5
|
||||
|
||||
The following command switches between 3 brightness values - 30%, 50%,
|
||||
90% :
|
||||
ControlMyMonitor.exe /SwitchValue "\\.\DISPLAY1\Monitor0" 10 30 50 90
|
||||
|
||||
/GetValue <Monitor String> <VCP Code>
|
||||
Return the value of the specified VCP Code for the specified monitor.
|
||||
|
||||
Example for batch file:
|
||||
ControlMyMonitor.exe /GetValue "\\.\DISPLAY1\Monitor0" 10
|
||||
echo %errorlevel%
|
||||
|
||||
/TurnOff <Monitor String>
|
||||
Turn off the specified monitor.
|
||||
|
||||
Example:
|
||||
ControlMyMonitor.exe /TurnOff "\\.\DISPLAY3\Monitor0"
|
||||
|
||||
/TurnOn <Monitor String>
|
||||
Turn on the specified monitor.
|
||||
|
||||
Example:
|
||||
ControlMyMonitor.exe /TurnOn "\\.\DISPLAY1\Monitor0"
|
||||
|
||||
/SwitchOffOn <Monitor String>
|
||||
Switch the specified monitor between on and off state.
|
||||
|
||||
Example:
|
||||
ControlMyMonitor.exe /SwitchOffOn "\\.\DISPLAY2\Monitor0"
|
||||
|
||||
/SaveConfig <Filename> <Monitor String>
|
||||
Saves all read+write values of the specified monitor into a file.
|
||||
For example:
|
||||
ControlMyMonitor.exe /SaveConfig "c:\temp\mon1.cfg" Primary
|
||||
ControlMyMonitor.exe /SaveConfig "c:\temp\mon1.cfg"
|
||||
"\\.\DISPLAY2\Monitor0"
|
||||
|
||||
/LoadConfig <Filename> <Monitor String>
|
||||
Loads all values stored in configuration file into the specified monitor.
|
||||
For example:
|
||||
ControlMyMonitor.exe /LoadConfig "c:\temp\mon1.cfg" Primary
|
||||
ControlMyMonitor.exe /LoadConfig "c:\temp\mon1.cfg"
|
||||
"\\.\DISPLAY2\Monitor0"
|
||||
|
||||
/stext <Filename> <Monitor String>
|
||||
Save the current monitor settings into a simple text file.
|
||||
|
||||
/stab <Filename> <Monitor String>
|
||||
Save the current monitor settings into a tab-delimited text file.
|
||||
|
||||
/scomma <Filename> <Monitor String>
|
||||
Save the current monitor settings into a comma-delimited text file (csv).
|
||||
|
||||
/shtml <Filename> <Monitor String>
|
||||
Save the current monitor settings into HTML file (Horizontal).
|
||||
|
||||
/sverhtml <Filename> <Monitor String>
|
||||
Save the current monitor settings into HTML file (Vertical).
|
||||
|
||||
/sxml <Filename> <Monitor String>
|
||||
Save the current monitor settings into XML file.
|
||||
|
||||
/sjson <Filename> <Monitor String>
|
||||
Save the current monitor settings into JSON file.
|
||||
|
||||
/smonitors <Filename>
|
||||
Save the current monitors list into a simple text file.
|
||||
|
||||
For all save command-line options, you can specify empty filename in
|
||||
order to send the data to stdout, for example:
|
||||
ControlMyMonitor.exe /scomma "" | more
|
||||
|
||||
|
||||
|
||||
Get value of the specified VCP Code using GetNir tool
|
||||
=====================================================
|
||||
|
||||
There is also an option to get the current value of the specified VCP
|
||||
Code with GetNir tool. The value is sent to stdout.
|
||||
For example, the following command sends the current monitor brightness
|
||||
to stdout:
|
||||
ControlMyMonitor.exe /stab "" | GetNir "Current Value" "VCPCode=10"
|
||||
|
||||
|
||||
|
||||
Translating ControlMyMonitor to other languages
|
||||
===============================================
|
||||
|
||||
In order to translate ControlMyMonitor to other language, follow the
|
||||
instructions below:
|
||||
1. Run ControlMyMonitor with /savelangfile parameter:
|
||||
ControlMyMonitor.exe /savelangfile
|
||||
A file named ControlMyMonitor_lng.ini will be created in the folder of
|
||||
ControlMyMonitor utility.
|
||||
2. Open the created language file in Notepad or in any other text
|
||||
editor.
|
||||
3. Translate all string entries to the desired language. Optionally,
|
||||
you can also add your name and/or a link to your Web site.
|
||||
(TranslatorName and TranslatorURL values) If you add this information,
|
||||
it'll be used in the 'About' window.
|
||||
4. After you finish the translation, Run ControlMyMonitor, and all
|
||||
translated strings will be loaded from the language file.
|
||||
If you want to run ControlMyMonitor without the translation, simply
|
||||
rename the language file, or move it to another folder.
|
||||
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This utility is released as freeware. You are allowed to freely
|
||||
distribute this utility via floppy disk, CD-ROM, Internet, or in any
|
||||
other way, as long as you don't charge anything for this and you don't
|
||||
sell it or distribute it as a part of commercial product. If you
|
||||
distribute this utility, you must include all files in the distribution
|
||||
package, without any modification !
|
||||
|
||||
|
||||
|
||||
Disclaimer
|
||||
==========
|
||||
|
||||
The software is provided "AS IS" without any warranty, either expressed
|
||||
or implied, including, but not limited to, the implied warranties of
|
||||
merchantability and fitness for a particular purpose. The author will not
|
||||
be liable for any special, incidental, consequential or indirect damages
|
||||
due to loss of data or any other reason.
|
||||
|
||||
|
||||
|
||||
Feedback
|
||||
========
|
||||
|
||||
If you have any problem, suggestion, comment, or you found a bug in my
|
||||
utility, you can send a message to nirsofer@yahoo.com
|
||||
72
Library/ViewModel/XMonitor.cs
Normal file
72
Library/ViewModel/XMonitor.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using CMM.Library.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.ViewModel
|
||||
{
|
||||
public class XMonitor : PropertyBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 裝置路徑
|
||||
/// </summary>
|
||||
public string MonitorDeviceName
|
||||
{
|
||||
get => _MonitorDeviceName;
|
||||
set { SetProperty(ref _MonitorDeviceName, value); }
|
||||
}
|
||||
string _MonitorDeviceName;
|
||||
|
||||
/// <summary>
|
||||
/// 裝置名稱
|
||||
/// </summary>
|
||||
public string MonitorName
|
||||
{
|
||||
get => _MonitorName;
|
||||
set { SetProperty(ref _MonitorName, value); }
|
||||
}
|
||||
string _MonitorName;
|
||||
|
||||
/// <summary>
|
||||
/// 裝置序號
|
||||
/// </summary>
|
||||
public string SerialNumber
|
||||
{
|
||||
get => _SerialNumber;
|
||||
set { SetProperty(ref _SerialNumber, value); }
|
||||
}
|
||||
string _SerialNumber;
|
||||
|
||||
/// <summary>
|
||||
/// 訊號裝置
|
||||
/// </summary>
|
||||
public string AdapterName
|
||||
{
|
||||
get => _AdapterName;
|
||||
set { SetProperty(ref _AdapterName, value); }
|
||||
}
|
||||
string _AdapterName;
|
||||
|
||||
/// <summary>
|
||||
/// 裝置識別碼
|
||||
/// </summary>
|
||||
public string MonitorID
|
||||
{
|
||||
get => _MonitorID;
|
||||
set { SetProperty(ref _MonitorID, value); }
|
||||
}
|
||||
string _MonitorID;
|
||||
|
||||
/// <summary>
|
||||
/// 狀態
|
||||
/// </summary>
|
||||
public ObservableRangeCollection<XMonitorStatus> Status
|
||||
{
|
||||
get => _Status;
|
||||
set { SetProperty(ref _Status, value); }
|
||||
}
|
||||
ObservableRangeCollection<XMonitorStatus> _Status = new();
|
||||
}
|
||||
}
|
||||
54
Library/ViewModel/XMonitorStatus.cs
Normal file
54
Library/ViewModel/XMonitorStatus.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using CMM.Library.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.ViewModel
|
||||
{
|
||||
public class XMonitorStatus : PropertyBase
|
||||
{
|
||||
public string VCP_Code
|
||||
{
|
||||
get => _VCP_Code;
|
||||
set { SetProperty(ref _VCP_Code, value); }
|
||||
}
|
||||
string _VCP_Code;
|
||||
|
||||
public string VCPCodeName
|
||||
{
|
||||
get => _VCPCodeName;
|
||||
set { SetProperty(ref _VCPCodeName, value); }
|
||||
}
|
||||
string _VCPCodeName;
|
||||
|
||||
public string Read_Write
|
||||
{
|
||||
get => _Read_Write;
|
||||
set { SetProperty(ref _Read_Write, value); }
|
||||
}
|
||||
string _Read_Write;
|
||||
|
||||
public int? CurrentValue
|
||||
{
|
||||
get => _CurrentValue;
|
||||
set { SetProperty(ref _CurrentValue, value); }
|
||||
}
|
||||
int? _CurrentValue;
|
||||
|
||||
public int? MaximumValue
|
||||
{
|
||||
get => _MaximumValue;
|
||||
set { SetProperty(ref _MaximumValue, value); }
|
||||
}
|
||||
int? _MaximumValue;
|
||||
|
||||
public string PossibleValues
|
||||
{
|
||||
get => _PossibleValues;
|
||||
set { SetProperty(ref _PossibleValues, value); }
|
||||
}
|
||||
string _PossibleValues;
|
||||
}
|
||||
}
|
||||
44
Library/WinAPI/Blur.cs
Normal file
44
Library/WinAPI/Blur.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMM.Library.WinAPI
|
||||
{
|
||||
#region 透明背景
|
||||
public enum AccentState
|
||||
{
|
||||
ACCENT_DISABLED = 0,
|
||||
ACCENT_ENABLE_GRADIENT = 1,
|
||||
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
|
||||
ACCENT_ENABLE_BLURBEHIND = 3,
|
||||
ACCENT_INVALID_STATE = 4
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct AccentPolicy
|
||||
{
|
||||
public AccentState AccentState;
|
||||
public int AccentFlags;
|
||||
public int GradientColor;
|
||||
public int AnimationId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WindowCompositionAttributeData
|
||||
{
|
||||
public WindowCompositionAttribute Attribute;
|
||||
public IntPtr Data;
|
||||
public int SizeOfData;
|
||||
}
|
||||
|
||||
public enum WindowCompositionAttribute
|
||||
{
|
||||
// ...
|
||||
WCA_ACCENT_POLICY = 19
|
||||
// ...
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
50
Library/WinAPI/Win32Api.cs
Normal file
50
Library/WinAPI/Win32Api.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace CMM.Library.WinAPI
|
||||
{
|
||||
public static class Win32
|
||||
{
|
||||
public const int WM_SETTEXT = 0x000C;
|
||||
public const int WM_CLICK = 0x00F5;
|
||||
public const int CHILDID_SELF = 0;
|
||||
public const int CHILDID_1 = 1;
|
||||
public const int OBJID_CLIENT = -4;
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowText", CharSet = CharSet.Unicode)]
|
||||
public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int cch);
|
||||
[DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
|
||||
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
|
||||
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
|
||||
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
|
||||
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, StringBuilder lParam);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern int PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetWindowRect(IntPtr hwnd, out Rectangle lpRect);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
|
||||
|
||||
public static bool IsUAC()
|
||||
{
|
||||
var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
|
||||
return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user