mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-21 00:01:48 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e8e77d89b | ||
|
|
18f32e1d46 | ||
|
|
4ed670c01b | ||
|
|
9a9424f1af | ||
|
|
27bc0505b7 | ||
|
|
4f4ce54ade | ||
|
|
b9db10262b | ||
|
|
b8d64c7322 | ||
|
|
fbd25f46b7 | ||
|
|
0c86466d7f | ||
|
|
fd5a2aa7fe | ||
|
|
bc162af76e | ||
|
|
dd3a996172 | ||
|
|
ab2ca92827 | ||
|
|
f08dcb7661 | ||
|
|
b1120c8d49 | ||
|
|
c958e6cb04 | ||
|
|
5611c1bea7 | ||
|
|
6b3b0b4b17 | ||
|
|
bc565abd38 | ||
|
|
db19a9ad68 | ||
|
|
9fd8e8f9bb | ||
|
|
6eae7db459 | ||
|
|
2c5b08af72 | ||
|
|
3c5c2b3e4e | ||
|
|
c6f9bedcd2 | ||
|
|
de3a1a6e72 | ||
|
|
966b8336de | ||
|
|
bc102334c8 | ||
|
|
4186d4add5 | ||
|
|
e0d1ba13f0 | ||
|
|
21bd8e2080 | ||
|
|
3086058ebe | ||
|
|
464da6ccb8 | ||
|
|
7e1eb8bfa8 | ||
|
|
04d447a48b | ||
|
|
3ef21278cd | ||
|
|
3d7abd991c | ||
|
|
97b931f433 | ||
|
|
7543cca15d | ||
|
|
58e03313e0 | ||
|
|
fa013b056f | ||
|
|
8c186679cf |
No files matched your search
@@ -0,0 +1,40 @@
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.Services;
|
||||
|
||||
namespace ColorControl.UI;
|
||||
|
||||
public static class Blazor
|
||||
{
|
||||
public static void Start(Config? config = null)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorComponents()
|
||||
.AddInteractiveServerComponents();
|
||||
|
||||
builder.Services.AddSingleton<AppState>(new AppState { SelectedTheme = (config?.UseDarkMode ?? true) ? "dark" : "light" });
|
||||
builder.Services.AddTransient<RpcUiClientService>();
|
||||
builder.WebHost.ConfigureKestrel(o => o.ListenAnyIP(config?.UiPort > 0 ? config.UiPort : 5000));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseStaticFiles();
|
||||
app.UseAntiforgery();
|
||||
|
||||
app.MapRazorComponents<Components.App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
|
||||
app.Run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NLog" Version="5.2.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="Components\Pages\Generic\FieldDefs.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Generic\ConfirmModal.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Game\GameSummary.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Generic\TriggerInput.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Info.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\LG\LgExecuteActionModal.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Samsung\SamsungSummary.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Nvidia\NvidiaSettings.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Nvidia\NvidiaPreset.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Samsung\SamsungDevicePage.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Generic\StepsInput.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
<Content Update="Components\Pages\Samsung\SamsungServiceMenu.razor">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,50 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services
|
||||
@inject AppState AppState
|
||||
@inject RpcUiClientService ClientService;
|
||||
@inject NavigationManager _navigationManager;
|
||||
@implements IDisposable
|
||||
@attribute [StreamRendering]
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="@AppState.SelectedTheme">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="/" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="app.css" />
|
||||
<link rel="stylesheet" href="ColorControl.UI.styles.css" />
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<HeadOutlet />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<Routes />
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@code {
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var config = await ClientService.CallAsync<Config>("OptionsService", "GetConfig");
|
||||
|
||||
var newTheme = config.UseDarkMode ? "dark" : "light";
|
||||
|
||||
if (newTheme != AppState.SelectedTheme)
|
||||
{
|
||||
AppState.SelectedTheme = config.UseDarkMode ? "dark" : "light";
|
||||
_navigationManager.Refresh();
|
||||
}
|
||||
|
||||
AppState.OnChange += StateHasChanged;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
AppState.OnChange -= StateHasChanged;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<div class="page">
|
||||
<div class="sidebar">
|
||||
<NavMenu />
|
||||
</div>
|
||||
|
||||
<main>
|
||||
<TopMenu />
|
||||
|
||||
<article class="content px-4">
|
||||
@Body
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
An unhandled error has occurred.
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
@@ -0,0 +1,96 @@
|
||||
.page {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
background-image: linear-gradient(180deg, rgb(0, 40, 90) 0%, #101047 70%);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
justify-content: flex-end;
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
white-space: nowrap;
|
||||
margin-left: 1.5rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.top-row ::deep a:first-child {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (max-width: 640.98px) {
|
||||
.top-row {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.top-row ::deep a, .top-row ::deep .btn-link {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.page {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.top-row.auth ::deep a:first-child {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.top-row, article {
|
||||
padding-left: 2rem !important;
|
||||
padding-right: 1.5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
left: 0;
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="top-row ps-3 navbar navbar-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="">ColorControl Web App</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
|
||||
|
||||
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
|
||||
<nav class="flex-column">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link px-3" href="" Match="NavLinkMatch.All">
|
||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
@if (modules != null)
|
||||
{
|
||||
@foreach (var module in modules.Where(m => m.IsActive))
|
||||
{
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link px-3" href="@module.Link">
|
||||
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> @module.DisplayName
|
||||
</NavLink>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link px-3" href="options">
|
||||
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Options
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link px-3" href="logging">
|
||||
<span class="bi bi-list-logging-nav-menu" aria-hidden="true"></span> Logging
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link px-3" href="info">
|
||||
<span class="bi bi-list-logging-nav-menu" aria-hidden="true"></span> Info
|
||||
</NavLink>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private Config? config;
|
||||
private List<ModuleDto>? modules;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
config = await _rpcClientService.CallAsync<Config>("OptionsService", "GetConfig");
|
||||
modules = config?.Modules?.Select(m => new ModuleDto { DisplayName = m.DisplayName, IsActive = m.IsActive, Link = m.DisplayName.Split(' ')[0] }).ToList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
.navbar-toggler {
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
width: 3.5rem;
|
||||
height: 2.5rem;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 1rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.navbar-toggler:checked {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.bi {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin-right: 0.75rem;
|
||||
top: -1px;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bi-house-door-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-plus-square-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-nested-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-logging-nav-menu {
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-card-text" viewBox="0 0 16 16"><path d="M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2z"/><path d="M3 5.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5M3 8a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 8m0 2.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5"/></svg>');
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link {
|
||||
color: #d7d7d7;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-toggler:checked ~ .nav-scrollable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<div class="top-row px-4 pt-3 text-end">
|
||||
@* <button type="button" class="btn btn-primary me-2" @onclick="ChangeTheme">@ThemeTransitionName</button> *@
|
||||
<a href="https://github.com/Maassoft/ColorControl" target="_blank">GitHub</a>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
private string ThemeTransitionName = "Dark";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ThemeTransitionName = AppState.SelectedTheme == "light" ? "Dark theme" : "Light theme";
|
||||
}
|
||||
|
||||
private void ChangeTheme()
|
||||
{
|
||||
AppState.SetTheme(AppState.SelectedTheme == "light" ? "dark" : "light");
|
||||
ThemeTransitionName = AppState.SelectedTheme == "light" ? "Dark theme" : "Light theme";
|
||||
_navigationManager.Refresh();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
.navbar-toggler {
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
width: 3.5rem;
|
||||
height: 2.5rem;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
right: 1rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.navbar-toggler:checked {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.bi {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin-right: 0.75rem;
|
||||
top: -1px;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bi-house-door-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-plus-square-fill-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.bi-list-nested-nav-menu {
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.nav-item:first-of-type {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.nav-item:last-of-type {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link {
|
||||
color: #d7d7d7;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
height: 3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-item ::deep a.active {
|
||||
background-color: rgba(255,255,255,0.37);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-item ::deep .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navbar-toggler:checked ~ .nav-scrollable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 641px) {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav-scrollable {
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
|
||||
/* Allow sidebar to scroll for tall menus */
|
||||
height: calc(100vh - 3.5rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.AMD
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<div class="modal" id="presetModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" @onfocus="ModalOnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Preset?.IsDisplayPreset == true ? $"Settings for display {Preset?.displayName}" : Preset?.id == 0 ? $"Settings for new preset" : $"Settings of preset {Preset?.IdOrName}")</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1 needs-validation @WasValidated" novalidate>
|
||||
@if (Preset == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">Name</label>
|
||||
<input class="form-control" type="text" @bind="Preset.name" required />
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.ShowInQuickAccess" id="showInQuickAccess">
|
||||
<label class="form-check-label" for="showInQuickAccess">
|
||||
Show in Quick Access
|
||||
</label>
|
||||
</div>
|
||||
<ShortcutInput Label="Shortcut" @bind-Shortcut="Preset.shortcut" />
|
||||
}
|
||||
<div class="accordion accordion-flush" id="presetAccordion">
|
||||
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem; visibility: hidden" type="checkbox">
|
||||
}
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#displaySettings">
|
||||
Display
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="displaySettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.primaryDisplay" id="primaryDisplay">
|
||||
<label class="form-check-label" for="primaryDisplay">
|
||||
Primary display
|
||||
</label>
|
||||
</div>
|
||||
@if (displayPresets != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="mode">Display</label>
|
||||
<select class="form-select" id="mode" @bind="Preset.DisplayId" disabled="@(Preset.primaryDisplay)">
|
||||
@foreach (var display in displayPresets)
|
||||
{
|
||||
<option value="@display.DisplayId">@display.displayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.DisplayConfig.IsPrimary" id="setAsPrimaryDisplay" disabled="@(Preset.primaryDisplay)">
|
||||
<label class="form-check-label" for="setAsPrimaryDisplay">
|
||||
Set display as primary display
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (resolutions != null)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.DisplayConfig.ApplyResolution" id="applyResolution">
|
||||
}
|
||||
<button class="accordion-button py-2 @(!Preset.IsDisplayPreset ? "collapsed" : "") @(Preset.DisplayConfig.ApplyResolution ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#resolutionSettings">
|
||||
Resolution
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="resolutionSettings" class="accordion-collapse collapse @(Preset.IsDisplayPreset ? "show" : "")" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
@if (resolutions != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="activeResolution">Active resolution</label>
|
||||
<select class="form-select" id="activeResolution" @bind="selectedActiveResolution">
|
||||
@foreach (var resolution in resolutions)
|
||||
{
|
||||
<option value="@resolution.GetActiveString()">@resolution.GetActiveString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="virtualResolution">Virtual resolution</label>
|
||||
<select class="form-select" id="virtualResolution" @bind="selectedVirtualResolution">
|
||||
@foreach (var resolution in resolutions)
|
||||
{
|
||||
<option value="@resolution.GetVirtualString()">@resolution.GetVirtualString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="scaling">Scaling/Aspect ratio</label>
|
||||
<select class="form-select" id="scaling" @bind="Preset.DisplayConfig.Scaling">
|
||||
@foreach (var scaling in Enum.GetValues<Shared.Native.CCD.DisplayConfigScaling>())
|
||||
{
|
||||
<option value="@scaling.ToString()">@scaling.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="rotation">Rotation</label>
|
||||
<select class="form-select" id="rotation" @bind="Preset.DisplayConfig.Rotation">
|
||||
@foreach (var rotation in Enum.GetValues<Shared.Native.CCD.DisplayConfigRotation>())
|
||||
{
|
||||
<option value="@rotation.ToString()">@rotation.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (refreshRates != null)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.DisplayConfig.ApplyRefreshRate" id="applyRefreshRate">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.DisplayConfig.ApplyRefreshRate ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#refreshRateSettings">
|
||||
Refresh Rate
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="refreshRateSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="refreshRate">Refresh Rate</label>
|
||||
<select class="form-select" id="refreshRate" @bind="selectedRefreshRate">
|
||||
@foreach (var refreshRate in refreshRates)
|
||||
{
|
||||
<option value="@refreshRate.ToString()">@refreshRate.ToString() Hz</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyColorData" id="applyColorData">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyColorData ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#colorSettings">
|
||||
Color settings
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="colorSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="bitDepth">Bit depth</label>
|
||||
<select class="form-select" id="bitDepth" @bind="Preset.colorDepth">
|
||||
@foreach (var bitDepth in Enum.GetValues<ADLColorDepth>())
|
||||
{
|
||||
<option value="@bitDepth.ToString()">@bitDepth.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="colorFormat">Format</label>
|
||||
<select class="form-select" id="colorFormat" @bind="Preset.pixelFormat">
|
||||
@foreach (var format in Enum.GetValues<ADLPixelFormat>())
|
||||
{
|
||||
<option value="@format.ToString()">@format.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyDithering" id="applyDithering">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyDithering ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#ditherSettings">
|
||||
Dithering
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="ditherSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="state">State</label>
|
||||
<select class="form-select" id="state" @bind="Preset.ditherState">
|
||||
@foreach (var state in Enum.GetValues<ADLDitherState>())
|
||||
{
|
||||
<option value="@state.ToString()">@state.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyHDR" id="applyHDR">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyHDR ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#hdrSettings">
|
||||
HDR
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="hdrSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.HDREnabled" id="hdrEnabled">
|
||||
<label class="form-check-label" for="hdrEnabled">
|
||||
HDR enabled
|
||||
</label>
|
||||
</div>
|
||||
@if (!Preset.IsDisplayPreset) {
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.toggleHDR" id="toggleHdr">
|
||||
<label class="form-check-label" for="toggleHdr">
|
||||
Toggle HDR
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<div class="mb-2">
|
||||
<label class="form-range" for="sdrBrightness">SDR brightness (@Preset.SDRBrightness%)</label>
|
||||
<input class="form-range" type="range" min="0" max="100" @bind="Preset.SDRBrightness" id="sdrBrightness">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="submit" class="btn btn-primary" data-bs-dismiss="@(IsValid() ? "modal" : "")" @onclick="ApplyClick">@(Preset?.IsDisplayPreset == true ? "Apply" : "Save")</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
public AmdPreset? Preset { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public AmdPreset? PresetParam { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<AmdPreset, Task>? AfterApply { get; set; }
|
||||
|
||||
private string? selectedActiveResolution;
|
||||
private string? selectedVirtualResolution;
|
||||
private string? selectedRefreshRate;
|
||||
|
||||
private List<VirtualResolution>? resolutions;
|
||||
private List<Rational>? refreshRates;
|
||||
private List<AmdPreset>? displayPresets;
|
||||
|
||||
private string WasValidated = "";
|
||||
private bool IsVisible;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
Preset = PresetParam == null ? null : PresetParam.CloneWithId();
|
||||
if (Preset != null && PresetParam != null)
|
||||
{
|
||||
resolutions = await _rpcClientService.CallAsync<List<VirtualResolution>>("AmdService", "GetAvailableResolutionsV2", Preset);
|
||||
refreshRates = await _rpcClientService.CallAsync<List<Rational>>("AmdService", "GetAvailableRefreshRatesV2", Preset);
|
||||
}
|
||||
selectedActiveResolution = Preset?.DisplayConfig.Resolution?.GetActiveString();
|
||||
selectedVirtualResolution = Preset?.DisplayConfig.Resolution?.GetVirtualString();
|
||||
selectedRefreshRate = Preset?.DisplayConfig.RefreshRate?.ToString();
|
||||
|
||||
if (Preset?.IsDisplayPreset != true)
|
||||
{
|
||||
displayPresets = await _rpcClientService.CallAsync<List<AmdPreset>>("AmdService", "GetDisplayPresets");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
WasValidated = "was-validated";
|
||||
return;
|
||||
}
|
||||
|
||||
var newResolution = resolutions?.FirstOrDefault(r => r.GetActiveString() == selectedActiveResolution);
|
||||
if (newResolution != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(selectedVirtualResolution) && selectedActiveResolution != selectedVirtualResolution)
|
||||
{
|
||||
newResolution = new VirtualResolution(newResolution.ActiveWidth, newResolution.ActiveHeight);
|
||||
var parts = selectedVirtualResolution.Split('x');
|
||||
newResolution.VirtualWidth = uint.Parse(parts[0]);
|
||||
newResolution.VirtualHeight = uint.Parse(parts[1]);
|
||||
}
|
||||
Preset.DisplayConfig.Resolution = newResolution;
|
||||
}
|
||||
|
||||
var newRefreshRate = refreshRates?.FirstOrDefault(r => r.ToString() == selectedRefreshRate);
|
||||
if (newRefreshRate != null)
|
||||
{
|
||||
Preset.DisplayConfig.RefreshRate = newRefreshRate;
|
||||
}
|
||||
|
||||
if (Preset.IsDisplayPreset)
|
||||
{
|
||||
Preset.UpdateAutoApplySettings(PresetParam);
|
||||
|
||||
await ApplyDisplayPreset();
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("AmdService", "UpdatePreset", Preset);
|
||||
|
||||
if (AfterApply != null)
|
||||
{
|
||||
await AfterApply.Invoke(Preset);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyDisplayPreset()
|
||||
{
|
||||
var result = await _rpcClientService.CallAsync<bool>("AmdService", "ApplyPreset", Preset);
|
||||
}
|
||||
|
||||
private void ModalOnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
WasValidated = "";
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValid()
|
||||
{
|
||||
return Preset?.IsDisplayPreset == true || !string.IsNullOrEmpty(Preset?.name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.AMD
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<div class="modal" id="settingsModal" tabindex="-1" @onfocus="OnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">AMD settings</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => Config = null"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1">
|
||||
@if (Config == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ShortcutInput Label="Quick Access Shortcut" @bind-Shortcut="Config.QuickAccessShortcut" />
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => Config = null">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private AmdServiceConfig? Config { get; set; }
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Config == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("AmdService", "UpdateConfig", Config);
|
||||
|
||||
if (result)
|
||||
{
|
||||
Config = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (Config != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Config = await _rpcClientService.CallAsync<AmdServiceConfig>("AmdService", "GetConfig");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
@page "/AMD"
|
||||
|
||||
@using ColorControl.Shared.Common
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.AMD
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject ProtectedLocalStorage _localStorage
|
||||
|
||||
<PageTitle>AMD controller</PageTitle>
|
||||
|
||||
<AmdSettings />
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<h1>AMD controller</h1>
|
||||
<div class="d-flex ms-auto">
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#settingsModal">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Displays</h2>
|
||||
|
||||
<AmdPresetPage PresetParam="CurrentPreset" AfterApply="AfterPresetApplied" />
|
||||
<ConfirmModal Title="Delete preset" Message="Are you sure you want to delete the preset?" OnConfirm="PresetOnDeleteConfirmed" />
|
||||
|
||||
@if (DisplayPresets == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row mb-3">
|
||||
@if (!DisplayPresets.Any())
|
||||
{
|
||||
<span>No displays found</span>
|
||||
}
|
||||
@foreach (var preset in DisplayPresets)
|
||||
{
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex align-items-baseline">
|
||||
<span>
|
||||
@preset.displayName
|
||||
@if (preset.DisplayConfig.IsPrimary == true)
|
||||
{
|
||||
<small class="text-muted ms-2">Primary</small>
|
||||
}
|
||||
</span>
|
||||
<div class="d-flex ms-auto">
|
||||
<button type="button" class="btn btn-sm btn-primary ms-2" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => DisplayPresetOnClick(preset)">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<small class="text-body">@preset.DisplayConfig.Resolution.ToString() @@ @preset.DisplayConfig.RefreshRate.ToString()Hz</small>
|
||||
<small class="text-muted">@preset.colorDepth, @preset.pixelFormat</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Presets == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2 d-flex align-items-center">
|
||||
<h2>Presets</h2>
|
||||
<div class="d-flex ms-auto">
|
||||
<select class="form-select me-2" id="presetOrder" @bind="PresetOrder" @bind:after="PresetOrderChanged">
|
||||
@foreach (var order in Enum.GetValues<PresetOrder>())
|
||||
{
|
||||
<option value="@order">Order by: @order.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => AddPresetOnClick()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="list-group">
|
||||
@foreach (var preset in Presets)
|
||||
{
|
||||
<a class="list-group-item list-group-item-action" @onclick="() => PresetOnClick(preset)" @onclick:preventDefault @onclick:stopPropagation>
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div>
|
||||
<h5 class="mb-1">
|
||||
@preset.name <small class="text-muted">@(preset.primaryDisplay ? "Primary display" : preset.displayName)</small>
|
||||
@if (preset.ShowInQuickAccess)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-warning" title="Show in Quick Access">QA</span>
|
||||
}
|
||||
</h5>
|
||||
</div>
|
||||
<span>
|
||||
<button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#confirmModal" @onclick="() => PresetOnDeleteClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Delete</button>
|
||||
<button class="btn btn-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnCloneClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Clone</button>
|
||||
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnEditClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Edit</button>
|
||||
</span>
|
||||
</div>
|
||||
<p class="mb-1">@preset.DisplayConfig.Resolution.ToString() @@ @preset.DisplayConfig.RefreshRate.ToString()Hz @(preset.applyColorData ? preset.colorDepth : "")</p>
|
||||
<small class="text-muted">@preset.shortcut</small>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<AmdPreset>? Presets;
|
||||
private List<AmdPreset>? DisplayPresets;
|
||||
private List<VirtualResolution>? Resolutions;
|
||||
|
||||
private AmdPreset? CurrentPreset;
|
||||
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await RefreshPresets();
|
||||
DisplayPresets = await _rpcClientService.CallAsync<List<AmdPreset>>("AmdService", "GetDisplayPresets");
|
||||
Resolutions = await _rpcClientService.CallAsync<List<VirtualResolution>>("AmdService", "GetAvailableResolutionsV2", DisplayPresets?.FirstOrDefault());
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstTime)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
PresetOrder = await _localStorage.TryGet<PresetOrder>("AmdPresetOrder");
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PresetOnClick(AmdPreset preset)
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("AmdService", "ApplyPresetWithId", preset.id);
|
||||
}
|
||||
|
||||
private async Task PresetOnEditClick(AmdPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnCloneClick(AmdPreset preset)
|
||||
{
|
||||
CurrentPreset = new AmdPreset(preset);
|
||||
CurrentPreset.name = preset.name;
|
||||
CurrentPreset.SetCloneValues();
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteClick(AmdPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteConfirmed()
|
||||
{
|
||||
if (CurrentPreset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("AmdService", "DeletePreset", CurrentPreset.id);
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task DisplayPresetOnClick(AmdPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task AddPresetOnClick()
|
||||
{
|
||||
CurrentPreset = new AmdPreset();
|
||||
}
|
||||
|
||||
private async Task AfterPresetApplied(AmdPreset preset)
|
||||
{
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task PresetOrderChanged()
|
||||
{
|
||||
await _localStorage.SetAsync("AmdPresetOrder", PresetOrder);
|
||||
await RefreshPresets();
|
||||
}
|
||||
|
||||
private async Task RefreshPresets()
|
||||
{
|
||||
Presets = await _rpcClientService.CallAsync<List<AmdPreset>>("AmdService", "GetPresets");
|
||||
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
@page "/Error"
|
||||
@using System.Diagnostics
|
||||
|
||||
<PageTitle>Error</PageTitle>
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
|
||||
@code{
|
||||
[CascadingParameter]
|
||||
private HttpContext? HttpContext { get; set; }
|
||||
|
||||
private string? RequestId { get; set; }
|
||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
protected override void OnInitialized() =>
|
||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Contracts.Game
|
||||
@using ColorControl.Shared.Services
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal" id="presetModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" @onfocus="ModalOnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Preset?.id == 0 ? $"Settings for new preset" : $"Settings of preset {Preset?.IdOrName}")</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1 needs-validation @WasValidated" novalidate>
|
||||
@if (Preset == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">Name</label>
|
||||
<input class="form-control" id="name" type="text" @bind="Preset.name" required />
|
||||
</div>
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.ShowInQuickAccess" id="showInQuickAccess">
|
||||
<label class="form-check-label" for="showInQuickAccess">
|
||||
Show in Quick Access
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="path">File/URI</label>
|
||||
<div class="input-group mb-2">
|
||||
<input class="form-control" id="path" type="text" @bind="Preset.Path" required />
|
||||
<button type="button" class="btn btn-primary" @onclick="SelectFileOnClick" disabled="@SelectingFile">
|
||||
<span class="@(SelectingFile ? "spinner-border spinner-border-sm" : "")" aria-hidden="true"></span>
|
||||
<span role="status">Select...</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="selectFileHelp" class="form-text">
|
||||
Selecting a file opens a file dialog outside of the browser on the system where the ColorControl application is running.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="parameters">Parameters</label>
|
||||
<input class="form-control" id="parameters" type="text" @bind="Preset.Parameters" />
|
||||
</div>
|
||||
|
||||
<div class="accordion accordion-flush" id="presetAccordion">
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#advancedSettings">
|
||||
Advanced settings
|
||||
</button>
|
||||
</h2>
|
||||
<div id="advancedSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.RunAsAdministrator" id="runAsAdministrator">
|
||||
<label class="form-check-label" for="runAsAdministrator">
|
||||
Run as administrator
|
||||
</label>
|
||||
</div>
|
||||
<FlagsInput Label="Process affinity" Labels="CpuAffinityLabels" @bind-Value="Preset.ProcessAffinityMask"></FlagsInput>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="priority">Process priority</label>
|
||||
<select class="form-select" id="priority" @bind="Preset.GameProcessPriorityClass">
|
||||
@foreach (var priority in Enum.GetValues<GamePriorityClass>())
|
||||
{
|
||||
<option value="@priority.ToString()">@priority.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#autoApplySettings">
|
||||
Auto-apply settings
|
||||
</button>
|
||||
</h2>
|
||||
<div id="autoApplySettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.AutoSettings.AllowAutoApply" id="autoApply">
|
||||
<label class="form-check-label" for="autoApply">
|
||||
Automatically execute preset when process starts
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="autoApplyAction">Auto-apply action</label>
|
||||
<select class="form-select" id="priority" @bind="Preset.AutoSettings.ProcessAutoAction">
|
||||
@foreach (var action in Enum.GetValues<ProcessAutoAction>())
|
||||
{
|
||||
<option value="@action.ToString()">@action.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#steps">
|
||||
Steps
|
||||
</button>
|
||||
</h2>
|
||||
<div id="steps" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<StepsInput Label="Pre-launch" @bind-Steps="Preset.PreLaunchSteps" TPreset="GamePreset"></StepsInput>
|
||||
<StepsInput Label="Post-launch" @bind-Steps="Preset.PostLaunchSteps" TPreset="GamePreset"></StepsInput>
|
||||
<StepsInput Label="Finalize" @bind-Steps="Preset.FinalizeSteps" TPreset="GamePreset"></StepsInput>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="submit" class="btn btn-primary" data-bs-dismiss="@(IsValid() ? "modal" : "")" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private GamePreset? Preset;
|
||||
|
||||
[Parameter]
|
||||
public GamePreset? PresetParam { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<GamePreset, Task>? AfterApply { get; set; }
|
||||
|
||||
public List<string> CpuAffinityLabels = Enumerable.Range(0, Environment.ProcessorCount).Select(i => $"CPU #{i}").ToList();
|
||||
|
||||
public bool SelectingFile { get; set; }
|
||||
|
||||
private string WasValidated = "";
|
||||
private bool IsVisible;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (PresetParam == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Preset = PresetParam.CloneWithId();
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
WasValidated = "was-validated";
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("GameService", "UpdatePreset", Preset);
|
||||
|
||||
if (AfterApply != null)
|
||||
{
|
||||
await AfterApply.Invoke(Preset);
|
||||
}
|
||||
|
||||
IsVisible = false;
|
||||
}
|
||||
|
||||
private bool IsValid()
|
||||
{
|
||||
return !string.IsNullOrEmpty(Preset?.name) && !string.IsNullOrEmpty(Preset?.Path);
|
||||
}
|
||||
|
||||
private async Task SelectFileOnClick(MouseEventArgs e)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SelectingFile = true;
|
||||
try
|
||||
{
|
||||
var options = new RpcUiClientOptions
|
||||
{
|
||||
Timeout = 60000
|
||||
};
|
||||
|
||||
var result = await _rpcClientService.CallWithOptionsAsync<string>("GameService", "SelectPath", options);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
Preset.Path = result;
|
||||
if (string.IsNullOrEmpty(Preset.name))
|
||||
{
|
||||
Preset.name = Path.GetFileNameWithoutExtension(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
SelectingFile = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ModalOnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
WasValidated = "";
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Contracts.Game
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<div class="modal" id="settingsModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">NVIDIA settings</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1">
|
||||
@if (Config == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ShortcutInput Label="Quick Access Shortcut" @bind-Shortcut="Config.QuickAccessShortcut" />
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="Config.ApplyExternallyLaunched" id="applyExternallyLaunched">
|
||||
<label class="form-check-label" for="applyExternallyLaunched">
|
||||
Apply presets when launching games externally
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private GameServiceConfig? Config { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<GameServiceConfig>("GameService", "GetConfig");
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Config == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("GameService", "UpdateConfig", Config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
@page "/Game"
|
||||
|
||||
@using ColorControl.Shared.Contracts;
|
||||
@using ColorControl.Shared.Contracts.Game;
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject ProtectedLocalStorage _localStorage
|
||||
|
||||
<PageTitle>Game launcher</PageTitle>
|
||||
|
||||
<GameSettings />
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<h1>Game launcher</h1>
|
||||
<div class="d-flex ms-auto">
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#settingsModal">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2 d-flex align-items-center">
|
||||
<h2>Presets</h2>
|
||||
<div class="d-flex ms-auto">
|
||||
<select class="form-select me-2" id="presetOrder" @bind="PresetOrder" @bind:after="PresetOrderChanged">
|
||||
@foreach (var order in Enum.GetValues<PresetOrder>())
|
||||
{
|
||||
<option value="@order">Order by: @order.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => AddPresetOnClick()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<GamePresetPage PresetParam="CurrentPreset" AfterApply="AfterPresetApplied" />
|
||||
<ConfirmModal Title="Delete preset" Message="Are you sure you want to delete the preset?" OnConfirm="PresetOnDeleteConfirmed" />
|
||||
|
||||
@if (Presets == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="list-group">
|
||||
@foreach (var preset in Presets)
|
||||
{
|
||||
<a class="list-group-item list-group-item-action" @onclick="() => PresetOnClick(preset)">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div>
|
||||
<h5 class="mb-1">
|
||||
@preset.name
|
||||
@if (preset.ShowInQuickAccess)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-warning" title="Show in Quick Access">QA</span>
|
||||
}
|
||||
</h5>
|
||||
</div>
|
||||
<span>
|
||||
<button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#confirmModal" @onclick="() => PresetOnDeleteClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Delete</button>
|
||||
<button class="btn btn-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnCloneClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Clone</button>
|
||||
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnEditClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Edit</button>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<GamePreset>? Presets;
|
||||
private GamePreset? CurrentPreset;
|
||||
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await RefreshPresets();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstTime)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
PresetOrder = await _localStorage.TryGet<PresetOrder>("GamePresetOrder");
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PresetOnClick(GamePreset preset)
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("GameService", "ApplyPresetWithId", preset.id);
|
||||
}
|
||||
|
||||
private async Task PresetOnEditClick(GamePreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnCloneClick(GamePreset preset)
|
||||
{
|
||||
CurrentPreset = new GamePreset(preset);
|
||||
CurrentPreset.SetCloneValues();
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteClick(GamePreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteConfirmed()
|
||||
{
|
||||
if (CurrentPreset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("GameService", "DeletePreset", CurrentPreset.id);
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task AddPresetOnClick()
|
||||
{
|
||||
CurrentPreset = new GamePreset();
|
||||
}
|
||||
|
||||
private async Task AfterPresetApplied(GamePreset preset)
|
||||
{
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task PresetOrderChanged()
|
||||
{
|
||||
await _localStorage.SetAsync("GamePresetOrder", PresetOrder);
|
||||
await RefreshPresets();
|
||||
}
|
||||
|
||||
private async Task RefreshPresets()
|
||||
{
|
||||
Presets = await _rpcClientService.CallAsync<List<GamePreset>>("GameService", "GetPresets");
|
||||
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<FieldsModal ModalId="confirmModal" Fields="Fields" Title="@Title" OnConfirm="ConfirmClick"></FieldsModal>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? Title { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string? Message { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<Task>? OnConfirm { get; set; }
|
||||
|
||||
public List<FieldDefinition>? Fields { get; set; }
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (Message != null)
|
||||
{
|
||||
Fields = [new FieldDefinition { FieldType = FieldType.Label, Label = Message }];
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ConfirmClick()
|
||||
{
|
||||
if (OnConfirm != null)
|
||||
{
|
||||
await OnConfirm();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
@if (Fields == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@foreach (var field in Fields)
|
||||
{
|
||||
if (field.FieldType == FieldType.Text)
|
||||
{
|
||||
var fieldId = $"fld_{Random.Shared.Next()}";
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="@fieldId">@field.Label</label>
|
||||
<input class="form-control" type="text" @bind="field.StringValue" id="@fieldId">
|
||||
@if (field.SubLabel != null)
|
||||
{
|
||||
<div id="@(fieldId)_help" class="form-text">
|
||||
@field.SubLabel
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
if (field.FieldType == FieldType.Label)
|
||||
{
|
||||
var fieldId = $"fld_{Random.Shared.Next()}";
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="@fieldId">@field.Label</label>
|
||||
@if (field.SubLabel != null)
|
||||
{
|
||||
<div id="@(fieldId)_help" class="form-text">
|
||||
@field.SubLabel
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else if (field.FieldType == FieldType.DropDown)
|
||||
{
|
||||
var fieldId = $"fld_{Random.Shared.Next()}";
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="@fieldId">@field.Label</label>
|
||||
<select class="form-select" id="@fieldId" @bind="field.StringValue">
|
||||
@if (field.ValueType != null)
|
||||
{
|
||||
@foreach (var item in Enum.GetValues(field.ValueType))
|
||||
{
|
||||
<option value="@item.ToString()">@((item as IConvertible).GetDescription())</option>
|
||||
}
|
||||
}
|
||||
else if (field.Values != null)
|
||||
{
|
||||
@foreach (var item in field.Values)
|
||||
{
|
||||
<option value="@item.ToString()">@item.ToString()</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
@if (field.SubLabel != null)
|
||||
{
|
||||
<div id="@(fieldId)_help" class="form-text">
|
||||
@field.SubLabel
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else if (field.FieldType == FieldType.Shortcut)
|
||||
{
|
||||
<ShortcutInput Label="@field.Label" @bind-Shortcut="field.StringValue"></ShortcutInput>
|
||||
}
|
||||
else if (field.FieldType == FieldType.CheckBox)
|
||||
{
|
||||
var fieldId = $"fld_{Random.Shared.Next()}";
|
||||
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="field.BoolValue" id="@fieldId">
|
||||
<label class="form-check-label" for="@fieldId">
|
||||
@field.Label
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
else if (field.FieldType == FieldType.Numeric && (field.MaxValue - field.MinValue) <= 50)
|
||||
{
|
||||
var fieldId = $"fld_{Random.Shared.Next()}";
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="@fieldId">@field.Label</label>
|
||||
<input class="form-control" type="number" @bind="field.IntValue" min="@((int)field.MinValue)" max="@((int)field.MaxValue)" id="@fieldId">
|
||||
@if (field.SubLabel != null)
|
||||
{
|
||||
<div id="@(fieldId)_help" class="form-text">
|
||||
@field.SubLabel
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else if (field.FieldType == FieldType.Numeric && (field.MaxValue - field.MinValue) > 50)
|
||||
{
|
||||
var fieldId = $"fld_{Random.Shared.Next()}";
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-range" for="@fieldId">@field.Label (Current value: @field.IntValue)</label>
|
||||
<input class="form-range" type="range" min="@((int)field.MinValue)" max="@((int)field.MaxValue)" @bind="field.IntValue" id="@fieldId">
|
||||
@if (field.SubLabel != null)
|
||||
{
|
||||
<div id="@(fieldId)_help" class="form-text">
|
||||
@field.SubLabel
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public List<FieldDefinition>? Fields { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal" id="@ModalId" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" @onfocus="ModalFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@Title</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="OnClose"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if (IsVisible)
|
||||
{
|
||||
<FieldDefs Fields="Fields"></FieldDefs>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="OnClose">Cancel</button>
|
||||
@if (SecondaryCaption != null)
|
||||
{
|
||||
<button type="button" class="btn btn-secondary" @onclick="SecondaryClick">@SecondaryCaption</button>
|
||||
}
|
||||
<button class="btn btn-primary" type="button" disabled="@IsNextDisabled" data-bs-dismiss="@Dismiss" @onclick="ConfirmClick">
|
||||
@if (IsNextDisabled)
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm me-1" aria-hidden="true"></span>
|
||||
}
|
||||
<span role="status">@ConfirmCaption</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? ModalId { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string? ConfirmCaption { get; set; } = "Yes";
|
||||
|
||||
[Parameter]
|
||||
public string? SecondaryCaption { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string? Dismiss { get; set; } = "modal";
|
||||
|
||||
[Parameter]
|
||||
public string? Title { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string? Message { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<FieldDefinition>? Fields { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<Task>? OnConfirm { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<Task>? OnSecondary { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<Task>? OnShow { get; set; }
|
||||
|
||||
private bool IsVisible { get; set; }
|
||||
private bool IsNextDisabled { get; set; }
|
||||
|
||||
private async Task ConfirmClick(MouseEventArgs e)
|
||||
{
|
||||
if (OnConfirm == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dismissing = Dismiss == "modal";
|
||||
IsNextDisabled = Dismiss == null;
|
||||
try
|
||||
{
|
||||
await OnConfirm();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsNextDisabled = false;
|
||||
}
|
||||
|
||||
if (dismissing)
|
||||
{
|
||||
IsVisible = false;
|
||||
Dismiss = "modal";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SecondaryClick(MouseEventArgs e)
|
||||
{
|
||||
if (OnSecondary == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await OnSecondary();
|
||||
}
|
||||
|
||||
private async Task ModalFocus(FocusEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
IsVisible = true;
|
||||
|
||||
if (OnShow != null)
|
||||
{
|
||||
await OnShow();
|
||||
//StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnClose(MouseEventArgs e)
|
||||
{
|
||||
IsVisible = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.EventDispatcher
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
<div class="row mx-0 mb-2">
|
||||
<label class="form-label ps-0">@Label</label>
|
||||
|
||||
@if (Labels != null)
|
||||
{
|
||||
var index = 1;
|
||||
var checkValue = 1;
|
||||
foreach (var label in Labels)
|
||||
{
|
||||
var name = $"check{index}";
|
||||
var checkIndex = index;
|
||||
|
||||
<div class="form-check form-check-inline col-@(Col)">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="@name" checked="@((Value & checkValue) == checkValue)" @onchange="(ChangeEventArgs e) => CheckOnChange(e, checkIndex)">
|
||||
<label class="form-check-label" for="@name">@label</label>
|
||||
</div>
|
||||
|
||||
index++;
|
||||
checkValue *= 2;
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public List<string>? Labels { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string? Label { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public uint Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<uint> ValueChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int Col { get; set; } = 4;
|
||||
|
||||
private async Task CheckOnChange(ChangeEventArgs e, int index)
|
||||
{
|
||||
var checkValue = (uint)Math.Pow(2, index - 1);
|
||||
|
||||
Value += (uint)((e.Value is bool boolValue && boolValue) ? checkValue : -checkValue);
|
||||
|
||||
await ValueChanged.InvokeAsync(Value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.EventDispatcher
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@if (Label != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">@Label</label>
|
||||
<input class="form-control" type="text" readonly value="@Shortcut"
|
||||
@onchange="(ChangeEventArgs e) => ShortcutOnChange(e)"
|
||||
@onkeydown="ShortcutOnKeyDown"
|
||||
@onkeyup="(KeyboardEventArgs e) => ShortcutOnKeyUp(e)"
|
||||
@onfocus="ShortcutOnFocus"
|
||||
@onblur="ShortcutOnBlur"/>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? Label { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string? Shortcut { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string?> ShortcutChanged { get; set; }
|
||||
|
||||
private async Task ShortcutOnChange(ChangeEventArgs e)
|
||||
{
|
||||
Shortcut = e.Value?.ToString();
|
||||
await ShortcutChanged.InvokeAsync(Shortcut);
|
||||
}
|
||||
|
||||
private void ShortcutOnKeyDown(KeyboardEventArgs e)
|
||||
{
|
||||
if (e.Key == "Tab")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var text = KeyboardShortcutDispatcher.FormatKeyboardShortcut(e.ShiftKey, e.CtrlKey, e.AltKey, e.Key, e.Code);
|
||||
Shortcut = text;
|
||||
}
|
||||
|
||||
private async Task ShortcutOnKeyUp(KeyboardEventArgs e)
|
||||
{
|
||||
//KeyboardShortcutDispatcher.HandleKeyboardShortcutUp()
|
||||
await ShortcutChanged.InvokeAsync(Shortcut);
|
||||
}
|
||||
|
||||
private void ShortcutOnFocus(FocusEventArgs e)
|
||||
{
|
||||
KeyboardShortcutDispatcher.IsActive = false;
|
||||
}
|
||||
|
||||
private void ShortcutOnBlur(FocusEventArgs e)
|
||||
{
|
||||
KeyboardShortcutDispatcher.IsActive = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.Shared.EventDispatcher
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@typeparam TPreset where TPreset : PresetBase
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
@if (Label != null && Steps != null)
|
||||
{
|
||||
var index = 0;
|
||||
|
||||
<div class="mb-2">
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="form-label" for="name">@Label</label>
|
||||
<div class="d-flex ms-auto">
|
||||
@if (NvPresets != null || SamsungPresets != null || CustomItems != null)
|
||||
{
|
||||
<div class="dropdown dropend mb-1">
|
||||
<button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false" data-bs-auto-close="outside">Add</button>
|
||||
<form class="dropdown-menu p-4 dropdown-menu-end" style="width: 200px">
|
||||
@if (NvPresets != null && NvPresetsEnabled)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="nvPreset">NVIDIA preset</label>
|
||||
<select class="form-select" id="nvPreset" @bind="NvPresetToAddId">
|
||||
<option value="">Select preset</option>
|
||||
@foreach (var preset in NvPresets)
|
||||
{
|
||||
<option value="@preset.id">@preset.IdOrName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
@if (SamsungPresets != null && SamsungPresetsEnabled)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="samsungPreset">Samsung preset</label>
|
||||
<select class="form-select" id="samsungPreset" @bind="SamsungPresetToAddId">
|
||||
<option value="">Select preset</option>
|
||||
@foreach (var preset in SamsungPresets)
|
||||
{
|
||||
<option value="@preset.id">@preset.IdOrName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
@if (LgPresets != null && LgPresetsEnabled)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="lgPreset">LG preset</label>
|
||||
<select class="form-select" id="lgPreset" @bind="LgPresetToAddId">
|
||||
<option value="">Select preset</option>
|
||||
@foreach (var preset in LgPresets)
|
||||
{
|
||||
<option value="@preset.id">@preset.IdOrName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
@if (CustomItems != null)
|
||||
{
|
||||
foreach (var customItem in CustomItems)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="customItem">@customItem.Name</label>
|
||||
<select class="form-select" id="customItem" @bind="customItem.SelectedItem">
|
||||
<option value="">Select item</option>
|
||||
@foreach (var item in customItem.Items)
|
||||
{
|
||||
<option value="@item">@item</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@if (ActionItems != null)
|
||||
{
|
||||
foreach (var customItem in ActionItems)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="advancedCustomItem">@customItem.Name</label>
|
||||
<select class="form-select" id="advancedCustomItem" @bind="customItem.SelectedActionName" @bind:after="() => AdvancedItemChanged(customItem)">
|
||||
<option value="">Select action</option>
|
||||
@foreach (var keyValue in customItem.GroupedActions)
|
||||
{
|
||||
<optgroup label="@keyValue.Key">
|
||||
@foreach (var item in keyValue.Value)
|
||||
{
|
||||
<option value="@item.Name">@item.Title</option>
|
||||
}
|
||||
</optgroup>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<FieldDefs Fields="ActionFields"></FieldDefs>
|
||||
}
|
||||
}
|
||||
<button type="button" class="btn btn-sm btn-primary" @onclick="() => AddPresetOnClick()">Add items</button>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<nav>
|
||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
||||
<button class="nav-link active" id="nav-home-tab" data-bs-toggle="tab" data-bs-target="#nav-click" type="button" role="tab" aria-controls="nav-click" aria-selected="true">Visual steps</button>
|
||||
<button class="nav-link" id="nav-profile-tab" data-bs-toggle="tab" data-bs-target="#nav-raw" type="button" role="tab" aria-controls="nav-raw" aria-selected="false">Raw text</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
<div class="tab-pane fade show active" id="nav-click" role="tabpanel" aria-labelledby="nav-click-tab" tabindex="0">
|
||||
<div class="btn-group btn-group-sm d-inline-flex flex-wrap" role="group" aria-label="Small button group">
|
||||
|
||||
@foreach (var step in PresetSteps)
|
||||
{
|
||||
var stepIndex = index;
|
||||
|
||||
<button type="button" class="btn btn-outline-primary dropdown-toggle text-break text-wrap" data-bs-toggle="dropdown" aria-expanded="false" data-bs-auto-close="outside">@step.Raw</button>
|
||||
<form class="dropdown-menu p-4 dropdown-menu-end" style="width: 200px">
|
||||
<div class="mb-2">
|
||||
<button type="button" class="btn btn-primary btn-sm" data-bs-dismiss="dropdown" @onclick="() => RemoveOnClick(stepIndex)">Remove</button>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="delay">Delay (@(step.Delay)ms)</label>
|
||||
<input class="form-range" id="delay" type="range" min="0" max="10000" step="50" @bind="step.Delay" @bind:after="() => AfterDelayChanged()">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
index++;
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-raw" role="tabpanel" aria-labelledby="nav-raw-tab" tabindex="0">
|
||||
<textarea class="form-control" id="rawStepText" rows="3" @onchange="RawTextOnChange" @onblur="RawTextOnBlur" value="@RawText"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? Label { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<string>? Steps { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<List<string>?> StepsChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<CustomStepItem>? CustomItems { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<ActionStepItem>? ActionItems { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool NvPresetsEnabled { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool SamsungPresetsEnabled { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public bool LgPresetsEnabled { get; set; } = true;
|
||||
|
||||
public class ActionStepItem
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public List<InvokableActionDto<TPreset>> Actions { get; private set; }
|
||||
public string? SelectedActionName { get; set; }
|
||||
public Dictionary<string, List<InvokableActionDto<TPreset>>> GroupedActions;
|
||||
|
||||
public ActionStepItem(string name, List<InvokableActionDto<TPreset>> actions)
|
||||
{
|
||||
Name = name;
|
||||
Actions = actions;
|
||||
|
||||
GroupedActions = actions.GroupBy(a => a.Category).ToDictionary(k => k.Key, v => v.ToList());
|
||||
}
|
||||
|
||||
public string GetStepString(List<FieldDefinition>? fields)
|
||||
{
|
||||
if (string.IsNullOrEmpty(SelectedActionName))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var action = Actions.FirstOrDefault(a => a.Name == SelectedActionName);
|
||||
|
||||
if (action == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var field = fields?.FirstOrDefault();
|
||||
|
||||
if (field == null || field.Value == null)
|
||||
{
|
||||
return $"{action.Name}";
|
||||
}
|
||||
|
||||
return $"{action.Name}({field.Value?.ToString()})";
|
||||
}
|
||||
}
|
||||
|
||||
private List<NvPreset>? NvPresets { get; set; }
|
||||
private List<SamsungPreset>? SamsungPresets { get; set; }
|
||||
private List<LgPreset>? LgPresets { get; set; }
|
||||
|
||||
private int? NvPresetToAddId { get; set; }
|
||||
private int? SamsungPresetToAddId { get; set; }
|
||||
private int? LgPresetToAddId { get; set; }
|
||||
|
||||
private List<PresetStep> PresetSteps = new();
|
||||
|
||||
private string? RawText;
|
||||
|
||||
private List<FieldDefinition>? ActionFields;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (Steps != null)
|
||||
{
|
||||
PresetSteps.Clear();
|
||||
PresetSteps.AddRange(Steps.Select(s => PresetStep.Parse(s)));
|
||||
RawText = string.Join(", ", PresetSteps);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var config = await _rpcClientService.CallAsync<Config>("OptionsService", "GetConfig");
|
||||
|
||||
if (config.HasModule(Module.NvModule))
|
||||
{
|
||||
NvPresets = (await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetPresets"))?.OrderBy(p => p.name).ToList();
|
||||
}
|
||||
|
||||
if (config.HasModule(Module.SamsungModule))
|
||||
{
|
||||
SamsungPresets = (await _rpcClientService.CallAsync<List<SamsungPreset>>("SamsungService", "GetPresets"))?.OrderBy(p => p.name).ToList();
|
||||
}
|
||||
|
||||
if (config.HasModule(Module.LgModule))
|
||||
{
|
||||
LgPresets = (await _rpcClientService.CallAsync<List<LgPreset>>("LgService", "GetPresets"))?.OrderBy(p => p.name).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RemoveOnClick(int index)
|
||||
{
|
||||
if (PresetSteps.Count > index)
|
||||
{
|
||||
PresetSteps.RemoveAt(index);
|
||||
}
|
||||
|
||||
await EmitSteps();
|
||||
}
|
||||
|
||||
private async Task AfterDelayChanged()
|
||||
{
|
||||
await EmitSteps();
|
||||
}
|
||||
|
||||
private async Task AddPresetOnClick()
|
||||
{
|
||||
AddPreset(NvPresets, "NvPreset", NvPresetToAddId);
|
||||
AddPreset(SamsungPresets, "SamsungPreset", SamsungPresetToAddId);
|
||||
AddPreset(LgPresets, "LgPreset", LgPresetToAddId);
|
||||
|
||||
if (CustomItems != null && Steps != null)
|
||||
{
|
||||
foreach (var customItem in CustomItems)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(customItem.SelectedItem))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
PresetSteps.Add(PresetStep.Parse(customItem.SelectedItem));
|
||||
//customItem.SelectedItem = null;
|
||||
}
|
||||
}
|
||||
if (ActionItems != null && Steps != null)
|
||||
{
|
||||
foreach (var customItem in ActionItems)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(customItem.SelectedActionName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var stepString = customItem.GetStepString(ActionFields);
|
||||
|
||||
PresetSteps.Add(PresetStep.Parse(stepString));
|
||||
//customItem.SelectedItem = null;
|
||||
}
|
||||
}
|
||||
|
||||
await EmitSteps();
|
||||
}
|
||||
|
||||
private void AddPreset<T>(List<T>? presets, string type, int? id) where T : PresetBase
|
||||
{
|
||||
var preset = presets?.FirstOrDefault(p => p.id == id);
|
||||
|
||||
if (preset == null || Steps == null || preset.id == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PresetSteps.Add(PresetStep.Parse($"{type}({preset.name})"));
|
||||
}
|
||||
|
||||
private async Task EmitSteps()
|
||||
{
|
||||
if (Steps != null)
|
||||
{
|
||||
Steps.Clear();
|
||||
Steps.AddRange(PresetSteps.Select(ps => ps.UpdatedRaw));
|
||||
RawText = string.Join(", ", PresetSteps);
|
||||
|
||||
await StepsChanged.InvokeAsync(Steps);
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task RawTextOnBlur(FocusEventArgs e)
|
||||
{
|
||||
var newSteps = new List<string>();
|
||||
|
||||
Utils.ParseWords(newSteps, RawText);
|
||||
|
||||
PresetSteps.Clear();
|
||||
PresetSteps.AddRange(newSteps.Select(s => PresetStep.Parse(s)));
|
||||
|
||||
await EmitSteps();
|
||||
}
|
||||
|
||||
private async Task RawTextOnChange(ChangeEventArgs e)
|
||||
{
|
||||
RawText = e.Value?.ToString();
|
||||
}
|
||||
|
||||
private void AdvancedItemChanged(ActionStepItem customItem)
|
||||
{
|
||||
var action = customItem.Actions.FirstOrDefault(a => a.Name == customItem.SelectedActionName);
|
||||
|
||||
if (action == null)
|
||||
{
|
||||
ActionFields = null;
|
||||
return;
|
||||
}
|
||||
|
||||
ActionFields = [CreateField(action)];
|
||||
}
|
||||
|
||||
private FieldDefinition CreateField(InvokableActionDto<TPreset> action)
|
||||
{
|
||||
var fieldType = FieldType.Numeric;
|
||||
var strValue = default(string);
|
||||
var subLabel = default(string);
|
||||
var label = action.Title;
|
||||
|
||||
if (action.EnumType != null)
|
||||
{
|
||||
fieldType = FieldType.DropDown;
|
||||
strValue = Enum.GetNames(action.EnumType).First();
|
||||
subLabel = "Note: not all values are available on all models.";
|
||||
}
|
||||
else if (action.MinValue == action.MaxValue)
|
||||
{
|
||||
fieldType = FieldType.Label;
|
||||
label = $"This will execute {action.Title}";
|
||||
}
|
||||
|
||||
var field = new FieldDefinition
|
||||
{
|
||||
FieldType = fieldType,
|
||||
Label = label,
|
||||
SubLabel = subLabel,
|
||||
ValueType = action.EnumType,
|
||||
MinValue = action.MinValue,
|
||||
MaxValue = action.MaxValue,
|
||||
};
|
||||
|
||||
if (fieldType == FieldType.Numeric)
|
||||
{
|
||||
field.IntValue = action.CurrentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
field.StringValue = strValue;
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.EventDispatcher
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@if (Triggers != null)
|
||||
{
|
||||
foreach (var trigger in Triggers)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="triggerType">Trigger type</label>
|
||||
<select class="form-select" id="triggerType" @bind="trigger.Trigger">
|
||||
@foreach (var type in Enum.GetValues<PresetTriggerType>())
|
||||
{
|
||||
<option value="@type.ToString()">@type.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<FlagsInput Label="Conditions" Value="@((uint)trigger.Conditions)" Labels="ConditionLabels" Col="6" ValueChanged="ConditionsChanged"></FlagsInput>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="includedProcesses">Included processes</label>
|
||||
<input class="form-control" type="text" @bind="trigger.IncludedProcessesAsString" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="excludedProcesses">Excluded processes</label>
|
||||
<input class="form-control" type="text" @bind="trigger.ExcludedProcessesAsString" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public List<PresetTrigger>? Triggers { get; set; }
|
||||
|
||||
private List<string> ConditionLabels = Utils.GetDescriptions<PresetConditionType>(fromValue: 1).ToList();
|
||||
|
||||
public void ConditionsChanged(uint value)
|
||||
{
|
||||
if (Triggers == null || !Triggers.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var trigger = Triggers.First();
|
||||
trigger.Conditions = (PresetConditionType)value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
@page "/"
|
||||
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<PageTitle>Home</PageTitle>
|
||||
|
||||
<h1>Color Control</h1>
|
||||
|
||||
<h2>Modules</h2>
|
||||
|
||||
@if (Modules == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
@foreach (var module in Modules.Where(m => m.IsActive))
|
||||
{
|
||||
<div class="col">
|
||||
<div class="card h-100 mb-3">
|
||||
<div class="card-header">
|
||||
@module.DisplayName
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<a href="@module.Link" class="btn btn-primary stretched-link mb-2">Open module</a>
|
||||
<ul>
|
||||
@foreach (var info in module.Info)
|
||||
{
|
||||
<li>@info</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private Config? Config;
|
||||
private List<ModuleDto>? Modules;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<Config>("OptionsService", "GetConfig");
|
||||
Modules = await _rpcClientService.CallAsync<List<ModuleDto>>("OptionsService", "GetModules");
|
||||
if (Modules != null)
|
||||
{
|
||||
Modules.ForEach(m => m.Link = m.DisplayName.Split(' ')[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
@page "/info"
|
||||
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.Shared.Services;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<PageTitle>Logging</PageTitle>
|
||||
|
||||
<h1>Information</h1>
|
||||
|
||||
@if (info == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<h3 class="mb-2">@info.ApplicationTitle - @info.LegalCopyright</h3>
|
||||
|
||||
<h5>This app contains the following 3rd party plugins:</h5>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">lgtv.net by gr4b4z</li>
|
||||
<li class="list-group-item">Newtonsoft.Json by James Newton-King</li>
|
||||
<li class="list-group-item">NLog by Jarek Kowalski, Kim Christensen, Julian Verdurmen</li>
|
||||
<li class="list-group-item">NvAPIWrapper.Net by Soroush Falahati</li>
|
||||
<li class="list-group-item">NWin32 by zmjack</li>
|
||||
<li class="list-group-item">TaskScheduler by David Hall</li>
|
||||
<li class="list-group-item">NVIDIA Profile Inspector by Orbmu2k</li>
|
||||
<li class="list-group-item">NvidiaML wrapper by LibreHardwareMonitor</li>
|
||||
<li class="list-group-item">Novideo sRGB by ledoge</li>
|
||||
<li class="list-group-item">NLogViewer by dojo90</li>
|
||||
<li class="list-group-item">WPFDarkTheme by AngryCarrot789</li>
|
||||
<li class="list-group-item">Little-CMS by mm2</li>
|
||||
<li class="list-group-item">MHC2 by dantmnf</li>
|
||||
</ul>
|
||||
}
|
||||
|
||||
@code {
|
||||
private InfoDto? info;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
info = await _rpcClientService.CallAsync<InfoDto>("OptionsService", "GetInfo");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.Shared.Services
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal" id="deviceModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Device?.Name == null ? $"Settings for new device" : $"Settings of device {Device.Name}")</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1">
|
||||
@if (Device == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">Name</label>
|
||||
<input class="form-control" id="name" type="text" @bind="Device.Name" />
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="Device.IsCustom" id="isCustom">
|
||||
<label class="form-check-label" for="isCustom">
|
||||
Is custom device
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="ipAddress">IP-address</label>
|
||||
<input class="form-control" id="ipAddress" type="text" @bind="Device.IpAddress" disabled="@(!Device.IsCustom)" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="macAddress">MAC-address</label>
|
||||
<input class="form-control" id="macAddress" type="text" @bind="Device.MacAddress" disabled="@(!Device.IsCustom)" />
|
||||
</div>
|
||||
@if (!Device.IsConnected)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<button class="btn btn-primary me-2" type="button" disabled="@IsTestingConnection" @onclick="TestConnectionClick">
|
||||
@if (IsTestingConnection)
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm me-1" aria-hidden="true"></span>
|
||||
}
|
||||
<span role="status">Test connection</span>
|
||||
</button>
|
||||
@if (IsTestConnectionSuccessful != null)
|
||||
{
|
||||
if (IsTestConnectionSuccessful == true)
|
||||
{
|
||||
<span class="text-success">Connection test was successful!</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-danger">Connection failed!</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="accordion accordion-flush" id="accordion">
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#deviceOptions">
|
||||
Device options
|
||||
</button>
|
||||
</h2>
|
||||
<div id="deviceOptions" class="accordion-collapse collapse" data-bs-parent="#accordion">
|
||||
<div class="accordion-body">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnAfterStartup" @bind="Device.Options.PowerOnAfterStartup">
|
||||
<label class="form-check-label" for="checkPowerOnAfterStartup">Power on after startup</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnAfterResume" @bind="Device.Options.PowerOnAfterResume">
|
||||
<label class="form-check-label" for="checkPowerOnAfterResume">Power on after resume from standby</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOffOnShutdown" @bind="Device.Options.PowerOffOnShutdown">
|
||||
<label class="form-check-label" for="checkPowerOffOnShutdown">Power off on shutdown</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOffOnStandby" @bind="Device.Options.PowerOffOnStandby">
|
||||
<label class="form-check-label" for="checkPowerOffOnStandby">Power off on standby</label>
|
||||
</div>
|
||||
<div class="form-check form-switch mb-2">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOffOnScreensaverStart" @bind="Device.Options.PowerOffOnScreenSaver">
|
||||
<label class="form-check-label" for="checkPowerOffOnScreensaverStart">Power off when screensaver activates</label>
|
||||
<button class="btn btn-sm btn-primary ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#screenSaverSettings" aria-expanded="false" aria-controls="screenSaverSettings">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
<div class="collapse mb-3" id="screenSaverSettings">
|
||||
<div class="card card-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="minScreenSaverDuration">Minimal screen saver duration (seconds)</label>
|
||||
<input class="form-control" id="minScreenSaverDuration" type="number" @bind="Device.Options.ScreenSaverMinimalDuration" />
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkTurnScreenOffInsteadOfPowerOff" @bind="Device.Options.TurnScreenOffOnScreenSaver">
|
||||
<label class="form-check-label" for="checkTurnScreenOffInsteadOfPowerOff">Turn screen off instead of power off</label>
|
||||
<div class="form-text">NOTE: turning the screen off might not work correctly on all models</div>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkTurnScreenOnInsteadOfPowerOn" @bind="Device.Options.TurnScreenOnAfterScreenSaver">
|
||||
<label class="form-check-label" for="checkTurnScreenOnInsteadOfPowerOn">Turn screen on instead of power on</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPerformActionOnManualScreenSaver" @bind="Device.Options.HandleManualScreenSaver">
|
||||
<label class="form-check-label" for="checkPerformActionOnManualScreenSaver">Perform action even on manually executed screen saver</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnOnScreensaverEnd" @bind="Device.Options.PowerOnAfterScreenSaver">
|
||||
<label class="form-check-label" for="checkPowerOnOnScreensaverEnd">Power on when screensaver deactivates</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnAfterManualPowerOff" @bind="Device.Options.PowerOnAfterManualPowerOff">
|
||||
<label class="form-check-label" for="checkPowerOnAfterManualPowerOff">Power on even after manual power off</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkAllowTriggers" @bind="Device.Options.TriggersEnabled">
|
||||
<label class="form-check-label" for="checkAllowTriggers">Allow triggers to be fired for this device</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkWindowsPowerOn" @bind="Device.Options.PowerOnByWindows">
|
||||
<label class="form-check-label" for="checkWindowsPowerOn">Use Windows power settings to power on</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkWindowsPowerOff" @bind="Device.Options.PowerOffByWindows">
|
||||
<label class="form-check-label" for="checkWindowsPowerOff">Use Windows power settings to power off</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkUseSecureConnection" @bind="Device.Options.UseSecureConnection">
|
||||
<label class="form-check-label" for="checkUseSecureConnection">Use secure connection</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private LgDeviceDto? _device;
|
||||
|
||||
[Parameter]
|
||||
public LgDeviceDto? Device { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<LgDeviceDto, Task>? AfterApply { get; set; }
|
||||
|
||||
private bool IsTestingConnection;
|
||||
private bool? IsTestConnectionSuccessful;
|
||||
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (_device != Device)
|
||||
{
|
||||
_device = Device;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Device == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("LgService", "UpdateDevice", Device);
|
||||
|
||||
if (AfterApply != null)
|
||||
{
|
||||
await AfterApply.Invoke(Device);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task TestConnectionClick(MouseEventArgs e)
|
||||
{
|
||||
IsTestingConnection = true;
|
||||
try
|
||||
{
|
||||
IsTestConnectionSuccessful = await _rpcClientService.CallWithOptionsAsync<bool>("LgService", "TestDevice", new RpcUiClientOptions { Timeout = 120000 }, Device);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsTestingConnection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<FieldsModal ModalId="executeActionModal" Fields="Fields" Title="@Title" ConfirmCaption="Apply" OnConfirm="ConfirmClick"></FieldsModal>
|
||||
|
||||
@code {
|
||||
|
||||
[Parameter]
|
||||
public InvokableActionDto<LgPreset>? Action { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<LgDeviceDto>? Devices { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<Task>? OnConfirm { get; set; }
|
||||
|
||||
public string? Title { get; set; }
|
||||
|
||||
public List<FieldDefinition>? Fields { get; set; }
|
||||
|
||||
private FieldDefinition? Field;
|
||||
private FieldDefinition? DeviceField;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (Action == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Title = $"Execute action {Action.Title}";
|
||||
|
||||
Field = CreateField(Action);
|
||||
|
||||
if (Devices?.Any() == true)
|
||||
{
|
||||
DeviceField = FieldDefinition.CreateDropDownField("Device", Devices.Select(d => d.ToString()).ToList());
|
||||
DeviceField.Value = Devices.FirstOrDefault(d => d.IsSelected)?.ToString();
|
||||
|
||||
Fields = [DeviceField, Field];
|
||||
}
|
||||
else
|
||||
{
|
||||
Fields = [Field];
|
||||
}
|
||||
}
|
||||
|
||||
private FieldDefinition CreateField(InvokableActionDto<LgPreset> action)
|
||||
{
|
||||
var fieldType = FieldType.Numeric;
|
||||
var strValue = default(string);
|
||||
var subLabel = default(string);
|
||||
var label = action.Title;
|
||||
|
||||
if (action.EnumType != null)
|
||||
{
|
||||
fieldType = FieldType.DropDown;
|
||||
strValue = Enum.GetNames(action.EnumType).First();
|
||||
subLabel = "Note: not all values are available on all models.";
|
||||
}
|
||||
else if (action.MinValue == action.MaxValue)
|
||||
{
|
||||
fieldType = FieldType.Label;
|
||||
label = $"This will execute {action.Title}. Press Apply to continue.";
|
||||
}
|
||||
|
||||
var field = new FieldDefinition
|
||||
{
|
||||
FieldType = fieldType,
|
||||
Label = label,
|
||||
SubLabel = subLabel,
|
||||
ValueType = action.EnumType,
|
||||
MinValue = action.MinValue,
|
||||
MaxValue = action.MaxValue,
|
||||
};
|
||||
|
||||
if (fieldType == FieldType.Numeric)
|
||||
{
|
||||
field.IntValue = action.CurrentValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
field.StringValue = strValue;
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private async Task ConfirmClick()
|
||||
{
|
||||
if (Action == null || Field == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Devices != null && DeviceField != null)
|
||||
{
|
||||
Action.SelectedDevice = Devices.FirstOrDefault(d => d.ToString() == DeviceField.Value?.ToString());
|
||||
}
|
||||
|
||||
var parameters = new List<string> { Field.StringValue };
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("LgService", "ExecuteInvokableAction", Action, parameters);
|
||||
|
||||
if (OnConfirm != null)
|
||||
{
|
||||
await OnConfirm();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.Shared.Services
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
@using static ColorControl.UI.Components.Pages.Generic.StepsInput<ColorControl.Shared.Contracts.LG.LgPreset>
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal" id="presetModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" @onfocus="ModalOnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Preset?.id == 0 ? $"Settings for new preset" : $"Settings of preset {Preset?.IdOrName}")</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1 needs-validation @WasValidated" novalidate>
|
||||
@if (Preset == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">Name</label>
|
||||
<input class="form-control" id="name" type="text" @bind="Preset.name" required />
|
||||
</div>
|
||||
@if (Devices != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="device">Device</label>
|
||||
<select class="form-select" id="device" @bind="Preset.DeviceMacAddress">
|
||||
<option value="">Globally selected device</option>
|
||||
@foreach (var device in Devices)
|
||||
{
|
||||
<option value="@device.MacAddress">@device.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.ShowInQuickAccess" id="showInQuickAccess">
|
||||
<label class="form-check-label" for="showInQuickAccess">
|
||||
Show in Quick Access
|
||||
</label>
|
||||
</div>
|
||||
<ShortcutInput Label="Shortcut" @bind-Shortcut="Preset.shortcut" />
|
||||
|
||||
<div class="accordion accordion-flush" id="presetAccordion">
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#advancedSettings">
|
||||
Advanced settings
|
||||
</button>
|
||||
</h2>
|
||||
<div id="advancedSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<TriggerInput Triggers="Preset.Triggers"></TriggerInput>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#steps">
|
||||
Steps
|
||||
</button>
|
||||
</h2>
|
||||
<div id="steps" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<StepsInput Label="Steps" @bind-Steps="Preset.steps" CustomItems="CustomItems" ActionItems="CustomActions" LgPresetsEnabled="false" TPreset="LgPreset"></StepsInput>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="description">Description</label>
|
||||
<textarea class="form-control" id="description" type="text" @bind="Preset.Description" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="@(!IsValid() ? "" : "modal")" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private LgPreset? Preset;
|
||||
|
||||
[Parameter]
|
||||
public LgPreset? PresetParam { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<LgDeviceDto>? Devices { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<LgPreset, Task>? AfterApply { get; set; }
|
||||
|
||||
private List<CustomStepItem>? CustomItems;
|
||||
private List<ActionStepItem>? CustomActions;
|
||||
|
||||
private string WasValidated = "";
|
||||
private bool IsVisible;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (PresetParam == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Preset = PresetParam.CloneWithId();
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
CustomItems = [new CustomStepItem("RC buttons", Enum.GetValues<ButtonType>().Select(b =>
|
||||
{
|
||||
var result = b.ToString();
|
||||
|
||||
if (result[0] == '_')
|
||||
{
|
||||
result = result.Substring(1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}).ToList())];
|
||||
|
||||
|
||||
var actions = await _rpcClientService.CallAsync<List<InvokableActionDto<LgPreset>>>("LgService", "GetInvokableActions");
|
||||
|
||||
if (actions != null)
|
||||
{
|
||||
CustomActions = [new ActionStepItem("Actions", actions.Where(a => !a.Advanced).ToList())];
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
WasValidated = "was-validated";
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("LgService", "UpdatePreset", Preset);
|
||||
|
||||
if (AfterApply != null)
|
||||
{
|
||||
await AfterApply.Invoke(Preset);
|
||||
}
|
||||
}
|
||||
|
||||
private void ModalOnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
WasValidated = "";
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValid()
|
||||
{
|
||||
return !string.IsNullOrEmpty(Preset?.name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<FieldsModal Title="Lg settings" ConfirmCaption="Save" ModalId="settingsModal" Fields="Fields" OnConfirm="ApplyClick" OnShow="ModalOnShow"></FieldsModal>
|
||||
|
||||
@code {
|
||||
private LgServiceConfigDto? Config { get; set; }
|
||||
private List<FieldDefinition>? Fields { get; set; }
|
||||
|
||||
protected async Task ModalOnShow()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<LgServiceConfigDto>("LgService", "GetConfig");
|
||||
Fields = LgFields.GetSettingsFields(Config);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task ApplyClick()
|
||||
{
|
||||
if (Config == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FieldDefinition.UpdateObject(Fields, Config);
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("LgService", "UpdateConfig", Config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
@page "/LG"
|
||||
|
||||
@using ColorControl.Shared.Common
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Contracts.LG
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject ProtectedLocalStorage _localStorage
|
||||
|
||||
<PageTitle>LG controller</PageTitle>
|
||||
|
||||
<LgSettings />
|
||||
<LgExecuteActionModal Action="@CurrentInvokableAction" Devices="Devices" />
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<h1>LG controller</h1>
|
||||
<div class="d-flex ms-auto">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-primary dropdown-toggle me-2" data-bs-toggle="dropdown" aria-expanded="false" data-bs-auto-close="outside">
|
||||
Buttons
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@foreach (var button in Enum.GetValues<ButtonType>())
|
||||
{
|
||||
<li>
|
||||
<a class="dropdown-item" @onclick="() => ButtonOnClick(button)">@button.GetDescription()</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@if (ActionGroups != null)
|
||||
{
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-primary dropdown-toggle me-2" data-bs-toggle="dropdown" aria-expanded="false" data-bs-auto-close="outside">
|
||||
Expert
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@foreach (var group in ActionGroups)
|
||||
{
|
||||
<li class="dropstart">
|
||||
<a class="dropdown-item dropdown-toggle" data-bs-toggle="dropdown" href="#">@group.Name</a>
|
||||
<ul class="dropdown-menu dropdown-submenu">
|
||||
@foreach (var action in group.Actions)
|
||||
{
|
||||
<li><a class="dropdown-item" @onclick="() => ActionOnclick(action)" data-bs-toggle="modal" data-bs-target="#executeActionModal">@action.Title</a></li>
|
||||
}
|
||||
</ul>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#settingsModal">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<LgDevicePage Device="CurrentDevice" />
|
||||
<LgPresetPage PresetParam="CurrentPreset" Devices="Devices" AfterApply="AfterPresetApplied" />
|
||||
<ConfirmModal Title="Delete preset" Message="Are you sure you want to delete the preset?" OnConfirm="PresetOnDeleteConfirmed" />
|
||||
|
||||
@if (Devices == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2 d-flex align-items-center">
|
||||
<h2>Devices</h2>
|
||||
<div class="d-flex ms-auto">
|
||||
<button type="button" class="btn btn-sm btn-primary me-2" disabled="@IsRefreshDisabled" @onclick="RefreshDevicesOnClick">
|
||||
@if (IsRefreshDisabled)
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm me-1" aria-hidden="true"></span>
|
||||
}
|
||||
<span role="status">Refresh</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#deviceModal" @onclick="() => AddDeviceOnClick()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
@if (!Devices.Any())
|
||||
{
|
||||
<span>No devices found</span>
|
||||
}
|
||||
@foreach (var device in Devices)
|
||||
{
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex align-items-baseline">
|
||||
<span>
|
||||
@device.Name
|
||||
@if (device.IsConnected)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-success" title="Device is connected">Connected</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ms-2 badge text-bg-danger" title="Device is disconnected">Disconnected</span>
|
||||
}
|
||||
@if (device.IsSelected)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-primary" title="Global device">Primary</span>
|
||||
}
|
||||
</span>
|
||||
<div class="d-flex ms-auto">
|
||||
@if (!device.IsSelected)
|
||||
{
|
||||
<button class="btn btn-sm btn-secondary ms-2" @onclick="() => SetAsPrimaryOnClick(device)">Set as primary</button>
|
||||
}
|
||||
<button type="button" class="btn btn-sm btn-primary ms-2" data-bs-toggle="modal" data-bs-target="#deviceModal" @onclick="() => DeviceOnClick(device)">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<small class="text-muted">@device.IpAddress (@(device.MacAddress ?? "No MAC-address entered"))</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Presets == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2 d-flex align-items-center">
|
||||
<h2>Presets</h2>
|
||||
<div class="d-flex ms-auto">
|
||||
<select class="form-select me-2" id="presetOrder" @bind="PresetOrder" @bind:after="PresetOrderChanged">
|
||||
@foreach (var order in Enum.GetValues<PresetOrder>())
|
||||
{
|
||||
<option value="@order">Order by: @order.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => AddPresetOnClick()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="list-group">
|
||||
@foreach (var preset in Presets)
|
||||
{
|
||||
<a class="list-group-item list-group-item-action" @onclick="() => PresetOnClick(preset)" @onclick:preventDefault @onclick:stopPropagation>
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div>
|
||||
<h5 class="mb-1">@preset.name <small class="text-muted">@GetDeviceName(preset)</small></h5>
|
||||
@if (preset.Triggers.Any(t => t.Trigger != PresetTriggerType.None))
|
||||
{
|
||||
<div><small class="text-muted">Trigger: @preset.Triggers[0].ToString()</small></div>
|
||||
}
|
||||
<div><small class="text-muted">@preset.shortcut</small></div>
|
||||
</div>
|
||||
<span>
|
||||
<button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#confirmModal" @onclick="() => PresetOnDeleteClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Delete</button>
|
||||
<button class="btn btn-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnCloneClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Clone</button>
|
||||
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnEditClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Edit</button>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private class ActionGroup
|
||||
{
|
||||
public string Name { get; }
|
||||
public List<InvokableActionDto<LgPreset>> Actions { get; }
|
||||
|
||||
public ActionGroup(string name, List<InvokableActionDto<LgPreset>> actions)
|
||||
{
|
||||
Name = (name ?? "Misc");
|
||||
Actions = actions;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<LgPreset>? Presets;
|
||||
private List<LgDeviceDto>? Devices;
|
||||
private List<InvokableActionDto<LgPreset>>? InvokableActions;
|
||||
private List<ActionGroup>? ActionGroups;
|
||||
|
||||
private LgServiceConfigDto? Config;
|
||||
private LgPreset? CurrentPreset;
|
||||
private LgDeviceDto? CurrentDevice;
|
||||
private bool IsRefreshDisabled;
|
||||
private InvokableActionDto<LgPreset>? CurrentInvokableAction;
|
||||
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<LgServiceConfigDto>("LgService", "GetConfig");
|
||||
await RefreshPresets();
|
||||
Devices = await _rpcClientService.CallAsync<List<LgDeviceDto>>("LgService", "GetDevices");
|
||||
InvokableActions = await _rpcClientService.CallAsync<List<InvokableActionDto<LgPreset>>>("LgService", "GetInvokableActions");
|
||||
|
||||
ActionGroups = InvokableActions.GroupBy(a => a.Category).Select(g => new ActionGroup(g.Key, g.ToList())).ToList();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstTime)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
PresetOrder = await _localStorage.TryGet<PresetOrder>("LgPresetOrder");
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PresetOnClick(LgPreset preset)
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("LgService", "ApplyPresetWithId", preset.id);
|
||||
}
|
||||
|
||||
private async Task PresetOnEditClick(LgPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnCloneClick(LgPreset preset)
|
||||
{
|
||||
CurrentPreset = new LgPreset(preset);
|
||||
CurrentPreset.SetCloneValues();
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteClick(LgPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteConfirmed()
|
||||
{
|
||||
if (CurrentPreset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("LgService", "DeletePreset", CurrentPreset.id);
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task DeviceOnClick(LgDeviceDto device)
|
||||
{
|
||||
CurrentDevice = device;
|
||||
}
|
||||
|
||||
private async Task AddDeviceOnClick()
|
||||
{
|
||||
CurrentDevice = new LgDeviceDto { IsCustom = true };
|
||||
}
|
||||
|
||||
private async Task AddPresetOnClick()
|
||||
{
|
||||
CurrentPreset = new LgPreset();
|
||||
}
|
||||
|
||||
private async Task AfterPresetApplied(LgPreset preset)
|
||||
{
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task RefreshDevicesOnClick(MouseEventArgs e)
|
||||
{
|
||||
IsRefreshDisabled = true;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("LgService", "RefreshDevices");
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
Devices = await _rpcClientService.CallAsync<List<LgDeviceDto>>("LgService", "GetDevices");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsRefreshDisabled = false;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task ActionOnclick(InvokableActionDto<LgPreset> action)
|
||||
{
|
||||
CurrentInvokableAction = action;
|
||||
}
|
||||
|
||||
private string GetDeviceName(LgPreset preset)
|
||||
{
|
||||
if (string.IsNullOrEmpty(preset.DeviceMacAddress))
|
||||
{
|
||||
return "Global";
|
||||
}
|
||||
|
||||
return Devices?.FirstOrDefault(d => d.MacAddress == preset.DeviceMacAddress)?.Name ?? preset.DeviceMacAddress;
|
||||
}
|
||||
|
||||
private async Task SetAsPrimaryOnClick(LgDeviceDto device)
|
||||
{
|
||||
var result = await _rpcClientService.CallAsync<bool>("LgService", "SetSelectedDevice", device);
|
||||
|
||||
if (result)
|
||||
{
|
||||
Devices = await _rpcClientService.CallAsync<List<LgDeviceDto>>("LgService", "GetDevices");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PresetOrderChanged()
|
||||
{
|
||||
await _localStorage.SetAsync("LgPresetOrder", PresetOrder);
|
||||
await RefreshPresets();
|
||||
}
|
||||
|
||||
private async Task RefreshPresets()
|
||||
{
|
||||
Presets = await _rpcClientService.CallAsync<List<LgPreset>>("LgService", "GetPresets");
|
||||
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
}
|
||||
|
||||
private async Task ButtonOnClick(ButtonType button)
|
||||
{
|
||||
var preset = new LgPreset(button.ToString(), null, [button.ToString()]);
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("LgService", "ApplyPreset", preset);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
@page "/logging"
|
||||
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<PageTitle>Logging</PageTitle>
|
||||
|
||||
<h1>Logging</h1>
|
||||
|
||||
@if (config == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Settings</h5>
|
||||
</div>
|
||||
<form class="ms-3 me-3">
|
||||
<div class="mb-3 col-md-3">
|
||||
<label class="form-label" for="logLevel">
|
||||
Log Level
|
||||
</label>
|
||||
<select class="form-select" @bind="logLevel" id="logLevel" @oninput="LogLevelInput">
|
||||
@foreach (var level in logLevels)
|
||||
{
|
||||
<option value="@level.Name">@level.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-3">
|
||||
<label class="form-label" for="logSource">
|
||||
Show log from
|
||||
</label>
|
||||
<select class="form-select" @bind="logSource" id="logSource" @bind:after="GetLog">
|
||||
<option value="0">Main application</option>
|
||||
<option value="1">Service</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<label class="form-label" for="logOrder">
|
||||
Order
|
||||
</label>
|
||||
<select class="form-select" @bind="logOrder" id="logOrder" @bind:after="GetLog">
|
||||
<option value="0">Newest first</option>
|
||||
<option value="1">Oldest first</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<label class="form-label" for="maxLines">
|
||||
Maximum number of lines to show
|
||||
</label>
|
||||
<select class="form-select" @bind="maxLines" id="maxLines" @bind:after="GetLog">
|
||||
<option value="1000">1000</option>
|
||||
<option value="10000">10000</option>
|
||||
<option value="999999999">Show all</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">TimeStamp</th>
|
||||
<th scope="col">
|
||||
<select class="form-select fw-bold" id="logLevel" @oninput="LogLevelFilterInput">
|
||||
@foreach (var level in logLevels)
|
||||
{
|
||||
<option class="fw-bold" value="@level.Name">@level.Name</option>
|
||||
}
|
||||
</select>
|
||||
</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var logLine in logLines.Where(l => l.Show(logLevelFilter)))
|
||||
{
|
||||
<tr class="table-@logLine.BsClass">
|
||||
<td style="min-width: 220px">@logLine.TimeStamp</td>
|
||||
<td style="min-width: 120px">@logLine.Level</td>
|
||||
<td>@logLine.Name</td>
|
||||
<td>@logLine.Message</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
private Config? config;
|
||||
private string logLevel = "0";
|
||||
private int logSource = 0;
|
||||
private int maxLines = 1000;
|
||||
private int logOrder = 0;
|
||||
private List<string>? allLines;
|
||||
private List<LogLine> logLines = new();
|
||||
private string logLevelFilterName = NLog.LogLevel.Debug.Name;
|
||||
private NLog.LogLevel logLevelFilter = NLog.LogLevel.Debug;
|
||||
private List<NLog.LogLevel> logLevels = [NLog.LogLevel.Trace, NLog.LogLevel.Debug, NLog.LogLevel.Info, NLog.LogLevel.Warn, NLog.LogLevel.Error, NLog.LogLevel.Fatal];
|
||||
|
||||
private class LogLine
|
||||
{
|
||||
public string TimeStamp { get; }
|
||||
public string Level { get; }
|
||||
public string Name { get; }
|
||||
public string Message { get; }
|
||||
public NLog.LogLevel LogLevel { get; }
|
||||
|
||||
public LogLine(string timeStamp, string level, string name, string message)
|
||||
{
|
||||
TimeStamp = timeStamp;
|
||||
Level = level;
|
||||
Name = name;
|
||||
Message = message;
|
||||
LogLevel = NLog.LogLevel.FromString(level);
|
||||
}
|
||||
|
||||
public string BsClass => Level switch
|
||||
{
|
||||
"TRACE" => "dark",
|
||||
"DEBUG" => "secondary",
|
||||
"INFO" => "info",
|
||||
"WARN" => "warning",
|
||||
"ERROR" => "danger",
|
||||
"FATAL" => "secondary",
|
||||
};
|
||||
|
||||
public bool Show(NLog.LogLevel level) => LogLevel >= level;
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
config = await _rpcClientService.CallAsync<Config>("OptionsService", "GetConfig");
|
||||
logLevel = config.LogLevel;
|
||||
|
||||
await GetLog();
|
||||
}
|
||||
|
||||
private async Task GetLog()
|
||||
{
|
||||
allLines = await _rpcClientService.CallAsync<List<string>>("LoggingService", "LoadLog", logSource, maxLines, logOrder);
|
||||
|
||||
ProcessLines();
|
||||
}
|
||||
|
||||
private void ProcessLines()
|
||||
{
|
||||
logLines.Clear();
|
||||
if (allLines == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var lastLogLine = default(LogLine);
|
||||
|
||||
foreach (var line in allLines)
|
||||
{
|
||||
var strings = line.Split('|');
|
||||
|
||||
if (strings.Count() == 4)
|
||||
{
|
||||
lastLogLine = new LogLine(strings[0], strings[1], strings[2], strings[3]);
|
||||
|
||||
logLines.Add(lastLogLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task LogLevelInput(ChangeEventArgs e)
|
||||
{
|
||||
var value = e.Value ?? NLog.LogLevel.Debug.Name;
|
||||
await _rpcClientService.CallAsync<bool>("LoggingService", "SetLogLevel", value);
|
||||
}
|
||||
|
||||
private async Task LogLevelFilterInput(ChangeEventArgs e)
|
||||
{
|
||||
var value = e.Value as string ?? NLog.LogLevel.Debug.Name;
|
||||
logLevelFilter = NLog.LogLevel.FromString(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Services;
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal modal-lg" id="ditheringModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Test dithering</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1">
|
||||
<div class="row">
|
||||
@if (displayPresets != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="mode">Display</label>
|
||||
<select class="form-select" id="mode" @bind="SelectedDisplayId" disabled="@(displayPresets.Count <= 1)">
|
||||
@foreach (var display in displayPresets)
|
||||
{
|
||||
<option value="@display.DisplayId">@display.displayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (Preset == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="state">State</label>
|
||||
<select class="form-select" id="state" @bind="Preset.NvDitherState" @bind:after="ApplyNormalPreset">
|
||||
@foreach (var state in Enum.GetValues<NvDitherState>())
|
||||
{
|
||||
<option value="@state.ToString()">@state.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="mode">Mode</label>
|
||||
<select class="form-select" id="mode" @bind="Preset.NvDitherMode" @bind:after="ApplyNormalPreset">
|
||||
@foreach (var mode in Enum.GetValues<NvDitherMode>())
|
||||
{
|
||||
<option value="@mode.ToString()">@mode.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="bits">Bit depth</label>
|
||||
<select class="form-select" id="bits" @bind="Preset.NvDitherBits" @bind:after="ApplyNormalPreset">
|
||||
@foreach (var bits in Enum.GetValues<NvDitherBits>())
|
||||
{
|
||||
<option value="@bits.ToString()">@bits.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<div class="btn-group ms-2 mb-2">
|
||||
<button type="button" class="btn btn-sm btn-primary dropdown-toggle me-2" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Gradient
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" @onclick="() => GradientColor = GrayGradient">Grayscale</a></li>
|
||||
<li><a class="dropdown-item" @onclick="() => GradientColor = RedGradient">Red</a></li>
|
||||
<li><a class="dropdown-item" @onclick="() => GradientColor = GreenGradient">Green</a></li>
|
||||
<li><a class="dropdown-item" @onclick="() => GradientColor = BlueGradient">Blue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mb-2 col-24 mx-2" style="height: 200px; background: linear-gradient(to right, #000000 0%, @GradientColor 100%)">
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<span class="me-auto">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="SetDitherRegistryKeyOnClick">Set dither registry key</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="RestartDriverOnClick">Restart driver</button>
|
||||
</span>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
public const string GrayGradient = "#ffffff";
|
||||
public const string RedGradient = "#ff0000";
|
||||
public const string GreenGradient = "#00ff00";
|
||||
public const string BlueGradient = "#0000ff";
|
||||
|
||||
private bool _visible;
|
||||
|
||||
[Parameter]
|
||||
public bool Visible { get; set; }
|
||||
|
||||
public NvPreset? Preset { get; set; }
|
||||
|
||||
private string? SelectedDisplayId { get; set; }
|
||||
private List<NvPreset>? displayPresets;
|
||||
private string GradientColor { get; set; } = GrayGradient;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (_visible != Visible)
|
||||
{
|
||||
_visible = Visible;
|
||||
|
||||
if (Visible)
|
||||
{
|
||||
await GetSettingsAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task GetSettingsAsync()
|
||||
{
|
||||
displayPresets = await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetDisplayPresets");
|
||||
if (displayPresets?.Any() == true)
|
||||
{
|
||||
Preset = displayPresets.FirstOrDefault(d => d.DisplayConfig.IsPrimary == true) ?? displayPresets.First();
|
||||
SelectedDisplayId = Preset.DisplayId;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DitherOnChange(EventArgs e)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Preset.applyDithering = true;
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("NvService", "ApplyPresetWithId", Preset.id);
|
||||
}
|
||||
|
||||
private async Task ApplyNormalPreset()
|
||||
{
|
||||
await ApplyPreset();
|
||||
}
|
||||
|
||||
private async Task SetDitherRegistryKeyOnClick(MouseEventArgs e)
|
||||
{
|
||||
await ApplyPreset(true);
|
||||
}
|
||||
|
||||
private async Task RestartDriverOnClick(MouseEventArgs e)
|
||||
{
|
||||
await ApplyPreset(true, true);
|
||||
}
|
||||
|
||||
private async Task ApplyPreset(bool setRegistryKey = false, bool restartDriver = false)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Preset.applyDithering = true;
|
||||
Preset.SetDitherRegistryKey = setRegistryKey;
|
||||
Preset.RestartDriver = restartDriver;
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("NvService", "ApplyPreset", Preset);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Services;
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal modal-lg" id="driverSettingsModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" @onfocus="OnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Preset != null ? Preset.IsDisplayPreset ? $"Driver settings for display {Preset.displayName}" : $"Driver settings for {Preset.IdOrName}" : "Driver settings")</h5>
|
||||
@if (Preset == null)
|
||||
{
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn-close" data-bs-toggle="modal" data-bs-target="#presetModal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1">
|
||||
|
||||
@if (ProfileNames != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="profileName">Profile</label>
|
||||
<select class="form-select" id="profileName" @bind="CurrentProfileName" @bind:after="ProfileOnChange">
|
||||
@foreach (var profileName in ProfileNames)
|
||||
{
|
||||
<option value="@profileName">@profileName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="accordion accordion-flush" id="driverSettingsAccordion">
|
||||
@if (Groups != null)
|
||||
{
|
||||
foreach (var group in Groups)
|
||||
{
|
||||
var groupId = $"{group.Name.Replace(' ', '_')}Settings";
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2 @(group.HasChangedSettings ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#@groupId">
|
||||
@group.Name
|
||||
</button>
|
||||
</h2>
|
||||
<div id="@groupId" class="accordion-collapse collapse" data-bs-parent="#driverSettingsAccordion">
|
||||
<div class="accordion-body">
|
||||
@foreach (var setting in group.DriverSettings)
|
||||
{
|
||||
if (NvSettingConstants.RangeDriverSettings.Contains(setting.SettingId) && setting.Values != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label @(setting.Value != setting.DefaultValue && setting.Value != NvSettingConstants.UnsetDwordValue ? "text-warning fw-bold" : "")" for="@setting.SettingId">@setting.SettingText (@setting.Value)</label>
|
||||
<input class="form-range" type="range" min="@setting.Values.Min(v => v.Value)" max="@setting.Values.Max(v => v.Value)" @bind="setting.Value" id="@setting.SettingId">
|
||||
</div>
|
||||
}
|
||||
else if (setting.Values != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label @(setting.Value != setting.DefaultValue && setting.Value != NvSettingConstants.UnsetDwordValue ? "text-warning fw-bold" : "")" for="@setting.SettingId">@setting.SettingText</label>
|
||||
<select class="form-select" id="@setting.SettingId" @bind="setting.Value">
|
||||
@if (Preset != null)
|
||||
{
|
||||
<option value="@(NvSettingConstants.UnsetDwordValue)">Unchanged</option>
|
||||
}
|
||||
@foreach (var settingValue in setting.Values)
|
||||
{
|
||||
<option value="@settingValue.Value" class="@(setting.DefaultValue == settingValue.Value ? "text-success" : "")">@settingValue.ValueName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@if (Preset == null)
|
||||
{
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @onclick="ApplyClick">Apply</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="ApplyClick">Save</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
|
||||
public class GroupedSettings
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public List<NvSettingItemDto> DriverSettings { get; private set; }
|
||||
public bool HasChangedSettings { get; private set; }
|
||||
|
||||
public GroupedSettings(string name, List<NvSettingItemDto> settings, bool hasChangedSettings)
|
||||
{
|
||||
Name = name;
|
||||
DriverSettings = settings;
|
||||
HasChangedSettings = hasChangedSettings;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private NvPreset? _preset;
|
||||
|
||||
[Parameter]
|
||||
public NvPreset? Preset { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<NvPreset, Task>? AfterApply { get; set; }
|
||||
|
||||
private List<GroupedSettings>? Groups { get; set; }
|
||||
private List<NvSettingItemDto>? DriverSettings { get; set; }
|
||||
private List<string>? ProfileNames { get; set; }
|
||||
private string? CurrentProfileName { get; set; }
|
||||
|
||||
private bool IsVisible { get; set; }
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (_preset != Preset)
|
||||
{
|
||||
_preset = Preset;
|
||||
CurrentProfileName = Preset?.DriverProfileName;
|
||||
DriverSettings = null;
|
||||
await LoadDriverSettings();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task LoadDriverSettings()
|
||||
{
|
||||
DriverSettings = await _rpcClientService.CallAsync<List<NvSettingItemDto>>("NvService", "GetDriverSettings", CurrentProfileName);
|
||||
if (DriverSettings != null)
|
||||
{
|
||||
DriverSettings.ForEach(s => s.ValueChanged = false);
|
||||
}
|
||||
|
||||
if (DriverSettings != null)
|
||||
{
|
||||
if (Preset != null)
|
||||
{
|
||||
foreach (var setting in DriverSettings)
|
||||
{
|
||||
setting.Value = setting.DefaultValue;
|
||||
setting.ValueChanged = false;
|
||||
}
|
||||
|
||||
foreach (var presetSetting in Preset.driverSettings)
|
||||
{
|
||||
var setting = DriverSettings.FirstOrDefault(s => s.SettingId == presetSetting.Key);
|
||||
|
||||
if (setting == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
setting.Value = presetSetting.Value;
|
||||
//setting.ValueChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
Groups = DriverSettings.OrderBy(s => s.GroupName).GroupBy(s => s.GroupName).Select(g =>
|
||||
{
|
||||
var settings = g.ToList();
|
||||
var changedSettings = settings.Any(s => s.Value != s.DefaultValue && s.Value != NvSettingConstants.UnsetDwordValue);
|
||||
|
||||
var group = new GroupedSettings(g.Key, g.ToList(), changedSettings);
|
||||
|
||||
return group;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (DriverSettings == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var changedSettings = DriverSettings.Where(s => s.ValueChanged);
|
||||
|
||||
if (Preset != null)
|
||||
{
|
||||
Preset.UpdateDriverSettings(changedSettings);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var changedSettingsDictionary = changedSettings.ToDictionary(k => k.SettingId, v => v.Value);
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("NvService", "SetDriverSettings", changedSettingsDictionary, CurrentProfileName);
|
||||
}
|
||||
|
||||
private async Task ProfileOnChange()
|
||||
{
|
||||
if (CurrentProfileName?.Contains("Base") == true)
|
||||
{
|
||||
CurrentProfileName = null;
|
||||
}
|
||||
|
||||
if (Preset != null)
|
||||
{
|
||||
Preset.DriverProfileName = CurrentProfileName;
|
||||
}
|
||||
|
||||
DriverSettings = null;
|
||||
|
||||
await LoadDriverSettings();
|
||||
}
|
||||
|
||||
private async Task OnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
IsVisible = true;
|
||||
ProfileNames ??= await _rpcClientService.CallAsync<List<string>>("NvService", "GetDriverProfileNames");
|
||||
await LoadDriverSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,618 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common;
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal" id="presetModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" @onfocus="ModalOnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Preset?.IsDisplayPreset == true ? $"Settings for display {Preset?.displayName}" : Preset?.id == 0 ? $"Settings for new preset" : $"Settings of preset {Preset?.IdOrName}")</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1 needs-validation @WasValidated" novalidate>
|
||||
@if (Preset == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">Name</label>
|
||||
<input class="form-control" type="text" @bind="Preset.name" required />
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.ShowInQuickAccess" id="showInQuickAccess">
|
||||
<label class="form-check-label" for="showInQuickAccess">
|
||||
Show in Quick Access
|
||||
</label>
|
||||
</div>
|
||||
<ShortcutInput Label="Shortcut" @bind-Shortcut="Preset.shortcut" />
|
||||
}
|
||||
<div class="accordion accordion-flush" id="presetAccordion">
|
||||
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem; visibility: hidden" type="checkbox">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#displaySettings">
|
||||
Display
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="displaySettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.primaryDisplay" id="primaryDisplay">
|
||||
<label class="form-check-label" for="primaryDisplay">
|
||||
Primary display
|
||||
</label>
|
||||
</div>
|
||||
@if (displayPresets != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="mode">Display</label>
|
||||
<select class="form-select" id="mode" @bind="Preset.DisplayId" disabled="@(Preset.primaryDisplay)">
|
||||
@foreach (var display in displayPresets)
|
||||
{
|
||||
<option value="@display.DisplayId">@display.displayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.DisplayConfig.IsPrimary" id="setAsPrimaryDisplay" disabled="@(Preset.primaryDisplay)">
|
||||
<label class="form-check-label" for="setAsPrimaryDisplay">
|
||||
Set display as primary display
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (resolutions != null)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.DisplayConfig.ApplyResolution" id="applyResolution">
|
||||
}
|
||||
<button class="accordion-button py-2 @(!Preset.IsDisplayPreset ? "collapsed" : "") @(Preset.DisplayConfig.ApplyResolution ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#resolutionSettings">
|
||||
Resolution
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="resolutionSettings" class="accordion-collapse collapse @(Preset.IsDisplayPreset ? "show" : "")" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
@if (resolutions != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="activeResolution">Active resolution</label>
|
||||
<select class="form-select" id="activeResolution" @bind="selectedActiveResolution">
|
||||
<option value="0x0">Not set</option>
|
||||
@foreach (var resolution in resolutions)
|
||||
{
|
||||
<option value="@resolution.GetActiveString()">@resolution.GetActiveString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="virtualResolution">Virtual resolution</label>
|
||||
<select class="form-select" id="virtualResolution" @bind="selectedVirtualResolution">
|
||||
<option value="0x0">Not set</option>
|
||||
@foreach (var resolution in resolutions)
|
||||
{
|
||||
<option value="@resolution.GetVirtualString()">@resolution.GetVirtualString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="scaling">Scaling/Aspect ratio</label>
|
||||
<select class="form-select" id="scaling" @bind="Preset.DisplayConfig.Scaling">
|
||||
@foreach (var scaling in Enum.GetValues<Shared.Native.CCD.DisplayConfigScaling>().Where(s => s != Shared.Native.CCD.DisplayConfigScaling.ForceUint32))
|
||||
{
|
||||
<option value="@scaling.ToString()">@scaling.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="rotation">Rotation</label>
|
||||
<select class="form-select" id="rotation" @bind="Preset.DisplayConfig.Rotation">
|
||||
@foreach (var rotation in Enum.GetValues<Shared.Native.CCD.DisplayConfigRotation>().Where(s => s != Shared.Native.CCD.DisplayConfigRotation.ForceUint32))
|
||||
{
|
||||
<option value="@rotation.ToString()">@rotation.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (refreshRates != null)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.DisplayConfig.ApplyRefreshRate" id="applyRefreshRate">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.DisplayConfig.ApplyRefreshRate ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#refreshRateSettings">
|
||||
Refresh Rate
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="refreshRateSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
@if (refreshRates != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="refreshRate">Refresh Rate</label>
|
||||
<select class="form-select" id="refreshRate" @bind="selectedRefreshRate">
|
||||
@foreach (var refreshRate in refreshRates)
|
||||
{
|
||||
<option value="@refreshRate.ToString()">@refreshRate.ToString() Hz</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyColorData" id="applyColorData">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyColorData ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#colorSettings">
|
||||
Color settings
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="colorSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.colorData.UseDefaultSettings" id="useDefaultSettings">
|
||||
<label class="form-check-label" for="useDefaultSettings">
|
||||
Use default settings
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="bitDepth">Bit depth</label>
|
||||
<select class="form-select" id="bitDepth" @bind="Preset.colorData.ColorDepth" disabled="@Preset.colorData.UseDefaultSettings">
|
||||
@foreach (var bitDepth in Enum.GetValues<ColorDataDepth>())
|
||||
{
|
||||
<option value="@bitDepth.ToString()">@bitDepth.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="colorFormat">Format</label>
|
||||
<select class="form-select" id="colorFormat" @bind="Preset.colorData.ColorFormat" disabled="@Preset.colorData.UseDefaultSettings">
|
||||
@foreach (var format in Enum.GetValues<ColorDataFormat>())
|
||||
{
|
||||
<option value="@format.ToString()">@format.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="dynamicRange">Dynamic range</label>
|
||||
<select class="form-select" id="dynamicRange" @bind="Preset.colorData.DynamicRange" disabled="@Preset.colorData.UseDefaultSettings">
|
||||
@foreach (var range in Enum.GetValues<ColorDataDynamicRange>())
|
||||
{
|
||||
<option value="@range.ToString()">@range.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="colorimetry">Color space</label>
|
||||
<select class="form-select" id="colorimetry" @bind="Preset.colorData.Colorimetry" disabled="@Preset.colorData.UseDefaultSettings">
|
||||
@foreach (var space in Enum.GetValues<ColorDataColorimetry>())
|
||||
{
|
||||
<option value="@space.ToString()">@space.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.ApplyColorEnhancements" id="ApplyColorEnhancements">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.ApplyColorEnhancements ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#colorEnhancements">
|
||||
Color enhancements
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="colorEnhancements" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="digitalVibrance">Digital vibrance: @Preset.ColorEnhancementSettings.DigitalVibranceLevel</label>
|
||||
<input class="form-range" type="range" min="0" max="100" @bind="Preset.ColorEnhancementSettings.DigitalVibranceLevel" id="digitalVibrance">
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="hue">Hue: @Preset.ColorEnhancementSettings.HueAngle°</label>
|
||||
<input class="form-range" type="range" min="0" max="359" @bind="Preset.ColorEnhancementSettings.HueAngle" id="hue">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyDriverSettings" id="applyDriverSettings">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyDriverSettings ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#driverSettings">
|
||||
Driver settings
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="driverSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-3">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-bs-target="#driverSettingsModal" data-bs-toggle="modal" @onclick="DriverSettingsOnClick">Open driver settings</button>
|
||||
<span>@Preset.driverSettings.Count settings configured</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.ApplyNovideoSettings" id="applyNovideo">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.ApplyNovideoSettings ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#novideoSettings">
|
||||
Novideo settings
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="novideoSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.NovideoSettings.ApplyClamp" id="applyClamp">
|
||||
<label class="form-check-label" for="applyClamp">
|
||||
Apply clamp
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="novideoColorSpace">Target color space</label>
|
||||
<select class="form-select" id="novideoColorSpace" @bind="Preset.NovideoSettings.ColorSpace">
|
||||
@foreach (var colorSpace in Enum.GetValues<NovideoColorSpace>())
|
||||
{
|
||||
<option value="@colorSpace.ToString()">@colorSpace.ToString()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyDithering" id="applyDithering">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyDithering ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#ditherSettings">
|
||||
Dithering
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="ditherSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="state">State</label>
|
||||
<select class="form-select" id="state" @bind="Preset.NvDitherState">
|
||||
@foreach (var state in Enum.GetValues<NvDitherState>())
|
||||
{
|
||||
<option value="@state.ToString()">@state.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="mode">Mode</label>
|
||||
<select class="form-select" id="mode" @bind="Preset.NvDitherMode">
|
||||
@foreach (var mode in Enum.GetValues<NvDitherMode>())
|
||||
{
|
||||
<option value="@mode.ToString()">@mode.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="bits">Bit depth</label>
|
||||
<select class="form-select" id="bits" @bind="Preset.NvDitherBits">
|
||||
@foreach (var bits in Enum.GetValues<NvDitherBits>())
|
||||
{
|
||||
<option value="@bits.ToString()">@bits.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyHDR" id="applyHDR">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyHDR ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#hdrSettings">
|
||||
HDR
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="hdrSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.HDREnabled" id="hdrEnabled">
|
||||
<label class="form-check-label" for="hdrEnabled">
|
||||
HDR enabled
|
||||
</label>
|
||||
</div>
|
||||
@if (!Preset.IsDisplayPreset) {
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.toggleHDR" id="toggleHdr">
|
||||
<label class="form-check-label" for="toggleHdr">
|
||||
Toggle HDR
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="mode">Output mode</label>
|
||||
<select class="form-select" id="mode" @bind="Preset.HdrSettings.DisplayOutputMode">
|
||||
@foreach (var mode in Enum.GetValues<NvOutputMode>())
|
||||
{
|
||||
<option value="@mode.ToString()">@mode.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-range" for="sdrBrightness">SDR brightness (@Preset.SDRBrightness%)</label>
|
||||
<input class="form-range" type="range" min="0" max="100" @bind="Preset.SDRBrightness" id="sdrBrightness">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (!Preset.IsDisplayPreset || Preset.MonitorConnectionType == NvAPIWrapper.Native.GPU.MonitorConnectionType.HDMI)
|
||||
{
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<span class="d-flex align-items-baseline">
|
||||
@if (!Preset.IsDisplayPreset)
|
||||
{
|
||||
<input class="form-check-input me-1" style="font-size: 1rem" title="Apply these settings" type="checkbox" @bind="Preset.applyHdmiSettings" id="applyHdmiSettings">
|
||||
}
|
||||
<button class="accordion-button collapsed py-2 @(Preset.applyHdmiSettings ? "text-warning fw-bold" : "")" type="button" data-bs-toggle="collapse" data-bs-target="#hdmiSettings">
|
||||
HDMI settings
|
||||
</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div id="hdmiSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="contentType">Content type</label>
|
||||
<select class="form-select" id="contentType" @bind="Preset.HdmiInfoFrameSettings.ContentType" @oninput="HdmiSettingsOnInput">
|
||||
@foreach (var type in Enum.GetValues<InfoFrameVideoContentType>())
|
||||
{
|
||||
<option value="@type.ToString()">@type.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="colorimetry">Colorimetry</label>
|
||||
<select class="form-select" id="colorimetry" @bind="Preset.HdmiInfoFrameSettings.Colorimetry" @oninput="HdmiSettingsOnInput">
|
||||
@foreach (var colorimetry in Enum.GetValues<InfoFrameVideoColorimetry>())
|
||||
{
|
||||
<option value="@colorimetry.ToString()">@colorimetry.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="extendedColorimetry">Extended colorimetry</label>
|
||||
<select class="form-select" id="extendedColorimetry" @bind="Preset.HdmiInfoFrameSettings.ExtendedColorimetry" @oninput="HdmiSettingsOnInput">
|
||||
@foreach (var extendedColorimetry in Enum.GetValues<InfoFrameVideoExtendedColorimetry>())
|
||||
{
|
||||
<option value="@extendedColorimetry.ToString()">@extendedColorimetry.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="submit" class="btn btn-primary" data-bs-dismiss="@(IsValid() ? "modal" : "")" @onclick="ApplyClick">@(Preset?.IsDisplayPreset == true ? "Apply" : "Save")</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
public NvPreset? Preset { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public NvPreset? PresetParam { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<NvPreset, Task>? AfterApply { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<NvPreset, Task>? SetDriverSettingsPreset { get; set; }
|
||||
|
||||
private string? selectedActiveResolution;
|
||||
private string? selectedVirtualResolution;
|
||||
private string? selectedRefreshRate;
|
||||
|
||||
private List<VirtualResolution>? resolutions;
|
||||
private List<Rational>? refreshRates;
|
||||
private List<NvPreset>? displayPresets;
|
||||
|
||||
private string WasValidated = "";
|
||||
private bool IsVisible;
|
||||
private bool IsDriverSettingsOpened;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (IsDriverSettingsOpened && Preset != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Preset = PresetParam == null ? null : PresetParam.CloneWithId();
|
||||
if (Preset != null && PresetParam != null)
|
||||
{
|
||||
resolutions = await _rpcClientService.CallAsync<List<VirtualResolution>>("NvService", "GetAvailableResolutionsV2", Preset);
|
||||
refreshRates = await _rpcClientService.CallAsync<List<Rational>>("NvService", "GetAvailableRefreshRatesV2", Preset);
|
||||
}
|
||||
selectedActiveResolution = Preset?.DisplayConfig.Resolution?.GetActiveString();
|
||||
selectedVirtualResolution = Preset?.DisplayConfig.Resolution?.GetVirtualString();
|
||||
selectedRefreshRate = Preset?.DisplayConfig.RefreshRate?.ToString();
|
||||
|
||||
if (Preset?.IsDisplayPreset != true)
|
||||
{
|
||||
displayPresets = await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetDisplayPresets");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
{
|
||||
// if (IsVisible && Preset?.IsDisplayPreset == false)
|
||||
// {
|
||||
// Preset.UpdateAutoApplySettings(keepChanges: true);
|
||||
// }
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
WasValidated = "was-validated";
|
||||
return;
|
||||
}
|
||||
|
||||
var newResolution = resolutions?.FirstOrDefault(r => r.GetActiveString() == selectedActiveResolution);
|
||||
if (newResolution != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(selectedVirtualResolution) && selectedActiveResolution != selectedVirtualResolution)
|
||||
{
|
||||
newResolution = new VirtualResolution(newResolution.ActiveWidth, newResolution.ActiveHeight);
|
||||
var parts = selectedVirtualResolution.Split('x');
|
||||
newResolution.VirtualWidth = uint.Parse(parts[0]);
|
||||
newResolution.VirtualHeight = uint.Parse(parts[1]);
|
||||
}
|
||||
Preset.DisplayConfig.Resolution = newResolution;
|
||||
}
|
||||
else
|
||||
{
|
||||
Preset.DisplayConfig.Resolution = new VirtualResolution(0, 0);
|
||||
}
|
||||
|
||||
var newRefreshRate = refreshRates?.FirstOrDefault(r => r.ToString() == selectedRefreshRate);
|
||||
if (newRefreshRate != null)
|
||||
{
|
||||
Preset.DisplayConfig.RefreshRate = newRefreshRate;
|
||||
}
|
||||
|
||||
Preset.ApplyNovideoSettings = Preset.NovideoSettings.ApplyClamp;
|
||||
|
||||
if (Preset.IsDisplayPreset)
|
||||
{
|
||||
Preset.UpdateAutoApplySettings(PresetParam);
|
||||
|
||||
await ApplyDisplayPreset();
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await _rpcClientService.CallAsync<bool>("NvService", "UpdatePreset", Preset);
|
||||
}
|
||||
|
||||
if (AfterApply != null)
|
||||
{
|
||||
await AfterApply.Invoke(Preset);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyDisplayPreset()
|
||||
{
|
||||
var result = await _rpcClientService.CallAsync<bool>("NvService", "ApplyPreset", Preset);
|
||||
}
|
||||
|
||||
private void HdmiSettingsOnInput(ChangeEventArgs e)
|
||||
{
|
||||
Preset!.applyHdmiSettings = true;
|
||||
}
|
||||
|
||||
private async Task DriverSettingsOnClick(MouseEventArgs e)
|
||||
{
|
||||
IsDriverSettingsOpened = true;
|
||||
SetDriverSettingsPreset?.Invoke(Preset!);
|
||||
}
|
||||
|
||||
private void ModalOnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (IsVisible && IsDriverSettingsOpened)
|
||||
{
|
||||
IsDriverSettingsOpened = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
if (!IsVisible)
|
||||
{
|
||||
WasValidated = "";
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValid()
|
||||
{
|
||||
return Preset?.IsDisplayPreset == true || !string.IsNullOrEmpty(Preset?.name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<div class="modal" id="settingsModal" tabindex="-1" @onfocus="OnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">NVIDIA settings</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => Config = null"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1">
|
||||
@if (Config == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ShortcutInput Label="Quick Access Shortcut" @bind-Shortcut="Config.QuickAccessShortcut" />
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="Config.ShowOverclocking" id="showOverclocking">
|
||||
<label class="form-check-label" for="showOverclocking">
|
||||
Show overclocking
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="Config.ApplyNovideoOnStartup" id="applyNovideoOnStartup">
|
||||
<label class="form-check-label" for="applyNovideoOnStartup">
|
||||
Apply Novideo settings on startup
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => Config = null">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private NvServiceConfig? Config { get; set; }
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Config == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("NvService", "UpdateConfig", Config);
|
||||
|
||||
if (result)
|
||||
{
|
||||
Config = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (Config != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Config = await _rpcClientService.CallAsync<NvServiceConfig>("NvService", "GetConfig");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
@page "/NVIDIA"
|
||||
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject ProtectedLocalStorage _localStorage
|
||||
|
||||
<PageTitle>NVIDIA controller</PageTitle>
|
||||
|
||||
<NvidiaSettings />
|
||||
<NvidiaDithering Visible="DitheringVisible" />
|
||||
<NvidiaDriverSettings Preset="CurrentDriverSettingsPreset" />
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<h1>NVIDIA controller</h1>
|
||||
<div class="d-flex ms-auto">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-primary dropdown-toggle me-2" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Tools
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#ditheringModal" @onclick="() => DitheringVisible = true">Test dithering</a></li>
|
||||
<li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#driverSettingsModal" @onclick="() => CurrentDriverSettingsPreset = null">Driver settings</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#settingsModal">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Displays</h2>
|
||||
|
||||
<NvidiaPreset PresetParam="CurrentPreset" AfterApply="AfterPresetApplied" SetDriverSettingsPreset="SetDriverSettingsPreset" />
|
||||
<ConfirmModal Title="Delete preset" Message="Are you sure you want to delete the preset?" OnConfirm="PresetOnDeleteConfirmed" />
|
||||
|
||||
@if (DisplayPresets == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row mb-3">
|
||||
@if (!DisplayPresets.Any())
|
||||
{
|
||||
<span>No displays found</span>
|
||||
}
|
||||
@foreach (var preset in DisplayPresets)
|
||||
{
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex align-items-baseline">
|
||||
<span>
|
||||
@preset.displayName
|
||||
@if (preset.DisplayConfig.IsPrimary == true)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-primary" title="Primary display">Primary</span>
|
||||
}
|
||||
</span>
|
||||
<div class="d-flex ms-auto">
|
||||
<button type="button" class="btn btn-sm btn-primary ms-2" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => DisplayPresetOnClick(preset)">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<small class="text-body">@preset.DisplayConfig.Resolution.ToString() @@ @preset.DisplayConfig.RefreshRate.ToString()Hz</small>
|
||||
<small class="text-muted">@preset.colorData</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Presets == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2 d-flex align-items-center">
|
||||
<h2>Presets</h2>
|
||||
<div class="d-flex ms-auto">
|
||||
<select class="form-select me-2" id="presetOrder" @bind="PresetOrder" @bind:after="PresetOrderChanged">
|
||||
@foreach (var order in Enum.GetValues<PresetOrder>())
|
||||
{
|
||||
<option value="@order">Order by: @order.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => AddPresetOnClick()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="list-group">
|
||||
@foreach (var preset in Presets)
|
||||
{
|
||||
<a class="list-group-item list-group-item-action" @onclick="() => PresetOnClick(preset)" @onclick:preventDefault @onclick:stopPropagation>
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div>
|
||||
<h5 class="mb-1">
|
||||
@preset.name <small class="text-muted">@(preset.primaryDisplay ? "Primary display" : preset.displayName)</small>
|
||||
@if (preset.ShowInQuickAccess)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-warning" title="Show in Quick Access">QA</span>
|
||||
}
|
||||
</h5>
|
||||
</div>
|
||||
<span>
|
||||
<button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#confirmModal" @onclick="() => PresetOnDeleteClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Delete</button>
|
||||
<button class="btn btn-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnCloneClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Clone</button>
|
||||
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnEditClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Edit</button>
|
||||
</span>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
@preset.DisplayConfig.Resolution.ToString() @@ @preset.DisplayConfig.RefreshRate.ToString()Hz
|
||||
@(preset.applyColorData ? " " + preset.colorData : "")
|
||||
@if (preset.ApplyColorEnhancements)
|
||||
{
|
||||
<span>, @preset.ColorEnhancementSettings</span>
|
||||
}
|
||||
@if (preset.applyHDR)
|
||||
{
|
||||
<span>, HDR: @preset.GetHdrDescription()</span>
|
||||
}
|
||||
@if (preset.applyDriverSettings)
|
||||
{
|
||||
<span>, @preset.driverSettings.Count changed driver settings</span>
|
||||
}
|
||||
@if (preset.ApplyNovideoSettings)
|
||||
{
|
||||
<span>, @preset.NovideoSettings</span>
|
||||
}
|
||||
</p>
|
||||
<small class="text-muted">@preset.shortcut</small>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<NvPreset>? Presets;
|
||||
private List<NvPreset>? DisplayPresets;
|
||||
|
||||
private NvPreset? CurrentPreset;
|
||||
private NvPreset? CurrentDriverSettingsPreset;
|
||||
private bool DitheringVisible;
|
||||
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await RefreshPresets();
|
||||
DisplayPresets = await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetDisplayPresets");
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstTime)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
PresetOrder = await _localStorage.TryGet<PresetOrder>("NvidiaPresetOrder");
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PresetOnClick(NvPreset preset)
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("NvService", "ApplyPresetWithId", preset.id);
|
||||
}
|
||||
|
||||
private async Task PresetOnEditClick(NvPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnCloneClick(NvPreset preset)
|
||||
{
|
||||
CurrentPreset = new NvPreset(preset);
|
||||
CurrentPreset.name = preset.name;
|
||||
CurrentPreset.SetCloneValues();
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteClick(NvPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteConfirmed()
|
||||
{
|
||||
if (CurrentPreset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("NvService", "DeletePreset", CurrentPreset.id);
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task DisplayPresetOnClick(NvPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task AddPresetOnClick()
|
||||
{
|
||||
CurrentPreset = new NvPreset();
|
||||
}
|
||||
|
||||
private async Task AfterPresetApplied(NvPreset preset)
|
||||
{
|
||||
if (preset.IsDisplayPreset)
|
||||
{
|
||||
DisplayPresets = await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetDisplayPresets");
|
||||
}
|
||||
else
|
||||
{
|
||||
await RefreshPresets();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task SetDriverSettingsPreset(NvPreset preset)
|
||||
{
|
||||
CurrentDriverSettingsPreset = preset;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task PresetOrderChanged()
|
||||
{
|
||||
await _localStorage.SetAsync("NvidiaPresetOrder", PresetOrder);
|
||||
await RefreshPresets();
|
||||
}
|
||||
|
||||
private async Task RefreshPresets()
|
||||
{
|
||||
Presets = await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetPresets");
|
||||
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
@page "/options"
|
||||
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<PageTitle>Options</PageTitle>
|
||||
|
||||
<h1>Options</h1>
|
||||
|
||||
@if (config == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">General</h5>
|
||||
<form>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.AutoStart" id="startAfterLogin" @oninput="StartAfterLoginInput">
|
||||
<label class="form-check-label" for="startAfterLogin">
|
||||
Automatically start after login
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.CheckForUpdates" id="checkForUpdates" @oninput="CheckForUpdatesInput">
|
||||
<label class="form-check-label" for="checkForUpdates">
|
||||
Automatically check for updates
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.AutoInstallUpdates" id="autoInstallUpdates" @oninput="AutoInstallUpdatesInput">
|
||||
<label class="form-check-label" for="autoInstallUpdates">
|
||||
Automatically install updates
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="elevationMethod">
|
||||
Elevation Method
|
||||
</label>
|
||||
<select class="form-select" @bind="config.ElevationMethod" id="elevationMethod" @oninput="ElevationMethodInput" aria-describedby="elevationMethodHelp">
|
||||
@foreach (var method in Enum.GetValues<ElevationMethod>())
|
||||
{
|
||||
<option value="@method">@method.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
<div id="elevationMethodHelp" class="form-text">
|
||||
Elevation is needed in some cases where ColorControl needs administrator rights.
|
||||
Some operations like installing a service, changing the priority of a process or creating a temporary IP-route for improved WOL-functionality will not work without those rights.
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">UI-settings</h5>
|
||||
<form>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="uiType">Default UI</label>
|
||||
<select class="form-select" id="uiType" @bind="config.UiType" @oninput="UiTypeOnInput">
|
||||
@foreach (var type in Enum.GetValues<UiType>())
|
||||
{
|
||||
<option value="@type.ToString()">@type.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="webUiPort">
|
||||
Web UI port
|
||||
</label>
|
||||
<input class="form-control" type="number" @bind="config.UiPort" id="webUiPort" @bind:after="UiPortBlur">
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.MinimizeOnClose" id="minimizeOnClose" @oninput="MinimizeOnCloseInput">
|
||||
<label class="form-check-label" for="minimizeOnClose">
|
||||
Minimize on close
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.StartMinimized" id="startMinimized" @oninput="StartMinimizedInput">
|
||||
<label class="form-check-label" for="startMinimized">
|
||||
Start minimized
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.MinimizeToTray" id="minimizeToTray" @oninput="MinimizeToTrayInput">
|
||||
<label class="form-check-label" for="minimizeToTray">
|
||||
Minimize to system tray
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.UseDarkMode" id="useDarkMode" @oninput="UseDarkModeInput">
|
||||
<label class="form-check-label" for="useDarkMode">
|
||||
Dark Mode
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Modules</h5>
|
||||
<form>
|
||||
@foreach (var module in config.Modules)
|
||||
{
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="@("module_" + module.DisplayName)" @bind="module.IsActive" @oninput="(ChangeEventArgs e) => ModuleOnInput(module, e)">
|
||||
<label class="form-check-label" for="@("module_" + module.DisplayName)">@module.DisplayName</label>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Advanced</h5>
|
||||
<form>
|
||||
<div class="mb-3 form-check">
|
||||
<label class="form-range" for="processMonitorPollingInterval">
|
||||
Polling interval of process monitor (@config.ProcessMonitorPollingInterval milliseconds)
|
||||
</label>
|
||||
<input class="form-range" type="range" min="50" max="10000" step="50" @bind="config.ProcessMonitorPollingInterval" id="processMonitorPollingInterval" aria-describedby="processMonitorPollingIntervalHelp" @bind:after="PollingIntervalOnInput">
|
||||
<div id="processMonitorPollingIntervalHelp" class="form-text">Decreasing this delay may execute triggered presets sooner but can cause a higher CPU load</div>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.UseRawInput" id="useRawInput" aria-describedby="useRawInputHelp" @oninput="UseRawInputInput">
|
||||
<label class="form-check-label" for="useRawInput">
|
||||
Use Raw Input for shortcuts (hot keys)
|
||||
</label>
|
||||
<div id="useRawInputHelp" class="form-text">This enables shortcuts to work during applications/games that block certain keys (like WinKey or Control). NOTE: if the application in the foreground runs with higher privileges than ColorControl, Raw Input does not work and normal hot keys are used</div>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.SetMinTmlAndMaxTml" id="setMinTmlAndMaxTml" @oninput="SetMinMaxTmlInput">
|
||||
<label class="form-check-label" for="setMinTmlAndMaxTml">
|
||||
Set MinTML and MaxTML when applying color profiles
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.DisableErrorPopupWhenApplyingPreset" id="disableErrorPopupWhenApplyingPreset" @oninput="DisableErrorPopupInput">
|
||||
<label class="form-check-label" for="disableErrorPopupWhenApplyingPreset">
|
||||
Disable error popup when applying presets
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Miscellaneous</h5>
|
||||
<form>
|
||||
<div class="mb-3 form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="config.FixChromeFonts" id="fixChromeFonts" aria-describedby="fixChromeFontsHelp" @bind:after="FixChromeFontsInput">
|
||||
<label class="form-check-label" for="fixChromeFonts">
|
||||
ClearType: fix the bad fonts in Chrome when using a monitor with a different pixel structure
|
||||
</label>
|
||||
<div id="fixChromeFontsHelp" class="form-text">This will add the parameter --disable-lcd-text to Chrome which enables grayscale anti-aliasing</div>
|
||||
</div>
|
||||
<ShortcutInput Label="Shortcut to start the blank screensaver" @bind-Shortcut="config.ScreenSaverShortcut" @bind-Shortcut:after="UpdateScreenSaverShortcut" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
private Config? config;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
config = await _rpcClientService.CallAsync<Config>("OptionsService", "GetConfig");
|
||||
}
|
||||
|
||||
private async Task SaveConfig()
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("OptionsService", "SetConfig", config);
|
||||
}
|
||||
|
||||
private async Task UseDarkModeInput(ChangeEventArgs e)
|
||||
{
|
||||
var value = e.Value != null ? (bool)e.Value : false;
|
||||
var result = await UpdateBoolSetting("SetDarkMode", e);
|
||||
|
||||
if (result)
|
||||
{
|
||||
AppState.SetTheme(value ? "dark" : "light");
|
||||
//ThemeTransitionName = AppState.SelectedTheme == "light" ? "Dark theme" : "Light theme";
|
||||
_navigationManager.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task StartAfterLoginInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetStartAfterLogin", e);
|
||||
}
|
||||
|
||||
private async Task MinimizeOnCloseInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetMinimizeOnClose", e);
|
||||
}
|
||||
|
||||
private async Task StartMinimizedInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetStartMinimized", e);
|
||||
}
|
||||
|
||||
private async Task MinimizeToTrayInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetMinimizeToTray", e);
|
||||
}
|
||||
|
||||
private async Task CheckForUpdatesInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetCheckForUpdates", e);
|
||||
}
|
||||
|
||||
private async Task AutoInstallUpdatesInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetAutoInstallUpdates", e);
|
||||
}
|
||||
|
||||
private async Task ModuleOnInput(Module module, ChangeEventArgs e)
|
||||
{
|
||||
module.IsActive = e.Value != null ? (bool)e.Value : false;
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("OptionsService", "UpdateModule", module);
|
||||
|
||||
if (result)
|
||||
{
|
||||
_navigationManager.NavigateTo("/options", true);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PollingIntervalOnInput()
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("OptionsService", "SetProcessMonitorPollingInterval", config!.ProcessMonitorPollingInterval);
|
||||
}
|
||||
|
||||
private async Task UseRawInputInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetUseRawInput", e);
|
||||
}
|
||||
|
||||
private async Task SetMinMaxTmlInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetMinTmlAndMaxTml", e);
|
||||
}
|
||||
|
||||
private async Task DisableErrorPopupInput(ChangeEventArgs e)
|
||||
{
|
||||
await UpdateBoolSetting("SetDisableErrorPopupWhenApplyingPreset", e);
|
||||
}
|
||||
|
||||
private async Task FixChromeFontsInput()
|
||||
{
|
||||
await UpdateBoolSetting2("SetFixChromeFonts", config!.FixChromeFonts);
|
||||
}
|
||||
|
||||
private async Task UpdateScreenSaverShortcut()
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("OptionsService", "SetScreenSaverShortcut", config!.ScreenSaverShortcut);
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateBoolSetting(string method, ChangeEventArgs e)
|
||||
{
|
||||
var value = e.Value != null ? (bool)e.Value : false;
|
||||
return await UpdateBoolSetting2(method, value);
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateBoolSetting2(string method, bool value)
|
||||
{
|
||||
return await _rpcClientService.CallAsync<bool>("OptionsService", method, value);
|
||||
}
|
||||
|
||||
private async Task ElevationMethodInput(ChangeEventArgs e)
|
||||
{
|
||||
var value = e.Value != null ? (ElevationMethod)int.Parse((string)e.Value) : ElevationMethod.None;
|
||||
await _rpcClientService.CallAsync<bool>("OptionsService", "SetElevationMethod", value);
|
||||
}
|
||||
|
||||
private async Task UiTypeOnInput(ChangeEventArgs e)
|
||||
{
|
||||
if (Enum.TryParse<UiType>(e.Value?.ToString(), out var uiType))
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("OptionsService", "SetUiType", uiType);
|
||||
|
||||
config!.UiType = uiType;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UiPortBlur()
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("OptionsService", "SetUiPort", config!.UiPort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.Shared.Services
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal" id="deviceModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" @onfocus="ModalOnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Device?.Name == null ? $"Add new device" : $"Settings of device {Device.Name}")</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1 needs-validation @WasValidated" novalidate>
|
||||
@if (Device == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">Name</label>
|
||||
<input class="form-control" id="name" type="text" @bind="Device.Name" required />
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" @bind="Device.IsCustom" id="isCustom">
|
||||
<label class="form-check-label" for="isCustom">
|
||||
Is custom device
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="ipAddress">IP-address</label>
|
||||
<input class="form-control" id="ipAddress" type="text" @bind="Device.IpAddress" disabled="@(!Device.IsCustom)" required="Device.IsCustom" />
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="macAddress">MAC-address</label>
|
||||
<input class="form-control" id="macAddress" type="text" @bind="Device.MacAddress" disabled="@(!Device.IsCustom)" />
|
||||
</div>
|
||||
@if (!Device.IsConnected)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<button class="btn btn-primary me-2" type="button" disabled="@IsTestingConnection" @onclick="TestConnectionClick">
|
||||
@if (IsTestingConnection)
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm me-1" aria-hidden="true"></span>
|
||||
}
|
||||
<span role="status">Test connection</span>
|
||||
</button>
|
||||
@if (IsTestConnectionSuccessful != null)
|
||||
{
|
||||
if (IsTestConnectionSuccessful == true)
|
||||
{
|
||||
<span class="text-success">Connection test was successful!</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-danger">Connection failed!</span>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="accordion accordion-flush" id="accordion">
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#deviceOptions">
|
||||
Device options
|
||||
</button>
|
||||
</h2>
|
||||
<div id="deviceOptions" class="accordion-collapse collapse" data-bs-parent="#accordion">
|
||||
<div class="accordion-body">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnAfterStartup" @bind="Device.Options.PowerOnAfterStartup">
|
||||
<label class="form-check-label" for="checkPowerOnAfterStartup">Power on after startup</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnAfterResume" @bind="Device.Options.PowerOnAfterResume">
|
||||
<label class="form-check-label" for="checkPowerOnAfterResume">Power on after resume from standby</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOffOnShutdown" @bind="Device.Options.PowerOffOnShutdown">
|
||||
<label class="form-check-label" for="checkPowerOffOnShutdown">Power off on shutdown</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOffOnStandby" @bind="Device.Options.PowerOffOnStandby">
|
||||
<label class="form-check-label" for="checkPowerOffOnStandby">Power off on standby</label>
|
||||
</div>
|
||||
<div class="form-check form-switch mb-2">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOffOnScreensaverStart" @bind="Device.Options.PowerOffOnScreenSaver">
|
||||
<label class="form-check-label" for="checkPowerOffOnScreensaverStart">Power off when screensaver activates</label>
|
||||
<button class="btn btn-sm btn-primary ms-2" type="button" data-bs-toggle="collapse" data-bs-target="#screenSaverSettings" aria-expanded="false" aria-controls="screenSaverSettings">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
<div class="collapse mb-3" id="screenSaverSettings">
|
||||
<div class="card card-body">
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="minScreenSaverDuration">Minimal screen saver duration (seconds)</label>
|
||||
<input class="form-control" id="minScreenSaverDuration" type="number" @bind="Device.Options.ScreenSaverMinimalDuration" />
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkTurnScreenOffInsteadOfPowerOff" @bind="Device.Options.TurnScreenOffOnScreenSaver">
|
||||
<label class="form-check-label" for="checkTurnScreenOffInsteadOfPowerOff">Turn screen off instead of power off</label>
|
||||
<div class="form-text">NOTE: turning the screen off might not work correctly on all models</div>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkTurnScreenOnInsteadOfPowerOn" @bind="Device.Options.TurnScreenOnAfterScreenSaver">
|
||||
<label class="form-check-label" for="checkTurnScreenOnInsteadOfPowerOn">Turn screen on instead of power on</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPerformActionOnManualScreenSaver" @bind="Device.Options.HandleManualScreenSaver">
|
||||
<label class="form-check-label" for="checkPerformActionOnManualScreenSaver">Perform action even on manually executed screen saver</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnOnScreensaverEnd" @bind="Device.Options.PowerOnAfterScreenSaver">
|
||||
<label class="form-check-label" for="checkPowerOnOnScreensaverEnd">Power on when screensaver deactivates</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkPowerOnAfterManualPowerOff" @bind="Device.Options.PowerOnAfterManualPowerOff">
|
||||
<label class="form-check-label" for="checkPowerOnAfterManualPowerOff">Power on even after manual power off</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkAllowTriggers" @bind="Device.Options.TriggersEnabled">
|
||||
<label class="form-check-label" for="checkAllowTriggers">Allow triggers to be fired for this device</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkWindowsPowerOn" @bind="Device.Options.PowerOnByWindows">
|
||||
<label class="form-check-label" for="checkWindowsPowerOn">Use Windows power settings to power on</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkWindowsPowerOff" @bind="Device.Options.PowerOffByWindows">
|
||||
<label class="form-check-label" for="checkWindowsPowerOff">Use Windows power settings to power off</label>
|
||||
</div>
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" id="checkUseSecureConnection" @bind="Device.Options.UseSecureConnection">
|
||||
<label class="form-check-label" for="checkUseSecureConnection">Use secure connection</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="@(IsValid() ? "modal" : "")" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private SamsungDeviceDto? _device;
|
||||
|
||||
[Parameter]
|
||||
public SamsungDeviceDto? Device { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<SamsungDeviceDto, Task>? AfterApply { get; set; }
|
||||
|
||||
private bool IsTestingConnection;
|
||||
private bool? IsTestConnectionSuccessful;
|
||||
|
||||
private string WasValidated = "";
|
||||
private bool IsVisible;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (_device != Device)
|
||||
{
|
||||
_device = Device;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Device == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
WasValidated = "was-validated";
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("SamsungService", "UpdateDevice", Device);
|
||||
|
||||
if (AfterApply != null)
|
||||
{
|
||||
await AfterApply.Invoke(Device);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task TestConnectionClick(MouseEventArgs e)
|
||||
{
|
||||
IsTestingConnection = true;
|
||||
try
|
||||
{
|
||||
IsTestConnectionSuccessful = await _rpcClientService.CallWithOptionsAsync<bool>("SamsungService", "TestDevice", new RpcUiClientOptions { Timeout = 120000 }, Device);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsTestingConnection = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ModalOnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
WasValidated = "";
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValid()
|
||||
{
|
||||
return !string.IsNullOrEmpty(Device?.Name) && (Device?.IsCustom != true || !string.IsNullOrEmpty(Device?.IpAddress));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.Shared.Services
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using NvAPIWrapper.Native.Display
|
||||
@using ColorControl.Shared.Common
|
||||
@using static ColorControl.UI.Components.Pages.Generic.StepsInput<ColorControl.Shared.Contracts.Samsung.SamsungPreset>
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject AppState AppState
|
||||
@inject NavigationManager _navigationManager;
|
||||
|
||||
<div class="modal" id="presetModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false" @onfocus="ModalOnFocus">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(Preset?.id == 0 ? $"Settings for new preset" : $"Settings of preset {Preset?.IdOrName}")</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" @onclick="() => IsVisible = false"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="row g-1 needs-validation @WasValidated" novalidate>
|
||||
@if (Preset == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="name">Name</label>
|
||||
<input class="form-control" id="name" type="text" @bind="Preset.name" required />
|
||||
</div>
|
||||
@if (Devices != null)
|
||||
{
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="device">Device</label>
|
||||
<select class="form-select" id="device" @bind="Preset.DeviceMacAddress">
|
||||
<option value="">Globally selected device</option>
|
||||
@foreach (var device in Devices)
|
||||
{
|
||||
<option value="@device.MacAddress">@device.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
}
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="checkbox" @bind="Preset.ShowInQuickAccess" id="showInQuickAccess">
|
||||
<label class="form-check-label" for="showInQuickAccess">
|
||||
Show in Quick Access
|
||||
</label>
|
||||
</div>
|
||||
<ShortcutInput Label="Shortcut" @bind-Shortcut="Preset.shortcut" />
|
||||
|
||||
<div class="accordion accordion-flush" id="presetAccordion">
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#advancedSettings">
|
||||
Advanced settings
|
||||
</button>
|
||||
</h2>
|
||||
<div id="advancedSettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<TriggerInput Triggers="Preset.Triggers"></TriggerInput>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header">
|
||||
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#steps">
|
||||
Steps
|
||||
</button>
|
||||
</h2>
|
||||
<div id="steps" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
|
||||
<div class="accordion-body">
|
||||
<StepsInput Label="Steps" @bind-Steps="Preset.Steps" CustomItems="CustomItems" ActionItems="CustomActions" SamsungPresetsEnabled="false" TPreset="SamsungPreset"></StepsInput>
|
||||
<div class="mb-2">
|
||||
<label class="form-label" for="description">Description</label>
|
||||
<textarea class="form-control" id="description" type="text" @bind="Preset.Description" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
}
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" @onclick="() => IsVisible = false">Close</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="@(IsValid() ? "modal" : "")" @onclick="ApplyClick">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private SamsungPreset? Preset;
|
||||
|
||||
[Parameter]
|
||||
public SamsungPreset? PresetParam { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<SamsungDeviceDto>? Devices { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<SamsungPreset, Task>? AfterApply { get; set; }
|
||||
|
||||
private List<CustomStepItem>? CustomItems;
|
||||
private List<ActionStepItem>? CustomActions;
|
||||
|
||||
private string WasValidated = "";
|
||||
private bool IsVisible;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (PresetParam == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Preset = PresetParam.CloneWithId();
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
CustomItems = [new CustomStepItem("RC buttons", Enum.GetValues<ButtonType>().Select(b => b.ToString()).ToList())];
|
||||
|
||||
var actions = await _rpcClientService.CallAsync<List<InvokableActionDto<SamsungPreset>>>("SamsungService", "GetInvokableActions");
|
||||
|
||||
if (actions != null)
|
||||
{
|
||||
CustomActions = [new ActionStepItem("Actions", actions.Where(a => !a.Advanced).ToList())];
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ApplyClick(MouseEventArgs e)
|
||||
{
|
||||
if (Preset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
WasValidated = "was-validated";
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("SamsungService", "UpdatePreset", Preset);
|
||||
|
||||
if (AfterApply != null)
|
||||
{
|
||||
await AfterApply.Invoke(Preset);
|
||||
}
|
||||
}
|
||||
|
||||
private void ModalOnFocus(FocusEventArgs e)
|
||||
{
|
||||
if (!IsVisible)
|
||||
{
|
||||
WasValidated = "";
|
||||
IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsValid()
|
||||
{
|
||||
return !string.IsNullOrEmpty(Preset?.name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<FieldsModal ModalId="serviceMenuModal" Title="@Title" ConfirmCaption="@ConfirmCaption" SecondaryCaption="@SecondaryCaption"
|
||||
Fields="Fields" OnConfirm="NextClick" OnSecondary="SecondaryClick" Dismiss="@Dismiss" OnShow="OnShow"></FieldsModal>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public List<SamsungDeviceDto>? Devices { get; set; }
|
||||
|
||||
private string? Title { get; set; }
|
||||
private string? ConfirmCaption { get; set; }
|
||||
private string? SecondaryCaption { get; set; }
|
||||
private string? Dismiss { get; set; }
|
||||
private List<FieldDefinition>? Fields { get; set; }
|
||||
private FieldDefinition? DeviceField { get; set; }
|
||||
private Func<Task>? NextAction;
|
||||
private Func<Task>? SecondaryAction;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// NextAction = FirstStepExit;
|
||||
// Title = "Access Service Menu";
|
||||
// ConfirmCaption = "Next >";
|
||||
// Fields = [AddField("Service Menu Access Type", ServiceMenuType.FactoryMenu, subLabel: "Both types will not reset your settings. 'FactoryMenu' is recommended for 2024 series but will also work for older ones. Click 'Next >' to continue or 'X' to stop")];
|
||||
}
|
||||
|
||||
protected async Task OnShow()
|
||||
{
|
||||
NextAction = FirstStepExit;
|
||||
Title = "Access Service Menu";
|
||||
ConfirmCaption = "Next >";
|
||||
SecondaryCaption = null;
|
||||
SecondaryAction = null;
|
||||
Dismiss = null;
|
||||
Fields = [AddField("Service Menu Access Type", ServiceMenuType.FactoryMenu, subLabel: "Both types will not reset your settings. 'FactoryMenu' is recommended for 2024 series but will also work for older ones. Click 'Next >' to continue or 'X' to stop")];
|
||||
|
||||
if (Devices?.Any() == true)
|
||||
{
|
||||
DeviceField = FieldDefinition.CreateDropDownField("Device", Devices.Select(d => d.ToString()).ToList());
|
||||
DeviceField.Value = Devices.FirstOrDefault(d => d.IsSelected)?.ToString();
|
||||
|
||||
Fields.Insert(0, DeviceField);
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task NextClick()
|
||||
{
|
||||
if (NextAction == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await NextAction();
|
||||
}
|
||||
|
||||
private async Task SecondaryClick()
|
||||
{
|
||||
if (SecondaryAction != null)
|
||||
{
|
||||
await SecondaryAction();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task FirstStepExit()
|
||||
{
|
||||
if (Fields == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var menuType = Fields.First(f => f.ValueType == typeof(ServiceMenuType)).ValueAsEnum<ServiceMenuType>();
|
||||
|
||||
if (menuType == ServiceMenuType.FactoryMenu)
|
||||
{
|
||||
await FactoryMenuFirstStepEnter();
|
||||
}
|
||||
else
|
||||
{
|
||||
await HospitalityMenuFirstStepEnter();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task FactoryMenuFirstStepEnter()
|
||||
{
|
||||
await ExecutePreset(SamsungFactoryMenuPresets.Preset1);
|
||||
|
||||
NextAction = FactoryMenuSecondStepEnter;
|
||||
Title = "Access Service Menu - Step 2";
|
||||
ConfirmCaption = "Next >";
|
||||
SecondaryCaption = "Skip";
|
||||
SecondaryAction = FactoryMenuSecondStepEnterWithoutExecute;
|
||||
Fields = [AddField("Service Menu - Advanced", null, FieldType.Label, "If the service menu opened and you want to access the Advanced settings, click 'Next >' or click 'Skip' to skip")];
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected async Task FactoryMenuSecondStepEnterWithoutExecute()
|
||||
{
|
||||
NextAction = FactoryMenuSecondStepExit;
|
||||
Title = "Exit Service Menu";
|
||||
ConfirmCaption = "Next >";
|
||||
SecondaryCaption = null;
|
||||
SecondaryAction = null;
|
||||
Fields = [AddField("Exit Service Menu Type", ExitServiceMenuType.Exit, subLabel: "Choose how to exit the service menu. You can either reboot the TV or just exit the service menu (if, for example, no changes have been made)")];
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected async Task FactoryMenuSecondStepEnter()
|
||||
{
|
||||
await ExecutePreset(SamsungFactoryMenuPresets.PresetAdvanced);
|
||||
|
||||
await FactoryMenuSecondStepEnterWithoutExecute();
|
||||
}
|
||||
|
||||
protected async Task FactoryMenuSecondStepExit()
|
||||
{
|
||||
if (Fields == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var menuType = Fields.First().ValueAsEnum<ExitServiceMenuType>();
|
||||
|
||||
if (menuType == ExitServiceMenuType.Exit)
|
||||
{
|
||||
await ExitServiceMenuEnter();
|
||||
}
|
||||
else
|
||||
{
|
||||
await RebootTvEnter();
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task ExitServiceMenuEnter()
|
||||
{
|
||||
await ExecutePreset(SamsungFactoryMenuPresets.Exit);
|
||||
|
||||
NextAction = null;
|
||||
Title = "Exited Service Menu";
|
||||
Dismiss = "modal";
|
||||
ConfirmCaption = "OK";
|
||||
SecondaryCaption = "Factory";
|
||||
SecondaryAction = ExecuteFactoryKey;
|
||||
Fields = [AddField("Service Menu - Exited", null, FieldType.Label, "Exited the service menu. Click OK to close. If the TV is stuck on cycling full screen RGB images, use the 'Factory' button below.")];
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected async Task RebootTvEnter()
|
||||
{
|
||||
await ExecutePreset(SamsungGenericPresets.Reboot);
|
||||
|
||||
NextAction = null;
|
||||
Title = "Rebooted TV";
|
||||
Dismiss = "modal";
|
||||
ConfirmCaption = "OK";
|
||||
Fields = [AddField("Service Menu - Rebooted TV", null, FieldType.Label, "Rebooted the TV. Power on the TV manually if the TV does not come on automatically.")];
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected async Task HospitalityMenuFirstStepEnter()
|
||||
{
|
||||
await ExecutePreset(SamsungHospitalityMenuPresets.Preset1);
|
||||
|
||||
NextAction = HospitalityMenuSecondStepEnter;
|
||||
Title = "Access Service Menu - Step 2";
|
||||
ConfirmCaption = "Next >";
|
||||
Fields = [AddField("Service Menu opened?", null, FieldType.Label, "If the menu is opened with the 'Hospitality Mode' item highlighted and the rest disabled, click 'Next >' to continue or 'X' to stop")];
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected async Task HospitalityMenuSecondStepEnter()
|
||||
{
|
||||
await ExecutePreset(SamsungHospitalityMenuPresets.Preset2);
|
||||
|
||||
NextAction = HospitalityMenuThirdStepEnter;
|
||||
Title = "Access Service Menu - Step 3";
|
||||
ConfirmCaption = "Next >";
|
||||
SecondaryCaption = "Skip";
|
||||
Fields = [AddField("Service Menu - Advanced", null, FieldType.Label, "If the 'Advanced' item is highlighted and you want to access these settings, click 'Next >' or click 'Skip' to skip")];
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected async Task HospitalityMenuThirdStepEnter()
|
||||
{
|
||||
await ExecutePreset(SamsungHospitalityMenuPresets.Preset3);
|
||||
|
||||
await FactoryMenuSecondStepEnterWithoutExecute();
|
||||
}
|
||||
|
||||
protected async Task ExecuteFactoryKey()
|
||||
{
|
||||
await ExecutePreset(SamsungFactoryMenuPresets.KeyFactory);
|
||||
}
|
||||
|
||||
private async Task ExecutePreset(SamsungPreset preset)
|
||||
{
|
||||
if (Devices != null && DeviceField?.Value != null)
|
||||
{
|
||||
var device = Devices.FirstOrDefault(d => d.ToString() == DeviceField.Value.ToString());
|
||||
preset.DeviceMacAddress = device?.MacAddress;
|
||||
}
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("SamsungService", "ApplyPreset", preset);
|
||||
//await Task.Delay(2000);
|
||||
}
|
||||
|
||||
private FieldDefinition AddField(string label, object? value, FieldType fieldType = FieldType.DropDown, string? subLabel = null)
|
||||
{
|
||||
return new FieldDefinition
|
||||
{
|
||||
FieldType = fieldType,
|
||||
Value = value,
|
||||
StringValue = value?.ToString(),
|
||||
ValueType = value?.GetType(),
|
||||
Label = label,
|
||||
SubLabel = subLabel
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.Shared.Common;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
|
||||
@rendermode InteractiveServer
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
|
||||
<FieldsModal Title="Samsung settings" ConfirmCaption="Save" ModalId="settingsModal" Fields="Fields" OnConfirm="ApplyClick" OnShow="ModalOnShow"></FieldsModal>
|
||||
|
||||
@code {
|
||||
private SamsungServiceConfigDto? Config { get; set; }
|
||||
private List<FieldDefinition>? Fields { get; set; }
|
||||
|
||||
protected async Task ModalOnShow()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<SamsungServiceConfigDto>("SamsungService", "GetConfig");
|
||||
Fields = SamsungFields.GetSettingsFields(Config);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task ApplyClick()
|
||||
{
|
||||
if (Config == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FieldDefinition.UpdateObject(Fields, Config);
|
||||
|
||||
var result = await _rpcClientService.CallAsync<bool>("SamsungService", "UpdateConfig", Config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
@page "/Samsung"
|
||||
|
||||
@using ColorControl.Shared.Common
|
||||
@using ColorControl.Shared.Contracts
|
||||
@using ColorControl.Shared.Contracts.NVIDIA
|
||||
@using ColorControl.Shared.Contracts.Samsung
|
||||
@using ColorControl.Shared.Services;
|
||||
@using ColorControl.UI.Components.Pages.Generic
|
||||
@using ColorControl.UI.Generics
|
||||
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
|
||||
|
||||
@rendermode InteractiveServer
|
||||
|
||||
@inject RpcUiClientService _rpcClientService
|
||||
@inject ProtectedLocalStorage _localStorage
|
||||
|
||||
<PageTitle>Samsung controller</PageTitle>
|
||||
|
||||
<SamsungSettings />
|
||||
<SamsungServiceMenu Devices="Devices"></SamsungServiceMenu>
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<h1>Samsung controller</h1>
|
||||
<div class="d-flex ms-auto">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-primary dropdown-toggle me-2" data-bs-toggle="dropdown" aria-expanded="false" data-bs-auto-close="outside">
|
||||
Buttons
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@foreach (var button in Enum.GetValues<ButtonType>())
|
||||
{
|
||||
<li>
|
||||
<a class="dropdown-item" @onclick="() => ButtonOnClick(button)">@button.GetDescription()</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
@if (InvokableActions != null)
|
||||
{
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-primary dropdown-toggle me-2" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Expert
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@foreach (var action in InvokableActions)
|
||||
{
|
||||
if (action.Name == "ServiceMenu")
|
||||
{
|
||||
<li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#serviceMenuModal">Service menu</a></li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li><a class="dropdown-item" @onclick="() => ActionOnclick(action)">@action.Name</a></li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#settingsModal">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SamsungDevicePage Device="CurrentDevice" AfterApply="AfterDeviceApplied" />
|
||||
<SamsungPresetPage PresetParam="CurrentPreset" Devices="Devices" AfterApply="AfterPresetApplied" />
|
||||
<ConfirmModal Title="Delete preset" Message="Are you sure you want to delete the preset?" OnConfirm="PresetOnDeleteConfirmed" />
|
||||
|
||||
@if (Devices == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2 d-flex align-items-center">
|
||||
<h2>Devices</h2>
|
||||
<div class="d-flex ms-auto">
|
||||
<button type="button" class="btn btn-sm btn-primary me-2" disabled="@IsRefreshDisabled" @onclick="RefreshDevicesOnClick">
|
||||
@if (IsRefreshDisabled)
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm me-1" aria-hidden="true"></span>
|
||||
}
|
||||
<span role="status">Refresh</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#deviceModal" @onclick="() => AddDeviceOnClick()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
@if (!Devices.Any())
|
||||
{
|
||||
<span>No devices found</span>
|
||||
}
|
||||
@foreach (var device in Devices)
|
||||
{
|
||||
<div class="col-lg-6 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-header d-flex align-items-baseline">
|
||||
<span>
|
||||
@device.Name
|
||||
@if (device.IsConnected)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-success" title="Device is connected">Connected</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ms-2 badge text-bg-danger" title="Device is disconnected">Disconnected</span>
|
||||
}
|
||||
@if (device.IsSelected)
|
||||
{
|
||||
<span class="ms-2 badge text-bg-primary" title="Global device">Primary</span>
|
||||
}
|
||||
</span>
|
||||
<div class="d-flex ms-auto">
|
||||
@if (!device.IsSelected)
|
||||
{
|
||||
<button class="btn btn-sm btn-secondary ms-2" @onclick="() => SetAsPrimaryOnClick(device)">Set as primary</button>
|
||||
}
|
||||
<button type="button" class="btn btn-sm btn-primary ms-2" data-bs-toggle="modal" data-bs-target="#deviceModal" @onclick="() => DeviceOnClick(device)">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<small class="text-muted">@device.IpAddress (@(device.MacAddress ?? "No MAC-address entered"))</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Presets == null)
|
||||
{
|
||||
<div>Loading...</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-2 d-flex align-items-center">
|
||||
<h2>Presets</h2>
|
||||
<div class="d-flex ms-auto">
|
||||
<select class="form-select me-2" id="presetOrder" @bind="PresetOrder" @bind:after="PresetOrderChanged">
|
||||
@foreach (var order in Enum.GetValues<PresetOrder>())
|
||||
{
|
||||
<option value="@order">Order by: @order.GetDescription()</option>
|
||||
}
|
||||
</select>
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => AddPresetOnClick()">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="list-group">
|
||||
@foreach (var preset in Presets)
|
||||
{
|
||||
<a class="list-group-item list-group-item-action" @onclick="() => PresetOnClick(preset)" @onclick:preventDefault @onclick:stopPropagation>
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div>
|
||||
<h5 class="mb-1">@preset.name <small class="text-muted">@GetDeviceName(preset)</small></h5>
|
||||
@if (preset.Triggers.Any(t => t.Trigger != PresetTriggerType.None))
|
||||
{
|
||||
<div><small class="text-muted">Trigger: @preset.Triggers[0].ToString()</small></div>
|
||||
}
|
||||
<div><small class="text-muted">@preset.shortcut</small></div>
|
||||
</div>
|
||||
<span>
|
||||
<button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#confirmModal" @onclick="() => PresetOnDeleteClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Delete</button>
|
||||
<button class="btn btn-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnCloneClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Clone</button>
|
||||
<button class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#presetModal" @onclick="() => PresetOnEditClick(preset)" @onclick:preventDefault @onclick:stopPropagation>Edit</button>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<SamsungPreset>? Presets;
|
||||
private List<SamsungDeviceDto>? Devices;
|
||||
private List<InvokableActionDto<SamsungPreset>>? InvokableActions;
|
||||
|
||||
private SamsungServiceConfigDto? Config;
|
||||
private SamsungPreset? CurrentPreset;
|
||||
private SamsungDeviceDto? CurrentDevice;
|
||||
private bool IsRefreshDisabled;
|
||||
|
||||
private PresetOrder PresetOrder;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Config = await _rpcClientService.CallAsync<SamsungServiceConfigDto>("SamsungService", "GetConfig");
|
||||
await RefreshPresets();
|
||||
Devices = await _rpcClientService.CallAsync<List<SamsungDeviceDto>>("SamsungService", "GetDevices");
|
||||
InvokableActions = await _rpcClientService.CallAsync<List<InvokableActionDto<SamsungPreset>>>("SamsungService", "GetInvokableActions");
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstTime)
|
||||
{
|
||||
if (firstTime)
|
||||
{
|
||||
PresetOrder = await _localStorage.TryGet<PresetOrder>("SamsungPresetOrder");
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PresetOnClick(SamsungPreset preset)
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("SamsungService", "ApplyPresetWithId", preset.id);
|
||||
}
|
||||
|
||||
private async Task PresetOnEditClick(SamsungPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnCloneClick(SamsungPreset preset)
|
||||
{
|
||||
CurrentPreset = new SamsungPreset(preset);
|
||||
CurrentPreset.SetCloneValues();
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteClick(SamsungPreset preset)
|
||||
{
|
||||
CurrentPreset = preset;
|
||||
}
|
||||
|
||||
private async Task PresetOnDeleteConfirmed()
|
||||
{
|
||||
if (CurrentPreset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("SamsungService", "DeletePreset", CurrentPreset.id);
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task DeviceOnClick(SamsungDeviceDto device)
|
||||
{
|
||||
CurrentDevice = device;
|
||||
}
|
||||
|
||||
private async Task AddDeviceOnClick()
|
||||
{
|
||||
CurrentDevice = new SamsungDeviceDto { IsCustom = true };
|
||||
}
|
||||
|
||||
private async Task AddPresetOnClick()
|
||||
{
|
||||
CurrentPreset = new SamsungPreset();
|
||||
}
|
||||
|
||||
private async Task AfterPresetApplied(SamsungPreset preset)
|
||||
{
|
||||
await RefreshPresets();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task AfterDeviceApplied(SamsungDeviceDto device)
|
||||
{
|
||||
Devices = await _rpcClientService.CallAsync<List<SamsungDeviceDto>>("SamsungService", "GetDevices");
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task RefreshDevicesOnClick(MouseEventArgs e)
|
||||
{
|
||||
IsRefreshDisabled = true;
|
||||
try
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("SamsungService", "RefreshDevices");
|
||||
Devices = await _rpcClientService.CallAsync<List<SamsungDeviceDto>>("SamsungService", "GetDevices");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsRefreshDisabled = false;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task ActionOnclick(InvokableActionDto<SamsungPreset> action)
|
||||
{
|
||||
await _rpcClientService.CallAsync<bool>("SamsungService", "ExecuteInvokableAction", action);
|
||||
}
|
||||
|
||||
private string GetDeviceName(SamsungPreset preset)
|
||||
{
|
||||
if (string.IsNullOrEmpty(preset.DeviceMacAddress))
|
||||
{
|
||||
return "Global";
|
||||
}
|
||||
|
||||
return Devices?.FirstOrDefault(d => d.MacAddress == preset.DeviceMacAddress)?.Name ?? preset.DeviceMacAddress;
|
||||
}
|
||||
|
||||
private async Task SetAsPrimaryOnClick(SamsungDeviceDto device)
|
||||
{
|
||||
var result = await _rpcClientService.CallAsync<bool>("SamsungService", "SetSelectedDevice", device);
|
||||
|
||||
if (result)
|
||||
{
|
||||
Devices = await _rpcClientService.CallAsync<List<SamsungDeviceDto>>("SamsungService", "GetDevices");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PresetOrderChanged()
|
||||
{
|
||||
await _localStorage.SetAsync("SamsungPresetOrder", PresetOrder);
|
||||
await RefreshPresets();
|
||||
}
|
||||
|
||||
private async Task RefreshPresets()
|
||||
{
|
||||
Presets = await _rpcClientService.CallAsync<List<SamsungPreset>>("SamsungService", "GetPresets");
|
||||
|
||||
Presets = Presets?.OrderPresetsBy(PresetOrder);
|
||||
}
|
||||
|
||||
private async Task ButtonOnClick(ButtonType button)
|
||||
{
|
||||
var preset = new SamsungPreset(button.ToString(), null, [button.ToString()]);
|
||||
|
||||
await _rpcClientService.CallAsync<bool>("SamsungService", "ApplyPreset", preset);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<Router AppAssembly="@typeof(Blazor).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
||||
</Found>
|
||||
</Router>
|
||||
@@ -0,0 +1,10 @@
|
||||
@using System.Net.Http
|
||||
@using System.Net.Http.Json
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using static Microsoft.AspNetCore.Components.Web.RenderMode
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using ColorControl.UI
|
||||
@using ColorControl.UI.Components
|
||||
@@ -0,0 +1,43 @@
|
||||
using ColorControl.Shared.Contracts;
|
||||
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace ColorControl.UI.Generics;
|
||||
|
||||
public static class PresetExtensions
|
||||
{
|
||||
public static List<T>? OrderPresetsBy<T>(this List<T> presets, PresetOrder order) where T : PresetBase
|
||||
{
|
||||
if (presets == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (order == PresetOrder.ByName)
|
||||
{
|
||||
presets = presets.OrderBy(p => p.name).ToList();
|
||||
}
|
||||
else if (order == PresetOrder.ByLastUsed)
|
||||
{
|
||||
presets = presets.OrderByDescending(p => p.LastUsed).ToList();
|
||||
}
|
||||
|
||||
return presets;
|
||||
}
|
||||
|
||||
public static async ValueTask<TValue?> TryGet<TValue>(this ProtectedBrowserStorage storage, string key, TValue? def = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await storage.GetAsync<TValue>(key);
|
||||
var value = result.Success ? result.Value : def;
|
||||
|
||||
return value;
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
await storage.DeleteAsync(key);
|
||||
return def;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
//using ColorControl.UI;
|
||||
|
||||
//Blazor.Start();
|
||||
|
||||
//var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
//// Add services to the container.
|
||||
//builder.Services.AddRazorComponents()
|
||||
// .AddInteractiveServerComponents();
|
||||
|
||||
//builder.Services.AddSingleton<AppState>();
|
||||
//builder.Services.AddSingleton<OptionsService>();
|
||||
|
||||
//var app = builder.Build();
|
||||
|
||||
//// Configure the HTTP request pipeline.
|
||||
//if (!app.Environment.IsDevelopment())
|
||||
//{
|
||||
// app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||
// // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
// app.UseHsts();
|
||||
//}
|
||||
|
||||
//app.UseHttpsRedirection();
|
||||
|
||||
//app.UseStaticFiles();
|
||||
//app.UseAntiforgery();
|
||||
|
||||
//app.MapRazorComponents<App>()
|
||||
// .AddInteractiveServerRenderMode();
|
||||
|
||||
//app.Run();
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:31433",
|
||||
"sslPort": 44330
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5175",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7135;http://localhost:5175",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace ColorControl.UI;
|
||||
|
||||
public class AppState
|
||||
{
|
||||
public string SelectedTheme { get; set; } = "light";
|
||||
|
||||
public event Action? OnChange;
|
||||
|
||||
public void SetTheme(string theme)
|
||||
{
|
||||
SelectedTheme = theme;
|
||||
NotifyStateChanged();
|
||||
}
|
||||
|
||||
private void NotifyStateChanged() => OnChange?.Invoke();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
html, body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
a, .btn-link {
|
||||
color: #006bb7;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #1b6ec2;
|
||||
border-color: #1861ac;
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
|
||||
h1:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid #e50000;
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: #e50000;
|
||||
}
|
||||
|
||||
.blazor-error-boundary {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
||||
padding: 1rem 1rem 1rem 3.7rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.blazor-error-boundary::after {
|
||||
content: "An error has occurred."
|
||||
}
|
||||
|
||||
.darker-border-checkbox.form-check-input {
|
||||
border-color: #929292;
|
||||
}
|
||||
|
||||
.dropdown-item, .list-group-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
@charset "UTF-8";/*!
|
||||
* Bootstrap v5.1.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-body-rgb:33,37,41;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-bg:#fff}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){leLine truncated
|
||||
/*# sourceMappingURL=bootstrap.min.css.map */
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_root.scss","../../scss/_reboot.scss","dist/css/bootstrap.css","../../scss/vendor/_rfs.scss","../../scss/mixins/_border-radius.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/_containers.scss","../../scss/mixins/_container.scss","../../scss/mixins/_breakpoints.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/_tables.scss","../../scss/mixins/_table-variants.scss","../../scss/forms/_labels.scss","../../scss/forms/_form-text.scss","../../scss/forms/_form-control.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_gradients.scss","../../scss/forms/_form-select.scss","../../scss/forms/_form-check.scss","../../scss/forms/_form-range.scss","../../scss/forms/_floating-labels.scss","../../scss/forms/_input-group.scss","../../scss/mixins/_forms.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/_button-group.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_accordion.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_toasts.scss","../../scss/_modal.scss","../../scss/mixins/_backdrop.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/mixins/_clearfix.scss","../../scss/_spinners.scss","../../scss/_offcanvas.scss","../../scss/_placeholders.scss","../../scss/helpers/_colored-links.scss","../../scss/helpers/_ratio.scss","../../scss/helpers/_position.scss","../../scss/helpers/_stacks.scss","../../scss/helpers/_visually-hidden.scss","../../scss/mixins/_visually-hidden.scss","../../scss/helpers/_stretched-link.scss","../../scss/helpers/_text-truncation.scss","../../scss/mixins/_text-truncate.scss","../../scss/helpers/_vr.scss","../../scss/mixins/_utilities.scss","../../scss/utilities/_api.scss"],"names":[],"mappings":"iBAAA;;;;;ACAA,MAQI,UAAA,QAAA,YAAA,QAAA,YAAA,QAAA,UAAA,QAAA,SAAA,QAAA,YAAA,QAAA,YAAA,QAAA,WAAA,QAAA,UAAA,QAAA,UAAA,QAAA,WAAA,KAAA,UAAA,QAAA,eAAA,QAIA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAAA,cAAA,QAIA,aAAA,QAAA,eAAA,QAAA,aAAA,QAAA,UAAA,QAAA,aAAA,QAAA,YAAA,QAAA,WAAA,QAAA,UAAA,QAIA,iBAAA,EAAA,CAAA,GAAA,CAAA,IAAA,mBAAA,GAAA,CAAA,GAAA,CAAA,IAAA,iBAAA,EAAA,CAAA,GAAA,CAAA,GAAA,cAAA,EAAA,CAAA,GAAA,CAAA,IAAA,iBAAA,GAAA,CAAA,GAAA,CAAA,EAAA,gBAAA,GAAA,CAAA,EAAA,CAAA,GAAA,eAAA,GAAA,CAAA,GAAA,CAAA,IAAA,cAAA,EAAA,CAAA,EAAA,CAAA,GAGF,eAAA,GAAA,CAAA,GAAA,CAAA,IACA,eAAA,CAAA,CAAA,CAAA,CAAA,EACA,cAAA,EAAA,CAAA,EAAA,CAAA,GAMA,qBAAA,SAAA,CAAA,aAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,WAAA,CAAA,iBAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBACA,oBAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UACA,cAAA,2EAQA,sBAAA,0BACA,oBAAA,KACA,sBAAA,IACA,sBAAA,IACA,gBAAA,QAIA,aAAA,KClCF,EC+CA,QADA,SD3CE,WAAA,WAeE,8CANJ,MAOM,gBAAA,QAcN,KACE,OAAA,EACA,YAAA,2BEmPI,UAAA,yBFjPJ,YAAA,2BACA,YAAA,2BACA,MAAA,qBACA,WAAA,0BACA,iBAAA,kBACA,yBAAA,KACA,4BAAA,YAUF,GACE,OAAA,KAAA,EACA,MAAA,QACA,iBAAA,aACA,OAAA,EACA,QAAA,IAGF,eACE,OAAA,IAUF,IAAA,IAAA,IAAA,IAAA,IAAA,IAAA,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAGA,YAAA,IACA,YAAA,IAIF,IAAA,GEwMQ,UAAA,uBAlKJ,0BFtCJ,IAAA,GE+MQ,UAAA,QF1MR,IAAA,GEmMQ,UAAA,sBAlKJ,0BFjCJ,IAAA,GE0MQ,UAAA,MFrMR,IAAA,GE8LQ,UAAA,oBAlKJ,0BF5BJ,IAAA,GEqMQ,UAAA,SFhMR,IAAA,GEyLQ,UAAA,sBAlKJ,0BFvBJ,IAAA,GEgMQ,UAAA,QF3LR,IAAA,GEgLM,UAAA,QF3KN,IAAA,GE2KM,UAAA,KFhKN,EACE,WAAA,EACA,cAAA,KCmBF,6BDRA,YAEE,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,iCAAA,KAAA,yBAAA,KAMF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QAMF,GCIA,GDFE,aAAA,KCQF,GDLA,GCIA,GDDE,WAAA,EACA,cAAA,KAGF,MCKA,MACA,MAFA,MDAE,cAAA,EAGF,GACE,YAAA,IAKF,GACE,cAAA,MACA,YAAA,EAMF,WACE,OAAA,EAAA,EAAA,KAQF,ECNA,ODQE,YAAA,OAQF,OAAA,ME4EM,UAAA,OFrEN,MAAA,KACE,QAAA,KACA,iBAAA,QASF,ICpBA,IDsBE,SAAA,SEwDI,UAAA,MFtDJ,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAKN,EACE,MAAA,QACA,gBAAA,UAEA,QACE,MAAA,QAWF,2BAAA,iCAEE,MAAA,QACA,gBAAA,KCxBJ,KACA,ID8BA,IC7BA,KDiCE,YAAA,yBEcI,UAAA,IFZJ,UAAA,IACA,aAAA,cAOF,IACE,QAAA,MACA,WAAA,EACA,cAAA,KACA,SAAA,KEAI,UAAA,OFKJ,SELI,UAAA,QFOF,MAAA,QACA,WAAA,OAIJ,KEZM,UAAA,OFcJ,MAAA,QACA,UAAA,WAGA,OACE,MAAA,QAIJ,IACE,QAAA,MAAA,MExBI,UAAA,OF0BJ,MAAA,KACA,iBAAA,QG7SE,cAAA,MHgTF,QACE,QAAA,EE/BE,UAAA,IFiCF,YAAA,IASJ,OACE,OAAA,EAAA,EAAA,KAMF,ICjDA,IDmDE,eAAA,OAQF,MACE,aAAA,OACA,gBAAA,SAGF,QACE,YAAA,MACA,eAAA,MACA,MAAA,QACA,WAAA,KAOF,GAEE,WAAA,QACA,WAAA,qBCxDF,MAGA,GAFA,MAGA,GDuDA,MCzDA,GD+DE,aAAA,QACA,aAAA,MACA,aAAA,EAQF,MACE,QAAA,aAMF,OAEE,cAAA,EAQF,iCACE,QAAA,ECtEF,OD2EA,MCzEA,SADA,OAEA,SD6EE,OAAA,EACA,YAAA,QE9HI,UAAA,QFgIJLine truncated
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
+62
-2
@@ -9,6 +9,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nspector", "Nspector\Nspect
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvAPIWrapper", "NvAPIWrapper\NvAPIWrapper.csproj", "{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "novideo_srgb", "novideo_srgb\novideo_srgb.csproj", "{A6A97834-7BE1-474A-B92F-A512DB1D5186}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NLogViewer", "NLogViewer\NLogViewer.csproj", "{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LittleCms", "LittleCms\LittleCms.csproj", "{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MHC2Gen", "MHC2Gen\MHC2Gen.csproj", "{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ColorControl.UI", "ColorControl.UI\ColorControl.UI.csproj", "{85EA3079-BB73-4CE5-A72F-E56906187051}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -23,8 +35,8 @@ Global
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|x64.ActiveCfg = Release|x64
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|x64.Build.0 = Release|x64
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A6005D08-70F0-44CB-A384-9219EBA84F21}.Release|x64.Build.0 = Release|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{76797290-48F5-4A82-86C3-FAD25DAE4500}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
@@ -41,6 +53,54 @@ Global
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{42E2B4A6-6857-4427-AEF1-DF4C7EF8CC7C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A6A97834-7BE1-474A-B92F-A512DB1D5186}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D5E4D314-CFCD-4859-98FC-68F660AC7FB4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8F38D6B0-82DA-4DD1-89EB-918D8A18AEB1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{42D251AE-42AF-4C0D-B163-7C7A13C4A9A6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Debug|x64.Build.0 = Debug|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|Any CPU.Build.0 = Release|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|x64.ActiveCfg = Release|x64
|
||||
{9FDF741F-0ECF-46DB-8671-AB11ACEB9F41}.Release|x64.Build.0 = Release|x64
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{85EA3079-BB73-4CE5-A72F-E56906187051}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
using ColorControl.Common;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
|
||||
namespace ColorControl
|
||||
{
|
||||
public class AppContext
|
||||
{
|
||||
public static AppContext CurrentContext { get; private set; }
|
||||
|
||||
public Config Config { get; private set; }
|
||||
|
||||
public StartUpParams StartUpParams { get; private set; }
|
||||
public string DataPath { get; private set; }
|
||||
public SynchronizationContext SynchronizationContext { get; set; } = AsyncOperationManager.SynchronizationContext;
|
||||
|
||||
public AppContext(Config config, StartUpParams startUpParams, string dataPath)
|
||||
{
|
||||
Config = config;
|
||||
StartUpParams = startUpParams;
|
||||
DataPath = dataPath;
|
||||
|
||||
CurrentContext = this;
|
||||
}
|
||||
|
||||
public bool IsServiceRunning()
|
||||
{
|
||||
return Utils.IsServiceRunning();
|
||||
}
|
||||
}
|
||||
}
|
||||
+150
-111
@@ -1,113 +1,152 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>false</MapFileExtensions>
|
||||
<UpdateUrl>https://www.maassoft.com/downloads/ColorControl/</UpdateUrl>
|
||||
<ProductName>ColorControl</ProductName>
|
||||
<PublisherName>Maassoft</PublisherName>
|
||||
<Company>Maassoft</Company>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>9.2.0.0</ApplicationVersion>
|
||||
<Version>9.2.0.0</Version>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>false</UseWPF>
|
||||
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
|
||||
<ApplicationIcon>pngbarn.ico</ApplicationIcon>
|
||||
<SupportedOSPlatformVersion>10.0.20348.0</SupportedOSPlatformVersion>
|
||||
<Copyright>2020-2023 Maassoft</Copyright>
|
||||
<Authors>Maassoft</Authors>
|
||||
<ManifestCertificateThumbprint>CF0BC153EA664CD97AC6F234B91F45D34630958F</ManifestCertificateThumbprint>
|
||||
<ManifestKeyFile>ColorControl_1_TemporaryKey.pfx</ManifestKeyFile>
|
||||
<GenerateManifests>true</GenerateManifests>
|
||||
<TargetZone>LocalIntranet</TargetZone>
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
<SignManifests>true</SignManifests>
|
||||
<AssemblyOriginatorKeyFile>ColorControl_TemporaryKey.pfx</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Services\Common\QuickAccessForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="services\lg\RemoteControlPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Services\NVIDIA\NvPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Resources\LG_register.json" />
|
||||
<EmbeddedResource Include="Resources\RC_coords.txt" />
|
||||
<EmbeddedResource Include="Resources\LG_remote.jpg" />
|
||||
<Content Include="LgPresets.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="pngbarn.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="bin\x64\Debug\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="IWshRuntimeLibrary">
|
||||
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.1.2" />
|
||||
<PackageReference Include="NStandard" Version="0.24.0" />
|
||||
<PackageReference Include="NWin32" Version="1.2.6" />
|
||||
<PackageReference Include="System.Management" Version="7.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.4.13" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nspector\Nspector.csproj" />
|
||||
<ProjectReference Include="..\NvAPIWrapper\NvAPIWrapper.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>false</MapFileExtensions>
|
||||
<UpdateUrl>https://www.maassoft.com/downloads/ColorControl/</UpdateUrl>
|
||||
<ProductName>ColorControl</ProductName>
|
||||
<PublisherName>Maassoft</PublisherName>
|
||||
<Company>Maassoft</Company>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>10.0.0.1</ApplicationVersion>
|
||||
<Version>10.0.0.1</Version>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<UseWPF>false</UseWPF>
|
||||
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
|
||||
<ApplicationIcon>Resources\pngbarn.ico</ApplicationIcon>
|
||||
<SupportedOSPlatformVersion>10.0.20348.0</SupportedOSPlatformVersion>
|
||||
<Copyright>2020-2024 Maassoft</Copyright>
|
||||
<Authors>Maassoft</Authors>
|
||||
<ManifestCertificateThumbprint>CF0BC153EA664CD97AC6F234B91F45D34630958F</ManifestCertificateThumbprint>
|
||||
<ManifestKeyFile>ColorControl_1_TemporaryKey.pfx</ManifestKeyFile>
|
||||
<GenerateManifests>true</GenerateManifests>
|
||||
<TargetZone>LocalIntranet</TargetZone>
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
<SignManifests>true</SignManifests>
|
||||
<AssemblyOriginatorKeyFile>ColorControl_TemporaryKey.pfx</AssemblyOriginatorKeyFile>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<PathMap Condition="'$(Configuration)' == 'Release'">$(MSBuildThisFileDirectory)=.\</PathMap>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="XForms\BrowserWindow.xaml" />
|
||||
<None Remove="XForms\ColorProfileWindow.xaml" />
|
||||
<None Remove="XForms\LogWindow.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Forms\OptionsPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Forms\InfoPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<Generator></Generator>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Services\Common\QuickAccessForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Update="services\lg\RemoteControlPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Services\NVIDIA\NvInfoPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Services\NVIDIA\NvPanel.cs" />
|
||||
<Compile Update="Services\Samsung\SamsungPanel.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Resources\LG_register.json" />
|
||||
<EmbeddedResource Include="Resources\RC_coords.txt" />
|
||||
<EmbeddedResource Include="Resources\LG_remote.jpg" />
|
||||
<EmbeddedResource Include="Resources\pngbarn.ico" />
|
||||
<Content Include="LgPresets.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="bin\x64\Debug\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="IWshRuntimeLibrary">
|
||||
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2277.86" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.2.8" />
|
||||
<PackageReference Include="NStandard" Version="0.59.0" />
|
||||
<PackageReference Include="NWin32" Version="1.2.6" />
|
||||
<PackageReference Include="System.Management" Version="8.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.4.17" />
|
||||
<PackageReference Include="RawInput.Sharp" Version="0.1.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="XForms\ColorProfileWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="XForms\BrowserWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="XForms\LogWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ColorControl.UI\ColorControl.UI.csproj" />
|
||||
<ProjectReference Include="..\MHC2Gen\MHC2Gen.csproj" />
|
||||
<ProjectReference Include="..\NLogViewer\NLogViewer.csproj" />
|
||||
<ProjectReference Include="..\novideo_srgb\novideo_srgb.csproj" />
|
||||
<ProjectReference Include="..\Nspector\Nspector.csproj" />
|
||||
<ProjectReference Include="..\NvAPIWrapper\NvAPIWrapper.csproj" />
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Services\Samsung\SamsungPanel.resx">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,126 @@
|
||||
using ColorControl.Services.AMD;
|
||||
using ColorControl.Services.LG;
|
||||
using ColorControl.Services.NVIDIA;
|
||||
using ColorControl.Services.Samsung;
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Svc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl
|
||||
{
|
||||
public static class CommandLineHandler
|
||||
{
|
||||
public static async Task<bool> HandleStartupParams(StartUpParams startUpParams, Process existingProcess)
|
||||
{
|
||||
if (startUpParams.StartElevated)
|
||||
{
|
||||
await StartElevated();
|
||||
return true;
|
||||
}
|
||||
|
||||
var useConsole = startUpParams.NoGui || existingProcess != null;
|
||||
|
||||
if (!useConsole)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
startUpParams.NoGui = true;
|
||||
|
||||
var result = false;
|
||||
|
||||
if (startUpParams.ExecuteHelp)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($@"ColorControl CLI {Application.ProductVersion}
|
||||
Syntax : ColorControl command options
|
||||
Commands:
|
||||
--nvpreset <preset name or id>: execute NVIDIA-preset
|
||||
--amdpreset <preset name or id>: execute AMD-preset
|
||||
--lgpreset <preset name> : execute LG-preset
|
||||
--sampreset <preset name> : execute Samsung-preset
|
||||
--help : displays this help info
|
||||
Options:
|
||||
--nogui : starts command from the command line and will not open GUI (is forced when GUI is already running)
|
||||
--no-refresh: when using LG or Samsung-preset: skip refreshing devices (speeds up executing preset)");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteLgPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing LG-preset '{startUpParams.LgPresetName}'...");
|
||||
await LgService.ExecutePresetAsync(startUpParams.LgPresetName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteSamsungPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing Samsung-preset '{startUpParams.SamsungPresetName}'...");
|
||||
await SamsungService.ExecutePresetAsync(startUpParams.SamsungPresetName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteNvidiaPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing NVIDIA-preset '{startUpParams.NvidiaPresetIdOrName}'...");
|
||||
await NvService.ExecutePresetAsync(startUpParams.NvidiaPresetIdOrName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteAmdPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing AMD-preset '{startUpParams.AmdPresetIdOrName}'...");
|
||||
await AmdService.ExecutePresetAsync(startUpParams.AmdPresetIdOrName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static async Task StartElevated()
|
||||
{
|
||||
try
|
||||
{
|
||||
var backgroundService = Program.ServiceProvider.GetRequiredService<ColorControlBackgroundService>();
|
||||
|
||||
backgroundService.PipeName = PipeUtils.ElevatedPipe;
|
||||
|
||||
await backgroundService.StartAndStopWithMutex();
|
||||
|
||||
Application.Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Error while initializing elevated application: " + ex.ToLogString(Environment.StackTrace), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
using ColorControl.Svc;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO.Pipes;
|
||||
using System.Security.Principal;
|
||||
|
||||
namespace ColorControl.Common
|
||||
{
|
||||
public static class PipeUtils
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public static string SendMessage(string message, int timeout = 2000)
|
||||
{
|
||||
var pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.None);
|
||||
try
|
||||
{
|
||||
pipeClient.Connect(timeout);
|
||||
try
|
||||
{
|
||||
var ss = new StreamString(pipeClient);
|
||||
|
||||
ss.WriteString(message);
|
||||
|
||||
var result = ss.ReadString();
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
pipeClient.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(ex, "PipeUtils.SendMessage");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static SvcResultMessage SendMessage(SvcMessage message, int timeout = 2000)
|
||||
{
|
||||
var messageJson = JsonConvert.SerializeObject(message);
|
||||
|
||||
var resultJson = SendMessage(messageJson, timeout);
|
||||
|
||||
if (resultJson == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var resultMessage = JsonConvert.DeserializeObject<SvcResultMessage>(resultJson);
|
||||
|
||||
return resultMessage;
|
||||
}
|
||||
|
||||
public static SvcResultMessage SendMessage(SvcMessageType messageType)
|
||||
{
|
||||
var message = new SvcMessage { MessageType = messageType };
|
||||
|
||||
return SendMessage(message);
|
||||
}
|
||||
|
||||
public static bool? SendRpcMessage(string command)
|
||||
{
|
||||
var message = new SvcMessage { MessageType = SvcMessageType.ExecuteRpc, Data = command };
|
||||
|
||||
var messageJson = JsonConvert.SerializeObject(message);
|
||||
|
||||
var resultJson = SendMessage(messageJson);
|
||||
|
||||
if (resultJson == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var resultMessage = JsonConvert.DeserializeObject<SvcResultMessage>(resultJson);
|
||||
|
||||
return resultMessage.Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using Vanara.PInvoke;
|
||||
using static Vanara.PInvoke.IpHlpApi;
|
||||
|
||||
namespace ColorControl.Common
|
||||
{
|
||||
class WOL
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private const string ArgumentExceptionInvalidMacAddressLength = "Invalid MAC address length.";
|
||||
private const string ArgumentExceptionInvalidPasswordLength = "Invalid password length.";
|
||||
private const int DefaultWolPort = 9;
|
||||
|
||||
public static bool WakeFunction(string macAddress, string ipAddress = null)
|
||||
{
|
||||
return WakeFunctionToAllNics(macAddress, ipAddress);
|
||||
}
|
||||
|
||||
public static bool WakeFunctionCheckAdmin(string macAddress, string ipAddress = null)
|
||||
{
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
return WakeFunction(macAddress, ipAddress);
|
||||
}
|
||||
|
||||
var result = PipeUtils.SendRpcMessage($"{StartUpParams.SendWakeOnLanParam} {macAddress} {ipAddress}");
|
||||
|
||||
// Execute local WOL anyway because pipe failed
|
||||
if (!result.HasValue)
|
||||
{
|
||||
result = WakeFunction(macAddress, ipAddress);
|
||||
}
|
||||
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
public static bool WakeFunctionToAllNics(string macAddress, string ipAddressString)
|
||||
{
|
||||
var result = false;
|
||||
Logger.Debug($"Sending WOL packet to MAC-address {macAddress}");
|
||||
|
||||
try
|
||||
{
|
||||
var physicalAddress = PhysicalAddress.Parse(macAddress);
|
||||
var addressBytes = physicalAddress.GetAddressBytes();
|
||||
var data = GetWolPacket(addressBytes);
|
||||
var ipAddress = ipAddressString != null ? IPAddress.Parse(ipAddressString) : null;
|
||||
|
||||
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
|
||||
|
||||
foreach (var ni in interfaces)
|
||||
{
|
||||
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback || ni.Name.Contains("VirtualBox") || ni.Name.Contains("vEthernet") || ni.Description.Contains("Virtual"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Logger.Debug($"Found network: {ni.Name} ({ni.Description}), type: {ni.NetworkInterfaceType}");
|
||||
try
|
||||
{
|
||||
if (ni.SupportsMulticast && ni.GetIPProperties().GetIPv4Properties() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var uip in ni.GetIPProperties().UnicastAddresses)
|
||||
{
|
||||
if (uip.Address.ToString().StartsWith("169.254") || uip.Address.AddressFamily != AddressFamily.InterNetwork)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.Debug($"Broadcast WOL in network: {ni.Name} ({ni.Description}), local address: {uip.Address}, destination IP-address: {ipAddressString ?? "broadcast"}");
|
||||
|
||||
if (ipAddress != null && Utils.IsAdministrator())
|
||||
{
|
||||
var localEP = new IPEndPoint(uip.Address, 0);
|
||||
|
||||
SendWolToIpAddress(uip.Address, ipAddress, data, physicalAddress);
|
||||
}
|
||||
|
||||
BroadcastWol(uip.Address, IPAddress.Broadcast, data);
|
||||
|
||||
var parts = uip.Address.ToString().Split(".").ToList();
|
||||
parts[3] = "0";
|
||||
var broadcastAddress = IPAddress.Parse(string.Join(".", parts));
|
||||
BroadcastWol(uip.Address, broadcastAddress, data);
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"WakeFunctionToAllNics: while sending to specific network: {ni.Name} ({ni.Description}): {ex.ToLogString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"WakeFunctionToAllNics: {ex.ToLogString()}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <exception cref="ArgumentNullException"><paramref name="macAddress"/> is null.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="macAddress"/> is not 6.</exception>
|
||||
/// <exception cref="ArgumentException">The length of the <see cref="T:System.Byte" /> array <paramref name="password"/> is not 0 or 6.</exception>
|
||||
private static byte[] GetWolPacket(byte[] macAddress, byte[] password = null)
|
||||
{
|
||||
if (macAddress == null)
|
||||
throw new ArgumentNullException(nameof(macAddress));
|
||||
if (macAddress.Length != 6)
|
||||
throw new ArgumentException(ArgumentExceptionInvalidMacAddressLength);
|
||||
|
||||
password = password ?? new byte[0];
|
||||
if (password.Length != 0 && password.Length != 6)
|
||||
throw new ArgumentException(ArgumentExceptionInvalidPasswordLength);
|
||||
|
||||
var packet = new byte[17 * 6 + password.Length];
|
||||
|
||||
int offset, i;
|
||||
for (offset = 0; offset < 6; ++offset)
|
||||
packet[offset] = 0xFF;
|
||||
|
||||
for (offset = 6; offset < 17 * 6; offset += 6)
|
||||
for (i = 0; i < 6; ++i)
|
||||
packet[i + offset] = macAddress[i];
|
||||
|
||||
if (password.Length > 0)
|
||||
{
|
||||
for (offset = 16 * 6 + 6; offset < (17 * 6 + password.Length); offset += 6)
|
||||
for (i = 0; i < 6; ++i)
|
||||
packet[i + offset] = password[i];
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
private static void BroadcastWol(IPAddress localAddress, IPAddress broadCastAddress, byte[] data)
|
||||
{
|
||||
//var localEP = new IPEndPoint(localAddress, 0);
|
||||
var udpc = new UdpClient();
|
||||
|
||||
udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
|
||||
//udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontRoute, 1);
|
||||
|
||||
var target = new IPEndPoint(broadCastAddress, DefaultWolPort);
|
||||
|
||||
udpc.Send(data, data.Length, target);
|
||||
}
|
||||
|
||||
private static void SendWolToIpAddress(IPAddress localAddress, IPAddress remoteAddress, byte[] data, PhysicalAddress physicalAddress)
|
||||
{
|
||||
//var localEP = new IPEndPoint(localAddress, 0);
|
||||
|
||||
var netLuid = CreateTransientLocalNetEntry(remoteAddress, physicalAddress);
|
||||
try
|
||||
{
|
||||
var udpc = new UdpClient();
|
||||
udpc.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
|
||||
|
||||
var target = new IPEndPoint(remoteAddress, DefaultWolPort);
|
||||
|
||||
udpc.Send(data, data.Length, target);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DeleteNetEntry(netLuid, remoteAddress);
|
||||
}
|
||||
}
|
||||
|
||||
private static NET_LUID CreateTransientLocalNetEntry(IPAddress ipAddress, PhysicalAddress macAddress)
|
||||
{
|
||||
var ipBytes = ipAddress.GetAddressBytes();
|
||||
|
||||
var address = new Ws2_32.SOCKADDR_INET
|
||||
{
|
||||
si_family = Ws2_32.ADDRESS_FAMILY.AF_INET,
|
||||
Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort),
|
||||
};
|
||||
|
||||
var net = new NET_LUID();
|
||||
var addr = new Ws2_32.SOCKADDR_INET();
|
||||
|
||||
MIB_IPFORWARD_ROW2 forwardRow;
|
||||
var result = GetBestRoute2(net, 0, addr, address, 0, out forwardRow, out _);
|
||||
|
||||
if (result != Win32Error.ERROR_SUCCESS)
|
||||
{
|
||||
Logger.Debug($"Cannot find best route: {result}");
|
||||
|
||||
var luidDummy = new NET_LUID();
|
||||
|
||||
return luidDummy;
|
||||
}
|
||||
var luid = forwardRow.InterfaceLuid;
|
||||
|
||||
var macAddressBytes = macAddress.GetAddressBytes();
|
||||
var bytes = new byte[32];
|
||||
|
||||
macAddressBytes.CopyTo(bytes, 0);
|
||||
|
||||
var row = new MIB_IPNET_ROW2
|
||||
{
|
||||
Address = address,
|
||||
InterfaceLuid = luid,
|
||||
PhysicalAddress = bytes,
|
||||
PhysicalAddressLength = 6
|
||||
};
|
||||
|
||||
result = CreateIpNetEntry2(ref row);
|
||||
|
||||
if (result != Win32Error.ERROR_SUCCESS)
|
||||
{
|
||||
Logger.Debug($"Cannot create ip net entry: {result}");
|
||||
}
|
||||
|
||||
return luid;
|
||||
}
|
||||
|
||||
private static void DeleteNetEntry(NET_LUID luid, IPAddress ipAddress)
|
||||
{
|
||||
if (luid.Value == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ipBytes = ipAddress.GetAddressBytes();
|
||||
|
||||
var address = new Ws2_32.SOCKADDR_INET
|
||||
{
|
||||
si_family = Ws2_32.ADDRESS_FAMILY.AF_INET,
|
||||
Ipv4 = new Ws2_32.SOCKADDR_IN(new Ws2_32.IN_ADDR(ipBytes), DefaultWolPort)
|
||||
|
||||
};
|
||||
|
||||
var row = new MIB_IPNET_ROW2
|
||||
{
|
||||
Address = address,
|
||||
InterfaceLuid = luid,
|
||||
};
|
||||
|
||||
var result = DeleteIpNetEntry2(ref row);
|
||||
|
||||
if (result != Win32Error.ERROR_SUCCESS)
|
||||
{
|
||||
Logger.Debug($"Cannot delete ip net entry: {result}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl
|
||||
{
|
||||
public enum ElevationMethod
|
||||
{
|
||||
None = 0,
|
||||
RunAsAdmin = 1,
|
||||
UseService = 2,
|
||||
UseElevatedProcess = 3
|
||||
}
|
||||
|
||||
public class ListViewSortState
|
||||
{
|
||||
public SortOrder SortOrder { get; set; }
|
||||
public int SortIndex { get; set; }
|
||||
}
|
||||
|
||||
public class Config
|
||||
{
|
||||
public bool StartMinimized { get; set; }
|
||||
public bool MinimizeOnClose { get; set; }
|
||||
public bool MinimizeToTray { get; set; }
|
||||
public bool CheckForUpdates { get; set; }
|
||||
public bool AutoInstallUpdates { get; set; }
|
||||
public bool UseDarkMode { get; set; }
|
||||
public int DisplaySettingsDelay { get; set; }
|
||||
public string ScreenSaverShortcut { get; set; }
|
||||
public int FormWidth { get; set; }
|
||||
public int FormHeight { get; set; }
|
||||
public int NvPresetId_ApplyOnStartup { get; set; }
|
||||
public int AmdPresetId_ApplyOnStartup { get; set; }
|
||||
public bool FixChromeFonts { get; set; }
|
||||
public bool UseGdiScaling { get; set; }
|
||||
public ListViewSortState NvPresetsSortState { get; set; }
|
||||
public ListViewSortState AmdPresetsSortState { get; set; }
|
||||
public ListViewSortState LgPresetsSortState { get; set; }
|
||||
public ListViewSortState GamePresetsSortState { get; set; }
|
||||
public string NvQuickAccessShortcut { get; set; }
|
||||
public string AmdQuickAccessShortcut { get; set; }
|
||||
public string LgQuickAccessShortcut { get; set; }
|
||||
public string GameQuickAccessShortcut { get; set; }
|
||||
public bool UseDedicatedElevatedProcess { get; set; }
|
||||
public ElevationMethod ElevationMethod { get; set; }
|
||||
public bool ElevationMethodAsked { get; set; }
|
||||
public List<Module> Modules { get; set; }
|
||||
|
||||
public Config()
|
||||
{
|
||||
DisplaySettingsDelay = 1000;
|
||||
ScreenSaverShortcut = string.Empty;
|
||||
FormWidth = 900;
|
||||
FormHeight = 600;
|
||||
MinimizeToTray = true;
|
||||
CheckForUpdates = true;
|
||||
FixChromeFonts = false;
|
||||
UseGdiScaling = true;
|
||||
UseDedicatedElevatedProcess = false;
|
||||
ElevationMethod = ElevationMethod.None;
|
||||
ElevationMethodAsked = false;
|
||||
LgPresetsSortState = new ListViewSortState();
|
||||
NvPresetsSortState = new ListViewSortState();
|
||||
AmdPresetsSortState = new ListViewSortState();
|
||||
GamePresetsSortState = new ListViewSortState();
|
||||
Modules = new List<Module>();
|
||||
}
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
namespace ColorControl.Forms
|
||||
{
|
||||
partial class ElevatedForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ElevatedForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(251, 124);
|
||||
this.Name = "ElevatedForm";
|
||||
this.Text = "ElevatedForm";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
using ColorControl.Native;
|
||||
using NWin32;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl.Forms
|
||||
{
|
||||
public partial class ElevatedForm : Form
|
||||
{
|
||||
public ElevatedForm()
|
||||
{
|
||||
File.Delete("d:\\Msg.txt");
|
||||
InitializeComponent();
|
||||
|
||||
FormBorderStyle = FormBorderStyle.None;
|
||||
ShowInTaskbar = false;
|
||||
Load += ElevatedForm_Load;
|
||||
Shown += ElevatedForm_Shown;
|
||||
|
||||
var filterStatus = new WinApi.CHANGEFILTERSTRUCT();
|
||||
filterStatus.size = (uint)Marshal.SizeOf(filterStatus);
|
||||
filterStatus.info = 0;
|
||||
|
||||
var result = WinApi.ChangeWindowMessageFilterEx(Handle, NativeConstants.WM_COPYDATA, WinApi.ChangeWindowMessageFilterExAction.Allow, ref filterStatus);
|
||||
//File.AppendAllLines("d:\\Msg.txt", new[] { "ChangeWindowMessageFilterEx result: " + result });
|
||||
|
||||
Task.Run(() => CheckMutexAsync());
|
||||
}
|
||||
|
||||
private void ElevatedForm_Shown(object sender, EventArgs e)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
protected void ElevatedForm_Load(object sender, EventArgs e)
|
||||
{
|
||||
Size = new Size(0, 0);
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (m.Msg == NativeConstants.WM_COPYDATA)
|
||||
{
|
||||
var container = (WinApi.COPYDATASTRUCT)m.GetLParam(typeof(WinApi.COPYDATASTRUCT));
|
||||
var message = Marshal.PtrToStringAnsi(container.lpData);
|
||||
|
||||
//File.AppendAllLines("d:\\Msg.txt", new[] { "Message received: " + message });
|
||||
|
||||
HandleMessage(message);
|
||||
|
||||
//Utils.StartProcess("notepad.exe");
|
||||
|
||||
//BackColor = Color.Red;
|
||||
//Text = "AHA!";
|
||||
//MessageForms.WarningOk("Received!");
|
||||
}
|
||||
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
private void HandleMessage(string message)
|
||||
{
|
||||
var args = message.Split(' ');
|
||||
|
||||
var startUpParams = StartUpParams.Parse(args);
|
||||
|
||||
try
|
||||
{
|
||||
var _ = Program.HandleStartupParams(startUpParams, null);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckMutexAsync()
|
||||
{
|
||||
var mutex = new Mutex(false, Program.MutexId, out var created);
|
||||
|
||||
File.AppendAllLines("d:\\Msg.txt", new[] { "Mutex created: " + created });
|
||||
|
||||
try
|
||||
{
|
||||
mutex.WaitOne();
|
||||
File.AppendAllLines("d:\\Msg.txt", new[] { "Mutex released?" });
|
||||
}
|
||||
catch (AbandonedMutexException)
|
||||
{
|
||||
File.AppendAllLines("d:\\Msg.txt", new[] { "Mutex abandoned" });
|
||||
}
|
||||
BeginInvoke(() => Application.Exit());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<root>
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
Generated
+119
@@ -0,0 +1,119 @@
|
||||
namespace ColorControl.Forms
|
||||
{
|
||||
partial class InfoPanel
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
wvInfo = new Microsoft.Web.WebView2.WinForms.WebView2();
|
||||
grpInfo = new System.Windows.Forms.GroupBox();
|
||||
lbPlugins = new System.Windows.Forms.ListBox();
|
||||
label7 = new System.Windows.Forms.Label();
|
||||
lblInfo = new System.Windows.Forms.Label();
|
||||
((System.ComponentModel.ISupportInitialize)wvInfo).BeginInit();
|
||||
grpInfo.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// wvInfo
|
||||
//
|
||||
wvInfo.AllowExternalDrop = true;
|
||||
wvInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
wvInfo.CreationProperties = null;
|
||||
wvInfo.DefaultBackgroundColor = System.Drawing.Color.White;
|
||||
wvInfo.Location = new System.Drawing.Point(433, 3);
|
||||
wvInfo.Name = "wvInfo";
|
||||
wvInfo.Size = new System.Drawing.Size(671, 526);
|
||||
wvInfo.Source = new System.Uri("https://github.com/Maassoft/ColorControl/releases", System.UriKind.Absolute);
|
||||
wvInfo.TabIndex = 8;
|
||||
wvInfo.ZoomFactor = 1D;
|
||||
//
|
||||
// grpInfo
|
||||
//
|
||||
grpInfo.Controls.Add(lbPlugins);
|
||||
grpInfo.Controls.Add(label7);
|
||||
grpInfo.Controls.Add(lblInfo);
|
||||
grpInfo.Location = new System.Drawing.Point(4, 3);
|
||||
grpInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpInfo.Name = "grpInfo";
|
||||
grpInfo.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpInfo.Size = new System.Drawing.Size(422, 336);
|
||||
grpInfo.TabIndex = 7;
|
||||
grpInfo.TabStop = false;
|
||||
grpInfo.Text = "Info";
|
||||
//
|
||||
// lbPlugins
|
||||
//
|
||||
lbPlugins.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
lbPlugins.FormattingEnabled = true;
|
||||
lbPlugins.HorizontalScrollbar = true;
|
||||
lbPlugins.ItemHeight = 15;
|
||||
lbPlugins.Location = new System.Drawing.Point(11, 77);
|
||||
lbPlugins.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
lbPlugins.Name = "lbPlugins";
|
||||
lbPlugins.Size = new System.Drawing.Size(403, 244);
|
||||
lbPlugins.TabIndex = 3;
|
||||
//
|
||||
// label7
|
||||
//
|
||||
label7.AutoSize = true;
|
||||
label7.Location = new System.Drawing.Point(8, 59);
|
||||
label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label7.Name = "label7";
|
||||
label7.Size = new System.Drawing.Size(267, 15);
|
||||
label7.TabIndex = 2;
|
||||
label7.Text = "This app contains the following 3rd party plugins:";
|
||||
//
|
||||
// lblInfo
|
||||
//
|
||||
lblInfo.AutoSize = true;
|
||||
lblInfo.Location = new System.Drawing.Point(8, 23);
|
||||
lblInfo.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblInfo.Name = "lblInfo";
|
||||
lblInfo.Size = new System.Drawing.Size(28, 15);
|
||||
lblInfo.TabIndex = 1;
|
||||
lblInfo.Text = "Info";
|
||||
//
|
||||
// InfoPanel
|
||||
//
|
||||
Controls.Add(wvInfo);
|
||||
Controls.Add(grpInfo);
|
||||
Name = "InfoPanel";
|
||||
Size = new System.Drawing.Size(1110, 534);
|
||||
((System.ComponentModel.ISupportInitialize)wvInfo).EndInit();
|
||||
grpInfo.ResumeLayout(false);
|
||||
grpInfo.PerformLayout();
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Microsoft.Web.WebView2.WinForms.WebView2 wvInfo;
|
||||
private System.Windows.Forms.GroupBox grpInfo;
|
||||
private System.Windows.Forms.ListBox lbPlugins;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private System.Windows.Forms.Label lblInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using ColorControl.Shared.Forms;
|
||||
using ColorControl.Shared.Services;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl.Forms
|
||||
{
|
||||
public partial class InfoPanel : UserControl
|
||||
{
|
||||
private readonly WinApiService _winApiService;
|
||||
|
||||
public InfoPanel(WinApiService winApiService)
|
||||
{
|
||||
_winApiService = winApiService;
|
||||
InitializeComponent();
|
||||
|
||||
if (DarkModeUtils.UseDarkMode)
|
||||
{
|
||||
grpInfo.ForeColor = FormUtils.CurrentForeColor;
|
||||
}
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
var currentVersionInfo = FileVersionInfo.GetVersionInfo(Application.ExecutablePath);
|
||||
|
||||
var text = Application.ProductName + " " + Application.ProductVersion;
|
||||
|
||||
if (_winApiService.IsAdministrator())
|
||||
{
|
||||
text += " (administrator)";
|
||||
}
|
||||
|
||||
lblInfo.Text = text + " - " + currentVersionInfo.LegalCopyright;
|
||||
|
||||
lbPlugins.Items.Add("lgtv.net by gr4b4z");
|
||||
lbPlugins.Items.Add("Newtonsoft.Json by James Newton-King");
|
||||
lbPlugins.Items.Add("NLog by Jarek Kowalski, Kim Christensen, Julian Verdurmen");
|
||||
lbPlugins.Items.Add("NvAPIWrapper.Net by Soroush Falahati");
|
||||
lbPlugins.Items.Add("NWin32 by zmjack");
|
||||
lbPlugins.Items.Add("TaskScheduler by David Hall");
|
||||
lbPlugins.Items.Add("NVIDIA Profile Inspector by Orbmu2k");
|
||||
lbPlugins.Items.Add("NvidiaML wrapper by LibreHardwareMonitor");
|
||||
lbPlugins.Items.Add("Novideo sRGB by ledoge");
|
||||
lbPlugins.Items.Add("NLogViewer by dojo90");
|
||||
lbPlugins.Items.Add("WPFDarkTheme by AngryCarrot789");
|
||||
lbPlugins.Items.Add("Little-CMS by mm2");
|
||||
lbPlugins.Items.Add("MHC2 by dantmnf");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
+539
@@ -0,0 +1,539 @@
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.Drawing;
|
||||
using System;
|
||||
|
||||
namespace ColorControl.Forms
|
||||
{
|
||||
partial class OptionsPanel
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Component Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
grpOptionsModules = new System.Windows.Forms.GroupBox();
|
||||
label1 = new System.Windows.Forms.Label();
|
||||
chkModules = new System.Windows.Forms.CheckedListBox();
|
||||
grpMiscellaneousOptions = new System.Windows.Forms.GroupBox();
|
||||
btnOptionsColorProfiles = new System.Windows.Forms.Button();
|
||||
btnSetShortcutScreenSaver = new System.Windows.Forms.Button();
|
||||
label11 = new System.Windows.Forms.Label();
|
||||
edtBlankScreenSaverShortcut = new System.Windows.Forms.TextBox();
|
||||
lblFixChromeFontsDescription = new System.Windows.Forms.Label();
|
||||
chkFixChromeFonts = new System.Windows.Forms.CheckBox();
|
||||
grpGeneralOptions = new System.Windows.Forms.GroupBox();
|
||||
btnOptionsLog = new System.Windows.Forms.Button();
|
||||
btnOptionsAdvanced = new System.Windows.Forms.Button();
|
||||
chkAutoInstallUpdates = new System.Windows.Forms.CheckBox();
|
||||
btnStartStopService = new System.Windows.Forms.Button();
|
||||
btnElevationInfo = new System.Windows.Forms.Button();
|
||||
rbElevationService = new System.Windows.Forms.RadioButton();
|
||||
rbElevationProcess = new System.Windows.Forms.RadioButton();
|
||||
rbElevationAdmin = new System.Windows.Forms.RadioButton();
|
||||
label8 = new System.Windows.Forms.Label();
|
||||
rbElevationNone = new System.Windows.Forms.RadioButton();
|
||||
chkCheckForUpdates = new System.Windows.Forms.CheckBox();
|
||||
chkStartAfterLogin = new System.Windows.Forms.CheckBox();
|
||||
chkOptionsUseDarkMode = new System.Windows.Forms.CheckBox();
|
||||
chkGdiScaling = new System.Windows.Forms.CheckBox();
|
||||
chkMinimizeToSystemTray = new System.Windows.Forms.CheckBox();
|
||||
chkMinimizeOnClose = new System.Windows.Forms.CheckBox();
|
||||
chkStartMinimized = new System.Windows.Forms.CheckBox();
|
||||
mnuColorProfiles = new System.Windows.Forms.ContextMenuStrip(components);
|
||||
miCreateHDRColorProfile = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miCreateSDRColorProfile = new System.Windows.Forms.ToolStripMenuItem();
|
||||
lblUiType = new System.Windows.Forms.Label();
|
||||
cbxUiType = new System.Windows.Forms.ComboBox();
|
||||
grpUi = new System.Windows.Forms.GroupBox();
|
||||
grpOptionsModules.SuspendLayout();
|
||||
grpMiscellaneousOptions.SuspendLayout();
|
||||
grpGeneralOptions.SuspendLayout();
|
||||
mnuColorProfiles.SuspendLayout();
|
||||
grpUi.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// grpOptionsModules
|
||||
//
|
||||
grpOptionsModules.Controls.Add(label1);
|
||||
grpOptionsModules.Controls.Add(chkModules);
|
||||
grpOptionsModules.Location = new Point(14, 344);
|
||||
grpOptionsModules.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpOptionsModules.Name = "grpOptionsModules";
|
||||
grpOptionsModules.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpOptionsModules.Size = new Size(658, 131);
|
||||
grpOptionsModules.TabIndex = 11;
|
||||
grpOptionsModules.TabStop = false;
|
||||
grpOptionsModules.Text = "Modules";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
label1.AutoSize = true;
|
||||
label1.Location = new Point(7, 19);
|
||||
label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new Size(511, 15);
|
||||
label1.TabIndex = 7;
|
||||
label1.Text = "Here you can disable modules you do not want. A restart is required for a change to have effect.";
|
||||
//
|
||||
// chkModules
|
||||
//
|
||||
chkModules.ColumnWidth = 200;
|
||||
chkModules.FormattingEnabled = true;
|
||||
chkModules.Location = new Point(7, 40);
|
||||
chkModules.MultiColumn = true;
|
||||
chkModules.Name = "chkModules";
|
||||
chkModules.Size = new Size(507, 76);
|
||||
chkModules.TabIndex = 0;
|
||||
chkModules.ItemCheck += chkModules_ItemCheck;
|
||||
//
|
||||
// grpMiscellaneousOptions
|
||||
//
|
||||
grpMiscellaneousOptions.Controls.Add(btnOptionsColorProfiles);
|
||||
grpMiscellaneousOptions.Controls.Add(btnSetShortcutScreenSaver);
|
||||
grpMiscellaneousOptions.Controls.Add(label11);
|
||||
grpMiscellaneousOptions.Controls.Add(edtBlankScreenSaverShortcut);
|
||||
grpMiscellaneousOptions.Controls.Add(lblFixChromeFontsDescription);
|
||||
grpMiscellaneousOptions.Controls.Add(chkFixChromeFonts);
|
||||
grpMiscellaneousOptions.Location = new Point(14, 481);
|
||||
grpMiscellaneousOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpMiscellaneousOptions.Name = "grpMiscellaneousOptions";
|
||||
grpMiscellaneousOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpMiscellaneousOptions.Size = new Size(658, 131);
|
||||
grpMiscellaneousOptions.TabIndex = 5;
|
||||
grpMiscellaneousOptions.TabStop = false;
|
||||
grpMiscellaneousOptions.Text = "Miscellaneous";
|
||||
//
|
||||
// btnOptionsColorProfiles
|
||||
//
|
||||
btnOptionsColorProfiles.Location = new Point(538, 17);
|
||||
btnOptionsColorProfiles.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnOptionsColorProfiles.Name = "btnOptionsColorProfiles";
|
||||
btnOptionsColorProfiles.Size = new Size(112, 27);
|
||||
btnOptionsColorProfiles.TabIndex = 12;
|
||||
btnOptionsColorProfiles.Text = "Color Profiles...";
|
||||
btnOptionsColorProfiles.UseVisualStyleBackColor = true;
|
||||
btnOptionsColorProfiles.Click += btnOptionsColorProfiles_Click;
|
||||
//
|
||||
// btnSetShortcutScreenSaver
|
||||
//
|
||||
btnSetShortcutScreenSaver.Location = new Point(181, 98);
|
||||
btnSetShortcutScreenSaver.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSetShortcutScreenSaver.Name = "btnSetShortcutScreenSaver";
|
||||
btnSetShortcutScreenSaver.Size = new Size(40, 27);
|
||||
btnSetShortcutScreenSaver.TabIndex = 10;
|
||||
btnSetShortcutScreenSaver.Text = "Set";
|
||||
btnSetShortcutScreenSaver.UseVisualStyleBackColor = true;
|
||||
btnSetShortcutScreenSaver.Click += btnSetShortcutScreenSaver_Click;
|
||||
//
|
||||
// label11
|
||||
//
|
||||
label11.AutoSize = true;
|
||||
label11.Location = new Point(7, 80);
|
||||
label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label11.Name = "label11";
|
||||
label11.Size = new Size(238, 15);
|
||||
label11.TabIndex = 9;
|
||||
label11.Text = "Set a shortcut to start the blank screensaver:";
|
||||
//
|
||||
// edtBlankScreenSaverShortcut
|
||||
//
|
||||
edtBlankScreenSaverShortcut.Location = new Point(7, 101);
|
||||
edtBlankScreenSaverShortcut.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtBlankScreenSaverShortcut.Name = "edtBlankScreenSaverShortcut";
|
||||
edtBlankScreenSaverShortcut.ReadOnly = true;
|
||||
edtBlankScreenSaverShortcut.Size = new Size(165, 23);
|
||||
edtBlankScreenSaverShortcut.TabIndex = 7;
|
||||
edtBlankScreenSaverShortcut.KeyDown += edtShortcut_KeyDown;
|
||||
edtBlankScreenSaverShortcut.KeyUp += edtShortcut_KeyUp;
|
||||
//
|
||||
// lblFixChromeFontsDescription
|
||||
//
|
||||
lblFixChromeFontsDescription.AutoSize = true;
|
||||
lblFixChromeFontsDescription.Location = new Point(4, 45);
|
||||
lblFixChromeFontsDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblFixChromeFontsDescription.Name = "lblFixChromeFontsDescription";
|
||||
lblFixChromeFontsDescription.Size = new Size(427, 15);
|
||||
lblFixChromeFontsDescription.TabIndex = 6;
|
||||
lblFixChromeFontsDescription.Text = "This will add the parameter --disable-lcd-text to Chrome and requires elevation.";
|
||||
//
|
||||
// chkFixChromeFonts
|
||||
//
|
||||
chkFixChromeFonts.AutoSize = true;
|
||||
chkFixChromeFonts.Location = new Point(7, 22);
|
||||
chkFixChromeFonts.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkFixChromeFonts.Name = "chkFixChromeFonts";
|
||||
chkFixChromeFonts.Size = new Size(378, 19);
|
||||
chkFixChromeFonts.TabIndex = 4;
|
||||
chkFixChromeFonts.Text = "ClearType: fix bad fonts in Chrome (turn on grayscale anti-aliasing)";
|
||||
chkFixChromeFonts.UseVisualStyleBackColor = true;
|
||||
chkFixChromeFonts.CheckedChanged += chkFixChromeFonts_CheckedChanged;
|
||||
//
|
||||
// grpGeneralOptions
|
||||
//
|
||||
grpGeneralOptions.Controls.Add(btnOptionsLog);
|
||||
grpGeneralOptions.Controls.Add(btnOptionsAdvanced);
|
||||
grpGeneralOptions.Controls.Add(chkAutoInstallUpdates);
|
||||
grpGeneralOptions.Controls.Add(btnStartStopService);
|
||||
grpGeneralOptions.Controls.Add(btnElevationInfo);
|
||||
grpGeneralOptions.Controls.Add(rbElevationService);
|
||||
grpGeneralOptions.Controls.Add(rbElevationProcess);
|
||||
grpGeneralOptions.Controls.Add(rbElevationAdmin);
|
||||
grpGeneralOptions.Controls.Add(label8);
|
||||
grpGeneralOptions.Controls.Add(rbElevationNone);
|
||||
grpGeneralOptions.Controls.Add(chkCheckForUpdates);
|
||||
grpGeneralOptions.Controls.Add(chkStartAfterLogin);
|
||||
grpGeneralOptions.Location = new Point(7, 6);
|
||||
grpGeneralOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpGeneralOptions.Name = "grpGeneralOptions";
|
||||
grpGeneralOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpGeneralOptions.Size = new Size(662, 202);
|
||||
grpGeneralOptions.TabIndex = 2;
|
||||
grpGeneralOptions.TabStop = false;
|
||||
grpGeneralOptions.Text = "General";
|
||||
//
|
||||
// btnOptionsLog
|
||||
//
|
||||
btnOptionsLog.Location = new Point(405, 47);
|
||||
btnOptionsLog.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnOptionsLog.Name = "btnOptionsLog";
|
||||
btnOptionsLog.Size = new Size(88, 27);
|
||||
btnOptionsLog.TabIndex = 68;
|
||||
btnOptionsLog.Text = "Logging...";
|
||||
btnOptionsLog.UseVisualStyleBackColor = true;
|
||||
btnOptionsLog.Click += btnOptionsLog_Click;
|
||||
//
|
||||
// btnOptionsAdvanced
|
||||
//
|
||||
btnOptionsAdvanced.Location = new Point(405, 17);
|
||||
btnOptionsAdvanced.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnOptionsAdvanced.Name = "btnOptionsAdvanced";
|
||||
btnOptionsAdvanced.Size = new Size(88, 27);
|
||||
btnOptionsAdvanced.TabIndex = 11;
|
||||
btnOptionsAdvanced.Text = "Advanced...";
|
||||
btnOptionsAdvanced.UseVisualStyleBackColor = true;
|
||||
btnOptionsAdvanced.Click += btnOptionsAdvanced_Click;
|
||||
//
|
||||
// chkAutoInstallUpdates
|
||||
//
|
||||
chkAutoInstallUpdates.AutoSize = true;
|
||||
chkAutoInstallUpdates.Location = new Point(7, 72);
|
||||
chkAutoInstallUpdates.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkAutoInstallUpdates.Name = "chkAutoInstallUpdates";
|
||||
chkAutoInstallUpdates.Size = new Size(179, 19);
|
||||
chkAutoInstallUpdates.TabIndex = 66;
|
||||
chkAutoInstallUpdates.Text = "Automatically install updates";
|
||||
chkAutoInstallUpdates.UseVisualStyleBackColor = true;
|
||||
chkAutoInstallUpdates.CheckedChanged += chkAutoInstallUpdates_CheckedChanged;
|
||||
//
|
||||
// btnStartStopService
|
||||
//
|
||||
btnStartStopService.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnStartStopService.Location = new Point(405, 150);
|
||||
btnStartStopService.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnStartStopService.Name = "btnStartStopService";
|
||||
btnStartStopService.Size = new Size(40, 27);
|
||||
btnStartStopService.TabIndex = 65;
|
||||
btnStartStopService.Text = "Start";
|
||||
btnStartStopService.UseVisualStyleBackColor = true;
|
||||
btnStartStopService.Click += btnStartStopService_Click;
|
||||
//
|
||||
// btnElevationInfo
|
||||
//
|
||||
btnElevationInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnElevationInfo.Location = new Point(120, 88);
|
||||
btnElevationInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnElevationInfo.Name = "btnElevationInfo";
|
||||
btnElevationInfo.Size = new Size(22, 27);
|
||||
btnElevationInfo.TabIndex = 64;
|
||||
btnElevationInfo.Text = "?";
|
||||
btnElevationInfo.UseVisualStyleBackColor = true;
|
||||
btnElevationInfo.Click += btnElevationInfo_Click;
|
||||
//
|
||||
// rbElevationService
|
||||
//
|
||||
rbElevationService.AutoSize = true;
|
||||
rbElevationService.Location = new Point(7, 154);
|
||||
rbElevationService.Name = "rbElevationService";
|
||||
rbElevationService.Size = new Size(136, 19);
|
||||
rbElevationService.TabIndex = 63;
|
||||
rbElevationService.TabStop = true;
|
||||
rbElevationService.Tag = "2";
|
||||
rbElevationService.Text = "Use Windows Service";
|
||||
rbElevationService.UseVisualStyleBackColor = true;
|
||||
rbElevationService.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// rbElevationProcess
|
||||
//
|
||||
rbElevationProcess.AutoSize = true;
|
||||
rbElevationProcess.Location = new Point(7, 175);
|
||||
rbElevationProcess.Name = "rbElevationProcess";
|
||||
rbElevationProcess.Size = new Size(189, 19);
|
||||
rbElevationProcess.TabIndex = 62;
|
||||
rbElevationProcess.TabStop = true;
|
||||
rbElevationProcess.Tag = "3";
|
||||
rbElevationProcess.Text = "Use dedicated elevated process";
|
||||
rbElevationProcess.UseVisualStyleBackColor = true;
|
||||
rbElevationProcess.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// rbElevationAdmin
|
||||
//
|
||||
rbElevationAdmin.AutoSize = true;
|
||||
rbElevationAdmin.Location = new Point(7, 133);
|
||||
rbElevationAdmin.Name = "rbElevationAdmin";
|
||||
rbElevationAdmin.Size = new Size(97, 19);
|
||||
rbElevationAdmin.TabIndex = 61;
|
||||
rbElevationAdmin.TabStop = true;
|
||||
rbElevationAdmin.Tag = "1";
|
||||
rbElevationAdmin.Text = "Run as admin";
|
||||
rbElevationAdmin.UseVisualStyleBackColor = true;
|
||||
rbElevationAdmin.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// label8
|
||||
//
|
||||
label8.AutoSize = true;
|
||||
label8.Location = new Point(7, 94);
|
||||
label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label8.Name = "label8";
|
||||
label8.Size = new Size(105, 15);
|
||||
label8.TabIndex = 60;
|
||||
label8.Text = "Elevation-method:";
|
||||
//
|
||||
// rbElevationNone
|
||||
//
|
||||
rbElevationNone.AutoSize = true;
|
||||
rbElevationNone.Location = new Point(7, 112);
|
||||
rbElevationNone.Name = "rbElevationNone";
|
||||
rbElevationNone.Size = new Size(54, 19);
|
||||
rbElevationNone.TabIndex = 10;
|
||||
rbElevationNone.TabStop = true;
|
||||
rbElevationNone.Tag = "0";
|
||||
rbElevationNone.Text = "None";
|
||||
rbElevationNone.UseVisualStyleBackColor = true;
|
||||
rbElevationNone.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// chkCheckForUpdates
|
||||
//
|
||||
chkCheckForUpdates.AutoSize = true;
|
||||
chkCheckForUpdates.Location = new Point(7, 47);
|
||||
chkCheckForUpdates.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkCheckForUpdates.Name = "chkCheckForUpdates";
|
||||
chkCheckForUpdates.Size = new Size(197, 19);
|
||||
chkCheckForUpdates.TabIndex = 6;
|
||||
chkCheckForUpdates.Text = "Automatically check for updates";
|
||||
chkCheckForUpdates.UseVisualStyleBackColor = true;
|
||||
chkCheckForUpdates.CheckedChanged += chkCheckForUpdates_CheckedChanged;
|
||||
//
|
||||
// chkStartAfterLogin
|
||||
//
|
||||
chkStartAfterLogin.AutoSize = true;
|
||||
chkStartAfterLogin.Location = new Point(7, 22);
|
||||
chkStartAfterLogin.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkStartAfterLogin.Name = "chkStartAfterLogin";
|
||||
chkStartAfterLogin.Size = new Size(183, 19);
|
||||
chkStartAfterLogin.TabIndex = 2;
|
||||
chkStartAfterLogin.Text = "Automatically start after login";
|
||||
chkStartAfterLogin.UseVisualStyleBackColor = true;
|
||||
chkStartAfterLogin.CheckedChanged += chkStartAfterLogin_CheckedChanged;
|
||||
//
|
||||
// chkOptionsUseDarkMode
|
||||
//
|
||||
chkOptionsUseDarkMode.AutoSize = true;
|
||||
chkOptionsUseDarkMode.Location = new Point(329, 22);
|
||||
chkOptionsUseDarkMode.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkOptionsUseDarkMode.Name = "chkOptionsUseDarkMode";
|
||||
chkOptionsUseDarkMode.Size = new Size(224, 19);
|
||||
chkOptionsUseDarkMode.TabIndex = 67;
|
||||
chkOptionsUseDarkMode.Text = "Dark Mode (WinForms: experimental)";
|
||||
chkOptionsUseDarkMode.UseVisualStyleBackColor = true;
|
||||
chkOptionsUseDarkMode.CheckedChanged += chkOptionsUseDarkMode_CheckedChanged;
|
||||
//
|
||||
// chkGdiScaling
|
||||
//
|
||||
chkGdiScaling.AutoSize = true;
|
||||
chkGdiScaling.Location = new Point(329, 47);
|
||||
chkGdiScaling.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkGdiScaling.Name = "chkGdiScaling";
|
||||
chkGdiScaling.Size = new Size(257, 19);
|
||||
chkGdiScaling.TabIndex = 7;
|
||||
chkGdiScaling.Text = "WinForms: Use GDI Scaling (requires restart)";
|
||||
chkGdiScaling.UseVisualStyleBackColor = true;
|
||||
chkGdiScaling.CheckedChanged += chkGdiScaling_CheckedChanged;
|
||||
//
|
||||
// chkMinimizeToSystemTray
|
||||
//
|
||||
chkMinimizeToSystemTray.AutoSize = true;
|
||||
chkMinimizeToSystemTray.Location = new Point(7, 97);
|
||||
chkMinimizeToSystemTray.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkMinimizeToSystemTray.Name = "chkMinimizeToSystemTray";
|
||||
chkMinimizeToSystemTray.Size = new Size(152, 19);
|
||||
chkMinimizeToSystemTray.TabIndex = 5;
|
||||
chkMinimizeToSystemTray.Text = "Minimize to system tray";
|
||||
chkMinimizeToSystemTray.UseVisualStyleBackColor = true;
|
||||
chkMinimizeToSystemTray.CheckedChanged += chkMinimizeToSystemTray_CheckedChanged;
|
||||
//
|
||||
// chkMinimizeOnClose
|
||||
//
|
||||
chkMinimizeOnClose.AutoSize = true;
|
||||
chkMinimizeOnClose.Location = new Point(7, 72);
|
||||
chkMinimizeOnClose.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkMinimizeOnClose.Name = "chkMinimizeOnClose";
|
||||
chkMinimizeOnClose.Size = new Size(122, 19);
|
||||
chkMinimizeOnClose.TabIndex = 4;
|
||||
chkMinimizeOnClose.Text = "Minimize on close";
|
||||
chkMinimizeOnClose.UseVisualStyleBackColor = true;
|
||||
chkMinimizeOnClose.CheckedChanged += chkMinimizeOnClose_CheckedChanged;
|
||||
//
|
||||
// chkStartMinimized
|
||||
//
|
||||
chkStartMinimized.AutoSize = true;
|
||||
chkStartMinimized.Location = new Point(7, 47);
|
||||
chkStartMinimized.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkStartMinimized.Name = "chkStartMinimized";
|
||||
chkStartMinimized.Size = new Size(109, 19);
|
||||
chkStartMinimized.TabIndex = 3;
|
||||
chkStartMinimized.Text = "Start minimized";
|
||||
chkStartMinimized.UseVisualStyleBackColor = true;
|
||||
chkStartMinimized.CheckedChanged += chkStartMinimized_CheckedChanged;
|
||||
//
|
||||
// mnuColorProfiles
|
||||
//
|
||||
mnuColorProfiles.ImageScalingSize = new Size(20, 20);
|
||||
mnuColorProfiles.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miCreateHDRColorProfile, miCreateSDRColorProfile });
|
||||
mnuColorProfiles.Name = "mnuLgButtons";
|
||||
mnuColorProfiles.Size = new Size(214, 48);
|
||||
//
|
||||
// miCreateHDRColorProfile
|
||||
//
|
||||
miCreateHDRColorProfile.Name = "miCreateHDRColorProfile";
|
||||
miCreateHDRColorProfile.Size = new Size(213, 22);
|
||||
miCreateHDRColorProfile.Text = "Create HDR Color Profile...";
|
||||
miCreateHDRColorProfile.Click += miCreateHDRColorProfile_Click;
|
||||
//
|
||||
// miCreateSDRColorProfile
|
||||
//
|
||||
miCreateSDRColorProfile.Name = "miCreateSDRColorProfile";
|
||||
miCreateSDRColorProfile.Size = new Size(213, 22);
|
||||
miCreateSDRColorProfile.Text = "Create SDR Color Profile...";
|
||||
miCreateSDRColorProfile.Click += miCreateSDRColorProfile_Click;
|
||||
//
|
||||
// lblUiType
|
||||
//
|
||||
lblUiType.AutoSize = true;
|
||||
lblUiType.Location = new Point(6, 21);
|
||||
lblUiType.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblUiType.Name = "lblUiType";
|
||||
lblUiType.Size = new Size(62, 15);
|
||||
lblUiType.TabIndex = 70;
|
||||
lblUiType.Text = "Default UI:";
|
||||
//
|
||||
// cbxUiType
|
||||
//
|
||||
cbxUiType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
cbxUiType.FormattingEnabled = true;
|
||||
cbxUiType.Items.AddRange(new object[] { "WinForms", "Web (default browser)", "Web (embedded browser)" });
|
||||
cbxUiType.Location = new Point(105, 18);
|
||||
cbxUiType.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
cbxUiType.Name = "cbxUiType";
|
||||
cbxUiType.Size = new Size(208, 23);
|
||||
cbxUiType.TabIndex = 69;
|
||||
cbxUiType.SelectedIndexChanged += cbxUiType_SelectedIndexChanged;
|
||||
//
|
||||
// grpUi
|
||||
//
|
||||
grpUi.Controls.Add(lblUiType);
|
||||
grpUi.Controls.Add(chkStartMinimized);
|
||||
grpUi.Controls.Add(chkOptionsUseDarkMode);
|
||||
grpUi.Controls.Add(cbxUiType);
|
||||
grpUi.Controls.Add(chkMinimizeOnClose);
|
||||
grpUi.Controls.Add(chkMinimizeToSystemTray);
|
||||
grpUi.Controls.Add(chkGdiScaling);
|
||||
grpUi.Location = new Point(7, 214);
|
||||
grpUi.Name = "grpUi";
|
||||
grpUi.Size = new Size(662, 124);
|
||||
grpUi.TabIndex = 8;
|
||||
grpUi.TabStop = false;
|
||||
grpUi.Text = "UI-settings";
|
||||
//
|
||||
// OptionsPanel
|
||||
//
|
||||
Controls.Add(grpUi);
|
||||
Controls.Add(grpOptionsModules);
|
||||
Controls.Add(grpMiscellaneousOptions);
|
||||
Controls.Add(grpGeneralOptions);
|
||||
Name = "OptionsPanel";
|
||||
Size = new Size(732, 615);
|
||||
grpOptionsModules.ResumeLayout(false);
|
||||
grpOptionsModules.PerformLayout();
|
||||
grpMiscellaneousOptions.ResumeLayout(false);
|
||||
grpMiscellaneousOptions.PerformLayout();
|
||||
grpGeneralOptions.ResumeLayout(false);
|
||||
grpGeneralOptions.PerformLayout();
|
||||
mnuColorProfiles.ResumeLayout(false);
|
||||
grpUi.ResumeLayout(false);
|
||||
grpUi.PerformLayout();
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
private System.Windows.Forms.GroupBox grpGeneralOptions;
|
||||
private System.Windows.Forms.CheckBox chkStartMinimized;
|
||||
private System.Windows.Forms.CheckBox chkStartAfterLogin;
|
||||
private System.Windows.Forms.TabPage tabInfo;
|
||||
private System.Windows.Forms.GroupBox grpMiscellaneousOptions;
|
||||
private System.Windows.Forms.CheckBox chkFixChromeFonts;
|
||||
private System.Windows.Forms.Label lblFixChromeFontsDescription;
|
||||
private System.Windows.Forms.Button btnSetShortcutScreenSaver;
|
||||
private System.Windows.Forms.Label label11;
|
||||
private System.Windows.Forms.TextBox edtBlankScreenSaverShortcut;
|
||||
private System.Windows.Forms.CheckBox chkMinimizeOnClose;
|
||||
private System.Windows.Forms.CheckBox chkMinimizeToSystemTray;
|
||||
private System.Windows.Forms.CheckBox chkCheckForUpdates;
|
||||
private System.Windows.Forms.CheckBox chkGdiScaling;
|
||||
private System.Windows.Forms.RadioButton rbElevationService;
|
||||
private System.Windows.Forms.RadioButton rbElevationProcess;
|
||||
private System.Windows.Forms.RadioButton rbElevationAdmin;
|
||||
private System.Windows.Forms.Label label8;
|
||||
private System.Windows.Forms.RadioButton rbElevationNone;
|
||||
private System.Windows.Forms.Button btnElevationInfo;
|
||||
private System.Windows.Forms.Button btnStartStopService;
|
||||
private System.Windows.Forms.CheckBox chkAutoInstallUpdates;
|
||||
private System.Windows.Forms.Button btnUpdate;
|
||||
private System.Windows.Forms.GroupBox grpOptionsModules;
|
||||
private System.Windows.Forms.CheckedListBox chkModules;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.CheckBox chkOptionsUseDarkMode;
|
||||
private System.Windows.Forms.Button btnOptionsAdvanced;
|
||||
private System.Windows.Forms.Button btnOptionsLog;
|
||||
private System.Windows.Forms.Button btnOptionsColorProfiles;
|
||||
private System.Windows.Forms.ContextMenuStrip mnuColorProfiles;
|
||||
private System.Windows.Forms.ToolStripMenuItem miCreateHDRColorProfile;
|
||||
private System.Windows.Forms.ToolStripMenuItem miCreateSDRColorProfile;
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label lblUiType;
|
||||
private System.Windows.Forms.ComboBox cbxUiType;
|
||||
private System.Windows.Forms.GroupBox grpUi;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
using ColorControl.Services.Common;
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.EventDispatcher;
|
||||
using ColorControl.Shared.Forms;
|
||||
using ColorControl.Shared.Services;
|
||||
using ColorControl.XForms;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl.Forms;
|
||||
|
||||
public partial class OptionsPanel : UserControl
|
||||
{
|
||||
private readonly WinApiService _winApiService;
|
||||
private readonly WinApiAdminService _winApiAdminService;
|
||||
private readonly ElevationService _elevationService;
|
||||
private readonly KeyboardShortcutDispatcher _keyboardShortcutDispatcher;
|
||||
private readonly OptionsService _optionsService;
|
||||
private bool _initialized;
|
||||
private Config _config;
|
||||
|
||||
public OptionsPanel(WinApiService winApiService, WinApiAdminService winApiAdminService, ElevationService elevationService, KeyboardShortcutDispatcher keyboardShortcutDispatcher, OptionsService optionsService)
|
||||
{
|
||||
_winApiService = winApiService;
|
||||
_winApiAdminService = winApiAdminService;
|
||||
_elevationService = elevationService;
|
||||
_keyboardShortcutDispatcher = keyboardShortcutDispatcher;
|
||||
_optionsService = optionsService;
|
||||
_config = _optionsService.GetConfig();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
if (DarkModeUtils.UseDarkMode)
|
||||
{
|
||||
for (var i = 0; i < Controls.Count; i++)
|
||||
{
|
||||
var control = Controls[i];
|
||||
|
||||
DarkModeUtils.SetControlTheme(control);
|
||||
}
|
||||
}
|
||||
|
||||
Init();
|
||||
|
||||
UpdateServiceInfo();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
if (chkModules.Items.Count == 0)
|
||||
{
|
||||
foreach (var module in _config.Modules)
|
||||
{
|
||||
chkModules.Items.Add(module.DisplayName, module.IsActive);
|
||||
}
|
||||
}
|
||||
|
||||
chkStartMinimized.Checked = _config.StartMinimized;
|
||||
chkMinimizeOnClose.Checked = _config.MinimizeOnClose;
|
||||
chkMinimizeToSystemTray.Checked = _config.MinimizeToTray;
|
||||
chkCheckForUpdates.Checked = _config.CheckForUpdates;
|
||||
chkAutoInstallUpdates.Checked = _config.AutoInstallUpdates;
|
||||
chkAutoInstallUpdates.Enabled = _config.CheckForUpdates && _config.ElevationMethod == ElevationMethod.UseService;
|
||||
edtBlankScreenSaverShortcut.Text = _config.ScreenSaverShortcut;
|
||||
chkGdiScaling.Checked = _config.UseGdiScaling;
|
||||
chkOptionsUseDarkMode.Checked = _config.UseDarkMode;
|
||||
|
||||
chkStartAfterLogin.Checked = _winApiService.TaskExists(Program.TS_TASKNAME);
|
||||
|
||||
chkFixChromeFonts.Enabled = _winApiService.IsChromeInstalled();
|
||||
if (chkFixChromeFonts.Enabled)
|
||||
{
|
||||
chkFixChromeFonts.Checked = _winApiService.IsChromeFixInstalled();
|
||||
}
|
||||
|
||||
_initialized = false;
|
||||
try
|
||||
{
|
||||
var _ = _config.ElevationMethod switch
|
||||
{
|
||||
ElevationMethod.None => rbElevationNone.Checked = true,
|
||||
ElevationMethod.RunAsAdmin => rbElevationAdmin.Checked = true,
|
||||
ElevationMethod.UseService => rbElevationService.Checked = true,
|
||||
ElevationMethod.UseElevatedProcess => rbElevationProcess.Checked = true,
|
||||
_ => false
|
||||
};
|
||||
|
||||
|
||||
cbxUiType.SelectedIndex = (int)_config.UiType;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateServiceInfo()
|
||||
{
|
||||
var text = "Use Windows Service";
|
||||
btnStartStopService.Enabled = true;
|
||||
|
||||
if (_winApiService.IsServiceRunning())
|
||||
{
|
||||
text += " (running)";
|
||||
btnStartStopService.Text = "Stop";
|
||||
}
|
||||
else if (_winApiService.IsServiceInstalled())
|
||||
{
|
||||
text += " (installed, not running)";
|
||||
btnStartStopService.Text = "Start";
|
||||
}
|
||||
else
|
||||
{
|
||||
text += " (not installed)";
|
||||
btnStartStopService.Text = "Start";
|
||||
btnStartStopService.Enabled = false;
|
||||
}
|
||||
|
||||
rbElevationService.Text = text;
|
||||
}
|
||||
|
||||
private void edtShortcut_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
((TextBox)sender).Text = KeyboardShortcutDispatcher.FormatKeyboardShortcut(e);
|
||||
}
|
||||
|
||||
private void edtShortcut_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
KeyboardShortcutDispatcher.HandleKeyboardShortcutUp(e);
|
||||
}
|
||||
|
||||
private void btnSetShortcutScreenSaver_Click(object sender, EventArgs e)
|
||||
{
|
||||
var shortcut = edtBlankScreenSaverShortcut.Text.Trim();
|
||||
|
||||
if (!KeyboardShortcutDispatcher.ValidateShortcut(shortcut))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_config.ScreenSaverShortcut = shortcut;
|
||||
|
||||
_keyboardShortcutDispatcher.RegisterShortcut(MainWorker.SHORTCUTID_SCREENSAVER, shortcut);
|
||||
}
|
||||
|
||||
private void chkFixChromeFonts_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
_config.FixChromeFonts = chkFixChromeFonts.Checked;
|
||||
|
||||
var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
||||
_winApiAdminService.InstallChromeFix(chkFixChromeFonts.Checked, folder);
|
||||
}
|
||||
}
|
||||
|
||||
private void chkAutoInstallUpdates_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
_config.AutoInstallUpdates = chkAutoInstallUpdates.Checked;
|
||||
}
|
||||
}
|
||||
|
||||
private void chkMinimizeToSystemTray_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
_optionsService.SetMinimizeToTray(chkMinimizeToSystemTray.Checked);
|
||||
}
|
||||
}
|
||||
|
||||
private void chkCheckForUpdates_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
_config.CheckForUpdates = chkCheckForUpdates.Checked;
|
||||
chkAutoInstallUpdates.Enabled = _config.CheckForUpdates && _config.ElevationMethod == ElevationMethod.UseService;
|
||||
}
|
||||
}
|
||||
|
||||
private void chkGdiScaling_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
_config.UseGdiScaling = chkGdiScaling.Checked;
|
||||
}
|
||||
|
||||
private void chkStartAfterLogin_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var enabled = chkStartAfterLogin.Checked;
|
||||
_optionsService.SetStartAfterLogin(enabled);
|
||||
|
||||
rbElevationAdmin.Enabled = enabled;
|
||||
if (!enabled && rbElevationAdmin.Checked)
|
||||
{
|
||||
rbElevationNone.Checked = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void btnElevationInfo_Click(object sender, EventArgs e)
|
||||
{
|
||||
MessageForms.InfoOk(Utils.ELEVATION_MSG + @$"
|
||||
|
||||
NOTE: if ColorControl itself already runs as administrator this is indicated in the title: ColorControl {Application.ProductVersion} (administrator).
|
||||
|
||||
Currently ColorControl is {(_winApiService.IsAdministrator() ? "" : "not ")}running as administrator.
|
||||
");
|
||||
}
|
||||
|
||||
private void rbElevationNone_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (sender is not RadioButton button || !button.Checked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_elevationService.SetElevationMethod((ElevationMethod)Utils.ParseInt((string)button.Tag), chkStartAfterLogin.Checked);
|
||||
|
||||
UpdateServiceInfo();
|
||||
chkAutoInstallUpdates.Enabled = _config.CheckForUpdates && _config.ElevationMethod == ElevationMethod.UseService;
|
||||
}
|
||||
|
||||
private async void btnStartStopService_Click(object sender, EventArgs e)
|
||||
{
|
||||
btnStartStopService.Enabled = false;
|
||||
try
|
||||
{
|
||||
var start = btnStartStopService.Text == "Start";
|
||||
|
||||
if (start)
|
||||
{
|
||||
_winApiAdminService.StartService();
|
||||
}
|
||||
else
|
||||
{
|
||||
_winApiAdminService.StopService();
|
||||
}
|
||||
|
||||
var wait = 1500;
|
||||
|
||||
while (wait > 0)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
|
||||
if (start == _winApiService.IsServiceRunning())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
wait -= 100;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
btnStartStopService.Enabled = true;
|
||||
}
|
||||
|
||||
UpdateServiceInfo();
|
||||
}
|
||||
|
||||
private void chkMinimizeOnClose_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
_config.MinimizeOnClose = chkMinimizeOnClose.Checked;
|
||||
}
|
||||
|
||||
private void chkOptionsUseDarkMode_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_optionsService.SetDarkMode(chkOptionsUseDarkMode.Checked);
|
||||
}
|
||||
|
||||
private void btnOptionsAdvanced_Click(object sender, EventArgs e)
|
||||
{
|
||||
var processPollingIntervalField = new FieldDefinition
|
||||
{
|
||||
FieldType = FieldType.Numeric,
|
||||
Label = "Polling interval of process monitor (milliseconds).",
|
||||
SubLabel = "Decreasing this delay may execute triggered presets sooner but can cause a higher CPU load",
|
||||
MinValue = 50,
|
||||
MaxValue = 5000,
|
||||
Value = _config.ProcessMonitorPollingInterval
|
||||
};
|
||||
var useRawInputField = new FieldDefinition
|
||||
{
|
||||
FieldType = FieldType.CheckBox,
|
||||
Label = "Use Raw Input for shortcuts (hot keys)",
|
||||
SubLabel = "This enables shortcuts to work during applications/games that block certain keys (like WinKey or Control). NOTE: if the application in the foreground runs with higher privileges than ColorControl, Raw Input does not work and normal hot keys are used",
|
||||
Value = _config.UseRawInput
|
||||
};
|
||||
var setMinTmlAndMaxTmlField = new FieldDefinition
|
||||
{
|
||||
FieldType = FieldType.CheckBox,
|
||||
Label = "Set MinTML and MaxTML when applying color profiles",
|
||||
SubLabel = "When this is enabled MinTML and MaxTML will be automatically be set to respectively the minimum luminance and the maximum luminance of the color profile",
|
||||
Value = _config.SetMinTmlAndMaxTml
|
||||
};
|
||||
var disableErrorPopupField = new FieldDefinition
|
||||
{
|
||||
FieldType = FieldType.CheckBox,
|
||||
Label = "Disable error popup when applying presets",
|
||||
SubLabel = "Check this to disable the error popup when there was an error applying a preset",
|
||||
Value = _config.DisableErrorPopupWhenApplyingPreset
|
||||
};
|
||||
|
||||
var values = MessageForms.ShowDialog("Advanced settings", new[] { processPollingIntervalField, useRawInputField, setMinTmlAndMaxTmlField, disableErrorPopupField });
|
||||
|
||||
if (values?.Any() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_config.ProcessMonitorPollingInterval = processPollingIntervalField.ValueAsInt;
|
||||
_config.UseRawInput = useRawInputField.ValueAsBool;
|
||||
_config.SetMinTmlAndMaxTml = setMinTmlAndMaxTmlField.ValueAsBool;
|
||||
_config.DisableErrorPopupWhenApplyingPreset = disableErrorPopupField.ValueAsBool;
|
||||
|
||||
_keyboardShortcutDispatcher.SetUseRawInput(_config.UseRawInput);
|
||||
}
|
||||
|
||||
private void btnOptionsLog_Click(object sender, EventArgs e)
|
||||
{
|
||||
LogWindow.CreateAndShow();
|
||||
}
|
||||
|
||||
private void chkModules_ItemCheck(object sender, ItemCheckEventArgs e)
|
||||
{
|
||||
if (chkModules.Items.Count != _config.Modules.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var index = e.Index;
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var module = _config.Modules[index];
|
||||
module.IsActive = e.NewValue == CheckState.Checked;
|
||||
}
|
||||
|
||||
private void miCreateHDRColorProfile_Click(object sender, EventArgs e)
|
||||
{
|
||||
ColorProfileWindow.CreateAndShow();
|
||||
}
|
||||
|
||||
private void btnOptionsColorProfiles_Click(object sender, EventArgs e)
|
||||
{
|
||||
mnuColorProfiles.ShowCustom(btnOptionsColorProfiles);
|
||||
}
|
||||
|
||||
private void miCreateSDRColorProfile_Click(object sender, EventArgs e)
|
||||
{
|
||||
ColorProfileWindow.CreateAndShow(isHDR: false);
|
||||
}
|
||||
|
||||
private void chkStartMinimized_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
_config.StartMinimized = chkStartMinimized.Checked;
|
||||
}
|
||||
}
|
||||
|
||||
private void cbxUiType_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_config.UiType = (UiType)cbxUiType.SelectedIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="mnuColorProfiles.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -3,5 +3,6 @@
|
||||
internal interface IModulePanel
|
||||
{
|
||||
public void UpdateInfo();
|
||||
public void Init();
|
||||
}
|
||||
}
|
||||
Generated
+2
-538
@@ -28,63 +28,20 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||
tcMain = new System.Windows.Forms.TabControl();
|
||||
tabOptions = new System.Windows.Forms.TabPage();
|
||||
grpOptionsModules = new System.Windows.Forms.GroupBox();
|
||||
label1 = new System.Windows.Forms.Label();
|
||||
chkModules = new System.Windows.Forms.CheckedListBox();
|
||||
grpMiscellaneousOptions = new System.Windows.Forms.GroupBox();
|
||||
btnSetShortcutScreenSaver = new System.Windows.Forms.Button();
|
||||
label11 = new System.Windows.Forms.Label();
|
||||
edtBlankScreenSaverShortcut = new System.Windows.Forms.TextBox();
|
||||
lblFixChromeFontsDescription = new System.Windows.Forms.Label();
|
||||
chkFixChromeFonts = new System.Windows.Forms.CheckBox();
|
||||
grpGeneralOptions = new System.Windows.Forms.GroupBox();
|
||||
chkAutoInstallUpdates = new System.Windows.Forms.CheckBox();
|
||||
btnStartStopService = new System.Windows.Forms.Button();
|
||||
btnElevationInfo = new System.Windows.Forms.Button();
|
||||
rbElevationService = new System.Windows.Forms.RadioButton();
|
||||
rbElevationProcess = new System.Windows.Forms.RadioButton();
|
||||
rbElevationAdmin = new System.Windows.Forms.RadioButton();
|
||||
label8 = new System.Windows.Forms.Label();
|
||||
rbElevationNone = new System.Windows.Forms.RadioButton();
|
||||
chkGdiScaling = new System.Windows.Forms.CheckBox();
|
||||
chkCheckForUpdates = new System.Windows.Forms.CheckBox();
|
||||
chkMinimizeToSystemTray = new System.Windows.Forms.CheckBox();
|
||||
chkMinimizeOnClose = new System.Windows.Forms.CheckBox();
|
||||
chkStartMinimized = new System.Windows.Forms.CheckBox();
|
||||
chkStartAfterLogin = new System.Windows.Forms.CheckBox();
|
||||
tabLog = new System.Windows.Forms.TabPage();
|
||||
lblShowLog = new System.Windows.Forms.Label();
|
||||
cbxLogType = new System.Windows.Forms.ComboBox();
|
||||
btnClearLog = new System.Windows.Forms.Button();
|
||||
edtLog = new System.Windows.Forms.TextBox();
|
||||
tabInfo = new System.Windows.Forms.TabPage();
|
||||
grpNVIDIAInfo = new System.Windows.Forms.GroupBox();
|
||||
btnRefreshNVIDIAInfo = new System.Windows.Forms.Button();
|
||||
tvNVIDIAInfo = new System.Windows.Forms.TreeView();
|
||||
groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
lbPlugins = new System.Windows.Forms.ListBox();
|
||||
label7 = new System.Windows.Forms.Label();
|
||||
lblInfo = new System.Windows.Forms.Label();
|
||||
tabOptions = new System.Windows.Forms.TabPage();
|
||||
btnUpdate = new System.Windows.Forms.Button();
|
||||
tcMain.SuspendLayout();
|
||||
tabOptions.SuspendLayout();
|
||||
grpOptionsModules.SuspendLayout();
|
||||
grpMiscellaneousOptions.SuspendLayout();
|
||||
grpGeneralOptions.SuspendLayout();
|
||||
tabLog.SuspendLayout();
|
||||
tabInfo.SuspendLayout();
|
||||
grpNVIDIAInfo.SuspendLayout();
|
||||
groupBox3.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// tcMain
|
||||
//
|
||||
tcMain.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
tcMain.Controls.Add(tabOptions);
|
||||
tcMain.Controls.Add(tabLog);
|
||||
tcMain.Controls.Add(tabInfo);
|
||||
tcMain.Location = new System.Drawing.Point(14, 14);
|
||||
tcMain.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
@@ -96,9 +53,6 @@
|
||||
//
|
||||
// tabOptions
|
||||
//
|
||||
tabOptions.Controls.Add(grpOptionsModules);
|
||||
tabOptions.Controls.Add(grpMiscellaneousOptions);
|
||||
tabOptions.Controls.Add(grpGeneralOptions);
|
||||
tabOptions.Location = new System.Drawing.Point(4, 24);
|
||||
tabOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
tabOptions.Name = "tabOptions";
|
||||
@@ -108,367 +62,8 @@
|
||||
tabOptions.Text = "Options";
|
||||
tabOptions.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// grpOptionsModules
|
||||
//
|
||||
grpOptionsModules.Controls.Add(label1);
|
||||
grpOptionsModules.Controls.Add(chkModules);
|
||||
grpOptionsModules.Location = new System.Drawing.Point(7, 187);
|
||||
grpOptionsModules.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpOptionsModules.Name = "grpOptionsModules";
|
||||
grpOptionsModules.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpOptionsModules.Size = new System.Drawing.Size(522, 131);
|
||||
grpOptionsModules.TabIndex = 11;
|
||||
grpOptionsModules.TabStop = false;
|
||||
grpOptionsModules.Text = "Modules";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
label1.AutoSize = true;
|
||||
label1.Location = new System.Drawing.Point(7, 19);
|
||||
label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label1.Name = "label1";
|
||||
label1.Size = new System.Drawing.Size(511, 15);
|
||||
label1.TabIndex = 7;
|
||||
label1.Text = "Here you can disable modules you do not want. A restart is required for a change to have effect.";
|
||||
//
|
||||
// chkModules
|
||||
//
|
||||
chkModules.FormattingEnabled = true;
|
||||
chkModules.Location = new System.Drawing.Point(7, 40);
|
||||
chkModules.Name = "chkModules";
|
||||
chkModules.Size = new System.Drawing.Size(507, 76);
|
||||
chkModules.TabIndex = 0;
|
||||
chkModules.SelectedIndexChanged += chkModules_SelectedIndexChanged;
|
||||
//
|
||||
// grpMiscellaneousOptions
|
||||
//
|
||||
grpMiscellaneousOptions.Controls.Add(btnSetShortcutScreenSaver);
|
||||
grpMiscellaneousOptions.Controls.Add(label11);
|
||||
grpMiscellaneousOptions.Controls.Add(edtBlankScreenSaverShortcut);
|
||||
grpMiscellaneousOptions.Controls.Add(lblFixChromeFontsDescription);
|
||||
grpMiscellaneousOptions.Controls.Add(chkFixChromeFonts);
|
||||
grpMiscellaneousOptions.Location = new System.Drawing.Point(7, 324);
|
||||
grpMiscellaneousOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpMiscellaneousOptions.Name = "grpMiscellaneousOptions";
|
||||
grpMiscellaneousOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpMiscellaneousOptions.Size = new System.Drawing.Size(522, 131);
|
||||
grpMiscellaneousOptions.TabIndex = 5;
|
||||
grpMiscellaneousOptions.TabStop = false;
|
||||
grpMiscellaneousOptions.Text = "Miscellaneous";
|
||||
//
|
||||
// btnSetShortcutScreenSaver
|
||||
//
|
||||
btnSetShortcutScreenSaver.Location = new System.Drawing.Point(181, 98);
|
||||
btnSetShortcutScreenSaver.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnSetShortcutScreenSaver.Name = "btnSetShortcutScreenSaver";
|
||||
btnSetShortcutScreenSaver.Size = new System.Drawing.Size(40, 27);
|
||||
btnSetShortcutScreenSaver.TabIndex = 10;
|
||||
btnSetShortcutScreenSaver.Text = "Set";
|
||||
btnSetShortcutScreenSaver.UseVisualStyleBackColor = true;
|
||||
btnSetShortcutScreenSaver.Click += btnSetShortcutScreenSaver_Click;
|
||||
//
|
||||
// label11
|
||||
//
|
||||
label11.AutoSize = true;
|
||||
label11.Location = new System.Drawing.Point(7, 80);
|
||||
label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label11.Name = "label11";
|
||||
label11.Size = new System.Drawing.Size(238, 15);
|
||||
label11.TabIndex = 9;
|
||||
label11.Text = "Set a shortcut to start the blank screensaver:";
|
||||
//
|
||||
// edtBlankScreenSaverShortcut
|
||||
//
|
||||
edtBlankScreenSaverShortcut.Location = new System.Drawing.Point(7, 101);
|
||||
edtBlankScreenSaverShortcut.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtBlankScreenSaverShortcut.Name = "edtBlankScreenSaverShortcut";
|
||||
edtBlankScreenSaverShortcut.ReadOnly = true;
|
||||
edtBlankScreenSaverShortcut.Size = new System.Drawing.Size(165, 23);
|
||||
edtBlankScreenSaverShortcut.TabIndex = 7;
|
||||
edtBlankScreenSaverShortcut.KeyDown += edtShortcut_KeyDown;
|
||||
edtBlankScreenSaverShortcut.KeyUp += edtShortcut_KeyUp;
|
||||
//
|
||||
// lblFixChromeFontsDescription
|
||||
//
|
||||
lblFixChromeFontsDescription.AutoSize = true;
|
||||
lblFixChromeFontsDescription.Location = new System.Drawing.Point(4, 45);
|
||||
lblFixChromeFontsDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblFixChromeFontsDescription.Name = "lblFixChromeFontsDescription";
|
||||
lblFixChromeFontsDescription.Size = new System.Drawing.Size(427, 15);
|
||||
lblFixChromeFontsDescription.TabIndex = 6;
|
||||
lblFixChromeFontsDescription.Text = "This will add the parameter --disable-lcd-text to Chrome and requires elevation.";
|
||||
//
|
||||
// chkFixChromeFonts
|
||||
//
|
||||
chkFixChromeFonts.AutoSize = true;
|
||||
chkFixChromeFonts.Location = new System.Drawing.Point(7, 22);
|
||||
chkFixChromeFonts.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkFixChromeFonts.Name = "chkFixChromeFonts";
|
||||
chkFixChromeFonts.Size = new System.Drawing.Size(378, 19);
|
||||
chkFixChromeFonts.TabIndex = 4;
|
||||
chkFixChromeFonts.Text = "ClearType: fix bad fonts in Chrome (turn on grayscale anti-aliasing)";
|
||||
chkFixChromeFonts.UseVisualStyleBackColor = true;
|
||||
chkFixChromeFonts.CheckedChanged += chkFixChromeFonts_CheckedChanged;
|
||||
//
|
||||
// grpGeneralOptions
|
||||
//
|
||||
grpGeneralOptions.Controls.Add(chkAutoInstallUpdates);
|
||||
grpGeneralOptions.Controls.Add(btnStartStopService);
|
||||
grpGeneralOptions.Controls.Add(btnElevationInfo);
|
||||
grpGeneralOptions.Controls.Add(rbElevationService);
|
||||
grpGeneralOptions.Controls.Add(rbElevationProcess);
|
||||
grpGeneralOptions.Controls.Add(rbElevationAdmin);
|
||||
grpGeneralOptions.Controls.Add(label8);
|
||||
grpGeneralOptions.Controls.Add(rbElevationNone);
|
||||
grpGeneralOptions.Controls.Add(chkGdiScaling);
|
||||
grpGeneralOptions.Controls.Add(chkCheckForUpdates);
|
||||
grpGeneralOptions.Controls.Add(chkMinimizeToSystemTray);
|
||||
grpGeneralOptions.Controls.Add(chkMinimizeOnClose);
|
||||
grpGeneralOptions.Controls.Add(chkStartMinimized);
|
||||
grpGeneralOptions.Controls.Add(chkStartAfterLogin);
|
||||
grpGeneralOptions.Location = new System.Drawing.Point(7, 7);
|
||||
grpGeneralOptions.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpGeneralOptions.Name = "grpGeneralOptions";
|
||||
grpGeneralOptions.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpGeneralOptions.Size = new System.Drawing.Size(522, 174);
|
||||
grpGeneralOptions.TabIndex = 2;
|
||||
grpGeneralOptions.TabStop = false;
|
||||
grpGeneralOptions.Text = "General";
|
||||
//
|
||||
// chkAutoInstallUpdates
|
||||
//
|
||||
chkAutoInstallUpdates.AutoSize = true;
|
||||
chkAutoInstallUpdates.Location = new System.Drawing.Point(7, 147);
|
||||
chkAutoInstallUpdates.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkAutoInstallUpdates.Name = "chkAutoInstallUpdates";
|
||||
chkAutoInstallUpdates.Size = new System.Drawing.Size(179, 19);
|
||||
chkAutoInstallUpdates.TabIndex = 66;
|
||||
chkAutoInstallUpdates.Text = "Automatically install updates";
|
||||
chkAutoInstallUpdates.UseVisualStyleBackColor = true;
|
||||
chkAutoInstallUpdates.CheckedChanged += chkAutoInstallUpdates_CheckedChanged;
|
||||
//
|
||||
// btnStartStopService
|
||||
//
|
||||
btnStartStopService.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnStartStopService.Location = new System.Drawing.Point(474, 103);
|
||||
btnStartStopService.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnStartStopService.Name = "btnStartStopService";
|
||||
btnStartStopService.Size = new System.Drawing.Size(40, 27);
|
||||
btnStartStopService.TabIndex = 65;
|
||||
btnStartStopService.Text = "Start";
|
||||
btnStartStopService.UseVisualStyleBackColor = true;
|
||||
btnStartStopService.Click += btnStartStopService_Click;
|
||||
//
|
||||
// btnElevationInfo
|
||||
//
|
||||
btnElevationInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnElevationInfo.Location = new System.Drawing.Point(329, 41);
|
||||
btnElevationInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnElevationInfo.Name = "btnElevationInfo";
|
||||
btnElevationInfo.Size = new System.Drawing.Size(22, 27);
|
||||
btnElevationInfo.TabIndex = 64;
|
||||
btnElevationInfo.Text = "?";
|
||||
btnElevationInfo.UseVisualStyleBackColor = true;
|
||||
btnElevationInfo.Click += btnElevationInfo_Click;
|
||||
//
|
||||
// rbElevationService
|
||||
//
|
||||
rbElevationService.AutoSize = true;
|
||||
rbElevationService.Location = new System.Drawing.Point(216, 107);
|
||||
rbElevationService.Name = "rbElevationService";
|
||||
rbElevationService.Size = new System.Drawing.Size(136, 19);
|
||||
rbElevationService.TabIndex = 63;
|
||||
rbElevationService.TabStop = true;
|
||||
rbElevationService.Tag = "2";
|
||||
rbElevationService.Text = "Use Windows Service";
|
||||
rbElevationService.UseVisualStyleBackColor = true;
|
||||
rbElevationService.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// rbElevationProcess
|
||||
//
|
||||
rbElevationProcess.AutoSize = true;
|
||||
rbElevationProcess.Location = new System.Drawing.Point(216, 128);
|
||||
rbElevationProcess.Name = "rbElevationProcess";
|
||||
rbElevationProcess.Size = new System.Drawing.Size(189, 19);
|
||||
rbElevationProcess.TabIndex = 62;
|
||||
rbElevationProcess.TabStop = true;
|
||||
rbElevationProcess.Tag = "3";
|
||||
rbElevationProcess.Text = "Use dedicated elevated process";
|
||||
rbElevationProcess.UseVisualStyleBackColor = true;
|
||||
rbElevationProcess.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// rbElevationAdmin
|
||||
//
|
||||
rbElevationAdmin.AutoSize = true;
|
||||
rbElevationAdmin.Location = new System.Drawing.Point(216, 86);
|
||||
rbElevationAdmin.Name = "rbElevationAdmin";
|
||||
rbElevationAdmin.Size = new System.Drawing.Size(97, 19);
|
||||
rbElevationAdmin.TabIndex = 61;
|
||||
rbElevationAdmin.TabStop = true;
|
||||
rbElevationAdmin.Tag = "1";
|
||||
rbElevationAdmin.Text = "Run as admin";
|
||||
rbElevationAdmin.UseVisualStyleBackColor = true;
|
||||
rbElevationAdmin.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// label8
|
||||
//
|
||||
label8.AutoSize = true;
|
||||
label8.Location = new System.Drawing.Point(216, 47);
|
||||
label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label8.Name = "label8";
|
||||
label8.Size = new System.Drawing.Size(105, 15);
|
||||
label8.TabIndex = 60;
|
||||
label8.Text = "Elevation-method:";
|
||||
//
|
||||
// rbElevationNone
|
||||
//
|
||||
rbElevationNone.AutoSize = true;
|
||||
rbElevationNone.Location = new System.Drawing.Point(216, 65);
|
||||
rbElevationNone.Name = "rbElevationNone";
|
||||
rbElevationNone.Size = new System.Drawing.Size(54, 19);
|
||||
rbElevationNone.TabIndex = 10;
|
||||
rbElevationNone.TabStop = true;
|
||||
rbElevationNone.Tag = "0";
|
||||
rbElevationNone.Text = "None";
|
||||
rbElevationNone.UseVisualStyleBackColor = true;
|
||||
rbElevationNone.CheckedChanged += rbElevationNone_CheckedChanged;
|
||||
//
|
||||
// chkGdiScaling
|
||||
//
|
||||
chkGdiScaling.AutoSize = true;
|
||||
chkGdiScaling.Location = new System.Drawing.Point(216, 22);
|
||||
chkGdiScaling.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkGdiScaling.Name = "chkGdiScaling";
|
||||
chkGdiScaling.Size = new System.Drawing.Size(197, 19);
|
||||
chkGdiScaling.TabIndex = 7;
|
||||
chkGdiScaling.Text = "Use GDI Scaling (requires restart)";
|
||||
chkGdiScaling.UseVisualStyleBackColor = true;
|
||||
chkGdiScaling.CheckedChanged += chkGdiScaling_CheckedChanged;
|
||||
//
|
||||
// chkCheckForUpdates
|
||||
//
|
||||
chkCheckForUpdates.AutoSize = true;
|
||||
chkCheckForUpdates.Location = new System.Drawing.Point(7, 122);
|
||||
chkCheckForUpdates.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkCheckForUpdates.Name = "chkCheckForUpdates";
|
||||
chkCheckForUpdates.Size = new System.Drawing.Size(197, 19);
|
||||
chkCheckForUpdates.TabIndex = 6;
|
||||
chkCheckForUpdates.Text = "Automatically check for updates";
|
||||
chkCheckForUpdates.UseVisualStyleBackColor = true;
|
||||
chkCheckForUpdates.CheckedChanged += chkCheckForUpdates_CheckedChanged;
|
||||
//
|
||||
// chkMinimizeToSystemTray
|
||||
//
|
||||
chkMinimizeToSystemTray.AutoSize = true;
|
||||
chkMinimizeToSystemTray.Location = new System.Drawing.Point(7, 97);
|
||||
chkMinimizeToSystemTray.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkMinimizeToSystemTray.Name = "chkMinimizeToSystemTray";
|
||||
chkMinimizeToSystemTray.Size = new System.Drawing.Size(152, 19);
|
||||
chkMinimizeToSystemTray.TabIndex = 5;
|
||||
chkMinimizeToSystemTray.Text = "Minimize to system tray";
|
||||
chkMinimizeToSystemTray.UseVisualStyleBackColor = true;
|
||||
chkMinimizeToSystemTray.CheckedChanged += chkMinimizeToSystemTray_CheckedChanged;
|
||||
//
|
||||
// chkMinimizeOnClose
|
||||
//
|
||||
chkMinimizeOnClose.AutoSize = true;
|
||||
chkMinimizeOnClose.Location = new System.Drawing.Point(7, 72);
|
||||
chkMinimizeOnClose.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkMinimizeOnClose.Name = "chkMinimizeOnClose";
|
||||
chkMinimizeOnClose.Size = new System.Drawing.Size(122, 19);
|
||||
chkMinimizeOnClose.TabIndex = 4;
|
||||
chkMinimizeOnClose.Text = "Minimize on close";
|
||||
chkMinimizeOnClose.UseVisualStyleBackColor = true;
|
||||
chkMinimizeOnClose.CheckedChanged += chkMinimizeOnClose_CheckedChanged;
|
||||
//
|
||||
// chkStartMinimized
|
||||
//
|
||||
chkStartMinimized.AutoSize = true;
|
||||
chkStartMinimized.Location = new System.Drawing.Point(7, 47);
|
||||
chkStartMinimized.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkStartMinimized.Name = "chkStartMinimized";
|
||||
chkStartMinimized.Size = new System.Drawing.Size(109, 19);
|
||||
chkStartMinimized.TabIndex = 3;
|
||||
chkStartMinimized.Text = "Start minimized";
|
||||
chkStartMinimized.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkStartAfterLogin
|
||||
//
|
||||
chkStartAfterLogin.AutoSize = true;
|
||||
chkStartAfterLogin.Location = new System.Drawing.Point(7, 22);
|
||||
chkStartAfterLogin.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkStartAfterLogin.Name = "chkStartAfterLogin";
|
||||
chkStartAfterLogin.Size = new System.Drawing.Size(183, 19);
|
||||
chkStartAfterLogin.TabIndex = 2;
|
||||
chkStartAfterLogin.Text = "Automatically start after login";
|
||||
chkStartAfterLogin.UseVisualStyleBackColor = true;
|
||||
chkStartAfterLogin.CheckedChanged += chkStartAfterLogin_CheckedChanged;
|
||||
//
|
||||
// tabLog
|
||||
//
|
||||
tabLog.Controls.Add(lblShowLog);
|
||||
tabLog.Controls.Add(cbxLogType);
|
||||
tabLog.Controls.Add(btnClearLog);
|
||||
tabLog.Controls.Add(edtLog);
|
||||
tabLog.Location = new System.Drawing.Point(4, 24);
|
||||
tabLog.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
tabLog.Name = "tabLog";
|
||||
tabLog.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
tabLog.Size = new System.Drawing.Size(1114, 539);
|
||||
tabLog.TabIndex = 3;
|
||||
tabLog.Text = "Log";
|
||||
tabLog.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblShowLog
|
||||
//
|
||||
lblShowLog.AutoSize = true;
|
||||
lblShowLog.Location = new System.Drawing.Point(8, 14);
|
||||
lblShowLog.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblShowLog.Name = "lblShowLog";
|
||||
lblShowLog.Size = new System.Drawing.Size(88, 15);
|
||||
lblShowLog.TabIndex = 33;
|
||||
lblShowLog.Text = "Show log from:";
|
||||
//
|
||||
// cbxLogType
|
||||
//
|
||||
cbxLogType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
cbxLogType.FormattingEnabled = true;
|
||||
cbxLogType.Items.AddRange(new object[] { "Main application", "Service" });
|
||||
cbxLogType.Location = new System.Drawing.Point(102, 9);
|
||||
cbxLogType.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
cbxLogType.Name = "cbxLogType";
|
||||
cbxLogType.Size = new System.Drawing.Size(189, 23);
|
||||
cbxLogType.TabIndex = 32;
|
||||
cbxLogType.SelectedIndexChanged += cbxLogType_SelectedIndexChanged;
|
||||
//
|
||||
// btnClearLog
|
||||
//
|
||||
btnClearLog.Location = new System.Drawing.Point(299, 6);
|
||||
btnClearLog.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnClearLog.Name = "btnClearLog";
|
||||
btnClearLog.Size = new System.Drawing.Size(88, 27);
|
||||
btnClearLog.TabIndex = 2;
|
||||
btnClearLog.Text = "Clear log";
|
||||
btnClearLog.UseVisualStyleBackColor = true;
|
||||
btnClearLog.Click += btnClearLog_Click;
|
||||
//
|
||||
// edtLog
|
||||
//
|
||||
edtLog.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
edtLog.Location = new System.Drawing.Point(7, 40);
|
||||
edtLog.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtLog.MaxLength = 327670;
|
||||
edtLog.Multiline = true;
|
||||
edtLog.Name = "edtLog";
|
||||
edtLog.ReadOnly = true;
|
||||
edtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
edtLog.Size = new System.Drawing.Size(1098, 478);
|
||||
edtLog.TabIndex = 0;
|
||||
//
|
||||
// tabInfo
|
||||
//
|
||||
tabInfo.Controls.Add(grpNVIDIAInfo);
|
||||
tabInfo.Controls.Add(groupBox3);
|
||||
tabInfo.Location = new System.Drawing.Point(4, 24);
|
||||
tabInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
tabInfo.Name = "tabInfo";
|
||||
@@ -478,86 +73,6 @@
|
||||
tabInfo.Text = "Info";
|
||||
tabInfo.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// grpNVIDIAInfo
|
||||
//
|
||||
grpNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
grpNVIDIAInfo.Controls.Add(btnRefreshNVIDIAInfo);
|
||||
grpNVIDIAInfo.Controls.Add(tvNVIDIAInfo);
|
||||
grpNVIDIAInfo.Location = new System.Drawing.Point(463, 7);
|
||||
grpNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpNVIDIAInfo.Name = "grpNVIDIAInfo";
|
||||
grpNVIDIAInfo.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
grpNVIDIAInfo.Size = new System.Drawing.Size(643, 511);
|
||||
grpNVIDIAInfo.TabIndex = 4;
|
||||
grpNVIDIAInfo.TabStop = false;
|
||||
grpNVIDIAInfo.Text = "NVIDIA info";
|
||||
//
|
||||
// btnRefreshNVIDIAInfo
|
||||
//
|
||||
btnRefreshNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnRefreshNVIDIAInfo.Location = new System.Drawing.Point(7, 478);
|
||||
btnRefreshNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnRefreshNVIDIAInfo.Name = "btnRefreshNVIDIAInfo";
|
||||
btnRefreshNVIDIAInfo.Size = new System.Drawing.Size(88, 27);
|
||||
btnRefreshNVIDIAInfo.TabIndex = 1;
|
||||
btnRefreshNVIDIAInfo.Text = "Refresh";
|
||||
btnRefreshNVIDIAInfo.UseVisualStyleBackColor = true;
|
||||
btnRefreshNVIDIAInfo.Click += btnRefreshNVIDIAInfo_Click;
|
||||
//
|
||||
// tvNVIDIAInfo
|
||||
//
|
||||
tvNVIDIAInfo.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
tvNVIDIAInfo.Location = new System.Drawing.Point(7, 22);
|
||||
tvNVIDIAInfo.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
tvNVIDIAInfo.Name = "tvNVIDIAInfo";
|
||||
tvNVIDIAInfo.Size = new System.Drawing.Size(628, 448);
|
||||
tvNVIDIAInfo.TabIndex = 0;
|
||||
//
|
||||
// groupBox3
|
||||
//
|
||||
groupBox3.Controls.Add(lbPlugins);
|
||||
groupBox3.Controls.Add(label7);
|
||||
groupBox3.Controls.Add(lblInfo);
|
||||
groupBox3.Location = new System.Drawing.Point(7, 7);
|
||||
groupBox3.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
groupBox3.Name = "groupBox3";
|
||||
groupBox3.Padding = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
groupBox3.Size = new System.Drawing.Size(449, 254);
|
||||
groupBox3.TabIndex = 5;
|
||||
groupBox3.TabStop = false;
|
||||
groupBox3.Text = "Info";
|
||||
//
|
||||
// lbPlugins
|
||||
//
|
||||
lbPlugins.FormattingEnabled = true;
|
||||
lbPlugins.HorizontalScrollbar = true;
|
||||
lbPlugins.ItemHeight = 15;
|
||||
lbPlugins.Location = new System.Drawing.Point(10, 77);
|
||||
lbPlugins.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
lbPlugins.Name = "lbPlugins";
|
||||
lbPlugins.Size = new System.Drawing.Size(432, 169);
|
||||
lbPlugins.TabIndex = 3;
|
||||
//
|
||||
// label7
|
||||
//
|
||||
label7.AutoSize = true;
|
||||
label7.Location = new System.Drawing.Point(7, 59);
|
||||
label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
label7.Name = "label7";
|
||||
label7.Size = new System.Drawing.Size(267, 15);
|
||||
label7.TabIndex = 2;
|
||||
label7.Text = "This app contains the following 3rd party plugins:";
|
||||
//
|
||||
// lblInfo
|
||||
//
|
||||
lblInfo.AutoSize = true;
|
||||
lblInfo.Location = new System.Drawing.Point(7, 23);
|
||||
lblInfo.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblInfo.Name = "lblInfo";
|
||||
lblInfo.Size = new System.Drawing.Size(28, 15);
|
||||
lblInfo.TabIndex = 1;
|
||||
lblInfo.Text = "Info";
|
||||
//
|
||||
// btnUpdate
|
||||
//
|
||||
btnUpdate.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||
@@ -581,7 +96,6 @@
|
||||
ClientSize = new System.Drawing.Size(1150, 594);
|
||||
Controls.Add(btnUpdate);
|
||||
Controls.Add(tcMain);
|
||||
Icon = (System.Drawing.Icon)resources.GetObject("$this.Icon");
|
||||
Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
MinimumSize = new System.Drawing.Size(1140, 611);
|
||||
Name = "MainForm";
|
||||
@@ -589,8 +103,6 @@
|
||||
Activated += MainForm_Activated;
|
||||
Deactivate += MainForm_Deactivate;
|
||||
FormClosing += MainForm_FormClosing;
|
||||
FormClosed += MainForm_FormClosed;
|
||||
Load += MainForm_Load;
|
||||
Shown += MainForm_Shown;
|
||||
ResizeBegin += MainForm_ResizeBegin;
|
||||
ResizeEnd += MainForm_ResizeEnd;
|
||||
@@ -598,18 +110,6 @@
|
||||
Resize += MainForm_Resize;
|
||||
tcMain.ResumeLayout(false);
|
||||
tabOptions.ResumeLayout(false);
|
||||
grpOptionsModules.ResumeLayout(false);
|
||||
grpOptionsModules.PerformLayout();
|
||||
grpMiscellaneousOptions.ResumeLayout(false);
|
||||
grpMiscellaneousOptions.PerformLayout();
|
||||
grpGeneralOptions.ResumeLayout(false);
|
||||
grpGeneralOptions.PerformLayout();
|
||||
tabLog.ResumeLayout(false);
|
||||
tabLog.PerformLayout();
|
||||
tabInfo.ResumeLayout(false);
|
||||
grpNVIDIAInfo.ResumeLayout(false);
|
||||
groupBox3.ResumeLayout(false);
|
||||
groupBox3.PerformLayout();
|
||||
ResumeLayout(false);
|
||||
}
|
||||
|
||||
@@ -617,44 +117,8 @@
|
||||
|
||||
private System.Windows.Forms.TabControl tcMain;
|
||||
private System.Windows.Forms.TabPage tabOptions;
|
||||
private System.Windows.Forms.GroupBox grpGeneralOptions;
|
||||
private System.Windows.Forms.CheckBox chkStartMinimized;
|
||||
private System.Windows.Forms.CheckBox chkStartAfterLogin;
|
||||
private System.Windows.Forms.TabPage tabLog;
|
||||
private System.Windows.Forms.TextBox edtLog;
|
||||
private System.Windows.Forms.TabPage tabInfo;
|
||||
private System.Windows.Forms.GroupBox groupBox3;
|
||||
private System.Windows.Forms.ListBox lbPlugins;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private System.Windows.Forms.Label lblInfo;
|
||||
private System.Windows.Forms.GroupBox grpNVIDIAInfo;
|
||||
private System.Windows.Forms.TreeView tvNVIDIAInfo;
|
||||
private System.Windows.Forms.Button btnRefreshNVIDIAInfo;
|
||||
private System.Windows.Forms.GroupBox grpMiscellaneousOptions;
|
||||
private System.Windows.Forms.CheckBox chkFixChromeFonts;
|
||||
private System.Windows.Forms.Label lblFixChromeFontsDescription;
|
||||
private System.Windows.Forms.Button btnSetShortcutScreenSaver;
|
||||
private System.Windows.Forms.Label label11;
|
||||
private System.Windows.Forms.TextBox edtBlankScreenSaverShortcut;
|
||||
private System.Windows.Forms.CheckBox chkMinimizeOnClose;
|
||||
private System.Windows.Forms.Button btnClearLog;
|
||||
private System.Windows.Forms.CheckBox chkMinimizeToSystemTray;
|
||||
private System.Windows.Forms.CheckBox chkCheckForUpdates;
|
||||
private System.Windows.Forms.CheckBox chkGdiScaling;
|
||||
private System.Windows.Forms.RadioButton rbElevationService;
|
||||
private System.Windows.Forms.RadioButton rbElevationProcess;
|
||||
private System.Windows.Forms.RadioButton rbElevationAdmin;
|
||||
private System.Windows.Forms.Label label8;
|
||||
private System.Windows.Forms.RadioButton rbElevationNone;
|
||||
private System.Windows.Forms.Button btnElevationInfo;
|
||||
private System.Windows.Forms.Button btnStartStopService;
|
||||
private System.Windows.Forms.Label lblShowLog;
|
||||
private System.Windows.Forms.ComboBox cbxLogType;
|
||||
private System.Windows.Forms.CheckBox chkAutoInstallUpdates;
|
||||
private System.Windows.Forms.Button btnUpdate;
|
||||
private System.Windows.Forms.GroupBox grpOptionsModules;
|
||||
private System.Windows.Forms.CheckedListBox chkModules;
|
||||
private System.Windows.Forms.Label label1;
|
||||
}
|
||||
}
|
||||
|
||||
+343
-1394
File diff suppressed because it is too large.
Load diff
+63
-1779
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,189 @@
|
||||
using ColorControl.Services.Common;
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.EventDispatcher;
|
||||
using ColorControl.Shared.Forms;
|
||||
using ColorControl.Shared.Native;
|
||||
using ColorControl.Shared.Services;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ColorControl;
|
||||
|
||||
internal class MainWorker
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly BackgroundWorker _backgroundWorker;
|
||||
private readonly GlobalContext _globalContext;
|
||||
private readonly ServiceManager _serviceManager;
|
||||
private readonly Config _config;
|
||||
private readonly NotifyIconManager _notifyIconManager;
|
||||
private readonly WindowMessageDispatcher _windowMessageDispatcher;
|
||||
private readonly KeyboardShortcutDispatcher _keyboardShortcutDispatcher;
|
||||
private readonly PowerEventDispatcher _powerEventDispatcher;
|
||||
private readonly WinApiService _winApiService;
|
||||
private readonly WinApiAdminService _winApiAdminService;
|
||||
private readonly UpdateManager _updateManager;
|
||||
private nint _screenStateNotify;
|
||||
|
||||
public static int SHORTCUTID_SCREENSAVER = -100;
|
||||
|
||||
public MainWorker(
|
||||
GlobalContext globalContext,
|
||||
ServiceManager serviceManager,
|
||||
NotifyIconManager notifyIconManager,
|
||||
WindowMessageDispatcher windowMessageDispatcher,
|
||||
KeyboardShortcutDispatcher keyboardShortcutDispatcher,
|
||||
PowerEventDispatcher powerEventDispatcher,
|
||||
WinApiService winApiService,
|
||||
WinApiAdminService winApiAdminService,
|
||||
UpdateManager updateManager)
|
||||
{
|
||||
_backgroundWorker = new BackgroundWorker();
|
||||
_globalContext = globalContext;
|
||||
_serviceManager = serviceManager;
|
||||
_notifyIconManager = notifyIconManager;
|
||||
_windowMessageDispatcher = windowMessageDispatcher;
|
||||
_keyboardShortcutDispatcher = keyboardShortcutDispatcher;
|
||||
_powerEventDispatcher = powerEventDispatcher;
|
||||
_winApiService = winApiService;
|
||||
_winApiAdminService = winApiAdminService;
|
||||
_updateManager = updateManager;
|
||||
_config = _globalContext.Config;
|
||||
}
|
||||
|
||||
public async Task DoWork()
|
||||
{
|
||||
if (_backgroundWorker.CancellationPending)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await Init();
|
||||
|
||||
System.Windows.Forms.Application.Run(_windowMessageDispatcher.MessageForm);
|
||||
|
||||
_serviceManager.Save();
|
||||
_notifyIconManager.HideIcon();
|
||||
|
||||
if (_screenStateNotify != 0)
|
||||
{
|
||||
WinApi.UnregisterPowerSettingNotification(_screenStateNotify);
|
||||
_screenStateNotify = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
_globalContext.SynchronizationContext = AsyncOperationManager.SynchronizationContext;
|
||||
|
||||
_windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessageQueryEndSession, HandleQueryEndSessionEvent);
|
||||
_windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessagePowerBroadcast, HandlePowerBroadcastEvent);
|
||||
_windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessageShowWindow, HandleShowWindowEvent);
|
||||
_windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessageUserBringToFront, HandleUserBringToFrontEvent);
|
||||
|
||||
_screenStateNotify = WinApi.RegisterPowerSettingNotification(_windowMessageDispatcher.MessageForm.Handle, ref Utils.GUID_CONSOLE_DISPLAY_STATE, 0);
|
||||
|
||||
_keyboardShortcutDispatcher.SetUseRawInput(_config.UseRawInput);
|
||||
MessageForms.KeyboardShortcutDispatcher = _keyboardShortcutDispatcher;
|
||||
|
||||
_notifyIconManager.Build();
|
||||
|
||||
_serviceManager.LoadModules();
|
||||
|
||||
// Auto-apply fix if desired but not currently installed
|
||||
if (_config.FixChromeFonts && _winApiService.IsChromeInstalled() && !_winApiService.IsChromeFixInstalled())
|
||||
{
|
||||
_winApiAdminService.InstallChromeFix(true, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
|
||||
}
|
||||
|
||||
InitTheme();
|
||||
|
||||
_keyboardShortcutDispatcher.RegisterShortcut(SHORTCUTID_SCREENSAVER, _config.ScreenSaverShortcut);
|
||||
_keyboardShortcutDispatcher.RegisterEventHandler(KeyboardShortcutDispatcher.Event_HotKey, HandleHotKeyEvent);
|
||||
|
||||
if (_config.UiType != UiType.WinForms)
|
||||
{
|
||||
await Program.StartUiServer();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _startupSent = false;
|
||||
|
||||
private void HandleShowWindowEvent(object sender, WindowMessageEventArgs e)
|
||||
{
|
||||
if (_startupSent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_startupSent = true;
|
||||
|
||||
_ = _powerEventDispatcher.SendEventAsync(PowerEventDispatcher.Event_Startup);
|
||||
|
||||
_ = _updateManager.CheckForUpdates();
|
||||
|
||||
if (!_config.StartMinimized /*|| Debugger.IsAttached*/)
|
||||
{
|
||||
Program.OpenDefaultUi();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleUserBringToFrontEvent(object sender, WindowMessageEventArgs e)
|
||||
{
|
||||
Program.OpenDefaultUi();
|
||||
}
|
||||
|
||||
private void HandlePowerBroadcastEvent(object sender, WindowMessageEventArgs e)
|
||||
{
|
||||
if (e.Message.WParam.ToInt32() == WinApi.PBT_POWERSETTINGCHANGE)
|
||||
{
|
||||
var ps = Marshal.PtrToStructure<WinApi.POWERBROADCAST_SETTING>(e.Message.LParam);
|
||||
|
||||
var power = (WindowsMonitorPowerSetting)ps.Data;
|
||||
|
||||
Logger.Debug($"PBT_POWERSETTINGCHANGE: {power}");
|
||||
|
||||
_powerEventDispatcher.SendEvent(power == WindowsMonitorPowerSetting.Off ? PowerEventDispatcher.Event_MonitorOff : PowerEventDispatcher.Event_MonitorOn);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleQueryEndSessionEvent(object sender, WindowMessageEventArgs e)
|
||||
{
|
||||
Logger.Debug($"MainWorker: QueryEndSession");
|
||||
Logger.Debug($"MainWorker: SystemShutdown");
|
||||
|
||||
_powerEventDispatcher.SendEvent(PowerEventDispatcher.Event_Shutdown);
|
||||
}
|
||||
|
||||
private void HandleHotKeyEvent(object sender, KeyboardShortcutEventArgs args)
|
||||
{
|
||||
if (args.HotKeyId == SHORTCUTID_SCREENSAVER)
|
||||
{
|
||||
StartScreenSaver();
|
||||
}
|
||||
}
|
||||
|
||||
private void StartScreenSaver()
|
||||
{
|
||||
var screenSaver = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "scrnsave.scr");
|
||||
Process.Start("explorer.exe", screenSaver);
|
||||
}
|
||||
|
||||
private void InitTheme()
|
||||
{
|
||||
DarkModeUtils.SetDarkMode(_config.UseDarkMode);
|
||||
|
||||
WinApi.RefreshImmersiveColorPolicyState();
|
||||
|
||||
DarkModeUtils.InitWpfTheme();
|
||||
|
||||
DarkModeUtils.SetContextMenuForeColor(_notifyIconManager.NotifyIcon.ContextMenuStrip, FormUtils.CurrentForeColor);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl
|
||||
{
|
||||
public class Module
|
||||
{
|
||||
public bool IsActive { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
[JsonIgnore]
|
||||
public Func<UserControl> InitAction { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,564 +0,0 @@
|
||||
using NWin32;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ColorControl
|
||||
{
|
||||
// This class takes care of wrapping "Connecting and Configuring Displays(CCD) Win32 API"
|
||||
internal static class CCD
|
||||
{
|
||||
public enum DisplayTopology
|
||||
{
|
||||
Internal,
|
||||
External,
|
||||
Extend,
|
||||
Clone
|
||||
}
|
||||
|
||||
public static DisplayTopology GetDisplayTopology()
|
||||
{
|
||||
uint numPathArrayElements;
|
||||
uint numModeInfoArrayElements;
|
||||
|
||||
NativeMethods.GetDisplayConfigBufferSizes(QueryDisplayFlags.DatabaseCurrent, out numPathArrayElements, out numModeInfoArrayElements);
|
||||
|
||||
var pathArray = new DisplayConfigPathInfo[numPathArrayElements];
|
||||
var modeArray = new DisplayConfigModeInfo[numModeInfoArrayElements];
|
||||
|
||||
DisplayConfigTopologyId displayTopology;
|
||||
|
||||
NativeMethods.QueryDisplayConfig(QueryDisplayFlags.DatabaseCurrent, ref numPathArrayElements, pathArray, ref numModeInfoArrayElements, modeArray, out displayTopology);
|
||||
|
||||
switch (displayTopology)
|
||||
{
|
||||
case DisplayConfigTopologyId.External: return DisplayTopology.External;
|
||||
case DisplayConfigTopologyId.Internal: return DisplayTopology.Internal;
|
||||
case DisplayConfigTopologyId.Extend: return DisplayTopology.Extend;
|
||||
}
|
||||
|
||||
return DisplayTopology.Clone;
|
||||
}
|
||||
|
||||
public static void SetDisplayTopology(DisplayTopology displayTopology)
|
||||
{
|
||||
switch (displayTopology)
|
||||
{
|
||||
case DisplayTopology.External:
|
||||
NativeMethods.SetDisplayConfig(0, null, 0, null, (SdcFlags.Apply | SdcFlags.TopologyExternal));
|
||||
break;
|
||||
case DisplayTopology.Internal:
|
||||
NativeMethods.SetDisplayConfig(0, null, 0, null, (SdcFlags.Apply | SdcFlags.TopologyInternal));
|
||||
break;
|
||||
case DisplayTopology.Extend:
|
||||
NativeMethods.SetDisplayConfig(0, null, 0, null, (SdcFlags.Apply | SdcFlags.TopologyExtend));
|
||||
break;
|
||||
case DisplayTopology.Clone:
|
||||
NativeMethods.SetDisplayConfig(0, null, 0, null, (SdcFlags.Apply | SdcFlags.TopologyClone));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetHDRState(bool enabled, string displayName = null)
|
||||
{
|
||||
uint pathCount, modeCount;
|
||||
|
||||
var err = NativeMethods.GetDisplayConfigBufferSizes(QueryDisplayFlags.OnlyActivePaths, out pathCount, out modeCount);
|
||||
if (err == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
var pathsArray = new DisplayConfigPathInfo[pathCount];
|
||||
var modesArray = new DisplayConfigModeInfo[modeCount];
|
||||
|
||||
DisplayConfigTopologyId displayTopology;
|
||||
|
||||
err = NativeMethods.QueryDisplayConfig(QueryDisplayFlags.DatabaseCurrent, ref pathCount, pathsArray, ref modeCount, modesArray, out displayTopology);
|
||||
if (err == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
foreach (var path in pathsArray)
|
||||
{
|
||||
// get display name
|
||||
var info = new DISPLAYCONFIG_SOURCE_DEVICE_NAME();
|
||||
info.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
info.header.size = Marshal.SizeOf<DISPLAYCONFIG_SOURCE_DEVICE_NAME>();
|
||||
info.header.adapterId = path.sourceInfo.adapterId;
|
||||
info.header.id = path.sourceInfo.id;
|
||||
|
||||
err = NativeMethods.DisplayConfigGetDeviceInfo(ref info);
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var deviceName = info.viewGdiDeviceName;
|
||||
if (displayName != null && !EqualDisplayNames(deviceName, displayName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var setpacket = new DISPLAYCONFIG_SET_ADVANCED_COLOR_INFO();
|
||||
setpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
setpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE;
|
||||
setpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_SET_ADVANCED_COLOR_INFO>(); ;
|
||||
|
||||
var requestpacket = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
||||
requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>(); ;
|
||||
|
||||
for (int i = 0; i < modeCount; i++)
|
||||
{
|
||||
if (modesArray[i].infoType == DisplayConfigModeInfoType.Target)
|
||||
{
|
||||
setpacket.header.adapterId = modesArray[i].adapterId;
|
||||
setpacket.header.id = modesArray[i].id;
|
||||
requestpacket.header.adapterId = modesArray[i].adapterId;
|
||||
requestpacket.header.id = modesArray[i].id;
|
||||
|
||||
if (NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket) == NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
if (requestpacket.advancedColorSupported)
|
||||
{
|
||||
setpacket.enableAdvancedColor = enabled ? 1U : 0;
|
||||
NativeMethods.DisplayConfigSetDeviceInfo(ref setpacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool EqualDisplayNames(string displayName1, string displayName2)
|
||||
{
|
||||
displayName1 = displayName1.Replace("\\", string.Empty);
|
||||
displayName2 = displayName2.Replace("\\", string.Empty);
|
||||
|
||||
return displayName1.Equals(displayName2, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private enum DISPLAYCONFIG_MODE_INFO_TYPE
|
||||
{
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE = 3,
|
||||
}
|
||||
|
||||
private enum DISPLAYCONFIG_DEVICE_INFO_TYPE
|
||||
{
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct DISPLAYCONFIG_DEVICE_INFO_HEADER
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
|
||||
public int size;
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct LUID
|
||||
{
|
||||
uint LowPart;
|
||||
uint HighPart;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigVideoOutputTechnology : uint
|
||||
{
|
||||
Other = 4294967295, // -1
|
||||
Hd15 = 0,
|
||||
Svideo = 1,
|
||||
CompositeVideo = 2,
|
||||
ComponentVideo = 3,
|
||||
Dvi = 4,
|
||||
Hdmi = 5,
|
||||
Lvds = 6,
|
||||
DJpn = 8,
|
||||
Sdi = 9,
|
||||
DisplayportExternal = 10,
|
||||
DisplayportEmbedded = 11,
|
||||
UdiExternal = 12,
|
||||
UdiEmbedded = 13,
|
||||
Sdtvdongle = 14,
|
||||
Internal = 0x80000000,
|
||||
ForceUint32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
#region SdcFlags enum
|
||||
|
||||
[Flags]
|
||||
enum SdcFlags : uint
|
||||
{
|
||||
Zero = 0,
|
||||
|
||||
TopologyInternal = 0x00000001,
|
||||
TopologyClone = 0x00000002,
|
||||
TopologyExtend = 0x00000004,
|
||||
TopologyExternal = 0x00000008,
|
||||
TopologySupplied = 0x00000010,
|
||||
|
||||
UseSuppliedDisplayConfig = 0x00000020,
|
||||
Validate = 0x00000040,
|
||||
Apply = 0x00000080,
|
||||
NoOptimization = 0x00000100,
|
||||
SaveToDatabase = 0x00000200,
|
||||
AllowChanges = 0x00000400,
|
||||
PathPersistIfRequired = 0x00000800,
|
||||
ForceModeEnumeration = 0x00001000,
|
||||
AllowPathOrderChanges = 0x00002000,
|
||||
|
||||
UseDatabaseCurrent = TopologyInternal | TopologyClone | TopologyExtend | TopologyExternal
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigFlags : uint
|
||||
{
|
||||
Zero = 0x0,
|
||||
PathActive = 0x00000001
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigSourceStatus
|
||||
{
|
||||
Zero = 0x0,
|
||||
InUse = 0x00000001
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigTargetStatus : uint
|
||||
{
|
||||
Zero = 0x0,
|
||||
|
||||
InUse = 0x00000001,
|
||||
FORCIBLE = 0x00000002,
|
||||
ForcedAvailabilityBoot = 0x00000004,
|
||||
ForcedAvailabilityPath = 0x00000008,
|
||||
ForcedAvailabilitySystem = 0x00000010,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigRotation : uint
|
||||
{
|
||||
Zero = 0x0,
|
||||
|
||||
Identity = 1,
|
||||
Rotate90 = 2,
|
||||
Rotate180 = 3,
|
||||
Rotate270 = 4,
|
||||
ForceUint32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigPixelFormat : uint
|
||||
{
|
||||
Zero = 0x0,
|
||||
|
||||
Pixelformat8Bpp = 1,
|
||||
Pixelformat16Bpp = 2,
|
||||
Pixelformat24Bpp = 3,
|
||||
Pixelformat32Bpp = 4,
|
||||
PixelformatNongdi = 5,
|
||||
PixelformatForceUint32 = 0xffffffff
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigScaling : uint
|
||||
{
|
||||
Zero = 0x0,
|
||||
|
||||
Identity = 1,
|
||||
Centered = 2,
|
||||
Stretched = 3,
|
||||
Aspectratiocenteredmax = 4,
|
||||
Custom = 5,
|
||||
Preferred = 128,
|
||||
ForceUint32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfigRational
|
||||
{
|
||||
uint numerator;
|
||||
uint denominator;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigScanLineOrdering : uint
|
||||
{
|
||||
Unspecified = 0,
|
||||
Progressive = 1,
|
||||
Interlaced = 2,
|
||||
InterlacedUpperfieldfirst = Interlaced,
|
||||
InterlacedLowerfieldfirst = 3,
|
||||
ForceUint32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfigPathInfo
|
||||
{
|
||||
public DisplayConfigPathSourceInfo sourceInfo;
|
||||
public DisplayConfigPathTargetInfo targetInfo;
|
||||
public uint flags;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigModeInfoType : uint
|
||||
{
|
||||
Zero = 0,
|
||||
|
||||
Source = 1,
|
||||
Target = 2,
|
||||
ForceUint32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
struct DisplayConfigModeInfo
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public DisplayConfigModeInfoType infoType;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public uint id;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public LUID adapterId;
|
||||
|
||||
[FieldOffset(16)]
|
||||
public DisplayConfigTargetMode targetMode;
|
||||
|
||||
[FieldOffset(16)]
|
||||
public DisplayConfigSourceMode sourceMode;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfig2DRegion
|
||||
{
|
||||
uint cx;
|
||||
uint cy;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum D3DmdtVideoSignalStandard : uint
|
||||
{
|
||||
Uninitialized = 0,
|
||||
VesaDmt = 1,
|
||||
VesaGtf = 2,
|
||||
VesaCvt = 3,
|
||||
Ibm = 4,
|
||||
Apple = 5,
|
||||
NtscM = 6,
|
||||
NtscJ = 7,
|
||||
Ntsc443 = 8,
|
||||
PalB = 9,
|
||||
PalB1 = 10,
|
||||
PalG = 11,
|
||||
PalH = 12,
|
||||
PalI = 13,
|
||||
PalD = 14,
|
||||
PalN = 15,
|
||||
PalNc = 16,
|
||||
SecamB = 17,
|
||||
SecamD = 18,
|
||||
SecamG = 19,
|
||||
SecamH = 20,
|
||||
SecamK = 21,
|
||||
SecamK1 = 22,
|
||||
SecamL = 23,
|
||||
SecamL1 = 24,
|
||||
Eia861 = 25,
|
||||
Eia861A = 26,
|
||||
Eia861B = 27,
|
||||
PalK = 28,
|
||||
PalK1 = 29,
|
||||
PalL = 30,
|
||||
PalM = 31,
|
||||
Other = 255
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfigVideoSignalInfo
|
||||
{
|
||||
long pixelRate;
|
||||
DisplayConfigRational hSyncFreq;
|
||||
DisplayConfigRational vSyncFreq;
|
||||
DisplayConfig2DRegion activeSize;
|
||||
DisplayConfig2DRegion totalSize;
|
||||
|
||||
D3DmdtVideoSignalStandard videoStandard;
|
||||
DisplayConfigScanLineOrdering ScanLineOrdering;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfigTargetMode
|
||||
{
|
||||
DisplayConfigVideoSignalInfo targetVideoSignalInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct PointL
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfigSourceMode
|
||||
{
|
||||
uint width;
|
||||
uint height;
|
||||
DisplayConfigPixelFormat pixelFormat;
|
||||
PointL position;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfigPathSourceInfo
|
||||
{
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
public uint modeInfoIdx;
|
||||
|
||||
public DisplayConfigSourceStatus statusFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct DisplayConfigPathTargetInfo
|
||||
{
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
public uint modeInfoIdx;
|
||||
public DisplayConfigVideoOutputTechnology outputTechnology;
|
||||
public DisplayConfigRotation rotation;
|
||||
public DisplayConfigScaling scaling;
|
||||
public DisplayConfigRational refreshRate;
|
||||
public DisplayConfigScanLineOrdering scanLineOrdering;
|
||||
|
||||
public bool targetAvailable;
|
||||
public DisplayConfigTargetStatus statusFlags;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum QueryDisplayFlags : uint
|
||||
{
|
||||
Zero = 0x0,
|
||||
|
||||
AllPaths = 0x00000001,
|
||||
OnlyActivePaths = 0x00000002,
|
||||
DatabaseCurrent = 0x00000004
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum DisplayConfigTopologyId : uint
|
||||
{
|
||||
Zero = 0x0,
|
||||
|
||||
Internal = 0x00000001,
|
||||
Clone = 0x00000002,
|
||||
Extend = 0x00000004,
|
||||
External = 0x00000008,
|
||||
ForceUint32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
private enum DISPLAYCONFIG_COLOR_ENCODING
|
||||
{
|
||||
DISPLAYCONFIG_COLOR_ENCODING_RGB = 0,
|
||||
DISPLAYCONFIG_COLOR_ENCODING_YCBCR444 = 1,
|
||||
DISPLAYCONFIG_COLOR_ENCODING_YCBCR422 = 2,
|
||||
DISPLAYCONFIG_COLOR_ENCODING_YCBCR420 = 3,
|
||||
DISPLAYCONFIG_COLOR_ENCODING_INTENSITY = 4,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
public uint value;
|
||||
public DISPLAYCONFIG_COLOR_ENCODING colorEncoding;
|
||||
public int bitsPerColorChannel;
|
||||
|
||||
public bool advancedColorSupported => (value & 0x1) == 0x1;
|
||||
public bool advancedColorEnabled => (value & 0x2) == 0x2;
|
||||
public bool wideColorEnforced => (value & 0x4) == 0x4;
|
||||
public bool advancedColorForceDisabled => (value & 0x8) == 0x8;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct DISPLAYCONFIG_SET_ADVANCED_COLOR_INFO
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
public uint enableAdvancedColor;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
|
||||
{
|
||||
public uint value;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct DISPLAYCONFIG_TARGET_DEVICE_NAME
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
|
||||
public DisplayConfigVideoOutputTechnology outputTechnology;
|
||||
public ushort edidManufactureId;
|
||||
public ushort edidProductCodeId;
|
||||
public uint connectorInstance;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
|
||||
public string monitorFriendlyDeviceName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string monitorDevicePat;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct DISPLAYCONFIG_SOURCE_DEVICE_NAME
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string viewGdiDeviceName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
static class NativeMethods
|
||||
{
|
||||
[DllImport("User32.dll")]
|
||||
public static extern int GetDisplayConfigBufferSizes(QueryDisplayFlags flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
|
||||
|
||||
[DllImport("User32.dll")]
|
||||
public static extern int SetDisplayConfig(uint numPathArrayElements, [In] DisplayConfigPathInfo[] pathArray, uint numModeInfoArrayElements, [In] DisplayConfigModeInfo[] modeInfoArray, SdcFlags flags);
|
||||
|
||||
[DllImport("User32.dll")]
|
||||
public static extern int QueryDisplayConfig(QueryDisplayFlags flags, ref uint numPathArrayElements, [In, Out] DisplayConfigPathInfo[] pathInfoArray, ref uint modeInfoArrayElements, [In, Out] DisplayConfigModeInfo[] modeInfoArray, out DisplayConfigTopologyId id);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO requestPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigSetDeviceInfo(ref DISPLAYCONFIG_SET_ADVANCED_COLOR_INFO setPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME requestPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SOURCE_DEVICE_NAME requestPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,313 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl
|
||||
{
|
||||
public static class ScreenInterrogatory
|
||||
{
|
||||
public const int ERROR_SUCCESS = 0;
|
||||
|
||||
#region enums
|
||||
|
||||
public enum QUERY_DEVICE_CONFIG_FLAGS : uint
|
||||
{
|
||||
QDC_ALL_PATHS = 0x00000001,
|
||||
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
|
||||
QDC_DATABASE_CURRENT = 0x00000004
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY : uint
|
||||
{
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = 0xFFFFFFFF,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x80000000,
|
||||
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_SCANLINE_ORDERING : uint
|
||||
{
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
|
||||
DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_ROTATION : uint
|
||||
{
|
||||
DISPLAYCONFIG_ROTATION_IDENTITY = 1,
|
||||
DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
|
||||
DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
|
||||
DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
|
||||
DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_SCALING : uint
|
||||
{
|
||||
DISPLAYCONFIG_SCALING_IDENTITY = 1,
|
||||
DISPLAYCONFIG_SCALING_CENTERED = 2,
|
||||
DISPLAYCONFIG_SCALING_STRETCHED = 3,
|
||||
DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
|
||||
DISPLAYCONFIG_SCALING_CUSTOM = 5,
|
||||
DISPLAYCONFIG_SCALING_PREFERRED = 128,
|
||||
DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_PIXELFORMAT : uint
|
||||
{
|
||||
DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
|
||||
DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
|
||||
DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
|
||||
DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
|
||||
DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
|
||||
DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_MODE_INFO_TYPE : uint
|
||||
{
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
|
||||
DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint
|
||||
{
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
|
||||
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
|
||||
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
|
||||
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region structs
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct LUID
|
||||
{
|
||||
public uint LowPart;
|
||||
public int HighPart;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_PATH_SOURCE_INFO
|
||||
{
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
public uint modeInfoIdx;
|
||||
public uint statusFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_PATH_TARGET_INFO
|
||||
{
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
public uint modeInfoIdx;
|
||||
private DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
|
||||
private DISPLAYCONFIG_ROTATION rotation;
|
||||
private DISPLAYCONFIG_SCALING scaling;
|
||||
private DISPLAYCONFIG_RATIONAL refreshRate;
|
||||
private DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
|
||||
public bool targetAvailable;
|
||||
public uint statusFlags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_RATIONAL
|
||||
{
|
||||
public uint Numerator;
|
||||
public uint Denominator;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_PATH_INFO
|
||||
{
|
||||
public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
|
||||
public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
|
||||
public uint flags;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_2DREGION
|
||||
{
|
||||
public uint cx;
|
||||
public uint cy;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
|
||||
{
|
||||
public ulong pixelRate;
|
||||
public DISPLAYCONFIG_RATIONAL hSyncFreq;
|
||||
public DISPLAYCONFIG_RATIONAL vSyncFreq;
|
||||
public DISPLAYCONFIG_2DREGION activeSize;
|
||||
public DISPLAYCONFIG_2DREGION totalSize;
|
||||
public uint videoStandard;
|
||||
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_TARGET_MODE
|
||||
{
|
||||
public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINTL
|
||||
{
|
||||
private int x;
|
||||
private int y;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_SOURCE_MODE
|
||||
{
|
||||
public uint width;
|
||||
public uint height;
|
||||
public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
|
||||
public POINTL position;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct DISPLAYCONFIG_MODE_INFO_UNION
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public DISPLAYCONFIG_TARGET_MODE targetMode;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public DISPLAYCONFIG_SOURCE_MODE sourceMode;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_MODE_INFO
|
||||
{
|
||||
public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
|
||||
public uint id;
|
||||
public LUID adapterId;
|
||||
public DISPLAYCONFIG_MODE_INFO_UNION modeInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
|
||||
{
|
||||
public uint value;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
|
||||
public uint size;
|
||||
public LUID adapterId;
|
||||
public uint id;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME
|
||||
{
|
||||
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
|
||||
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
|
||||
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
|
||||
public ushort edidManufactureId;
|
||||
public ushort edidProductCodeId;
|
||||
public uint connectorInstance;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
|
||||
public string monitorFriendlyDeviceName;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string monitorDevicePath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DLL-Imports
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int GetDisplayConfigBufferSizes(
|
||||
QUERY_DEVICE_CONFIG_FLAGS flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int QueryDisplayConfig(
|
||||
QUERY_DEVICE_CONFIG_FLAGS flags,
|
||||
ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] PathInfoArray,
|
||||
ref uint numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] ModeInfoArray,
|
||||
IntPtr currentTopologyId
|
||||
);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName);
|
||||
|
||||
#endregion
|
||||
|
||||
private static string MonitorFriendlyName(LUID adapterId, uint targetId)
|
||||
{
|
||||
var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME
|
||||
{
|
||||
header =
|
||||
{
|
||||
size = (uint)Marshal.SizeOf(typeof (DISPLAYCONFIG_TARGET_DEVICE_NAME)),
|
||||
adapterId = adapterId,
|
||||
id = targetId,
|
||||
type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
|
||||
}
|
||||
};
|
||||
var error = DisplayConfigGetDeviceInfo(ref deviceName);
|
||||
if (error != ERROR_SUCCESS)
|
||||
throw new Win32Exception(error);
|
||||
return deviceName.monitorFriendlyDeviceName;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetAllMonitorsFriendlyNames()
|
||||
{
|
||||
uint pathCount, modeCount;
|
||||
var error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
|
||||
if (error != ERROR_SUCCESS)
|
||||
throw new Win32Exception(error);
|
||||
|
||||
var displayPaths = new DISPLAYCONFIG_PATH_INFO[pathCount];
|
||||
var displayModes = new DISPLAYCONFIG_MODE_INFO[modeCount];
|
||||
error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
|
||||
ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
|
||||
if (error != ERROR_SUCCESS)
|
||||
throw new Win32Exception(error);
|
||||
|
||||
for (var i = 0; i < modeCount; i++)
|
||||
if (displayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
|
||||
yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
|
||||
}
|
||||
|
||||
public static string DeviceFriendlyName(this Screen screen)
|
||||
{
|
||||
var allFriendlyNames = GetAllMonitorsFriendlyNames();
|
||||
for (var index = 0; index < Screen.AllScreens.Length; index++)
|
||||
if (Equals(screen, Screen.AllScreens[index]))
|
||||
return allFriendlyNames.ToArray()[index];
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
using NWin32.NativeTypes;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ColorControl.Native
|
||||
{
|
||||
public static class WinApi
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
internal struct POWERBROADCAST_SETTING
|
||||
{
|
||||
public Guid PowerSetting;
|
||||
public uint DataLength;
|
||||
public byte Data;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct COPYDATASTRUCT
|
||||
{
|
||||
public IntPtr dwData; // in C/C++ this is an UINT_PTR, not an UINT
|
||||
public int cbData;
|
||||
public IntPtr lpData;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CopyData : IDisposable
|
||||
{
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
|
||||
static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, ref CopyData target,
|
||||
SendMessageTimeoutFlags fuFlags, uint uTimeout, out UIntPtr lpdwResult);
|
||||
|
||||
[Flags]
|
||||
enum SendMessageTimeoutFlags : uint
|
||||
{
|
||||
SMTO_NORMAL = 0x0,
|
||||
SMTO_BLOCK = 0x1,
|
||||
SMTO_ABORTIFHUNG = 0x2,
|
||||
SMTO_NOTIMEOUTIFNOTHUNG = 0x8
|
||||
}
|
||||
const uint WM_COPYDATA = 0x4A;
|
||||
|
||||
public IntPtr dwData;
|
||||
public int cbData;
|
||||
public IntPtr lpData;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (lpData != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(lpData);
|
||||
lpData = IntPtr.Zero;
|
||||
cbData = 0;
|
||||
}
|
||||
}
|
||||
public string AsAnsiString
|
||||
{
|
||||
get { return Marshal.PtrToStringAnsi(lpData, cbData); }
|
||||
}
|
||||
public string AsUnicodeString
|
||||
{
|
||||
get { return Marshal.PtrToStringUni(lpData); }
|
||||
}
|
||||
public static CopyData CreateForString(int dwData, string value, bool Unicode = false)
|
||||
{
|
||||
var result = new CopyData();
|
||||
result.dwData = (IntPtr)dwData;
|
||||
result.lpData = Unicode ? Marshal.StringToCoTaskMemUni(value) : Marshal.StringToCoTaskMemAnsi(value);
|
||||
result.cbData = value.Length + 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static UIntPtr Send(IntPtr targetHandle, int dwData, string value, uint timeoutMs = 1000, bool Unicode = false)
|
||||
{
|
||||
var cds = CreateForString(dwData, value, Unicode);
|
||||
UIntPtr result;
|
||||
SendMessageTimeout(targetHandle, WM_COPYDATA, IntPtr.Zero, ref cds, SendMessageTimeoutFlags.SMTO_NORMAL, timeoutMs, out result);
|
||||
cds.Dispose();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MessageFilterInfo : uint
|
||||
{
|
||||
None = 0, AlreadyAllowed = 1, AlreadyDisAllowed = 2, AllowedHigher = 3
|
||||
};
|
||||
|
||||
public enum ChangeWindowMessageFilterExAction : uint
|
||||
{
|
||||
Reset = 0, Allow = 1, DisAllow = 2
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CHANGEFILTERSTRUCT
|
||||
{
|
||||
public uint size;
|
||||
public MessageFilterInfo info;
|
||||
}
|
||||
|
||||
public const int ENUM_CURRENT_SETTINGS = -1;
|
||||
public const int ENUM_REGISTRY_SETTINGS = -2;
|
||||
|
||||
public static int PBT_POWERSETTINGCHANGE = 32787;
|
||||
|
||||
public delegate void PCREATE_PROCESS_NOTIFY_ROUTINE(IntPtr ParentId, IntPtr ProcessId, bool Create);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern bool EnumDisplaySettingsA(string deviceName, int modeNum, out DEVMODEA devMode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool AllocConsole();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
public static extern bool AttachConsole(int processId);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool FreeConsole();
|
||||
|
||||
[DllImport(@"User32", SetLastError = true)]
|
||||
public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags);
|
||||
|
||||
[DllImport("User32.dll", SetLastError = true)]
|
||||
public static extern bool UnregisterPowerSettingNotification(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint msg, ChangeWindowMessageFilterExAction action, ref CHANGEFILTERSTRUCT changeInfo);
|
||||
|
||||
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
|
||||
public static extern int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList);
|
||||
|
||||
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#104")]
|
||||
public static extern int RefreshImmersiveColorPolicyState();
|
||||
|
||||
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#133")]
|
||||
public static extern int AllowDarkModeForWindow(IntPtr hWnd, bool allow);
|
||||
|
||||
[DllImport("uxtheme.dll", CharSet = CharSet.Unicode, EntryPoint = "#135")]
|
||||
public static extern int SetPreferredAppMode(int appMode);
|
||||
|
||||
[DllImport("uxtheme.dll", EntryPoint = "#136")]
|
||||
public static extern void FlushMenuThemes();
|
||||
|
||||
[DllImport("dwmapi.dll", PreserveSig = true)]
|
||||
public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NonInvasiveKeyboardHookLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// A struct to represent a keybind (key + modifiers)
|
||||
/// When the keybind struct is compared to another keybind struct, the equality is based on the
|
||||
/// modifiers and the virtual key code.
|
||||
/// </summary>
|
||||
internal class KeybindStruct : IEquatable<KeybindStruct>
|
||||
{
|
||||
public readonly int VirtualKeyCode;
|
||||
public readonly List<ModifierKeys> Modifiers;
|
||||
public readonly Guid? Identifier;
|
||||
|
||||
public KeybindStruct(IEnumerable<ModifierKeys> modifiers, int virtualKeyCode, Guid? identifier = null)
|
||||
{
|
||||
this.VirtualKeyCode = virtualKeyCode;
|
||||
this.Modifiers = new List<ModifierKeys>(modifiers);
|
||||
this.Identifier = identifier;
|
||||
}
|
||||
|
||||
public bool Equals(KeybindStruct other)
|
||||
{
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
if (this.VirtualKeyCode != other.VirtualKeyCode)
|
||||
return false;
|
||||
|
||||
if (this.Modifiers.Count != other.Modifiers.Count)
|
||||
return false;
|
||||
|
||||
foreach (var modifier in this.Modifiers)
|
||||
{
|
||||
if (!other.Modifiers.Contains(modifier))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
|
||||
return Equals((KeybindStruct) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = 13;
|
||||
hash = (hash * 7) + VirtualKeyCode.GetHashCode();
|
||||
|
||||
// Sum the modifiers separately, so that their order does not affect the final hash
|
||||
var modifiersHashSum = 0;
|
||||
foreach (var modifier in this.Modifiers)
|
||||
{
|
||||
modifiersHashSum += modifier.GetHashCode();
|
||||
}
|
||||
|
||||
hash = (hash * 7) + modifiersHashSum;
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NonInvasiveKeyboardHookLibrary
|
||||
{
|
||||
internal struct KeyboardParams
|
||||
{
|
||||
public IntPtr wParam;
|
||||
public int vkCode;
|
||||
|
||||
public KeyboardParams(IntPtr wParam, int vkCode)
|
||||
{
|
||||
this.wParam = wParam;
|
||||
this.vkCode = vkCode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A hotkey manager that uses a low-level global keyboard hook, but eventually only fires events for
|
||||
/// pre-registered hotkeys, i.e. not invading a user's privacy.
|
||||
/// </summary>
|
||||
public class KeyboardHookManager
|
||||
{
|
||||
#region Private Attributes
|
||||
/// <summary>
|
||||
/// Keeps track of all registered hotkeys
|
||||
/// </summary>
|
||||
private readonly Dictionary<KeybindStruct, Action> _registeredCallbacks;
|
||||
/// <summary>
|
||||
/// Keeps track of modifier keys that are held down
|
||||
/// </summary>
|
||||
private readonly HashSet<ModifierKeys> _downModifierKeys;
|
||||
/// <summary>
|
||||
/// Keeps track of all keys that are held down to prevent firing callbacks
|
||||
/// more than once for a single keypress
|
||||
/// </summary>
|
||||
private readonly HashSet<int> _downKeys;
|
||||
private readonly object _modifiersLock = new object();
|
||||
private LowLevelKeyboardProc _hook;
|
||||
private bool _isStarted;
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
/// Instantiates an empty keyboard hook manager.
|
||||
/// It is best practice to keep a single instance per process.
|
||||
/// Start() must be called to start the low-level keyboard hook manager
|
||||
/// </summary>
|
||||
public KeyboardHookManager()
|
||||
{
|
||||
this._registeredCallbacks = new Dictionary<KeybindStruct, Action>();
|
||||
this._downModifierKeys = new HashSet<ModifierKeys>();
|
||||
this._downKeys = new HashSet<int>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
/// <summary>
|
||||
/// Starts the low-level keyboard hook.
|
||||
/// Hotkeys can be registered regardless of the low-level keyboard hook's state, but their callbacks
|
||||
/// will only ever be invoked if the low-level keyboard hook is running and intercepting keys.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
if (this._isStarted) return;
|
||||
|
||||
this._hook = this.HookCallback;
|
||||
_hookId = SetHook(this._hook);
|
||||
this._isStarted = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses the low-level keyboard hook (without unregistering the existing hotkeys)
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if (this._isStarted)
|
||||
{
|
||||
UnhookWindowsHookEx(_hookId);
|
||||
this._isStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a hotkey.
|
||||
/// </summary>
|
||||
/// <param name="virtualKeyCode">The virtual key code of the hotkey</param>
|
||||
/// <param name="action">The callback action to invoke when this hotkey is pressed</param>
|
||||
/// <exception cref="HotkeyAlreadyRegisteredException">Thrown when the given key is already mapped to a callback</exception>
|
||||
/// /// <returns>Unique identifier of this hotkey, which can be used to remove it later</returns>
|
||||
public Guid RegisterHotkey(int virtualKeyCode, Action action)
|
||||
{
|
||||
return this.RegisterHotkey(new ModifierKeys[0], virtualKeyCode, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new key combination with one or more modifiers
|
||||
/// </summary>
|
||||
/// <param name="modifiers">Modifiers that must be held while hitting the key. Multiple modifiers can be provided using the flags bitwise OR operation</param>
|
||||
/// <param name="virtualKeyCode">The virtual key code of the standard key</param>
|
||||
/// <param name="action">The callback action to invoke when this combination is pressed</param>
|
||||
/// <exception cref="HotkeyAlreadyRegisteredException">Thrown when the given key combination is already mapped to a callback</exception>
|
||||
/// <returns>Unique identifier of this hotkey, which can be used to remove it later</returns>
|
||||
public Guid RegisterHotkey(ModifierKeys modifiers, int virtualKeyCode, Action action)
|
||||
{
|
||||
var allModifiers = Enum.GetValues(typeof(ModifierKeys)).Cast<ModifierKeys>().ToArray();
|
||||
|
||||
// Get the modifiers that were chained with bitwise OR operation as an array of modifiers
|
||||
var selectedModifiers = allModifiers.Where(modifier => modifiers.HasFlag(modifier)).ToArray();
|
||||
|
||||
return RegisterHotkey(selectedModifiers, virtualKeyCode, action);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new key combination.
|
||||
/// </summary>
|
||||
/// <param name="modifiers">Modifiers that must be held while hitting the key</param>
|
||||
/// <param name="virtualKeyCode">The virtual key code of the standard key</param>
|
||||
/// <param name="action">The callback action to invoke when this combination is pressed</param>
|
||||
/// <exception cref="HotkeyAlreadyRegisteredException">Thrown when the given key combination is already mapped to a callback</exception>
|
||||
/// <returns>Unique identifier of this hotkey, which can be used to remove it later</returns>
|
||||
public Guid RegisterHotkey(ModifierKeys[] modifiers, int virtualKeyCode, Action action)
|
||||
{
|
||||
var keybindIdentity = Guid.NewGuid();
|
||||
var keybind = new KeybindStruct(modifiers, virtualKeyCode, keybindIdentity);
|
||||
if (this._registeredCallbacks.ContainsKey(keybind))
|
||||
{
|
||||
throw new HotkeyAlreadyRegisteredException();
|
||||
}
|
||||
|
||||
this._registeredCallbacks[keybind] = action;
|
||||
return keybindIdentity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters all hotkeys (the low-level keyboard hook continues running)
|
||||
/// </summary>
|
||||
public void UnregisterAll()
|
||||
{
|
||||
this._registeredCallbacks.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a specific single-key hotkey
|
||||
/// </summary>
|
||||
/// <param name="virtualKeyCode">Virtual key code of the unregistered key</param>
|
||||
/// <exception cref="HotkeyNotRegisteredException">Thrown when the given key combination is not registered</exception>
|
||||
public void UnregisterHotkey(int virtualKeyCode)
|
||||
{
|
||||
this.UnregisterHotkey(new ModifierKeys[0], virtualKeyCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a specific key combination
|
||||
/// </summary>
|
||||
/// <param name="modifiers">The modifiers of the combination</param>
|
||||
/// <param name="virtualKeyCode">The key of the combination</param>
|
||||
/// <exception cref="HotkeyNotRegisteredException">Thrown when the given key combination is not registered</exception>
|
||||
public void UnregisterHotkey(ModifierKeys[] modifiers, int virtualKeyCode)
|
||||
{
|
||||
var keybind = new KeybindStruct(modifiers, virtualKeyCode);
|
||||
|
||||
if (!this._registeredCallbacks.Remove(keybind))
|
||||
{
|
||||
throw new HotkeyNotRegisteredException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a specific key by its unique identifier
|
||||
/// </summary>
|
||||
/// <param name="keybindIdentity">Keybind GUID, as returned by RegisterHotkey</param>
|
||||
public void UnregisterHotkey(Guid keybindIdentity)
|
||||
{
|
||||
var keybindToRemove = this._registeredCallbacks.Keys.FirstOrDefault(keybind =>
|
||||
keybind.Identifier.HasValue && keybind.Identifier.Value.Equals(keybindIdentity));
|
||||
|
||||
if (keybindToRemove == null || !this._registeredCallbacks.Remove(keybindToRemove))
|
||||
{
|
||||
throw new HotkeyNotRegisteredException();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
private void HandleKeyPress(int virtualKeyCode)
|
||||
{
|
||||
var currentKey = new KeybindStruct(this._downModifierKeys, virtualKeyCode);
|
||||
|
||||
if (!this._registeredCallbacks.ContainsKey(currentKey))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._registeredCallbacks.TryGetValue(currentKey, out var callback))
|
||||
{
|
||||
callback.Invoke();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Low level keyboard hook
|
||||
// Source: https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
|
||||
private const int WH_KEYBOARD_LL = 13;
|
||||
private const int WM_KEYDOWN = 0x0100;
|
||||
private const int WM_KEYUP = 0x0101;
|
||||
private const int WM_SYSKEYDOWN = 0x0104;
|
||||
private const int WM_SYSKEYUP = 0x0105;
|
||||
|
||||
private static IntPtr _hookId = IntPtr.Zero;
|
||||
|
||||
private static IntPtr SetHook(LowLevelKeyboardProc proc)
|
||||
{
|
||||
var userLibrary = LoadLibrary("User32");
|
||||
|
||||
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
|
||||
userLibrary, 0);
|
||||
}
|
||||
|
||||
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0)
|
||||
{
|
||||
var vkCode = Marshal.ReadInt32(lParam);
|
||||
|
||||
// Debug.WriteLine("Starting");
|
||||
// To prevent slowing keyboard input down, we use handle keyboard inputs in a separate thread
|
||||
//ThreadPool.QueueUserWorkItem(this.HandleSingleKeyboardInput, new KeyboardParams(wParam, vkCode));
|
||||
// Debug.WriteLine("Ending");
|
||||
|
||||
HandleSingleKeyboardInput(new KeyboardParams(wParam, vkCode));
|
||||
|
||||
//return IntPtr.Zero;
|
||||
}
|
||||
|
||||
return CallNextHookEx(_hookId, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a keyboard event based on the KeyboardParams it receives
|
||||
/// </summary>
|
||||
/// <param name="keyboardParamsObj">KeyboardParams struct (object type to comply with QueueUserWorkItem)</param>
|
||||
private void HandleSingleKeyboardInput(object keyboardParamsObj)
|
||||
{
|
||||
var keyboardParams = (KeyboardParams)keyboardParamsObj;
|
||||
var wParam = keyboardParams.wParam;
|
||||
var vkCode = keyboardParams.vkCode;
|
||||
|
||||
var modifierKey = ModifierKeysUtilities.GetModifierKeyFromCode(vkCode);
|
||||
|
||||
Debug.WriteLine("Modifiers: " + string.Join("+", _downModifierKeys) + ", ModKey: " + modifierKey + ", Key: " + vkCode);
|
||||
|
||||
// If the keyboard event is a KeyDown event (i.e. key pressed)
|
||||
if (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
|
||||
{
|
||||
// In this case, we only care about modifier keys
|
||||
if (modifierKey != null)
|
||||
{
|
||||
lock (this._modifiersLock)
|
||||
{
|
||||
this._downModifierKeys.Add(modifierKey.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger callbacks that are registered for this key, but only once per key press
|
||||
if (!this._downKeys.Contains(vkCode))
|
||||
{
|
||||
this.HandleKeyPress(vkCode);
|
||||
this._downKeys.Add(vkCode);
|
||||
}
|
||||
}
|
||||
|
||||
// If the keyboard event is a KeyUp event (i.e. key released)
|
||||
if (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
|
||||
{
|
||||
// If the released key is a modifier key, remove it from the HashSet of modifier keys
|
||||
if (modifierKey != null)
|
||||
{
|
||||
lock (this._modifiersLock)
|
||||
{
|
||||
this._downModifierKeys.Remove(modifierKey.Value);
|
||||
}
|
||||
}
|
||||
|
||||
this._downKeys.Remove(vkCode);
|
||||
}
|
||||
}
|
||||
|
||||
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr SetWindowsHookEx(int idHook,
|
||||
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
|
||||
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
|
||||
IntPtr wParam, IntPtr lParam);
|
||||
|
||||
/// <summary>
|
||||
/// Loads the library.
|
||||
/// </summary>
|
||||
/// <param name="lpFileName">Name of the library</param>
|
||||
/// <returns>A handle to the library</returns>
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr LoadLibrary(string lpFileName);
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Exceptions
|
||||
public class NonInvasiveKeyboardHookException : Exception
|
||||
{
|
||||
}
|
||||
|
||||
public class HotkeyAlreadyRegisteredException : NonInvasiveKeyboardHookException
|
||||
{
|
||||
}
|
||||
|
||||
public class HotkeyNotRegisteredException : NonInvasiveKeyboardHookException
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace NonInvasiveKeyboardHookLibrary
|
||||
{
|
||||
[Flags]
|
||||
public enum ModifierKeys
|
||||
{
|
||||
Alt = 1,
|
||||
Control = 2,
|
||||
Shift = 4,
|
||||
WindowsKey = 8,
|
||||
}
|
||||
|
||||
public static class ModifierKeysUtilities
|
||||
{
|
||||
public static ModifierKeys? GetModifierKeyFromCode(int keyCode)
|
||||
{
|
||||
switch (keyCode)
|
||||
{
|
||||
case 0xA0:
|
||||
case 0xA1:
|
||||
case 0x10:
|
||||
return ModifierKeys.Shift;
|
||||
|
||||
case 0xA2:
|
||||
case 0xA3:
|
||||
case 0x11:
|
||||
return ModifierKeys.Control;
|
||||
|
||||
case 0x12:
|
||||
case 0xA4:
|
||||
case 0xA5:
|
||||
return ModifierKeys.Alt;
|
||||
|
||||
case 0x5B:
|
||||
case 0x5C:
|
||||
return ModifierKeys.WindowsKey;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+220
-175
@@ -1,16 +1,23 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Forms;
|
||||
using ColorControl.Forms;
|
||||
using ColorControl.Services.AMD;
|
||||
using ColorControl.Services.Common;
|
||||
using ColorControl.Services.EventDispatcher;
|
||||
using ColorControl.Services.GameLauncher;
|
||||
using ColorControl.Services.LG;
|
||||
using ColorControl.Services.NVIDIA;
|
||||
using ColorControl.Services.Samsung;
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.EventDispatcher;
|
||||
using ColorControl.Shared.Forms;
|
||||
using ColorControl.Shared.Native;
|
||||
using ColorControl.Shared.Services;
|
||||
using ColorControl.Svc;
|
||||
using ColorControl.XForms;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Newtonsoft.Json;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NWin32;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@@ -29,16 +36,19 @@ namespace ColorControl
|
||||
public static string ConfigFilename { get; private set; }
|
||||
public static string LogFilename { get; private set; }
|
||||
public static Config Config { get; private set; }
|
||||
public static AppContext AppContext { get; private set; }
|
||||
|
||||
public static string MutexId { get; private set; }
|
||||
public static GlobalContext AppContext { get; private set; }
|
||||
|
||||
public static bool IsRestarting { get; private set; }
|
||||
public static bool UserExit = false;
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private static Mutex _mutex;
|
||||
private static MainForm _mainForm;
|
||||
public static MainForm _mainForm;
|
||||
private static LoggingRule _loggingRule;
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread] // autogenerated
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
@@ -46,37 +56,30 @@ namespace ColorControl
|
||||
MainAsync(args).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
//[STAThread]
|
||||
static async Task MainAsync(string[] args)
|
||||
{
|
||||
DataDir = Utils.GetDataPath();
|
||||
|
||||
//Utils.UpdateFiles(@"H:\temp\ColorControl\ColorControl", @"C:\Users\vinni\source\repos\ColorControl\ColorControl\bin\Debug\net6.0-windows10.0.20348.0");
|
||||
//Utils.UnZipFile(@"H:\temp\ColorControl\ColorControl.zip", @"H:\temp\ColorControl\temp");
|
||||
var runAsService = args.Contains("--service") || WinApiService.IsAdministratorStatic() && Process.GetCurrentProcess().Parent()?.ProcessName?.Equals("services", StringComparison.InvariantCultureIgnoreCase) == true;
|
||||
var runElevated = args.Contains("--elevated");
|
||||
|
||||
var runAsService = args.Contains("--service") || Utils.IsAdministrator() && Process.GetCurrentProcess().Parent()?.ProcessName?.Equals("services", StringComparison.InvariantCultureIgnoreCase) == true;
|
||||
|
||||
InitLogger(runAsService);
|
||||
InitLogger(runAsService, runElevated);
|
||||
|
||||
Logger.Debug($"Using data path: {DataDir}");
|
||||
//Logger.Debug("Parent process: " + Process.GetCurrentProcess().Parent()?.ProcessName);
|
||||
|
||||
var host = CreateHostBuilder().Build();
|
||||
ServiceProvider = host.Services;
|
||||
|
||||
if (runAsService)
|
||||
{
|
||||
AppContext = new AppContext(null, new StartUpParams(), DataDir);
|
||||
|
||||
await RunService(args);
|
||||
return;
|
||||
}
|
||||
|
||||
MutexId = $"Global\\{typeof(MainForm).GUID}";
|
||||
await RunApp(args);
|
||||
}
|
||||
|
||||
static async Task RunApp(string[] args)
|
||||
{
|
||||
var startTime = DateTime.Now;
|
||||
var currentDomain = AppDomain.CurrentDomain;
|
||||
// Handler for unhandled exceptions.
|
||||
currentDomain.UnhandledException += GlobalUnhandledExceptionHandler;
|
||||
@@ -87,18 +90,28 @@ namespace ColorControl
|
||||
|
||||
if (Config.UseGdiScaling)
|
||||
{
|
||||
Application.SetHighDpiMode(HighDpiMode.DpiUnawareGdiScaled);
|
||||
var result = Application.SetHighDpiMode(HighDpiMode.DpiUnawareGdiScaled);
|
||||
|
||||
Logger.Debug($"Result of setting SetHighDpiMode: {result}");
|
||||
}
|
||||
|
||||
var mutexId = $"Global\\{typeof(MainForm).GUID}";
|
||||
|
||||
var startUpParams = StartUpParams.Parse(args);
|
||||
|
||||
AppContext = new AppContext(Config, startUpParams, DataDir);
|
||||
AppContext = new GlobalContext(Config, startUpParams, DataDir, _loggingRule, null, startTime, mutexId);
|
||||
|
||||
var host = CreateHostBuilder().Build();
|
||||
ServiceProvider = host.Services;
|
||||
AppContext.ServiceProvider = ServiceProvider;
|
||||
|
||||
MessageForms.Title = AppContext.ApplicationTitle;
|
||||
|
||||
var existingProcess = Utils.GetProcessByName("ColorControl");
|
||||
|
||||
try
|
||||
{
|
||||
if (await HandleStartupParams(startUpParams, existingProcess))
|
||||
if (await CommandLineHandler.HandleStartupParams(startUpParams, existingProcess))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -108,7 +121,7 @@ namespace ColorControl
|
||||
Utils.CloseConsole();
|
||||
}
|
||||
|
||||
_mutex = new Mutex(true, MutexId, out var mutexCreated);
|
||||
_mutex = new Mutex(true, AppContext.MutexId, out var mutexCreated);
|
||||
try
|
||||
{
|
||||
if (!mutexCreated)
|
||||
@@ -128,23 +141,31 @@ namespace ColorControl
|
||||
_mutex.WaitOne();
|
||||
try
|
||||
{
|
||||
//if (Debugger.IsAttached)
|
||||
//{
|
||||
// Utils.StartService();
|
||||
//}
|
||||
|
||||
//var result = WinApi.SetPreferredAppMode(1);
|
||||
//result = WinApi.RefreshImmersiveColorPolicyState();
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
_mainForm = ServiceProvider.GetRequiredService<MainForm>();
|
||||
Application.Run(_mainForm);
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
//Utils.StartService();
|
||||
var winApiService = ServiceProvider.GetRequiredService<WinApiService>();
|
||||
|
||||
if (winApiService.IsAdministrator())
|
||||
{
|
||||
var backgroundService = ServiceProvider.GetRequiredService<ColorControlBackgroundService>();
|
||||
backgroundService.PipeName = PipeUtils.ElevatedPipe;
|
||||
|
||||
Task.Run(async () => await backgroundService.StartAsync(CancellationToken.None));
|
||||
}
|
||||
}
|
||||
|
||||
var worker = ServiceProvider.GetRequiredService<MainWorker>();
|
||||
|
||||
await worker.DoWork();
|
||||
|
||||
if (Debugger.IsAttached && !IsRestarting)
|
||||
{
|
||||
Utils.StopService();
|
||||
var winApiAdminService = ServiceProvider.GetRequiredService<WinApiAdminService>();
|
||||
winApiAdminService.StopService();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -162,6 +183,33 @@ namespace ColorControl
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenDefaultUi()
|
||||
{
|
||||
var _ = Config.UiType switch
|
||||
{
|
||||
UiType.WebDefaultBrowser => OpenNewUi(),
|
||||
UiType.WebEmbedded => OpenNewUiEmbedded(),
|
||||
_ => OpenMainForm()
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task OpenMainForm()
|
||||
{
|
||||
_mainForm ??= ServiceProvider.GetRequiredService<MainForm>();
|
||||
_mainForm.OpenForm();
|
||||
}
|
||||
|
||||
public static void Exit()
|
||||
{
|
||||
UserExit = true;
|
||||
_mainForm?.Close();
|
||||
|
||||
if (AppContext.MainHandle != 0)
|
||||
{
|
||||
NativeMethods.SendMessageW(AppContext.MainHandle, NativeConstants.WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Restart()
|
||||
{
|
||||
IsRestarting = true;
|
||||
@@ -175,22 +223,70 @@ namespace ColorControl
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
private static void InitLogger(bool runAsService)
|
||||
public static async Task OpenNewUi()
|
||||
{
|
||||
var config = new NLog.Config.LoggingConfiguration();
|
||||
if (await StartUiServer())
|
||||
{
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
var winApi = AppContext.ServiceProvider.GetRequiredService<WinApiAdminService>();
|
||||
|
||||
winApi.StartProcess(GetNewUiUrl());
|
||||
}
|
||||
|
||||
public static string GetNewUiUrl()
|
||||
{
|
||||
return $"http://localhost:{(Config.UiPort > 0 ? Config.UiPort : 5000)}";
|
||||
}
|
||||
|
||||
public static async Task OpenNewUiEmbedded()
|
||||
{
|
||||
if (await StartUiServer())
|
||||
{
|
||||
await Task.Delay(500);
|
||||
}
|
||||
|
||||
BrowserWindow.CreateAndShow(GetNewUiUrl());
|
||||
}
|
||||
|
||||
private static bool UiServerStarted;
|
||||
|
||||
public static async Task<bool> StartUiServer()
|
||||
{
|
||||
if (UiServerStarted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var backgroundService = ServiceProvider.GetRequiredService<ColorControlBackgroundService>();
|
||||
|
||||
backgroundService.PipeName = PipeUtils.MainPipe;
|
||||
|
||||
await backgroundService.StartAsync(CancellationToken.None);
|
||||
|
||||
var _ = Task.Run(() => ColorControl.UI.Blazor.Start(Config));
|
||||
UiServerStarted = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void InitLogger(bool runAsService, bool runElevated)
|
||||
{
|
||||
var config = new LoggingConfiguration();
|
||||
|
||||
// Targets where to log to: File and Console
|
||||
var logFileAppendix = runAsService ? "_svc" : "";
|
||||
var logFileAppendix = runAsService ? "_svc" : runElevated ? "_elevated" : "";
|
||||
|
||||
LogFilename = Path.Combine(DataDir, $"LogFile{logFileAppendix}.txt");
|
||||
|
||||
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = LogFilename };
|
||||
|
||||
//var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
|
||||
_loggingRule = new LoggingRule("*", LogLevel.Trace, LogLevel.Fatal, logfile);
|
||||
_loggingRule.RuleName = "ColorControl";
|
||||
|
||||
// Rules for mapping loggers to targets
|
||||
//config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole);
|
||||
config.AddRule(LogLevel.Trace, LogLevel.Fatal, logfile);
|
||||
config.AddRule(_loggingRule);
|
||||
|
||||
// Apply config
|
||||
LogManager.Configuration = config;
|
||||
@@ -214,137 +310,12 @@ namespace ColorControl
|
||||
}
|
||||
Config ??= new Config();
|
||||
|
||||
Utils.UseDedicatedElevatedProcess = Config.UseDedicatedElevatedProcess;
|
||||
}
|
||||
var minLogLevel = LogLevel.FromString(Config.LogLevel);
|
||||
|
||||
public static async Task<bool> HandleStartupParams(StartUpParams startUpParams, Process existingProcess)
|
||||
{
|
||||
if (startUpParams.ActivateChromeFontFix || startUpParams.DeactivateChromeFontFix)
|
||||
if (minLogLevel != LogLevel.Trace)
|
||||
{
|
||||
Utils.InstallChromeFix(startUpParams.ActivateChromeFontFix, startUpParams.ChromeFontFixApplicationDataFolder);
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.EnableAutoStart || startUpParams.DisableAutoStart)
|
||||
{
|
||||
Utils.RegisterTask(TS_TASKNAME, startUpParams.EnableAutoStart, startUpParams.AutoStartRunLevel);
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.SetProcessAffinity)
|
||||
{
|
||||
Utils.SetProcessAffinity(startUpParams.ProcessId, startUpParams.AffinityMask);
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.SetProcessPriority)
|
||||
{
|
||||
Utils.SetProcessPriority(startUpParams.ProcessId, startUpParams.PriorityClass);
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.StartElevated)
|
||||
{
|
||||
StartElevated();
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.SendWol)
|
||||
{
|
||||
return WOL.WakeFunction(startUpParams.WolMacAddress, startUpParams.WolIpAddress);
|
||||
}
|
||||
if (startUpParams.InstallService)
|
||||
{
|
||||
Utils.InstallService();
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.UninstallService)
|
||||
{
|
||||
Utils.UninstallService();
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.StartService)
|
||||
{
|
||||
Utils.StartService();
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.StopService)
|
||||
{
|
||||
Utils.StopService();
|
||||
return true;
|
||||
}
|
||||
|
||||
var useConsole = startUpParams.NoGui || existingProcess != null;
|
||||
|
||||
if (!useConsole)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
startUpParams.NoGui = true;
|
||||
|
||||
var result = false;
|
||||
|
||||
if (startUpParams.ExecuteHelp)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine("\nColorControl CLI");
|
||||
Console.WriteLine("Syntax : ColorControl command options");
|
||||
Console.WriteLine("Commands:");
|
||||
Console.WriteLine("--nvpreset <preset name or id>: execute NVIDIA-preset");
|
||||
Console.WriteLine("--amdpreset <preset name or id>: execute AMD-preset");
|
||||
Console.WriteLine("--lgpreset <preset name> : execute LG-preset");
|
||||
Console.WriteLine("--help : displays this help info");
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine("--nogui: starts command from the command line and will not open GUI (is forced when GUI is already running)");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteLgPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing LG-preset '{startUpParams.LgPresetName}'...");
|
||||
await LgService.ExecutePresetAsync(startUpParams.LgPresetName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteNvidiaPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing NVIDIA-preset '{startUpParams.NvidiaPresetIdOrName}'...");
|
||||
await NvService.ExecutePresetAsync(startUpParams.NvidiaPresetIdOrName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (startUpParams.ExecuteAmdPreset)
|
||||
{
|
||||
Utils.OpenConsole();
|
||||
|
||||
Console.WriteLine($"Executing AMD-preset '{startUpParams.AmdPresetIdOrName}'...");
|
||||
await AmdService.ExecutePresetAsync(startUpParams.AmdPresetIdOrName);
|
||||
|
||||
Console.WriteLine("Done.");
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void StartElevated()
|
||||
{
|
||||
try
|
||||
{
|
||||
Application.Run(new ElevatedForm());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Error while initializing elevated application: " + ex.ToLogString(Environment.StackTrace), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
_loggingRule.SetLoggingLevels(minLogLevel, LogLevel.Fatal);
|
||||
LogManager.ReconfigExistingLoggers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,18 +327,44 @@ namespace ColorControl
|
||||
{
|
||||
//services.AddSingleton<NvService>();
|
||||
services.RegisterSharedServices();
|
||||
services.AddSingleton<MainWorker>();
|
||||
services.AddSingleton<NotifyIconManager>();
|
||||
services.AddSingleton<LgService>();
|
||||
services.AddSingleton<GameService>();
|
||||
services.AddSingleton<SamsungService>();
|
||||
services.AddSingleton<AmdService>();
|
||||
services.AddSingleton<PowerEventDispatcher>();
|
||||
services.AddSingleton<ProcessEventDispatcher>();
|
||||
services.AddSingleton<WindowMessageDispatcher>();
|
||||
services.AddSingleton<KeyboardShortcutDispatcher>();
|
||||
services.AddSingleton<MainForm>();
|
||||
services.AddSingleton<ServiceManager>();
|
||||
services.AddSingleton<LogWindow>();
|
||||
services.AddSingleton<BrowserWindow>();
|
||||
services.AddTransient<ColorProfileWindow>();
|
||||
services.AddSingleton<RestartDetector>();
|
||||
services.AddSingleton<InfoPanel>();
|
||||
services.AddSingleton<OptionsPanel>();
|
||||
services.AddSingleton<ElevationService>();
|
||||
services.AddSingleton<UpdateManager>();
|
||||
|
||||
services.AddSingleton<OptionsService>();
|
||||
services.AddSingleton<LoggingService>();
|
||||
|
||||
services.AddSingleton<AmdPanel>();
|
||||
services.AddSingleton<NvPanel>();
|
||||
services.AddSingleton<LgPanel>();
|
||||
services.AddSingleton<SamsungPanel>();
|
||||
services.AddSingleton<GamePanel>();
|
||||
});
|
||||
}
|
||||
private static async Task RunService(string[] args)
|
||||
{
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
Logger.Debug("RUNNING SERVICE");
|
||||
|
||||
AppContext = new GlobalContext(null, new StartUpParams(), DataDir, _loggingRule, null, startTime);
|
||||
|
||||
using IHost host = Host.CreateDefaultBuilder(args)
|
||||
.UseWindowsService(options =>
|
||||
{
|
||||
@@ -376,17 +373,38 @@ namespace ColorControl
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.RegisterSharedServices();
|
||||
services.AddSingleton<PowerEventDispatcher>();
|
||||
services.AddHostedService<ColorControlBackgroundService>();
|
||||
})
|
||||
.Build();
|
||||
|
||||
ServiceProvider = host.Services;
|
||||
AppContext.ServiceProvider = ServiceProvider;
|
||||
|
||||
await host.RunAsync();
|
||||
}
|
||||
|
||||
private static void RegisterSharedServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<AppContextProvider>();
|
||||
services.AddSingleton(AppContext);
|
||||
services.AddSingleton<SessionSwitchDispatcher>();
|
||||
services.AddSingleton<WinApiAdminService>();
|
||||
services.AddSingleton<WinApiService>();
|
||||
services.AddSingleton<WinElevatedProcessManager>();
|
||||
services.AddTransient<RpcClientService>();
|
||||
services.AddTransient<RpcServerService>();
|
||||
services.AddSingleton<NvService>();
|
||||
services.AddSingleton<WolService>();
|
||||
services.AddSingleton<ColorControlBackgroundService>();
|
||||
services.AddSingleton<ServiceManager>();
|
||||
|
||||
RpcServerService.ServiceTypes.Add(typeof(NvService));
|
||||
RpcServerService.ServiceTypes.Add(typeof(GameService));
|
||||
RpcServerService.ServiceTypes.Add(typeof(OptionsService));
|
||||
RpcServerService.ServiceTypes.Add(typeof(LoggingService));
|
||||
RpcServerService.ServiceTypes.Add(typeof(SamsungService));
|
||||
RpcServerService.ServiceTypes.Add(typeof(LgService));
|
||||
RpcServerService.ServiceTypes.Add(typeof(AmdService));
|
||||
}
|
||||
|
||||
public static int EnumThreadWindows(IntPtr handle, IntPtr param)
|
||||
@@ -401,13 +419,18 @@ namespace ColorControl
|
||||
GlobalHandleException((Exception)e.ExceptionObject, "Unhandled exception");
|
||||
}
|
||||
|
||||
private static void GlobalThreadExceptionHandler(object sender, System.Threading.ThreadExceptionEventArgs e)
|
||||
private static void GlobalThreadExceptionHandler(object sender, ThreadExceptionEventArgs e)
|
||||
{
|
||||
GlobalHandleException(e.Exception, "Exception in thread");
|
||||
}
|
||||
|
||||
private static void GlobalHandleException(Exception exception, string type)
|
||||
{
|
||||
if (UserExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var trace = exception.ToLogString(Environment.StackTrace);
|
||||
var message = $"{type}: {trace}";
|
||||
|
||||
@@ -415,5 +438,27 @@ namespace ColorControl
|
||||
|
||||
MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
internal static void SetTheme(bool useDarkMode)
|
||||
{
|
||||
DarkModeUtils.SetDarkMode(useDarkMode);
|
||||
|
||||
WinApi.RefreshImmersiveColorPolicyState();
|
||||
|
||||
DarkModeUtils.InitWpfTheme();
|
||||
|
||||
var notifyIconManager = ServiceProvider.GetRequiredService<NotifyIconManager>();
|
||||
|
||||
DarkModeUtils.SetContextMenuForeColor(notifyIconManager.NotifyIcon.ContextMenuStrip, FormUtils.CurrentForeColor);
|
||||
|
||||
_mainForm?.SetTheme(useDarkMode);
|
||||
}
|
||||
|
||||
internal static NotifyIcon GetNotifyIcon()
|
||||
{
|
||||
var notifyIconManager = ServiceProvider.GetRequiredService<NotifyIconManager>();
|
||||
|
||||
return notifyIconManager.NotifyIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-5
@@ -22,7 +22,7 @@ namespace ColorControl.Properties {
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace ColorControl.Properties {
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ColorControl.Properties.Resources", typeof(Resources).Assembly);
|
||||
@@ -51,7 +51,7 @@ namespace ColorControl.Properties {
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
@@ -60,10 +60,20 @@ namespace ColorControl.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
|
||||
/// </summary>
|
||||
public static System.Drawing.Icon AppIcon {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("AppIcon", resourceCulture);
|
||||
return ((System.Drawing.Icon)(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Drawing.Bitmap.
|
||||
/// </summary>
|
||||
internal static System.Drawing.Bitmap LG_remote {
|
||||
public static System.Drawing.Bitmap LG_remote {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("LG_remote", resourceCulture);
|
||||
return ((System.Drawing.Bitmap)(obj));
|
||||
@@ -108,7 +118,7 @@ namespace ColorControl.Properties {
|
||||
///Rakuten TV;116;1218
|
||||
///Play;202 [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string RC_coords {
|
||||
public static string RC_coords {
|
||||
get {
|
||||
return ResourceManager.GetString("RC_coords", resourceCulture);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="AppIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\pngbarn.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
<data name="LG_remote" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\Resources\LG_remote.jpg;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||
</data>
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"profiles": {
|
||||
"ColorControl": {
|
||||
"commandName": "Project"
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -1,396 +0,0 @@
|
||||
#region Copyright
|
||||
|
||||
/*******************************************************************************
|
||||
Copyright(c) 2008 - 2009 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
Copyright (c) 2002 - 2006 ATI Technologies Inc. All Rights Reserved.
|
||||
|
||||
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
||||
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDED BUT NOT LIMITED TO
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||
PARTICULAR PURPOSE.
|
||||
|
||||
File: ADL.cs
|
||||
|
||||
Purpose: Implements ADL interface
|
||||
|
||||
Description: Implements some of the methods defined in ADL interface.
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
#endregion Copyright
|
||||
|
||||
#region Using
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using ADL_CONTEXT_HANDLE = System.IntPtr;
|
||||
using FARPROC = System.IntPtr;
|
||||
using HMODULE = System.IntPtr;
|
||||
|
||||
#endregion Using
|
||||
|
||||
#region ATI.ADL
|
||||
|
||||
namespace ATI.ADL
|
||||
{
|
||||
#region Export Struct
|
||||
|
||||
#region ADLAdapterInfo
|
||||
/// <summary> ADLAdapterInfo Structure</summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ADLAdapterInfo
|
||||
{
|
||||
/// <summary>The size of the structure</summary>
|
||||
int Size;
|
||||
/// <summary> Adapter Index</summary>
|
||||
internal int AdapterIndex;
|
||||
/// <summary> Adapter UDID</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string UDID;
|
||||
/// <summary> Adapter Bus Number</summary>
|
||||
internal int BusNumber;
|
||||
/// <summary> Adapter Driver Number</summary>
|
||||
internal int DriverNumber;
|
||||
/// <summary> Adapter Function Number</summary>
|
||||
internal int FunctionNumber;
|
||||
/// <summary> Adapter Vendor ID</summary>
|
||||
internal int VendorID;
|
||||
/// <summary> Adapter Adapter name</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string AdapterName;
|
||||
/// <summary> Adapter Display name</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string DisplayName;
|
||||
/// <summary> Adapter Present status</summary>
|
||||
internal int Present;
|
||||
/// <summary> Adapter Exist status</summary>
|
||||
internal int Exist;
|
||||
/// <summary> Adapter Driver Path</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string DriverPath;
|
||||
/// <summary> Adapter Driver Ext Path</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string DriverPathExt;
|
||||
/// <summary> Adapter PNP String</summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string PNPString;
|
||||
/// <summary> OS Display Index</summary>
|
||||
internal int OSDisplayIndex;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> ADLAdapterInfo Array</summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ADLAdapterInfoArray
|
||||
{
|
||||
/// <summary> ADLAdapterInfo Array </summary>
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)ADL.ADL_MAX_ADAPTERS)]
|
||||
internal ADLAdapterInfo[] ADLAdapterInfo;
|
||||
}
|
||||
#endregion ADLAdapterInfo
|
||||
|
||||
|
||||
#region ADLDisplayInfo
|
||||
/// <summary> ADLDisplayID Structure</summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ADLDisplayID
|
||||
{
|
||||
/// <summary> Display Logical Index </summary>
|
||||
internal int DisplayLogicalIndex;
|
||||
/// <summary> Display Physical Index </summary>
|
||||
internal int DisplayPhysicalIndex;
|
||||
/// <summary> Adapter Logical Index </summary>
|
||||
internal int DisplayLogicalAdapterIndex;
|
||||
/// <summary> Adapter Physical Index </summary>
|
||||
internal int DisplayPhysicalAdapterIndex;
|
||||
}
|
||||
|
||||
/// <summary> ADLDisplayInfo Structure</summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ADLDisplayInfo
|
||||
{
|
||||
/// <summary> Display Index </summary>
|
||||
internal ADLDisplayID DisplayID;
|
||||
/// <summary> Display Controller Index </summary>
|
||||
internal int DisplayControllerIndex;
|
||||
/// <summary> Display Name </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string DisplayName;
|
||||
/// <summary> Display Manufacturer Name </summary>
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)]
|
||||
internal string DisplayManufacturerName;
|
||||
/// <summary> Display Type : < The Display type. CRT, TV,CV,DFP are some of display types,</summary>
|
||||
internal int DisplayType;
|
||||
/// <summary> Display output type </summary>
|
||||
internal int DisplayOutputType;
|
||||
/// <summary> Connector type</summary>
|
||||
internal int DisplayConnector;
|
||||
///<summary> Indicating the display info bits' mask.<summary>
|
||||
internal int DisplayInfoMask;
|
||||
///<summary> Indicating the display info value.<summary>
|
||||
internal int DisplayInfoValue;
|
||||
}
|
||||
#endregion ADLDisplayInfo
|
||||
|
||||
#endregion Export Struct
|
||||
|
||||
#region ADL Class
|
||||
/// <summary> ADL Class</summary>
|
||||
internal static class ADL
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
#region Internal Constant
|
||||
/// <summary> Define the maximum path</summary>
|
||||
internal const int ADL_MAX_PATH = 256;
|
||||
/// <summary> Define the maximum adapters</summary>
|
||||
internal const int ADL_MAX_ADAPTERS = 40 /* 150 */;
|
||||
/// <summary> Define the maximum displays</summary>
|
||||
internal const int ADL_MAX_DISPLAYS = 40 /* 150 */;
|
||||
/// <summary> Define the maximum device name length</summary>
|
||||
internal const int ADL_MAX_DEVICENAME = 32;
|
||||
/// <summary> Define the successful</summary>
|
||||
internal const int ADL_SUCCESS = 0;
|
||||
/// <summary> Define the failure</summary>
|
||||
internal const int ADL_FAIL = -1;
|
||||
/// <summary> Define the driver ok</summary>
|
||||
internal const int ADL_DRIVER_OK = 0;
|
||||
/// <summary> Maximum number of GL-Sync ports on the GL-Sync module </summary>
|
||||
internal const int ADL_MAX_GLSYNC_PORTS = 8;
|
||||
/// <summary> Maximum number of GL-Sync ports on the GL-Sync module </summary>
|
||||
internal const int ADL_MAX_GLSYNC_PORT_LEDS = 8;
|
||||
/// <summary> Maximum number of ADLMOdes for the adapter </summary>
|
||||
internal const int ADL_MAX_NUM_DISPLAYMODES = 1024;
|
||||
|
||||
internal static Dictionary<Type, object> ADLDelegates = new Dictionary<Type, object>();
|
||||
|
||||
#endregion Internal Constant
|
||||
|
||||
#region Export Delegates
|
||||
/// <summary> ADL Memory allocation function allows ADL to callback for memory allocation</summary>
|
||||
/// <param name="size">input size</param>
|
||||
/// <returns> retrun ADL Error Code</returns>
|
||||
internal delegate IntPtr ADL_Main_Memory_Alloc(int size);
|
||||
|
||||
// ///// <summary> ADL Create Function to create ADL Data</summary>
|
||||
/// <param name="callback">Call back functin pointer which is ised to allocate memeory </param>
|
||||
/// <param name="enumConnectedAdapters">If it is 1, then ADL will only retuen the physical exist adapters </param>
|
||||
///// <returns> retrun ADL Error Code</returns>
|
||||
internal delegate int ADL_Main_Control_Create(ADL_Main_Memory_Alloc callback, int enumConnectedAdapters);
|
||||
|
||||
internal delegate int ADL2_Main_Control_Create(ADL_Main_Memory_Alloc callback, int enumConnectedAdapters, ref ADL_CONTEXT_HANDLE context);
|
||||
|
||||
/// <summary> ADL Destroy Function to free up ADL Data</summary>
|
||||
/// <returns> retrun ADL Error Code</returns>
|
||||
internal delegate int ADL_Main_Control_Destroy();
|
||||
|
||||
internal delegate int ADL2_Main_Control_Destroy(ADL_CONTEXT_HANDLE context);
|
||||
|
||||
/// <summary> ADL Function to get the number of adapters</summary>
|
||||
/// <param name="numAdapters">return number of adapters</param>
|
||||
/// <returns> retrun ADL Error Code</returns>
|
||||
internal delegate int ADL2_Adapter_NumberOfAdapters_Get(ADL_CONTEXT_HANDLE context, ref int numAdapters);
|
||||
|
||||
/// <summary> ADL Function to get the GPU adapter information</summary>
|
||||
/// <param name="info">return GPU adapter information</param>
|
||||
/// <param name="inputSize">the size of the GPU adapter struct</param>
|
||||
/// <returns> retrun ADL Error Code</returns>
|
||||
internal delegate int ADL2_Adapter_AdapterInfo_Get(ADL_CONTEXT_HANDLE context, IntPtr info, int inputSize);
|
||||
|
||||
/// <summary> Function to determine if the adapter is active or not.</summary>
|
||||
/// <remarks>The function is used to check if the adapter associated with iAdapterIndex is active</remarks>
|
||||
/// <param name="adapterIndex"> Adapter Index.</param>
|
||||
/// <param name="status"> Status of the adapter. True: Active; False: Dsiabled</param>
|
||||
/// <returns>Non zero is successfull</returns>
|
||||
internal delegate int ADL2_Adapter_Active_Get(ADL_CONTEXT_HANDLE context, int adapterIndex, ref int status);
|
||||
|
||||
/// <summary>Get display information based on adapter index</summary>
|
||||
/// <param name="adapterIndex">Adapter Index</param>
|
||||
/// <param name="numDisplays">return the total number of supported displays</param>
|
||||
/// <param name="displayInfoArray">return ADLDisplayInfo Array for supported displays' information</param>
|
||||
/// <param name="forceDetect">force detect or not</param>
|
||||
/// <returns>return ADL Error Code</returns>
|
||||
internal delegate int ADL2_Display_DisplayInfo_Get(ADL_CONTEXT_HANDLE context, int adapterIndex, ref int numDisplays, out IntPtr displayInfoArray, int forceDetect);
|
||||
|
||||
internal delegate int ADL2_Display_Size_Get(ADL_CONTEXT_HANDLE context, int adapterIndex, int displayIndex, ref int lpWidth, ref int lpHeight, ref int lpDefaultWidth, ref int lpDefaultHeight, ref int lpMinWidth, ref int lpMinHeight, ref int lpMaxWidth, ref int lpMaxHeight, ref int lpStepWidth, ref int lpStepHeight);
|
||||
|
||||
internal delegate int ADL2_Display_PixelFormat_Get(ADL_CONTEXT_HANDLE context, int adapterIndex, int displayIndex, ref int pixelFormat);
|
||||
internal delegate int ADL2_Display_PixelFormat_Set(ADL_CONTEXT_HANDLE context, int adapterIndex, int displayIndex, int pixelFormat);
|
||||
|
||||
internal delegate int ADL2_Display_ColorDepth_Get(ADL_CONTEXT_HANDLE context, int adapterIndex, int displayIndex, ref int colorDepth);
|
||||
internal delegate int ADL2_Display_ColorDepth_Set(ADL_CONTEXT_HANDLE context, int adapterIndex, int displayIndex, int colorDepth);
|
||||
|
||||
internal delegate int ADL2_Display_DitherState_Get(ADL_CONTEXT_HANDLE context, int adapterIndex, int displayIndex, ref int ditherState);
|
||||
internal delegate int ADL2_Display_DitherState_Set(ADL_CONTEXT_HANDLE context, int adapterIndex, int displayIndex, int ditherState);
|
||||
|
||||
internal delegate int ADL2_Display_HDRState_Get(ADL_CONTEXT_HANDLE context, int adapterIndex, ADLDisplayID displayID, ref int support, ref int enable);
|
||||
internal delegate int ADL2_Display_HDRState_Set(ADL_CONTEXT_HANDLE context, int adapterIndex, ADLDisplayID displayID, int enable);
|
||||
|
||||
#endregion Export Delegates
|
||||
|
||||
#region Class ADLImport
|
||||
/// <summary> ADLImport class</summary>
|
||||
private static class ADLImport
|
||||
{
|
||||
#region Internal Constant
|
||||
/// <summary> Atiadlxx_FileName </summary>
|
||||
internal const string Atiadlxx_FileName = "atiadlxx.dll";
|
||||
/// <summary> Kernel32_FileName </summary>
|
||||
internal const string Kernel32_FileName = "kernel32.dll";
|
||||
#endregion Internal Constant
|
||||
|
||||
#region DLLImport
|
||||
[DllImport(Kernel32_FileName)]
|
||||
internal static extern HMODULE GetModuleHandle(string moduleName);
|
||||
|
||||
[DllImport(Atiadlxx_FileName)]
|
||||
internal static extern int ADL_Main_Control_IsFunctionValid(HMODULE module, string procName);
|
||||
|
||||
[DllImport(Atiadlxx_FileName)]
|
||||
internal static extern FARPROC ADL_Main_Control_GetProcAddress(HMODULE module, string procName);
|
||||
|
||||
#endregion DLLImport
|
||||
}
|
||||
#endregion Class ADLImport
|
||||
|
||||
#region Class ADLCheckLibrary
|
||||
/// <summary> ADLCheckLibrary class</summary>
|
||||
private class ADLCheckLibrary
|
||||
{
|
||||
#region Private Members
|
||||
private HMODULE ADLLibrary = System.IntPtr.Zero;
|
||||
#endregion Private Members
|
||||
|
||||
#region Static Members
|
||||
/// <summary> new a private instance</summary>
|
||||
private static ADLCheckLibrary ADLCheckLibrary_ = new ADLCheckLibrary();
|
||||
#endregion Static Members
|
||||
|
||||
#region Constructor
|
||||
/// <summary> Constructor</summary>
|
||||
private ADLCheckLibrary()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (1 == ADLImport.ADL_Main_Control_IsFunctionValid(IntPtr.Zero, "ADL_Main_Control_Create"))
|
||||
{
|
||||
ADLLibrary = ADLImport.GetModuleHandle(ADLImport.Atiadlxx_FileName);
|
||||
}
|
||||
}
|
||||
catch (DllNotFoundException) { }
|
||||
catch (EntryPointNotFoundException) { }
|
||||
catch (Exception) { }
|
||||
}
|
||||
#endregion Constructor
|
||||
|
||||
#region Destructor
|
||||
/// <summary> Destructor to force calling ADL Destroy function before free up the ADL library</summary>
|
||||
~ADLCheckLibrary()
|
||||
{
|
||||
if (IntPtr.Zero != ADLCheckLibrary_.ADLLibrary)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL_Main_Control_Destroy>();
|
||||
if (del != null)
|
||||
{
|
||||
del();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion Destructor
|
||||
|
||||
#region Static IsFunctionValid
|
||||
/// <summary> Check the import function to see it exists or not</summary>
|
||||
/// <param name="functionName"> function name</param>
|
||||
/// <returns>return true, if function exists</returns>
|
||||
internal static bool IsFunctionValid(string functionName)
|
||||
{
|
||||
var result = false;
|
||||
if (IntPtr.Zero != ADLCheckLibrary_.ADLLibrary)
|
||||
{
|
||||
if (1 == ADLImport.ADL_Main_Control_IsFunctionValid(ADLCheckLibrary_.ADLLibrary, functionName))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion Static IsFunctionValid
|
||||
|
||||
#region Static GetProcAddress
|
||||
/// <summary> Get the unmanaged function pointer </summary>
|
||||
/// <param name="functionName"> function name</param>
|
||||
/// <returns>return function pointer, if function exists</returns>
|
||||
internal static FARPROC GetProcAddress(string functionName)
|
||||
{
|
||||
var result = IntPtr.Zero;
|
||||
if (IntPtr.Zero != ADLCheckLibrary_.ADLLibrary)
|
||||
{
|
||||
result = ADLImport.ADL_Main_Control_GetProcAddress(ADLCheckLibrary_.ADLLibrary, functionName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion Static GetProcAddress
|
||||
}
|
||||
#endregion Class ADLCheckLibrary
|
||||
|
||||
#region Export Functions
|
||||
|
||||
#region ADL_Main_Memory_Alloc
|
||||
/// <summary> Build in memory allocation function</summary>
|
||||
internal static ADL_Main_Memory_Alloc ADL_Main_Memory_Alloc_Func = ADL_Main_Memory_Alloc_;
|
||||
/// <summary> Build in memory allocation function</summary>
|
||||
/// <param name="size">input size</param>
|
||||
/// <returns>return the memory buffer</returns>
|
||||
private static IntPtr ADL_Main_Memory_Alloc_(int size)
|
||||
{
|
||||
IntPtr result = Marshal.AllocCoTaskMem(size);
|
||||
return result;
|
||||
}
|
||||
#endregion ADL_Main_Memory_Alloc
|
||||
|
||||
#region ADL_Main_Memory_Free
|
||||
/// <summary> Build in memory free function</summary>
|
||||
/// <param name="buffer">input buffer</param>
|
||||
internal static void ADL_Main_Memory_Free(IntPtr buffer)
|
||||
{
|
||||
if (IntPtr.Zero != buffer)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(buffer);
|
||||
}
|
||||
}
|
||||
#endregion ADL_Main_Memory_Free
|
||||
|
||||
public static T GetDelegate<T>() where T : class
|
||||
{
|
||||
var type = typeof(T);
|
||||
|
||||
lock (ADLDelegates)
|
||||
{
|
||||
if (ADLDelegates.ContainsKey(type))
|
||||
{
|
||||
return ADLDelegates[type] as T;
|
||||
}
|
||||
|
||||
var ptr = ADLCheckLibrary.GetProcAddress(type.Name);
|
||||
if (ptr != FARPROC.Zero)
|
||||
{
|
||||
var delegateValue = Marshal.GetDelegateForFunctionPointer(ptr, type);
|
||||
ADLDelegates.Add(type, delegateValue);
|
||||
|
||||
return delegateValue as T;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Error($"ADL-function not supported: {type.Name}");
|
||||
|
||||
return null;
|
||||
//throw new InvalidProgramException("ADL-function not supported");
|
||||
}
|
||||
|
||||
#endregion Export Functions
|
||||
}
|
||||
#endregion ADL Class
|
||||
}
|
||||
|
||||
#endregion ATI.ADL
|
||||
@@ -1,402 +0,0 @@
|
||||
using ATI.ADL;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using ADL_CONTEXT_HANDLE = System.IntPtr;
|
||||
|
||||
namespace ColorControl.Services.AMD
|
||||
{
|
||||
enum ADLPixelFormat
|
||||
{
|
||||
[Description("Unknown/unsupported")]
|
||||
UNKNOWN = 0,
|
||||
RGB_FULL_RANGE = 1,
|
||||
YCRCB444 = 2,
|
||||
YCRCB422 = 3,
|
||||
RGB_LIMITED_RANGE = 4,
|
||||
YCRCB420 = 8
|
||||
}
|
||||
|
||||
enum ADLColorDepth
|
||||
{
|
||||
[Description("Unknown/unsupported")]
|
||||
UNKNOWN = 0,
|
||||
BPC6 = 1,
|
||||
BPC8 = 2,
|
||||
BPC10 = 3,
|
||||
BPC12 = 4,
|
||||
BPC14 = 5,
|
||||
BPC16 = 6
|
||||
}
|
||||
|
||||
enum ADLDitherState
|
||||
{
|
||||
DISABLED = 0,
|
||||
DRIVER_DEFAULT = 1,
|
||||
FM6 = 2,
|
||||
FM8 = 3,
|
||||
FM10 = 4,
|
||||
DITH6 = 5,
|
||||
DITH8 = 6,
|
||||
DITH10 = 7,
|
||||
DITH6_NO_FRAME_RAND = 8,
|
||||
DITH8_NO_FRAME_RAND = 9,
|
||||
DITH10_NO_FRAME_RAND = 10,
|
||||
TRUN6 = 11,
|
||||
TRUN8 = 12,
|
||||
TRUN10 = 13,
|
||||
TRUN8_DITH8 = 14,
|
||||
TRUN10_DITH6 = 15,
|
||||
TRUN10_FM8 = 16,
|
||||
TRUN10_FM6 = 17,
|
||||
TRUN10_DITH8_FM6 = 18,
|
||||
DITH10_FM8 = 19,
|
||||
DITH10_FM6 = 20,
|
||||
TRUN8_DITH6 = 21,
|
||||
TRUN8_FM6 = 22,
|
||||
DITH8_FM6 = 23
|
||||
}
|
||||
|
||||
class ADLWrapper
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
private static ADL_CONTEXT_HANDLE context = IntPtr.Zero;
|
||||
|
||||
public static bool Initialize()
|
||||
{
|
||||
int ADLRet = -1;
|
||||
|
||||
//Logger.Debug("Initialize");
|
||||
|
||||
var del = ADL.GetDelegate<ADL.ADL_Main_Control_Create>();
|
||||
|
||||
if (del != null)
|
||||
{
|
||||
// Second parameter is 1: Get only the present adapters
|
||||
ADLRet = del(ADL.ADL_Main_Memory_Alloc_Func, 1);
|
||||
CheckError(ADLRet, nameof(ADL.ADL_Main_Control_Create));
|
||||
}
|
||||
|
||||
var del2 = ADL.GetDelegate<ADL.ADL2_Main_Control_Create>();
|
||||
|
||||
if (del2 != null)
|
||||
{
|
||||
// Second parameter is 1: Get only the present adapters
|
||||
ADLRet = del2(ADL.ADL_Main_Memory_Alloc_Func, 1, ref context);
|
||||
CheckError(ADLRet, nameof(ADL.ADL2_Main_Control_Create));
|
||||
}
|
||||
|
||||
return (ADL.ADL_SUCCESS == ADLRet);
|
||||
}
|
||||
|
||||
public static void Uninitialze()
|
||||
{
|
||||
if (!ADL.ADLDelegates.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var del = ADL.GetDelegate<ADL.ADL_Main_Control_Destroy>();
|
||||
|
||||
if (null != del)
|
||||
{
|
||||
del();
|
||||
}
|
||||
|
||||
var del2 = ADL.GetDelegate<ADL.ADL2_Main_Control_Destroy>();
|
||||
|
||||
if (null != del2 && context != IntPtr.Zero)
|
||||
{
|
||||
del2(context);
|
||||
}
|
||||
}
|
||||
|
||||
public static ADLAdapterInfoArray? GetAdapters()
|
||||
{
|
||||
int ADLRet = -1;
|
||||
int NumberOfAdapters = 0;
|
||||
|
||||
var delNumberOfAdapters = ADL.GetDelegate<ADL.ADL2_Adapter_NumberOfAdapters_Get>();
|
||||
|
||||
if (null != delNumberOfAdapters)
|
||||
{
|
||||
delNumberOfAdapters(context, ref NumberOfAdapters);
|
||||
}
|
||||
Logger.Debug("Number Of Adapters: " + NumberOfAdapters.ToString() + "\n");
|
||||
|
||||
if (NumberOfAdapters > 0)
|
||||
{
|
||||
// Get OS adpater info from ADL
|
||||
ADLAdapterInfoArray OSAdapterInfoData;
|
||||
OSAdapterInfoData = new ADLAdapterInfoArray();
|
||||
|
||||
var delAdapterInfo = ADL.GetDelegate<ADL.ADL2_Adapter_AdapterInfo_Get>();
|
||||
|
||||
if (null != delAdapterInfo)
|
||||
{
|
||||
IntPtr AdapterBuffer = IntPtr.Zero;
|
||||
int size = Marshal.SizeOf(OSAdapterInfoData);
|
||||
AdapterBuffer = Marshal.AllocCoTaskMem((int)size);
|
||||
Marshal.StructureToPtr(OSAdapterInfoData, AdapterBuffer, false);
|
||||
|
||||
ADLRet = delAdapterInfo(context, AdapterBuffer, size);
|
||||
if (ADL.ADL_SUCCESS == ADLRet)
|
||||
{
|
||||
OSAdapterInfoData = (ADLAdapterInfoArray)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType());
|
||||
int IsActive = 0;
|
||||
|
||||
var delActive = ADL.GetDelegate<ADL.ADL2_Adapter_Active_Get>();
|
||||
|
||||
for (int i = 0; i < NumberOfAdapters; i++)
|
||||
{
|
||||
// Check if the adapter is active
|
||||
if (null != delActive)
|
||||
ADLRet = delActive(context, OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref IsActive);
|
||||
|
||||
if (ADL.ADL_SUCCESS == ADLRet)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Debug("ADL_Adapter_AdapterInfo_Get() returned error code " + ADLRet.ToString());
|
||||
}
|
||||
// Release the memory for the AdapterInfo structure
|
||||
if (IntPtr.Zero != AdapterBuffer)
|
||||
{
|
||||
Marshal.FreeCoTaskMem(AdapterBuffer);
|
||||
}
|
||||
}
|
||||
return OSAdapterInfoData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<ADLDisplayInfo> GetAllDisplays(bool connected = true)
|
||||
{
|
||||
int ADLRet;
|
||||
int NumberOfDisplays = 0;
|
||||
|
||||
var DisplayInfoData = new List<ADLDisplayInfo>();
|
||||
|
||||
var OSAdapterInfoData = GetAdapters();
|
||||
if (OSAdapterInfoData == null || !OSAdapterInfoData.Value.ADLAdapterInfo.Any())
|
||||
{
|
||||
return DisplayInfoData;
|
||||
}
|
||||
var primaryAdapter = OSAdapterInfoData.Value.ADLAdapterInfo.First();
|
||||
|
||||
ADLDisplayInfo oneDisplayInfo = new ADLDisplayInfo();
|
||||
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_DisplayInfo_Get>();
|
||||
|
||||
if (null != del)
|
||||
{
|
||||
IntPtr DisplayBuffer = IntPtr.Zero;
|
||||
int j = 0;
|
||||
|
||||
// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection
|
||||
ADLRet = del(context, primaryAdapter.AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 1);
|
||||
if (ADL.ADL_SUCCESS == ADLRet)
|
||||
{
|
||||
for (j = 0; j < NumberOfDisplays; j++)
|
||||
{
|
||||
oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(DisplayBuffer.ToInt64() + j * Marshal.SizeOf(oneDisplayInfo)), oneDisplayInfo.GetType());
|
||||
if (!connected || (1 == (oneDisplayInfo.DisplayInfoValue & 1)))
|
||||
{
|
||||
DisplayInfoData.Add(oneDisplayInfo);
|
||||
}
|
||||
}
|
||||
Logger.Debug("Total Number of Displays supported: " + NumberOfDisplays.ToString());
|
||||
Logger.Debug("DispID DispPhyId AdpID Type OutType CnctType Connected Mapped InfoValue DisplayName ");
|
||||
|
||||
for (j = 0; j < DisplayInfoData.Count; j++)
|
||||
{
|
||||
int InfoValue = DisplayInfoData[j].DisplayInfoValue;
|
||||
string StrConnected = (1 == (InfoValue & 1)) ? "Yes" : "No ";
|
||||
string StrMapped = (2 == (InfoValue & 2)) ? "Yes" : "No ";
|
||||
int AdpID = DisplayInfoData[j].DisplayID.DisplayLogicalAdapterIndex;
|
||||
string StrAdpID = (AdpID < 0) ? "--" : AdpID.ToString("d2");
|
||||
|
||||
Logger.Debug(DisplayInfoData[j].DisplayID.DisplayLogicalIndex.ToString() + " " +
|
||||
DisplayInfoData[j].DisplayID.DisplayPhysicalIndex.ToString() + " " +
|
||||
StrAdpID + " " +
|
||||
DisplayInfoData[j].DisplayType.ToString() + " " +
|
||||
DisplayInfoData[j].DisplayOutputType.ToString() + " " +
|
||||
DisplayInfoData[j].DisplayConnector.ToString() + " " +
|
||||
StrConnected + " " +
|
||||
StrMapped + " " +
|
||||
InfoValue.ToString("x4") + " " +
|
||||
DisplayInfoData[j].DisplayName.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Debug("ADL_Display_DisplayInfo_Get() returned error code " + ADLRet.ToString());
|
||||
}
|
||||
// Release the memory for the DisplayInfo structure
|
||||
if (IntPtr.Zero != DisplayBuffer)
|
||||
Marshal.FreeCoTaskMem(DisplayBuffer);
|
||||
}
|
||||
return DisplayInfoData;
|
||||
}
|
||||
|
||||
private static bool CheckError(int ADLRet, string functionName)
|
||||
{
|
||||
var result = ADLRet == ADL.ADL_SUCCESS;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Logger.Error($"Error calling ADL ({functionName}): {ADLRet}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static bool GetDisplayResolution(ADLDisplayInfo display, ref int horizontal, ref int vertical)
|
||||
{
|
||||
var screen = Screen.PrimaryScreen;
|
||||
var bounds = screen.Bounds;
|
||||
|
||||
horizontal = bounds.Width;
|
||||
vertical = bounds.Height;
|
||||
|
||||
Logger.Debug($"GetDisplayResolution: {horizontal}x{vertical}");
|
||||
|
||||
//var del = ADL.GetDelegate<ADL.ADL2_Display_Size_Get>();
|
||||
|
||||
//if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
//{
|
||||
// int lpDefaultWidth, lpDefaultHeight, lpMinWidth, lpMinHeight, lpMaxWidth, lpMaxHeight, lpStepWidth, lpStepHeight;
|
||||
// lpDefaultWidth = lpDefaultHeight = lpMinWidth = lpMinHeight = lpMaxWidth = lpMaxHeight = lpStepWidth = lpStepHeight = 0;
|
||||
// var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref horizontal, ref vertical, ref lpDefaultWidth, ref lpDefaultHeight, ref lpMinWidth, ref lpMinHeight, ref lpMaxWidth, ref lpMaxHeight, ref lpStepWidth, ref lpStepHeight);
|
||||
|
||||
// return CheckError(ADLRet, nameof(ADL.ADL2_Display_Size_Get));
|
||||
//}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetDisplayPixelFormat(ADLDisplayInfo display, ref ADLPixelFormat pixelFormat)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_PixelFormat_Get>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
int pixelFormatInt = 0;
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref pixelFormatInt);
|
||||
|
||||
pixelFormat = (ADLPixelFormat)pixelFormatInt;
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_PixelFormat_Get));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool SetDisplayPixelFormat(ADLDisplayInfo display, ADLPixelFormat pixelFormat)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_PixelFormat_Set>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, (int)pixelFormat);
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_PixelFormat_Set));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool GetDisplayColorDepth(ADLDisplayInfo display, ref ADLColorDepth colorDepth)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_ColorDepth_Get>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
int colorDepthInt = 0;
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref colorDepthInt);
|
||||
|
||||
colorDepth = (ADLColorDepth)colorDepthInt;
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_ColorDepth_Get));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool SetDisplayColorDepth(ADLDisplayInfo display, ADLColorDepth colorDepth)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_ColorDepth_Set>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, (int)colorDepth);
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_ColorDepth_Set));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool GetDisplayDitherState(ADLDisplayInfo display, ref ADLDitherState ditherState)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_DitherState_Get>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
var ditherStateInt = 0;
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, ref ditherStateInt);
|
||||
|
||||
ditherState = (ADLDitherState)ditherStateInt;
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_DitherState_Get));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool SetDisplayDitherState(ADLDisplayInfo display, ADLDitherState ditherState)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_DitherState_Set>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID.DisplayLogicalIndex, (int)ditherState);
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_DitherState_Set));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool GetDisplayHDRState(ADLDisplayInfo display, ref bool supported, ref bool enabled)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_HDRState_Get>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
var supportedInt = 0;
|
||||
var enabledInt = 0;
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID, ref supportedInt, ref enabledInt);
|
||||
|
||||
supported = supportedInt != 0;
|
||||
enabled = enabledInt != 0;
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_HDRState_Get));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool SetDisplayHDRState(ADLDisplayInfo display, bool enabled)
|
||||
{
|
||||
var del = ADL.GetDelegate<ADL.ADL2_Display_HDRState_Set>();
|
||||
|
||||
if (display.DisplayID.DisplayPhysicalIndex >= 0 && del != null)
|
||||
{
|
||||
var ADLRet = del(context, display.DisplayID.DisplayLogicalAdapterIndex, display.DisplayID, enabled ? 1 : 0);
|
||||
|
||||
return CheckError(ADLRet, nameof(ADL.ADL2_Display_HDRState_Set));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,20 @@
|
||||
using ATI.ADL;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ColorControl.Services.AMD
|
||||
namespace ColorControl.Services.AMD;
|
||||
|
||||
class AmdDisplayInfo
|
||||
{
|
||||
class AmdDisplayInfo
|
||||
public ADLDisplayInfo Display { get; }
|
||||
|
||||
public List<string> Values { get; set; }
|
||||
|
||||
public string InfoLine { get; set; }
|
||||
|
||||
public AmdDisplayInfo(ADLDisplayInfo display, List<string> values, string infoLine)
|
||||
{
|
||||
public ADLDisplayInfo Display { get; }
|
||||
|
||||
public List<string> Values { get; }
|
||||
|
||||
public string InfoLine { get; }
|
||||
|
||||
public AmdDisplayInfo(ADLDisplayInfo display, List<string> values, string infoLine)
|
||||
{
|
||||
Display = display;
|
||||
Values = values;
|
||||
InfoLine = infoLine;
|
||||
}
|
||||
Display = display;
|
||||
Values = values;
|
||||
InfoLine = infoLine;
|
||||
}
|
||||
}
|
||||
+297
-283
@@ -28,384 +28,395 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.btnAmdSettings = new System.Windows.Forms.Button();
|
||||
this.chkAmdQuickAccess = new System.Windows.Forms.CheckBox();
|
||||
this.lblAmdPresetName = new System.Windows.Forms.Label();
|
||||
this.edtAmdPresetName = new System.Windows.Forms.TextBox();
|
||||
this.btnAddAmd = new System.Windows.Forms.Button();
|
||||
this.lblErrorAMD = new System.Windows.Forms.Label();
|
||||
this.btnDeleteAmd = new System.Windows.Forms.Button();
|
||||
this.btnCloneAmd = new System.Windows.Forms.Button();
|
||||
this.btnAmdPresetSave = new System.Windows.Forms.Button();
|
||||
this.lblAmdShortcut = new System.Windows.Forms.Label();
|
||||
this.edtAmdShortcut = new System.Windows.Forms.TextBox();
|
||||
this.btnChangeAmd = new System.Windows.Forms.Button();
|
||||
this.mnuAmdPresets = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.miAmdApply = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdPresetApplyOnStartup = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.mnuAmdDisplay = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdPrimaryDisplay = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAmdColorSettings = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdColorSettingsIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAmdRefreshRate = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdRefreshRateIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAmdDithering = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdDitheringIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuAmdHDR = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdHDRIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdHDRToggle = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdHDREnabled = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.miAmdCopyId = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.btnApplyAmd = new System.Windows.Forms.Button();
|
||||
this.lvAmdPresets = new System.Windows.Forms.ListView();
|
||||
this.mnuAmdPresets.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
components = new System.ComponentModel.Container();
|
||||
btnAmdSettings = new System.Windows.Forms.Button();
|
||||
chkAmdQuickAccess = new System.Windows.Forms.CheckBox();
|
||||
lblAmdPresetName = new System.Windows.Forms.Label();
|
||||
edtAmdPresetName = new System.Windows.Forms.TextBox();
|
||||
btnAddAmd = new System.Windows.Forms.Button();
|
||||
lblErrorAMD = new System.Windows.Forms.Label();
|
||||
btnDeleteAmd = new System.Windows.Forms.Button();
|
||||
btnCloneAmd = new System.Windows.Forms.Button();
|
||||
btnAmdPresetSave = new System.Windows.Forms.Button();
|
||||
lblAmdShortcut = new System.Windows.Forms.Label();
|
||||
edtAmdShortcut = new System.Windows.Forms.TextBox();
|
||||
btnChangeAmd = new System.Windows.Forms.Button();
|
||||
mnuAmdPresets = new System.Windows.Forms.ContextMenuStrip(components);
|
||||
miAmdApply = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdPresetApplyOnStartup = new System.Windows.Forms.ToolStripMenuItem();
|
||||
toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
mnuAmdDisplay = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdPrimaryDisplay = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuAmdColorSettings = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdColorSettingsIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuAmdRefreshRate = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdRefreshRateIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuAmdResolution = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdResolutionIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuAmdDithering = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdDitheringIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuAmdHDR = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdHDRIncluded = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdHDRToggle = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdHDREnabled = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdCopyId = new System.Windows.Forms.ToolStripMenuItem();
|
||||
btnApplyAmd = new System.Windows.Forms.Button();
|
||||
lvAmdPresets = new System.Windows.Forms.ListView();
|
||||
miAmdActiveResolution = new System.Windows.Forms.ToolStripMenuItem();
|
||||
miAmdVirtualResolution = new System.Windows.Forms.ToolStripMenuItem();
|
||||
mnuAmdPresets.SuspendLayout();
|
||||
SuspendLayout();
|
||||
//
|
||||
// btnAmdSettings
|
||||
//
|
||||
this.btnAmdSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnAmdSettings.Location = new System.Drawing.Point(1017, 429);
|
||||
this.btnAmdSettings.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.btnAmdSettings.Name = "btnAmdSettings";
|
||||
this.btnAmdSettings.Size = new System.Drawing.Size(88, 27);
|
||||
this.btnAmdSettings.TabIndex = 60;
|
||||
this.btnAmdSettings.Text = "Settings...";
|
||||
this.btnAmdSettings.UseVisualStyleBackColor = true;
|
||||
this.btnAmdSettings.Click += new System.EventHandler(this.btnAmdSettings_Click);
|
||||
btnAmdSettings.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right;
|
||||
btnAmdSettings.Location = new System.Drawing.Point(1017, 429);
|
||||
btnAmdSettings.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnAmdSettings.Name = "btnAmdSettings";
|
||||
btnAmdSettings.Size = new System.Drawing.Size(88, 27);
|
||||
btnAmdSettings.TabIndex = 60;
|
||||
btnAmdSettings.Text = "Settings...";
|
||||
btnAmdSettings.UseVisualStyleBackColor = true;
|
||||
btnAmdSettings.Click += btnAmdSettings_Click;
|
||||
//
|
||||
// chkAmdQuickAccess
|
||||
//
|
||||
this.chkAmdQuickAccess.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.chkAmdQuickAccess.AutoSize = true;
|
||||
this.chkAmdQuickAccess.Enabled = false;
|
||||
this.chkAmdQuickAccess.Location = new System.Drawing.Point(343, 465);
|
||||
this.chkAmdQuickAccess.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.chkAmdQuickAccess.Name = "chkAmdQuickAccess";
|
||||
this.chkAmdQuickAccess.Size = new System.Drawing.Size(141, 19);
|
||||
this.chkAmdQuickAccess.TabIndex = 46;
|
||||
this.chkAmdQuickAccess.Text = "Show in Quick Access";
|
||||
this.chkAmdQuickAccess.UseVisualStyleBackColor = true;
|
||||
chkAmdQuickAccess.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
chkAmdQuickAccess.AutoSize = true;
|
||||
chkAmdQuickAccess.Enabled = false;
|
||||
chkAmdQuickAccess.Location = new System.Drawing.Point(343, 465);
|
||||
chkAmdQuickAccess.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
chkAmdQuickAccess.Name = "chkAmdQuickAccess";
|
||||
chkAmdQuickAccess.Size = new System.Drawing.Size(141, 19);
|
||||
chkAmdQuickAccess.TabIndex = 46;
|
||||
chkAmdQuickAccess.Text = "Show in Quick Access";
|
||||
chkAmdQuickAccess.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblAmdPresetName
|
||||
//
|
||||
this.lblAmdPresetName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.lblAmdPresetName.AutoSize = true;
|
||||
this.lblAmdPresetName.Location = new System.Drawing.Point(7, 466);
|
||||
this.lblAmdPresetName.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblAmdPresetName.Name = "lblAmdPresetName";
|
||||
this.lblAmdPresetName.Size = new System.Drawing.Size(42, 15);
|
||||
this.lblAmdPresetName.TabIndex = 24;
|
||||
this.lblAmdPresetName.Text = "Name:";
|
||||
lblAmdPresetName.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblAmdPresetName.AutoSize = true;
|
||||
lblAmdPresetName.Location = new System.Drawing.Point(7, 466);
|
||||
lblAmdPresetName.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblAmdPresetName.Name = "lblAmdPresetName";
|
||||
lblAmdPresetName.Size = new System.Drawing.Size(42, 15);
|
||||
lblAmdPresetName.TabIndex = 24;
|
||||
lblAmdPresetName.Text = "Name:";
|
||||
//
|
||||
// edtAmdPresetName
|
||||
//
|
||||
this.edtAmdPresetName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.edtAmdPresetName.Enabled = false;
|
||||
this.edtAmdPresetName.Location = new System.Drawing.Point(102, 463);
|
||||
this.edtAmdPresetName.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.edtAmdPresetName.Name = "edtAmdPresetName";
|
||||
this.edtAmdPresetName.Size = new System.Drawing.Size(233, 23);
|
||||
this.edtAmdPresetName.TabIndex = 23;
|
||||
edtAmdPresetName.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
edtAmdPresetName.Enabled = false;
|
||||
edtAmdPresetName.Location = new System.Drawing.Point(102, 463);
|
||||
edtAmdPresetName.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtAmdPresetName.Name = "edtAmdPresetName";
|
||||
edtAmdPresetName.Size = new System.Drawing.Size(233, 23);
|
||||
edtAmdPresetName.TabIndex = 23;
|
||||
//
|
||||
// btnAddAmd
|
||||
//
|
||||
this.btnAddAmd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnAddAmd.Location = new System.Drawing.Point(385, 429);
|
||||
this.btnAddAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.btnAddAmd.Name = "btnAddAmd";
|
||||
this.btnAddAmd.Size = new System.Drawing.Size(88, 27);
|
||||
this.btnAddAmd.TabIndex = 18;
|
||||
this.btnAddAmd.Text = "Add";
|
||||
this.btnAddAmd.UseVisualStyleBackColor = true;
|
||||
this.btnAddAmd.Click += new System.EventHandler(this.btnAddAmd_Click);
|
||||
btnAddAmd.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnAddAmd.Location = new System.Drawing.Point(385, 429);
|
||||
btnAddAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnAddAmd.Name = "btnAddAmd";
|
||||
btnAddAmd.Size = new System.Drawing.Size(88, 27);
|
||||
btnAddAmd.TabIndex = 18;
|
||||
btnAddAmd.Text = "Add";
|
||||
btnAddAmd.UseVisualStyleBackColor = true;
|
||||
btnAddAmd.Click += btnAddAmd_Click;
|
||||
//
|
||||
// lblErrorAMD
|
||||
//
|
||||
this.lblErrorAMD.AutoSize = true;
|
||||
this.lblErrorAMD.Location = new System.Drawing.Point(7, 7);
|
||||
this.lblErrorAMD.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblErrorAMD.Name = "lblErrorAMD";
|
||||
this.lblErrorAMD.Size = new System.Drawing.Size(53, 15);
|
||||
this.lblErrorAMD.TabIndex = 8;
|
||||
this.lblErrorAMD.Text = "ErrorText";
|
||||
this.lblErrorAMD.Visible = false;
|
||||
lblErrorAMD.AutoSize = true;
|
||||
lblErrorAMD.Location = new System.Drawing.Point(7, 7);
|
||||
lblErrorAMD.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblErrorAMD.Name = "lblErrorAMD";
|
||||
lblErrorAMD.Size = new System.Drawing.Size(53, 15);
|
||||
lblErrorAMD.TabIndex = 8;
|
||||
lblErrorAMD.Text = "ErrorText";
|
||||
lblErrorAMD.Visible = false;
|
||||
//
|
||||
// btnDeleteAmd
|
||||
//
|
||||
this.btnDeleteAmd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnDeleteAmd.Enabled = false;
|
||||
this.btnDeleteAmd.Location = new System.Drawing.Point(290, 429);
|
||||
this.btnDeleteAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.btnDeleteAmd.Name = "btnDeleteAmd";
|
||||
this.btnDeleteAmd.Size = new System.Drawing.Size(88, 27);
|
||||
this.btnDeleteAmd.TabIndex = 17;
|
||||
this.btnDeleteAmd.Text = "Delete";
|
||||
this.btnDeleteAmd.UseVisualStyleBackColor = true;
|
||||
this.btnDeleteAmd.Click += new System.EventHandler(this.btnDeleteAmd_Click);
|
||||
btnDeleteAmd.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnDeleteAmd.Enabled = false;
|
||||
btnDeleteAmd.Location = new System.Drawing.Point(290, 429);
|
||||
btnDeleteAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnDeleteAmd.Name = "btnDeleteAmd";
|
||||
btnDeleteAmd.Size = new System.Drawing.Size(88, 27);
|
||||
btnDeleteAmd.TabIndex = 17;
|
||||
btnDeleteAmd.Text = "Delete";
|
||||
btnDeleteAmd.UseVisualStyleBackColor = true;
|
||||
btnDeleteAmd.Click += btnDeleteAmd_Click;
|
||||
//
|
||||
// btnCloneAmd
|
||||
//
|
||||
this.btnCloneAmd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnCloneAmd.Enabled = false;
|
||||
this.btnCloneAmd.Location = new System.Drawing.Point(196, 429);
|
||||
this.btnCloneAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.btnCloneAmd.Name = "btnCloneAmd";
|
||||
this.btnCloneAmd.Size = new System.Drawing.Size(88, 27);
|
||||
this.btnCloneAmd.TabIndex = 16;
|
||||
this.btnCloneAmd.Text = "Clone";
|
||||
this.btnCloneAmd.UseVisualStyleBackColor = true;
|
||||
this.btnCloneAmd.Click += new System.EventHandler(this.btnCloneAmd_Click);
|
||||
btnCloneAmd.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnCloneAmd.Enabled = false;
|
||||
btnCloneAmd.Location = new System.Drawing.Point(196, 429);
|
||||
btnCloneAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnCloneAmd.Name = "btnCloneAmd";
|
||||
btnCloneAmd.Size = new System.Drawing.Size(88, 27);
|
||||
btnCloneAmd.TabIndex = 16;
|
||||
btnCloneAmd.Text = "Clone";
|
||||
btnCloneAmd.UseVisualStyleBackColor = true;
|
||||
btnCloneAmd.Click += btnCloneAmd_Click;
|
||||
//
|
||||
// btnAmdPresetSave
|
||||
//
|
||||
this.btnAmdPresetSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnAmdPresetSave.Enabled = false;
|
||||
this.btnAmdPresetSave.Location = new System.Drawing.Point(479, 429);
|
||||
this.btnAmdPresetSave.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.btnAmdPresetSave.Name = "btnAmdPresetSave";
|
||||
this.btnAmdPresetSave.Size = new System.Drawing.Size(88, 27);
|
||||
this.btnAmdPresetSave.TabIndex = 15;
|
||||
this.btnAmdPresetSave.Text = "Save";
|
||||
this.btnAmdPresetSave.UseVisualStyleBackColor = true;
|
||||
this.btnAmdPresetSave.Click += new System.EventHandler(this.btnSetAmdShortcut_Click);
|
||||
btnAmdPresetSave.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnAmdPresetSave.Enabled = false;
|
||||
btnAmdPresetSave.Location = new System.Drawing.Point(479, 429);
|
||||
btnAmdPresetSave.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnAmdPresetSave.Name = "btnAmdPresetSave";
|
||||
btnAmdPresetSave.Size = new System.Drawing.Size(88, 27);
|
||||
btnAmdPresetSave.TabIndex = 15;
|
||||
btnAmdPresetSave.Text = "Save";
|
||||
btnAmdPresetSave.UseVisualStyleBackColor = true;
|
||||
btnAmdPresetSave.Click += btnSetAmdShortcut_Click;
|
||||
//
|
||||
// lblAmdShortcut
|
||||
//
|
||||
this.lblAmdShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.lblAmdShortcut.AutoSize = true;
|
||||
this.lblAmdShortcut.Location = new System.Drawing.Point(7, 496);
|
||||
this.lblAmdShortcut.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
this.lblAmdShortcut.Name = "lblAmdShortcut";
|
||||
this.lblAmdShortcut.Size = new System.Drawing.Size(55, 15);
|
||||
this.lblAmdShortcut.TabIndex = 14;
|
||||
this.lblAmdShortcut.Text = "Shortcut:";
|
||||
lblAmdShortcut.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
lblAmdShortcut.AutoSize = true;
|
||||
lblAmdShortcut.Location = new System.Drawing.Point(7, 496);
|
||||
lblAmdShortcut.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
|
||||
lblAmdShortcut.Name = "lblAmdShortcut";
|
||||
lblAmdShortcut.Size = new System.Drawing.Size(55, 15);
|
||||
lblAmdShortcut.TabIndex = 14;
|
||||
lblAmdShortcut.Text = "Shortcut:";
|
||||
//
|
||||
// edtAmdShortcut
|
||||
//
|
||||
this.edtAmdShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.edtAmdShortcut.Enabled = false;
|
||||
this.edtAmdShortcut.Location = new System.Drawing.Point(102, 493);
|
||||
this.edtAmdShortcut.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.edtAmdShortcut.Name = "edtAmdShortcut";
|
||||
this.edtAmdShortcut.ReadOnly = true;
|
||||
this.edtAmdShortcut.Size = new System.Drawing.Size(233, 23);
|
||||
this.edtAmdShortcut.TabIndex = 13;
|
||||
this.edtAmdShortcut.TextChanged += new System.EventHandler(this.edtAmdShortcut_TextChanged);
|
||||
this.edtAmdShortcut.KeyDown += new System.Windows.Forms.KeyEventHandler(this.edtShortcut_KeyDown);
|
||||
this.edtAmdShortcut.KeyUp += new System.Windows.Forms.KeyEventHandler(this.edtShortcut_KeyUp);
|
||||
edtAmdShortcut.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
edtAmdShortcut.Enabled = false;
|
||||
edtAmdShortcut.Location = new System.Drawing.Point(102, 493);
|
||||
edtAmdShortcut.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
edtAmdShortcut.Name = "edtAmdShortcut";
|
||||
edtAmdShortcut.ReadOnly = true;
|
||||
edtAmdShortcut.Size = new System.Drawing.Size(233, 23);
|
||||
edtAmdShortcut.TabIndex = 13;
|
||||
edtAmdShortcut.TextChanged += edtAmdShortcut_TextChanged;
|
||||
edtAmdShortcut.KeyDown += edtShortcut_KeyDown;
|
||||
edtAmdShortcut.KeyUp += edtShortcut_KeyUp;
|
||||
//
|
||||
// btnChangeAmd
|
||||
//
|
||||
this.btnChangeAmd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnChangeAmd.ContextMenuStrip = this.mnuAmdPresets;
|
||||
this.btnChangeAmd.Enabled = false;
|
||||
this.btnChangeAmd.Location = new System.Drawing.Point(102, 429);
|
||||
this.btnChangeAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.btnChangeAmd.Name = "btnChangeAmd";
|
||||
this.btnChangeAmd.Size = new System.Drawing.Size(88, 27);
|
||||
this.btnChangeAmd.TabIndex = 12;
|
||||
this.btnChangeAmd.Text = "Change...";
|
||||
this.btnChangeAmd.UseVisualStyleBackColor = true;
|
||||
this.btnChangeAmd.Click += new System.EventHandler(this.btnChangeAmd_Click);
|
||||
btnChangeAmd.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnChangeAmd.ContextMenuStrip = mnuAmdPresets;
|
||||
btnChangeAmd.Enabled = false;
|
||||
btnChangeAmd.Location = new System.Drawing.Point(102, 429);
|
||||
btnChangeAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnChangeAmd.Name = "btnChangeAmd";
|
||||
btnChangeAmd.Size = new System.Drawing.Size(88, 27);
|
||||
btnChangeAmd.TabIndex = 12;
|
||||
btnChangeAmd.Text = "Change...";
|
||||
btnChangeAmd.UseVisualStyleBackColor = true;
|
||||
btnChangeAmd.Click += btnChangeAmd_Click;
|
||||
//
|
||||
// mnuAmdPresets
|
||||
//
|
||||
this.mnuAmdPresets.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
this.mnuAmdPresets.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.miAmdApply,
|
||||
this.miAmdPresetApplyOnStartup,
|
||||
this.toolStripSeparator2,
|
||||
this.mnuAmdDisplay,
|
||||
this.mnuAmdColorSettings,
|
||||
this.mnuAmdRefreshRate,
|
||||
this.mnuAmdDithering,
|
||||
this.mnuAmdHDR,
|
||||
this.miAmdCopyId});
|
||||
this.mnuAmdPresets.Name = "mnuNvPresets";
|
||||
this.mnuAmdPresets.Size = new System.Drawing.Size(185, 186);
|
||||
this.mnuAmdPresets.Opening += new System.ComponentModel.CancelEventHandler(this.mnuAmdPresets_Opening);
|
||||
mnuAmdPresets.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||
mnuAmdPresets.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miAmdApply, miAmdPresetApplyOnStartup, toolStripSeparator2, mnuAmdDisplay, mnuAmdColorSettings, mnuAmdRefreshRate, mnuAmdResolution, mnuAmdDithering, mnuAmdHDR, miAmdCopyId });
|
||||
mnuAmdPresets.Name = "mnuNvPresets";
|
||||
mnuAmdPresets.Size = new System.Drawing.Size(185, 208);
|
||||
mnuAmdPresets.Opening += mnuAmdPresets_Opening;
|
||||
//
|
||||
// miAmdApply
|
||||
//
|
||||
this.miAmdApply.Name = "miAmdApply";
|
||||
this.miAmdApply.Size = new System.Drawing.Size(184, 22);
|
||||
this.miAmdApply.Text = "Apply";
|
||||
this.miAmdApply.Click += new System.EventHandler(this.btnApplyAmd_Click);
|
||||
miAmdApply.Name = "miAmdApply";
|
||||
miAmdApply.Size = new System.Drawing.Size(184, 22);
|
||||
miAmdApply.Text = "Apply";
|
||||
miAmdApply.Click += btnApplyAmd_Click;
|
||||
//
|
||||
// miAmdPresetApplyOnStartup
|
||||
//
|
||||
this.miAmdPresetApplyOnStartup.CheckOnClick = true;
|
||||
this.miAmdPresetApplyOnStartup.Name = "miAmdPresetApplyOnStartup";
|
||||
this.miAmdPresetApplyOnStartup.Size = new System.Drawing.Size(184, 22);
|
||||
this.miAmdPresetApplyOnStartup.Text = "Apply on startup";
|
||||
this.miAmdPresetApplyOnStartup.Click += new System.EventHandler(this.miAmdPresetApplyOnStartup_Click);
|
||||
miAmdPresetApplyOnStartup.CheckOnClick = true;
|
||||
miAmdPresetApplyOnStartup.Name = "miAmdPresetApplyOnStartup";
|
||||
miAmdPresetApplyOnStartup.Size = new System.Drawing.Size(184, 22);
|
||||
miAmdPresetApplyOnStartup.Text = "Apply on startup";
|
||||
miAmdPresetApplyOnStartup.Click += miAmdPresetApplyOnStartup_Click;
|
||||
//
|
||||
// toolStripSeparator2
|
||||
//
|
||||
this.toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
this.toolStripSeparator2.Size = new System.Drawing.Size(181, 6);
|
||||
toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
toolStripSeparator2.Size = new System.Drawing.Size(181, 6);
|
||||
//
|
||||
// mnuAmdDisplay
|
||||
//
|
||||
this.mnuAmdDisplay.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.miAmdPrimaryDisplay});
|
||||
this.mnuAmdDisplay.Name = "mnuAmdDisplay";
|
||||
this.mnuAmdDisplay.Size = new System.Drawing.Size(184, 22);
|
||||
this.mnuAmdDisplay.Text = "Display";
|
||||
mnuAmdDisplay.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miAmdPrimaryDisplay });
|
||||
mnuAmdDisplay.Name = "mnuAmdDisplay";
|
||||
mnuAmdDisplay.Size = new System.Drawing.Size(184, 22);
|
||||
mnuAmdDisplay.Text = "Display";
|
||||
//
|
||||
// miAmdPrimaryDisplay
|
||||
//
|
||||
this.miAmdPrimaryDisplay.Name = "miAmdPrimaryDisplay";
|
||||
this.miAmdPrimaryDisplay.Size = new System.Drawing.Size(155, 22);
|
||||
this.miAmdPrimaryDisplay.Text = "Primary display";
|
||||
this.miAmdPrimaryDisplay.Click += new System.EventHandler(this.displayMenuItemAmd_Click);
|
||||
miAmdPrimaryDisplay.Name = "miAmdPrimaryDisplay";
|
||||
miAmdPrimaryDisplay.Size = new System.Drawing.Size(155, 22);
|
||||
miAmdPrimaryDisplay.Text = "Primary display";
|
||||
miAmdPrimaryDisplay.Click += displayMenuItemAmd_Click;
|
||||
//
|
||||
// mnuAmdColorSettings
|
||||
//
|
||||
this.mnuAmdColorSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.miAmdColorSettingsIncluded});
|
||||
this.mnuAmdColorSettings.Name = "mnuAmdColorSettings";
|
||||
this.mnuAmdColorSettings.Size = new System.Drawing.Size(184, 22);
|
||||
this.mnuAmdColorSettings.Text = "Color settings";
|
||||
mnuAmdColorSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miAmdColorSettingsIncluded });
|
||||
mnuAmdColorSettings.Name = "mnuAmdColorSettings";
|
||||
mnuAmdColorSettings.Size = new System.Drawing.Size(184, 22);
|
||||
mnuAmdColorSettings.Text = "Color settings";
|
||||
//
|
||||
// miAmdColorSettingsIncluded
|
||||
//
|
||||
this.miAmdColorSettingsIncluded.Name = "miAmdColorSettingsIncluded";
|
||||
this.miAmdColorSettingsIncluded.Size = new System.Drawing.Size(120, 22);
|
||||
this.miAmdColorSettingsIncluded.Text = "Included";
|
||||
this.miAmdColorSettingsIncluded.Click += new System.EventHandler(this.miAmdColorSettingsIncluded_Click);
|
||||
miAmdColorSettingsIncluded.Name = "miAmdColorSettingsIncluded";
|
||||
miAmdColorSettingsIncluded.Size = new System.Drawing.Size(120, 22);
|
||||
miAmdColorSettingsIncluded.Text = "Included";
|
||||
miAmdColorSettingsIncluded.Click += miAmdColorSettingsIncluded_Click;
|
||||
//
|
||||
// mnuAmdRefreshRate
|
||||
//
|
||||
this.mnuAmdRefreshRate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.miAmdRefreshRateIncluded});
|
||||
this.mnuAmdRefreshRate.Name = "mnuAmdRefreshRate";
|
||||
this.mnuAmdRefreshRate.Size = new System.Drawing.Size(184, 22);
|
||||
this.mnuAmdRefreshRate.Text = "Refresh Rate";
|
||||
mnuAmdRefreshRate.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miAmdRefreshRateIncluded });
|
||||
mnuAmdRefreshRate.Name = "mnuAmdRefreshRate";
|
||||
mnuAmdRefreshRate.Size = new System.Drawing.Size(184, 22);
|
||||
mnuAmdRefreshRate.Text = "Refresh Rate";
|
||||
//
|
||||
// miAmdRefreshRateIncluded
|
||||
//
|
||||
this.miAmdRefreshRateIncluded.Name = "miAmdRefreshRateIncluded";
|
||||
this.miAmdRefreshRateIncluded.Size = new System.Drawing.Size(120, 22);
|
||||
this.miAmdRefreshRateIncluded.Text = "Included";
|
||||
this.miAmdRefreshRateIncluded.Click += new System.EventHandler(this.miAmdRefreshRateIncluded_Click);
|
||||
miAmdRefreshRateIncluded.Name = "miAmdRefreshRateIncluded";
|
||||
miAmdRefreshRateIncluded.Size = new System.Drawing.Size(180, 22);
|
||||
miAmdRefreshRateIncluded.Text = "Included";
|
||||
miAmdRefreshRateIncluded.Click += miAmdRefreshRateIncluded_Click;
|
||||
//
|
||||
// mnuAmdResolution
|
||||
//
|
||||
mnuAmdResolution.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miAmdResolutionIncluded, miAmdActiveResolution, miAmdVirtualResolution });
|
||||
mnuAmdResolution.Name = "mnuAmdResolution";
|
||||
mnuAmdResolution.Size = new System.Drawing.Size(184, 22);
|
||||
mnuAmdResolution.Text = "Resolution";
|
||||
//
|
||||
// miAmdResolutionIncluded
|
||||
//
|
||||
miAmdResolutionIncluded.Name = "miAmdResolutionIncluded";
|
||||
miAmdResolutionIncluded.Size = new System.Drawing.Size(180, 22);
|
||||
miAmdResolutionIncluded.Text = "Included";
|
||||
miAmdResolutionIncluded.Click += miAmdResolutionIncluded_Click;
|
||||
//
|
||||
// mnuAmdDithering
|
||||
//
|
||||
this.mnuAmdDithering.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.miAmdDitheringIncluded});
|
||||
this.mnuAmdDithering.Name = "mnuAmdDithering";
|
||||
this.mnuAmdDithering.Size = new System.Drawing.Size(184, 22);
|
||||
this.mnuAmdDithering.Text = "Dithering";
|
||||
mnuAmdDithering.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miAmdDitheringIncluded });
|
||||
mnuAmdDithering.Name = "mnuAmdDithering";
|
||||
mnuAmdDithering.Size = new System.Drawing.Size(184, 22);
|
||||
mnuAmdDithering.Text = "Dithering";
|
||||
//
|
||||
// miAmdDitheringIncluded
|
||||
//
|
||||
this.miAmdDitheringIncluded.Name = "miAmdDitheringIncluded";
|
||||
this.miAmdDitheringIncluded.Size = new System.Drawing.Size(120, 22);
|
||||
this.miAmdDitheringIncluded.Text = "Included";
|
||||
this.miAmdDitheringIncluded.Click += new System.EventHandler(this.miAmdDitheringIncluded_Click);
|
||||
miAmdDitheringIncluded.Name = "miAmdDitheringIncluded";
|
||||
miAmdDitheringIncluded.Size = new System.Drawing.Size(120, 22);
|
||||
miAmdDitheringIncluded.Text = "Included";
|
||||
miAmdDitheringIncluded.Click += miAmdDitheringIncluded_Click;
|
||||
//
|
||||
// mnuAmdHDR
|
||||
//
|
||||
this.mnuAmdHDR.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.miAmdHDRIncluded,
|
||||
this.miAmdHDRToggle,
|
||||
this.miAmdHDREnabled});
|
||||
this.mnuAmdHDR.Name = "mnuAmdHDR";
|
||||
this.mnuAmdHDR.Size = new System.Drawing.Size(184, 22);
|
||||
this.mnuAmdHDR.Text = "HDR";
|
||||
mnuAmdHDR.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miAmdHDRIncluded, miAmdHDRToggle, miAmdHDREnabled });
|
||||
mnuAmdHDR.Name = "mnuAmdHDR";
|
||||
mnuAmdHDR.Size = new System.Drawing.Size(184, 22);
|
||||
mnuAmdHDR.Text = "HDR";
|
||||
//
|
||||
// miAmdHDRIncluded
|
||||
//
|
||||
this.miAmdHDRIncluded.Name = "miAmdHDRIncluded";
|
||||
this.miAmdHDRIncluded.Size = new System.Drawing.Size(136, 22);
|
||||
this.miAmdHDRIncluded.Text = "Included";
|
||||
this.miAmdHDRIncluded.Click += new System.EventHandler(this.miAmdHDRIncluded_Click);
|
||||
miAmdHDRIncluded.Name = "miAmdHDRIncluded";
|
||||
miAmdHDRIncluded.Size = new System.Drawing.Size(136, 22);
|
||||
miAmdHDRIncluded.Text = "Included";
|
||||
miAmdHDRIncluded.Click += miAmdHDRIncluded_Click;
|
||||
//
|
||||
// miAmdHDRToggle
|
||||
//
|
||||
this.miAmdHDRToggle.Name = "miAmdHDRToggle";
|
||||
this.miAmdHDRToggle.Size = new System.Drawing.Size(136, 22);
|
||||
this.miAmdHDRToggle.Text = "Toggle HDR";
|
||||
this.miAmdHDRToggle.Click += new System.EventHandler(this.miAmdHDRToggle_Click);
|
||||
miAmdHDRToggle.Name = "miAmdHDRToggle";
|
||||
miAmdHDRToggle.Size = new System.Drawing.Size(136, 22);
|
||||
miAmdHDRToggle.Text = "Toggle HDR";
|
||||
miAmdHDRToggle.Click += miAmdHDRToggle_Click;
|
||||
//
|
||||
// miAmdHDREnabled
|
||||
//
|
||||
this.miAmdHDREnabled.Name = "miAmdHDREnabled";
|
||||
this.miAmdHDREnabled.Size = new System.Drawing.Size(136, 22);
|
||||
this.miAmdHDREnabled.Text = "Enabled";
|
||||
this.miAmdHDREnabled.Click += new System.EventHandler(this.miAmdHDREnabled_Click);
|
||||
miAmdHDREnabled.Name = "miAmdHDREnabled";
|
||||
miAmdHDREnabled.Size = new System.Drawing.Size(136, 22);
|
||||
miAmdHDREnabled.Text = "Enabled";
|
||||
miAmdHDREnabled.Click += miAmdHDREnabled_Click;
|
||||
//
|
||||
// miAmdCopyId
|
||||
//
|
||||
this.miAmdCopyId.Name = "miAmdCopyId";
|
||||
this.miAmdCopyId.Size = new System.Drawing.Size(184, 22);
|
||||
this.miAmdCopyId.Text = "Copy Id to Clipboard";
|
||||
this.miAmdCopyId.Click += new System.EventHandler(this.miAmdCopyId_Click);
|
||||
miAmdCopyId.Name = "miAmdCopyId";
|
||||
miAmdCopyId.Size = new System.Drawing.Size(184, 22);
|
||||
miAmdCopyId.Text = "Copy Id to Clipboard";
|
||||
miAmdCopyId.Click += miAmdCopyId_Click;
|
||||
//
|
||||
// btnApplyAmd
|
||||
//
|
||||
this.btnApplyAmd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnApplyAmd.Enabled = false;
|
||||
this.btnApplyAmd.Location = new System.Drawing.Point(7, 429);
|
||||
this.btnApplyAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.btnApplyAmd.Name = "btnApplyAmd";
|
||||
this.btnApplyAmd.Size = new System.Drawing.Size(88, 27);
|
||||
this.btnApplyAmd.TabIndex = 11;
|
||||
this.btnApplyAmd.Text = "Apply";
|
||||
this.btnApplyAmd.UseVisualStyleBackColor = true;
|
||||
this.btnApplyAmd.Click += new System.EventHandler(this.btnApplyAmd_Click);
|
||||
btnApplyAmd.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left;
|
||||
btnApplyAmd.Enabled = false;
|
||||
btnApplyAmd.Location = new System.Drawing.Point(7, 429);
|
||||
btnApplyAmd.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
btnApplyAmd.Name = "btnApplyAmd";
|
||||
btnApplyAmd.Size = new System.Drawing.Size(88, 27);
|
||||
btnApplyAmd.TabIndex = 11;
|
||||
btnApplyAmd.Text = "Apply";
|
||||
btnApplyAmd.UseVisualStyleBackColor = true;
|
||||
btnApplyAmd.Click += btnApplyAmd_Click;
|
||||
//
|
||||
// lvAmdPresets
|
||||
//
|
||||
this.lvAmdPresets.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.lvAmdPresets.CheckBoxes = true;
|
||||
this.lvAmdPresets.ContextMenuStrip = this.mnuAmdPresets;
|
||||
this.lvAmdPresets.FullRowSelect = true;
|
||||
this.lvAmdPresets.Location = new System.Drawing.Point(7, 7);
|
||||
this.lvAmdPresets.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.lvAmdPresets.MultiSelect = false;
|
||||
this.lvAmdPresets.Name = "lvAmdPresets";
|
||||
this.lvAmdPresets.ShowItemToolTips = true;
|
||||
this.lvAmdPresets.Size = new System.Drawing.Size(1098, 415);
|
||||
this.lvAmdPresets.TabIndex = 10;
|
||||
this.lvAmdPresets.UseCompatibleStateImageBehavior = false;
|
||||
this.lvAmdPresets.View = System.Windows.Forms.View.Details;
|
||||
this.lvAmdPresets.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lvLgPresets_ColumnClick);
|
||||
this.lvAmdPresets.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.lvNvPresets_ItemCheck);
|
||||
this.lvAmdPresets.ItemChecked += new System.Windows.Forms.ItemCheckedEventHandler(this.lvAmdPresets_ItemChecked);
|
||||
this.lvAmdPresets.SelectedIndexChanged += new System.EventHandler(this.lvAmdPresets_SelectedIndexChanged);
|
||||
this.lvAmdPresets.DoubleClick += new System.EventHandler(this.btnApplyAmd_Click);
|
||||
lvAmdPresets.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
|
||||
lvAmdPresets.CheckBoxes = true;
|
||||
lvAmdPresets.ContextMenuStrip = mnuAmdPresets;
|
||||
lvAmdPresets.FullRowSelect = true;
|
||||
lvAmdPresets.Location = new System.Drawing.Point(7, 7);
|
||||
lvAmdPresets.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
lvAmdPresets.MultiSelect = false;
|
||||
lvAmdPresets.Name = "lvAmdPresets";
|
||||
lvAmdPresets.ShowItemToolTips = true;
|
||||
lvAmdPresets.Size = new System.Drawing.Size(1098, 415);
|
||||
lvAmdPresets.TabIndex = 10;
|
||||
lvAmdPresets.UseCompatibleStateImageBehavior = false;
|
||||
lvAmdPresets.View = System.Windows.Forms.View.Details;
|
||||
lvAmdPresets.ColumnClick += lvLgPresets_ColumnClick;
|
||||
lvAmdPresets.ItemCheck += lvNvPresets_ItemCheck;
|
||||
lvAmdPresets.ItemChecked += lvAmdPresets_ItemChecked;
|
||||
lvAmdPresets.SelectedIndexChanged += lvAmdPresets_SelectedIndexChanged;
|
||||
lvAmdPresets.DoubleClick += btnApplyAmd_Click;
|
||||
//
|
||||
// miAmdActiveResolution
|
||||
//
|
||||
miAmdActiveResolution.Name = "miAmdActiveResolution";
|
||||
miAmdActiveResolution.Size = new System.Drawing.Size(180, 22);
|
||||
miAmdActiveResolution.Text = "Active";
|
||||
//
|
||||
// miAmdVirtualResolution
|
||||
//
|
||||
miAmdVirtualResolution.Name = "miAmdVirtualResolution";
|
||||
miAmdVirtualResolution.Size = new System.Drawing.Size(180, 22);
|
||||
miAmdVirtualResolution.Text = "Virtual";
|
||||
//
|
||||
// AmdPanel
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.btnAmdSettings);
|
||||
this.Controls.Add(this.chkAmdQuickAccess);
|
||||
this.Controls.Add(this.lblAmdPresetName);
|
||||
this.Controls.Add(this.edtAmdPresetName);
|
||||
this.Controls.Add(this.btnAddAmd);
|
||||
this.Controls.Add(this.lblErrorAMD);
|
||||
this.Controls.Add(this.btnDeleteAmd);
|
||||
this.Controls.Add(this.btnCloneAmd);
|
||||
this.Controls.Add(this.btnAmdPresetSave);
|
||||
this.Controls.Add(this.lblAmdShortcut);
|
||||
this.Controls.Add(this.edtAmdShortcut);
|
||||
this.Controls.Add(this.btnChangeAmd);
|
||||
this.Controls.Add(this.btnApplyAmd);
|
||||
this.Controls.Add(this.lvAmdPresets);
|
||||
this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
this.Name = "AmdPanel";
|
||||
this.Size = new System.Drawing.Size(1114, 539);
|
||||
this.mnuAmdPresets.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
Controls.Add(btnAmdSettings);
|
||||
Controls.Add(chkAmdQuickAccess);
|
||||
Controls.Add(lblAmdPresetName);
|
||||
Controls.Add(edtAmdPresetName);
|
||||
Controls.Add(btnAddAmd);
|
||||
Controls.Add(lblErrorAMD);
|
||||
Controls.Add(btnDeleteAmd);
|
||||
Controls.Add(btnCloneAmd);
|
||||
Controls.Add(btnAmdPresetSave);
|
||||
Controls.Add(lblAmdShortcut);
|
||||
Controls.Add(edtAmdShortcut);
|
||||
Controls.Add(btnChangeAmd);
|
||||
Controls.Add(btnApplyAmd);
|
||||
Controls.Add(lvAmdPresets);
|
||||
Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||
Name = "AmdPanel";
|
||||
Size = new System.Drawing.Size(1114, 539);
|
||||
mnuAmdPresets.ResumeLayout(false);
|
||||
ResumeLayout(false);
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -441,6 +452,9 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem miAmdCopyId;
|
||||
private System.Windows.Forms.CheckBox chkAmdQuickAccess;
|
||||
private System.Windows.Forms.Button btnAmdSettings;
|
||||
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuAmdResolution;
|
||||
private System.Windows.Forms.ToolStripMenuItem miAmdResolutionIncluded;
|
||||
private System.Windows.Forms.ToolStripMenuItem miAmdActiveResolution;
|
||||
private System.Windows.Forms.ToolStripMenuItem miAmdVirtualResolution;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,4 +1,64 @@
|
||||
<root>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
using ColorControl.Services.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ColorControl.Services.AMD
|
||||
{
|
||||
class AmdPreset : PresetBase
|
||||
{
|
||||
public bool applyColorData { get; set; }
|
||||
public ADLColorDepth colorDepth { get; set; }
|
||||
public ADLPixelFormat pixelFormat { get; set; }
|
||||
public bool applyHDR { get; set; }
|
||||
public bool HDREnabled { get; set; }
|
||||
public bool toggleHDR { get; set; }
|
||||
public bool applyDithering { get; set; }
|
||||
public ADLDitherState ditherState { get; set; }
|
||||
public bool applyRefreshRate { get; set; }
|
||||
public uint refreshRate { get; set; }
|
||||
public bool primaryDisplay { get; set; }
|
||||
public string displayName { get; set; }
|
||||
|
||||
public AmdPreset() : base()
|
||||
{
|
||||
applyColorData = true;
|
||||
applyDithering = false;
|
||||
ditherState = ADLDitherState.DRIVER_DEFAULT;
|
||||
applyHDR = false;
|
||||
HDREnabled = false;
|
||||
toggleHDR = false;
|
||||
applyRefreshRate = false;
|
||||
refreshRate = 60;
|
||||
primaryDisplay = true;
|
||||
}
|
||||
|
||||
public AmdPreset(AmdPreset preset) : this()
|
||||
{
|
||||
id = GetNewId();
|
||||
|
||||
primaryDisplay = preset.primaryDisplay;
|
||||
displayName = preset.displayName;
|
||||
|
||||
applyColorData = preset.applyColorData;
|
||||
colorDepth = preset.colorDepth;
|
||||
pixelFormat = preset.pixelFormat;
|
||||
|
||||
applyHDR = preset.applyHDR;
|
||||
HDREnabled = preset.HDREnabled;
|
||||
toggleHDR = preset.toggleHDR;
|
||||
applyDithering = preset.applyDithering;
|
||||
ditherState = preset.ditherState;
|
||||
applyRefreshRate = preset.applyRefreshRate;
|
||||
refreshRate = preset.refreshRate;
|
||||
}
|
||||
|
||||
public AmdPreset Clone()
|
||||
{
|
||||
var preset = new AmdPreset(this);
|
||||
|
||||
return preset;
|
||||
}
|
||||
|
||||
public static string[] GetColumnNames()
|
||||
{
|
||||
//return new[] { "BPC", "Format", "Dynamic range", "Toggle HDR", "Shortcut" };
|
||||
return new[] { "Name", "Display|140", "Color settings (BPC, format)|260", "Refresh rate|100", "Dithering", "HDR", "Shortcut", "Apply on startup" };
|
||||
}
|
||||
|
||||
public override List<string> GetDisplayValues(Config config = null)
|
||||
{
|
||||
var values = new List<string>();
|
||||
|
||||
values.Add(name);
|
||||
|
||||
var display = string.Format("{0}", primaryDisplay ? "Primary" : displayName);
|
||||
values.Add(display);
|
||||
|
||||
var colorSettings = string.Format("{0}: {1}, {2}", applyColorData ? "Included" : "Excluded", colorDepth, pixelFormat);
|
||||
|
||||
values.Add(colorSettings);
|
||||
values.Add(string.Format("{0}: {1}Hz", applyRefreshRate ? "Included" : "Excluded", refreshRate));
|
||||
values.Add(string.Format("{0}: {1}", applyDithering ? "Included" : "Excluded", ditherState));
|
||||
values.Add(string.Format("{0}: {1}", applyHDR ? "Included" : "Excluded", toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled"));
|
||||
values.Add(shortcut);
|
||||
values.Add(string.Format("{0}", config?.AmdPresetId_ApplyOnStartup == id ? "Yes" : string.Empty));
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
public static List<AmdPreset> GetDefaultPresets()
|
||||
{
|
||||
var presets = new List<AmdPreset>();
|
||||
|
||||
var preset = new AmdPreset();
|
||||
preset.colorDepth = ADLColorDepth.BPC8;
|
||||
preset.pixelFormat = ADLPixelFormat.RGB_FULL_RANGE;
|
||||
|
||||
presets.Add(preset);
|
||||
|
||||
return presets;
|
||||
}
|
||||
|
||||
public override string GetTextForMenuItem()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
sb.Append(name);
|
||||
sb.Append(" / ");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (displayName != null)
|
||||
{
|
||||
sb.AppendFormat("Display: {0} / ", displayName);
|
||||
}
|
||||
if (applyColorData)
|
||||
{
|
||||
var colorSettings = string.Format("Format: {0}, {1}", colorDepth, pixelFormat);
|
||||
sb.Append(colorSettings);
|
||||
sb.Append(" / ");
|
||||
}
|
||||
if (applyRefreshRate)
|
||||
{
|
||||
sb.AppendFormat("{0}Hz", refreshRate);
|
||||
sb.Append(" / ");
|
||||
}
|
||||
if (applyDithering)
|
||||
{
|
||||
sb.AppendFormat("Dithering: {0}", ditherState);
|
||||
sb.Append(" / ");
|
||||
}
|
||||
if (applyHDR)
|
||||
{
|
||||
sb.AppendFormat("HDR: {0}", toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled");
|
||||
sb.Append(" / ");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.ToString(0, Math.Max(0, sb.Length - 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,362 +1,554 @@
|
||||
using ATI.ADL;
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Services.Common;
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.Contracts.AMD;
|
||||
using ColorControl.Shared.Native;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl.Services.AMD
|
||||
{
|
||||
class AmdService : GraphicsService<AmdPreset>
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public override string ServiceName => "AMD";
|
||||
|
||||
protected override string PresetsBaseFilename => "AmdPresets.json";
|
||||
|
||||
private ADLDisplayInfo _currentDisplay;
|
||||
|
||||
public AmdService(AppContextProvider appContextProvider) : base(appContextProvider)
|
||||
{
|
||||
LoadPresets();
|
||||
}
|
||||
|
||||
public static async Task<bool> ExecutePresetAsync(string idOrName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var appContextProvider = Program.ServiceProvider.GetRequiredService<AppContextProvider>();
|
||||
|
||||
var service = new AmdService(appContextProvider);
|
||||
|
||||
var result = await service.ApplyPreset(idOrName);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Console.WriteLine("Preset not found or error while executing.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error executing preset: " + ex.ToLogString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override List<AmdPreset> GetDefaultPresets()
|
||||
{
|
||||
return AmdPreset.GetDefaultPresets();
|
||||
}
|
||||
|
||||
private void SavePresets()
|
||||
{
|
||||
Utils.WriteObject(_presetsFilename, _presets);
|
||||
}
|
||||
|
||||
public void GlobalSave()
|
||||
{
|
||||
SavePresets();
|
||||
}
|
||||
|
||||
public override bool HasDisplaysAttached(bool reinitialize = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetDisplays().Any();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCurrentDisplay(AmdPreset preset)
|
||||
{
|
||||
var displays = GetDisplays();
|
||||
if (preset.primaryDisplay)
|
||||
{
|
||||
_currentDisplay = displays.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentDisplay = displays.FirstOrDefault(x => x.DisplayName.Equals(preset.displayName));
|
||||
}
|
||||
}
|
||||
|
||||
public ADLDisplayInfo GetCurrentDisplay()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentDisplay.DisplayName))
|
||||
{
|
||||
_currentDisplay = GetDisplays().FirstOrDefault();
|
||||
}
|
||||
|
||||
return _currentDisplay;
|
||||
}
|
||||
|
||||
public async Task<bool> ApplyPreset(string idOrName)
|
||||
{
|
||||
var preset = GetPresetByIdOrName(idOrName);
|
||||
if (preset != null)
|
||||
{
|
||||
return await ApplyPreset(preset);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<bool> ApplyPreset(AmdPreset preset)
|
||||
{
|
||||
SetCurrentDisplay(preset);
|
||||
|
||||
if (string.IsNullOrEmpty(_currentDisplay.DisplayName))
|
||||
{
|
||||
Logger.Error("Could not set current display");
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = true;
|
||||
|
||||
if (preset.applyHDR)
|
||||
{
|
||||
var hdrEnabled = IsHDREnabled();
|
||||
if (preset.toggleHDR)
|
||||
{
|
||||
result = ADLWrapper.SetDisplayHDRState(_currentDisplay, !hdrEnabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ADLWrapper.SetDisplayHDRState(_currentDisplay, preset.HDREnabled);
|
||||
}
|
||||
|
||||
//if (preset.toggleHDR || preset.HDREnabled != hdrEnabled)
|
||||
//{
|
||||
// ToggleHDR(config.DisplaySettingsDelay);
|
||||
//}
|
||||
}
|
||||
|
||||
if (preset.applyRefreshRate)
|
||||
{
|
||||
{
|
||||
if (!SetRefreshRate(preset.refreshRate))
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.applyColorData)
|
||||
{
|
||||
if (!ADLWrapper.SetDisplayColorDepth(_currentDisplay, preset.colorDepth))
|
||||
{
|
||||
Logger.Error("Could not set color depth");
|
||||
result = false;
|
||||
}
|
||||
if (preset.pixelFormat != ADLPixelFormat.UNKNOWN && !ADLWrapper.SetDisplayPixelFormat(_currentDisplay, preset.pixelFormat))
|
||||
{
|
||||
Logger.Error("Could not set pixel format");
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.applyDithering)
|
||||
{
|
||||
if (!SetDithering(preset.ditherState))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
_lastAppliedPreset = preset;
|
||||
|
||||
PresetApplied();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool SetDithering(ADLDitherState ditherState)
|
||||
{
|
||||
var display = GetCurrentDisplay();
|
||||
|
||||
return ADLWrapper.SetDisplayDitherState(display, ditherState);
|
||||
}
|
||||
|
||||
public ADLDitherState GetDithering(ADLDisplayInfo display = default(ADLDisplayInfo))
|
||||
{
|
||||
if (string.IsNullOrEmpty(display.DisplayName))
|
||||
{
|
||||
display = GetCurrentDisplay();
|
||||
}
|
||||
|
||||
var ditherState = ADLDitherState.DRIVER_DEFAULT;
|
||||
|
||||
if (ADLWrapper.GetDisplayDitherState(display, ref ditherState))
|
||||
{
|
||||
return ditherState;
|
||||
}
|
||||
|
||||
return ditherState;
|
||||
}
|
||||
|
||||
public string GetDisplayDeviceName(ADLDisplayInfo display)
|
||||
{
|
||||
return Screen.PrimaryScreen.DeviceName;
|
||||
}
|
||||
|
||||
public bool SetRefreshRate(uint refreshRate)
|
||||
{
|
||||
var horizontal = 3840;
|
||||
var vertical = 2160;
|
||||
var display = GetCurrentDisplay();
|
||||
|
||||
ADLWrapper.GetDisplayResolution(display, ref horizontal, ref vertical);
|
||||
|
||||
var portrait = vertical > horizontal;
|
||||
|
||||
return SetRefreshRateInternal(GetDisplayDeviceName(display), (int)refreshRate, portrait, horizontal, vertical);
|
||||
}
|
||||
|
||||
public List<uint> GetAvailableRefreshRates(AmdPreset preset = null)
|
||||
{
|
||||
if (preset != null)
|
||||
{
|
||||
SetCurrentDisplay(preset);
|
||||
}
|
||||
|
||||
var horizontal = 3840;
|
||||
var vertical = 2160;
|
||||
var display = GetCurrentDisplay();
|
||||
|
||||
ADLWrapper.GetDisplayResolution(display, ref horizontal, ref vertical);
|
||||
|
||||
var portrait = vertical > horizontal;
|
||||
|
||||
return GetAvailableRefreshRatesInternal(GetDisplayDeviceName(display), portrait, horizontal, vertical);
|
||||
}
|
||||
|
||||
public bool IsHDREnabled()
|
||||
{
|
||||
var display = GetCurrentDisplay();
|
||||
|
||||
var supported = false;
|
||||
var enabled = false;
|
||||
ADLWrapper.GetDisplayHDRState(display, ref supported, ref enabled);
|
||||
|
||||
Logger.Debug($"IsHDREnabled: supported {supported}, enabled {enabled}");
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public List<ADLDisplayInfo> GetDisplays()
|
||||
{
|
||||
var displays = ADLWrapper.GetAllDisplays();
|
||||
|
||||
//if (!displays.Any())
|
||||
//{
|
||||
// displays.Add(new ADLDisplayInfo
|
||||
// {
|
||||
// DisplayName = "Dummy"
|
||||
// });
|
||||
//}
|
||||
|
||||
return displays;
|
||||
}
|
||||
|
||||
public string GetFullDisplayName(ADLDisplayInfo display)
|
||||
{
|
||||
var name = display.DisplayName;
|
||||
|
||||
var screen = GetScreenForDisplay(display);
|
||||
if (screen != null)
|
||||
{
|
||||
name = $"{screen.DeviceName} ({name})";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public Screen GetScreenForDisplay(ADLDisplayInfo display)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var screen in Screen.AllScreens)
|
||||
{
|
||||
Logger.Debug($"SCREEN[{index}]: {screen.DeviceName}, {screen.DeviceFriendlyName()}, {screen.Primary}");
|
||||
index++;
|
||||
}
|
||||
return Screen.AllScreens.FirstOrDefault(x => x.DeviceFriendlyName().Equals(display.DisplayName));
|
||||
}
|
||||
|
||||
public List<AmdDisplayInfo> GetDisplayInfos()
|
||||
{
|
||||
List<ADLDisplayInfo> displays;
|
||||
try
|
||||
{
|
||||
displays = GetDisplays();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("Error while getting displays: " + e.ToLogString());
|
||||
return null;
|
||||
}
|
||||
|
||||
var list = new List<AmdDisplayInfo>();
|
||||
|
||||
foreach (var display in displays)
|
||||
{
|
||||
var values = new List<string>();
|
||||
|
||||
values.Add("Current settings");
|
||||
|
||||
var screen = GetScreenForDisplay(display);
|
||||
|
||||
var name = GetFullDisplayName(display);
|
||||
values.Add(name);
|
||||
|
||||
var colorDepth = ADLColorDepth.UNKNOWN;
|
||||
ADLWrapper.GetDisplayColorDepth(display, ref colorDepth);
|
||||
|
||||
var pixelFormat = ADLPixelFormat.UNKNOWN;
|
||||
ADLWrapper.GetDisplayPixelFormat(display, ref pixelFormat);
|
||||
|
||||
var colorSettings = $"{colorDepth.GetDescription()}, {pixelFormat.GetDescription()}";
|
||||
values.Add(colorSettings);
|
||||
|
||||
var refreshRate = GetCurrentRefreshRate(screen?.DeviceName);
|
||||
values.Add($"{refreshRate}Hz");
|
||||
|
||||
var ditherState = GetDithering(display);
|
||||
values.Add(ditherState.GetDescription());
|
||||
|
||||
var hdrEnabled = IsHDREnabled();
|
||||
values.Add(hdrEnabled ? "Yes" : "No");
|
||||
|
||||
var infoLine = string.Format("{0}: {1}, {2}Hz, HDR: {3}", name, colorSettings, refreshRate, hdrEnabled ? "Yes" : "No");
|
||||
|
||||
var displayInfo = new AmdDisplayInfo(display, values, infoLine);
|
||||
|
||||
list.Add(displayInfo);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
if (!ADLWrapper.Initialize())
|
||||
{
|
||||
throw new InvalidOperationException("Cannot load AMD API");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Uninitialize()
|
||||
{
|
||||
ADLWrapper.Uninitialze();
|
||||
}
|
||||
}
|
||||
class AmdService : GraphicsService<AmdPreset>
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public override string ServiceName => "AMD";
|
||||
|
||||
protected override string PresetsBaseFilename => "AmdPresets.json";
|
||||
|
||||
private ADLDisplayInfo _currentDisplay;
|
||||
|
||||
public static readonly int SHORTCUTID_AMDQA = -201;
|
||||
|
||||
private string _configFilename;
|
||||
public AmdServiceConfig Config { get; private set; }
|
||||
|
||||
public AmdService(GlobalContext globalContext) : base(globalContext)
|
||||
{
|
||||
LoadPresets();
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
public static async Task<bool> ExecutePresetAsync(string idOrName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var globalContext = Program.ServiceProvider.GetRequiredService<GlobalContext>();
|
||||
|
||||
var service = new AmdService(globalContext);
|
||||
|
||||
var result = await service.ApplyPreset(idOrName);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Console.WriteLine("Preset not found or error while executing.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error executing preset: " + ex.ToLogString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void InstallEventHandlers()
|
||||
{
|
||||
base.InstallEventHandlers();
|
||||
|
||||
SetShortcuts(SHORTCUTID_AMDQA, Config.QuickAccessShortcut);
|
||||
}
|
||||
|
||||
private void LoadConfig()
|
||||
{
|
||||
_configFilename = Path.Combine(_dataPath, "AmdConfig.json");
|
||||
try
|
||||
{
|
||||
if (File.Exists(_configFilename))
|
||||
{
|
||||
Config = JsonConvert.DeserializeObject<AmdServiceConfig>(File.ReadAllText(_configFilename));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"LoadConfig: {ex.Message}");
|
||||
}
|
||||
Config ??= new AmdServiceConfig();
|
||||
}
|
||||
|
||||
protected override List<AmdPreset> GetDefaultPresets()
|
||||
{
|
||||
return AmdPreset.GetDefaultPresets();
|
||||
}
|
||||
|
||||
public override List<string> GetInfo()
|
||||
{
|
||||
return [$"{_presets.Count} presets"];
|
||||
}
|
||||
|
||||
private void SavePresets()
|
||||
{
|
||||
Utils.WriteObject(_presetsFilename, _presets);
|
||||
}
|
||||
|
||||
public void GlobalSave()
|
||||
{
|
||||
SavePresets();
|
||||
SaveConfig();
|
||||
}
|
||||
|
||||
public override bool HasDisplaysAttached(bool reinitialize = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
return GetDisplays().Any();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCurrentDisplay(AmdPreset preset)
|
||||
{
|
||||
var displays = GetDisplays();
|
||||
if (preset.primaryDisplay)
|
||||
{
|
||||
_currentDisplay = displays.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentDisplay = displays.FirstOrDefault(x => x.DisplayName.Equals(preset.displayName));
|
||||
}
|
||||
}
|
||||
|
||||
public ADLDisplayInfo GetCurrentDisplay()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_currentDisplay.DisplayName))
|
||||
{
|
||||
_currentDisplay = GetDisplays().FirstOrDefault();
|
||||
}
|
||||
|
||||
return _currentDisplay;
|
||||
}
|
||||
|
||||
public override async Task<bool> ApplyPreset(AmdPreset preset)
|
||||
{
|
||||
SetCurrentDisplay(preset);
|
||||
|
||||
if (string.IsNullOrEmpty(_currentDisplay.DisplayName))
|
||||
{
|
||||
Logger.Error("Could not set current display");
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = true;
|
||||
|
||||
if (preset.applyHDR)
|
||||
{
|
||||
var hdrEnabled = IsHDREnabled();
|
||||
if (preset.toggleHDR)
|
||||
{
|
||||
result = ADLWrapper.SetDisplayHDRState(_currentDisplay, !hdrEnabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ADLWrapper.SetDisplayHDRState(_currentDisplay, preset.HDREnabled);
|
||||
}
|
||||
|
||||
//if (preset.toggleHDR || preset.HDREnabled != hdrEnabled)
|
||||
//{
|
||||
// ToggleHDR(config.DisplaySettingsDelay);
|
||||
//}
|
||||
|
||||
if (preset.SDRBrightness.HasValue)
|
||||
{
|
||||
var deviceName = GetDisplayDeviceName(_currentDisplay);
|
||||
|
||||
SetSDRBrightness(deviceName, preset.SDRBrightness.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.DisplayConfig.ApplyRefreshRate || preset.DisplayConfig.ApplyResolution)
|
||||
{
|
||||
if (!SetMode(preset.DisplayConfig, true))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.applyColorData)
|
||||
{
|
||||
if (!ADLWrapper.SetDisplayColorDepth(_currentDisplay, preset.colorDepth))
|
||||
{
|
||||
Logger.Error("Could not set color depth");
|
||||
result = false;
|
||||
}
|
||||
if (preset.pixelFormat != ADLPixelFormat.UNKNOWN && !ADLWrapper.SetDisplayPixelFormat(_currentDisplay, preset.pixelFormat))
|
||||
{
|
||||
Logger.Error("Could not set pixel format");
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.applyDithering)
|
||||
{
|
||||
if (!SetDithering(preset.ditherState))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
_lastAppliedPreset = preset;
|
||||
|
||||
PresetApplied();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool SetDithering(ADLDitherState ditherState)
|
||||
{
|
||||
var display = GetCurrentDisplay();
|
||||
|
||||
return ADLWrapper.SetDisplayDitherState(display, ditherState);
|
||||
}
|
||||
|
||||
public ADLDitherState GetDithering(ADLDisplayInfo display = default(ADLDisplayInfo))
|
||||
{
|
||||
if (string.IsNullOrEmpty(display.DisplayName))
|
||||
{
|
||||
display = GetCurrentDisplay();
|
||||
}
|
||||
|
||||
var ditherState = ADLDitherState.DRIVER_DEFAULT;
|
||||
|
||||
if (ADLWrapper.GetDisplayDitherState(display, ref ditherState))
|
||||
{
|
||||
return ditherState;
|
||||
}
|
||||
|
||||
return ditherState;
|
||||
}
|
||||
|
||||
public string GetDisplayDeviceName(ADLDisplayInfo display)
|
||||
{
|
||||
return Screen.PrimaryScreen.DeviceName;
|
||||
}
|
||||
|
||||
public bool SetMode(DisplayConfig displayConfig, bool updateRegistry = false)
|
||||
{
|
||||
var display = GetCurrentDisplay();
|
||||
|
||||
return SetMode(GetDisplayDeviceName(display), displayConfig, updateRegistry);
|
||||
}
|
||||
|
||||
public List<Rational> GetAvailableRefreshRates(AmdPreset preset = null)
|
||||
{
|
||||
if (preset != null)
|
||||
{
|
||||
SetCurrentDisplay(preset);
|
||||
}
|
||||
|
||||
var horizontal = 3840;
|
||||
var vertical = 2160;
|
||||
var display = GetCurrentDisplay();
|
||||
|
||||
ADLWrapper.GetDisplayResolution(display, ref horizontal, ref vertical);
|
||||
|
||||
return GetAvailableRefreshRatesV2(GetDisplayDeviceName(display), horizontal, vertical);
|
||||
}
|
||||
|
||||
public List<VirtualResolution> GetAvailableResolutionsV2(AmdPreset preset = null)
|
||||
{
|
||||
if (preset != null)
|
||||
{
|
||||
SetCurrentDisplay(preset);
|
||||
}
|
||||
|
||||
var display = GetCurrentDisplay();
|
||||
var deviceName = GetDisplayDeviceName(display);
|
||||
if (deviceName == null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return GetAvailableResolutionsInternalV2(deviceName);
|
||||
}
|
||||
|
||||
public bool SetMode(VirtualResolution resolution = null, Rational refreshRate = null, bool updateRegistry = false, AmdPreset preset = null)
|
||||
{
|
||||
var display = preset == null ? GetCurrentDisplay() : GetPresetDisplay(preset);
|
||||
if (display.Equals(default(ADLDisplayInfo)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return SetMode(GetDisplayDeviceName(display), resolution, refreshRate, updateRegistry);
|
||||
}
|
||||
|
||||
public bool SetMode(DisplayConfig displayConfig, bool updateRegistry = false, AmdPreset preset = null)
|
||||
{
|
||||
var display = preset == null ? GetCurrentDisplay() : GetPresetDisplay(preset);
|
||||
if (display.DisplayID.DisplayPhysicalIndex == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return SetMode(GetDisplayDeviceName(display), displayConfig, updateRegistry);
|
||||
}
|
||||
|
||||
public ADLDisplayInfo GetPresetDisplay(AmdPreset preset)
|
||||
{
|
||||
return GetCurrentDisplay();
|
||||
}
|
||||
|
||||
public List<Rational> GetAvailableRefreshRatesV2(AmdPreset preset = null)
|
||||
{
|
||||
if (preset != null)
|
||||
{
|
||||
SetCurrentDisplay(preset);
|
||||
}
|
||||
|
||||
var display = _currentDisplay;
|
||||
if (_currentDisplay.DisplayID.DisplayLogicalAdapterIndex == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var desktopRect = preset?.DisplayConfig.ApplyResolution == true && preset?.DisplayConfig.Resolution.ActiveWidth > 0 ?
|
||||
new Rectangle(0, 0, (int)preset.DisplayConfig.Resolution.ActiveWidth, (int)preset.DisplayConfig.Resolution.ActiveHeight) :
|
||||
GetDesktopRect(display);
|
||||
|
||||
return GetAvailableRefreshRatesV2(Screen.PrimaryScreen.DeviceName, desktopRect.Width, desktopRect.Height);
|
||||
}
|
||||
|
||||
private Rectangle GetDesktopRect(ADLDisplayInfo display)
|
||||
{
|
||||
// TODO: improve this
|
||||
var screen = Screen.AllScreens.First();
|
||||
|
||||
return screen.Bounds;
|
||||
}
|
||||
|
||||
public bool IsHDREnabled(ADLDisplayInfo display = default)
|
||||
{
|
||||
if (display.Equals(default(ADLDisplayInfo)))
|
||||
{
|
||||
display = GetCurrentDisplay();
|
||||
}
|
||||
|
||||
var supported = false;
|
||||
var enabled = false;
|
||||
ADLWrapper.GetDisplayHDRState(display, ref supported, ref enabled);
|
||||
|
||||
Logger.Debug($"IsHDREnabled: supported {supported}, enabled {enabled}");
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public List<ADLDisplayInfo> GetDisplays()
|
||||
{
|
||||
var displays = ADLWrapper.GetAllDisplays();
|
||||
|
||||
//if (!displays.Any())
|
||||
//{
|
||||
// displays.Add(new ADLDisplayInfo
|
||||
// {
|
||||
// DisplayName = "Dummy"
|
||||
// });
|
||||
//}
|
||||
|
||||
return displays;
|
||||
}
|
||||
|
||||
public string GetFullDisplayName(ADLDisplayInfo display)
|
||||
{
|
||||
var name = display.DisplayName;
|
||||
|
||||
var screen = GetScreenForDisplay(display);
|
||||
if (screen != null)
|
||||
{
|
||||
name = $"{screen.DeviceName} ({name})";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public Screen GetScreenForDisplay(ADLDisplayInfo display)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var screen in Screen.AllScreens)
|
||||
{
|
||||
var info = CCD.GetDisplayInfo(screen.DeviceName);
|
||||
Logger.Debug($"SCREEN[{index}]: {screen.DeviceName}, {info?.FriendlyName}, {screen.Primary}");
|
||||
index++;
|
||||
}
|
||||
return Screen.AllScreens.FirstOrDefault(x => CCD.GetDisplayInfo(x.DeviceName)?.FriendlyName.Equals(display.DisplayName) ?? false);
|
||||
}
|
||||
|
||||
public List<AmdDisplayInfo> GetSimpleDisplayInfos()
|
||||
{
|
||||
List<ADLDisplayInfo> displays;
|
||||
try
|
||||
{
|
||||
displays = GetDisplays();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("Error while getting displays: " + e.ToLogString());
|
||||
return null;
|
||||
}
|
||||
|
||||
return displays.Select(d => new AmdDisplayInfo(d, null, null)).ToList();
|
||||
}
|
||||
|
||||
public List<AmdDisplayInfo> GetDisplayInfos()
|
||||
{
|
||||
var list = new List<AmdDisplayInfo>();
|
||||
|
||||
var displayInfos = GetSimpleDisplayInfos();
|
||||
|
||||
foreach (var displayInfo in displayInfos)
|
||||
{
|
||||
var preset = GetPresetForDisplay(displayInfo, displayInfos.Count());
|
||||
|
||||
displayInfo.Values = preset.GetDisplayValues(_globalContext.Config);
|
||||
displayInfo.InfoLine = preset.InfoLine;
|
||||
|
||||
list.Add(displayInfo);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
if (!ADLWrapper.Initialize())
|
||||
{
|
||||
//throw new InvalidOperationException("Cannot load AMD API");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Uninitialize()
|
||||
{
|
||||
ADLWrapper.Uninitialze();
|
||||
}
|
||||
|
||||
public List<AmdPreset> GetDisplayPresets()
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = new List<AmdPreset>();
|
||||
|
||||
var displayInfos = GetSimpleDisplayInfos();
|
||||
|
||||
foreach (var displayInfo in displayInfos)
|
||||
{
|
||||
var preset = GetPresetForDisplay(displayInfo, displayInfos.Count());
|
||||
|
||||
displayInfo.Values = preset.GetDisplayValues(_globalContext.Config);
|
||||
displayInfo.InfoLine = preset.InfoLine;
|
||||
|
||||
list.Add(preset);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("Error while getting displays: " + e.ToLogString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public AmdPreset GetPresetForDisplay(AmdDisplayInfo displayInfo, int displayCount = 1)
|
||||
{
|
||||
if (displayInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var display = displayInfo.Display;
|
||||
|
||||
var colorDepth = ADLColorDepth.UNKNOWN;
|
||||
ADLWrapper.GetDisplayColorDepth(display, ref colorDepth);
|
||||
|
||||
var pixelFormat = ADLPixelFormat.UNKNOWN;
|
||||
ADLWrapper.GetDisplayPixelFormat(display, ref pixelFormat);
|
||||
|
||||
var ditherState = GetDithering(display);
|
||||
|
||||
var screen = GetScreenForDisplay(display);
|
||||
var displayConfig = CCD.GetDisplayConfig(screen?.DeviceName);
|
||||
|
||||
var ccdDisplay = screen != null ? CCD.GetDisplayInfo(screen.DeviceName) : null;
|
||||
|
||||
var hdrEnabled = IsHDREnabled(display);
|
||||
|
||||
var preset = new AmdPreset
|
||||
{
|
||||
IsDisplayPreset = true,
|
||||
displayName = display.DisplayName,
|
||||
DisplayId = ccdDisplay?.DisplayId,
|
||||
primaryDisplay = screen?.Primary == true,
|
||||
colorDepth = colorDepth,
|
||||
pixelFormat = pixelFormat,
|
||||
ditherState = ditherState,
|
||||
DisplayConfig = displayConfig,
|
||||
SDRBrightness = hdrEnabled ? GetSDRBrightness(screen?.DeviceName) : null,
|
||||
HDREnabled = hdrEnabled,
|
||||
};
|
||||
|
||||
return preset;
|
||||
}
|
||||
|
||||
private void SaveConfig()
|
||||
{
|
||||
Utils.WriteObject(_configFilename, Config);
|
||||
}
|
||||
|
||||
public AmdServiceConfig GetConfig()
|
||||
{
|
||||
return Config;
|
||||
}
|
||||
|
||||
public bool UpdateConfig(AmdServiceConfig config)
|
||||
{
|
||||
Config.Update(config);
|
||||
|
||||
SetShortcuts(SHORTCUTID_AMDQA, Config.QuickAccessShortcut);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdatePreset(AmdPreset specPreset)
|
||||
{
|
||||
var currentPreset = _presets.FirstOrDefault(p => p.id == specPreset.id);
|
||||
|
||||
if (currentPreset != null)
|
||||
{
|
||||
currentPreset.name = specPreset.name;
|
||||
currentPreset.shortcut = specPreset.shortcut;
|
||||
currentPreset.Update(specPreset);
|
||||
return true;
|
||||
}
|
||||
|
||||
var newPreset = new AmdPreset(specPreset);
|
||||
newPreset.name = specPreset.name;
|
||||
newPreset.shortcut = specPreset.shortcut;
|
||||
|
||||
_presets.Add(newPreset);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace ColorControl.Services.Common
|
||||
{
|
||||
public class AppContextProvider
|
||||
{
|
||||
public AppContext GetAppContext()
|
||||
{
|
||||
return Program.AppContext;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.Forms;
|
||||
using ColorControl.Shared.Services;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ColorControl.Services.Common;
|
||||
|
||||
public class ElevationService
|
||||
{
|
||||
private readonly WinApiService _winApiService;
|
||||
private readonly WinApiAdminService _winApiAdminService;
|
||||
private readonly GlobalContext _globalContext;
|
||||
|
||||
private readonly Config _config;
|
||||
|
||||
public ElevationService(WinApiService winApiService, WinApiAdminService winApiAdminService, GlobalContext globalContext)
|
||||
{
|
||||
_winApiService = winApiService;
|
||||
_winApiAdminService = winApiAdminService;
|
||||
_globalContext = globalContext;
|
||||
|
||||
_config = globalContext.Config;
|
||||
}
|
||||
|
||||
public void SetElevationMethod(ElevationMethod elevationMethod, bool startAfterLoginChecked = false)
|
||||
{
|
||||
_config.ElevationMethod = elevationMethod;
|
||||
|
||||
var _ = _config.ElevationMethod switch
|
||||
{
|
||||
ElevationMethod.None => SetElevationMethodNone(startAfterLoginChecked),
|
||||
ElevationMethod.RunAsAdmin => SetElevationMethodRunAsAdmin(startAfterLoginChecked),
|
||||
ElevationMethod.UseService => SetElevationMethodUseService(),
|
||||
ElevationMethod.UseElevatedProcess => SetElevationMethodUseElevatedProcess(startAfterLoginChecked),
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
|
||||
public void RegisterScheduledTask(bool enabled = true)
|
||||
{
|
||||
_winApiAdminService.RegisterTask(Program.TS_TASKNAME, enabled, _config.ElevationMethod == ElevationMethod.RunAsAdmin ? Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest : Microsoft.Win32.TaskScheduler.TaskRunLevel.LUA);
|
||||
}
|
||||
|
||||
public void CheckElevationMethod()
|
||||
{
|
||||
if (_winApiService.IsAdministrator())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_config.ElevationMethodAsked)
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_config.ElevationMethod == ElevationMethod.UseService && !_winApiService.IsServiceInstalled() &&
|
||||
(MessageForms.QuestionYesNo("The elevation method is set to Windows Service but it is not installed. Do you want to install it now?") == DialogResult.Yes))
|
||||
{
|
||||
_winApiAdminService.InstallService();
|
||||
}
|
||||
else if (_config.ElevationMethod == ElevationMethod.UseService && !_winApiService.IsServiceRunning() &&
|
||||
(MessageForms.QuestionYesNo("The elevation method is set to Windows Service but it is not running. Do you want to start it now?") == DialogResult.Yes))
|
||||
{
|
||||
_winApiAdminService.StartService();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var result = MessageForms.QuestionYesNo(Utils.ELEVATION_MSG + @"
|
||||
|
||||
Do you want to install and start the Windows Service now? You can always change this on the Options-tab page.
|
||||
|
||||
NOTE: installing the service may cause a User Account Control popup.");
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
SetElevationMethod(ElevationMethod.UseService);
|
||||
}
|
||||
|
||||
_config.ElevationMethodAsked = true;
|
||||
}
|
||||
|
||||
private bool SetElevationMethodNone(bool startAfterLoginChecked = false)
|
||||
{
|
||||
if (startAfterLoginChecked)
|
||||
{
|
||||
RegisterScheduledTask();
|
||||
}
|
||||
|
||||
_winApiAdminService.UninstallService();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SetElevationMethodRunAsAdmin(bool startAfterLoginChecked = false)
|
||||
{
|
||||
if (startAfterLoginChecked)
|
||||
{
|
||||
RegisterScheduledTask(false);
|
||||
RegisterScheduledTask();
|
||||
}
|
||||
|
||||
_winApiAdminService.UninstallService();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SetElevationMethodUseService()
|
||||
{
|
||||
_winApiAdminService.InstallService();
|
||||
|
||||
if (_winApiService.IsServiceInstalled())
|
||||
{
|
||||
MessageForms.InfoOk("Service installed successfully.");
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageForms.ErrorOk("Service could not be installed. Check the logs.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool SetElevationMethodUseElevatedProcess(bool startAfterLoginChecked = false)
|
||||
{
|
||||
if (startAfterLoginChecked)
|
||||
{
|
||||
RegisterScheduledTask();
|
||||
}
|
||||
|
||||
_winApiAdminService.UninstallService();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
using ColorControl.Native;
|
||||
using ColorControl.Shared.Common;
|
||||
using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.Forms;
|
||||
using ColorControl.Shared.Native;
|
||||
using NWin32;
|
||||
using NWin32.NativeTypes;
|
||||
using Shared.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace ColorControl.Services.Common
|
||||
{
|
||||
@@ -14,7 +14,10 @@ namespace ColorControl.Services.Common
|
||||
{
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public GraphicsService(AppContextProvider appContextProvider) : base(appContextProvider)
|
||||
private int _lastSetSDRBrightness = -1;
|
||||
private int _lastReadSDRBrightness = -1;
|
||||
|
||||
public GraphicsService(GlobalContext globalContext) : base(globalContext)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -25,123 +28,111 @@ namespace ColorControl.Services.Common
|
||||
|
||||
public abstract bool HasDisplaysAttached(bool reinitialize = false);
|
||||
|
||||
protected void ToggleHDR(int delay = 1000)
|
||||
public bool SetMode(string displayName, VirtualResolution resolution = null, Rational refreshRate = null, bool updateRegistry = false)
|
||||
{
|
||||
Process.Start("ms-settings:display");
|
||||
Thread.Sleep(delay);
|
||||
var displayConfig = CCD.GetDisplayConfig(displayName);
|
||||
|
||||
var process = Process.GetProcessesByName("SystemSettings").FirstOrDefault();
|
||||
if (process != null)
|
||||
if (refreshRate != null)
|
||||
{
|
||||
System.Windows.Forms.SendKeys.SendWait("{TAB}");
|
||||
System.Windows.Forms.SendKeys.SendWait("{TAB}");
|
||||
System.Windows.Forms.SendKeys.SendWait(" ");
|
||||
System.Windows.Forms.SendKeys.SendWait("%{F4}");
|
||||
displayConfig.ApplyRefreshRate = true;
|
||||
displayConfig.RefreshRate = refreshRate;
|
||||
}
|
||||
|
||||
if (resolution != null)
|
||||
{
|
||||
displayConfig.ApplyResolution = true;
|
||||
displayConfig.Resolution = resolution;
|
||||
}
|
||||
|
||||
return SetMode(displayName, displayConfig, updateRegistry);
|
||||
}
|
||||
|
||||
protected void OpenDisplaySettings(int delay = 1000)
|
||||
public bool SetMode(string displayName, DisplayConfig displayConfig, bool updateRegistry = false)
|
||||
{
|
||||
Process.Start("ms-settings:display");
|
||||
Thread.Sleep(delay);
|
||||
var currentDisplayConfig = CCD.GetDisplayConfig(displayName);
|
||||
|
||||
var process = Process.GetProcessesByName("SystemSettings").FirstOrDefault();
|
||||
if (process != null)
|
||||
if (displayConfig.ApplyRefreshRate)
|
||||
{
|
||||
System.Windows.Forms.SendKeys.SendWait("%{F4}");
|
||||
currentDisplayConfig.RefreshRate = displayConfig.RefreshRate;
|
||||
}
|
||||
|
||||
if (displayConfig.ApplyResolution)
|
||||
{
|
||||
currentDisplayConfig.Resolution = displayConfig.Resolution;
|
||||
}
|
||||
|
||||
if (displayConfig.Scaling != CCD.DisplayConfigScaling.Zero)
|
||||
{
|
||||
currentDisplayConfig.Scaling = displayConfig.Scaling;
|
||||
}
|
||||
|
||||
if (displayConfig.Rotation != CCD.DisplayConfigRotation.Zero)
|
||||
{
|
||||
currentDisplayConfig.Rotation = displayConfig.Rotation;
|
||||
}
|
||||
|
||||
return CCD.SetDisplayConfig(displayName, currentDisplayConfig, updateRegistry);
|
||||
}
|
||||
|
||||
protected bool SetRefreshRateInternal(string displayName, int refreshRate, bool portrait, int horizontal, int vertical, bool updateRegistry = false)
|
||||
public void SetSDRBrightness(string displayName, int brightnessPercent)
|
||||
{
|
||||
uint i = 0;
|
||||
DEVMODEA devMode;
|
||||
while (NativeMethods.EnumDisplaySettingsA(displayName, i, out devMode))
|
||||
var hmon = FormUtils.GetMonitorForDisplayName(displayName);
|
||||
|
||||
if (hmon == IntPtr.Zero)
|
||||
{
|
||||
// Also compare width with vertical and height with horizontal in case of portrait mode
|
||||
if (((!portrait && devMode.dmPelsWidth == horizontal && devMode.dmPelsHeight == vertical) ||
|
||||
(portrait && devMode.dmPelsWidth == vertical && devMode.dmPelsHeight == horizontal))
|
||||
&& devMode.dmBitsPerPel == 32 && devMode.dmDisplayFrequency == refreshRate)
|
||||
hmon = NativeMethods.MonitorFromWindow(0, 1);
|
||||
}
|
||||
|
||||
var brightness = 1 + (double)brightnessPercent / 20;
|
||||
|
||||
WinApi.DwmpSDRToHDRBoostPtr(hmon, brightness);
|
||||
|
||||
_lastSetSDRBrightness = brightnessPercent;
|
||||
}
|
||||
|
||||
public int GetSDRBrightness(string displayName)
|
||||
{
|
||||
var whiteLevel = CCD.GetSDRWhiteLevel(displayName);
|
||||
|
||||
if (whiteLevel >= 1000)
|
||||
{
|
||||
var newBrightnessPercent = (int)(whiteLevel - 1000) / 50;
|
||||
|
||||
if (_lastSetSDRBrightness >= 0 && newBrightnessPercent == _lastReadSDRBrightness)
|
||||
{
|
||||
IntPtr bla = Marshal.AllocHGlobal(Marshal.SizeOf(devMode));
|
||||
Marshal.StructureToPtr(devMode, bla, false);
|
||||
var result = NativeMethods.ChangeDisplaySettingsExA(displayName, bla, IntPtr.Zero, updateRegistry ? (uint)NativeConstants.CDS_UPDATEREGISTRY : 0, IntPtr.Zero);
|
||||
if (result != NativeConstants.DISP_CHANGE_SUCCESSFUL)
|
||||
{
|
||||
Logger.Error($"Could not set refreshrate {refreshRate} on display {displayName} because ChangeDisplaySettingsExA returned a non-zero return code: {result}");
|
||||
}
|
||||
return result == NativeConstants.DISP_CHANGE_SUCCESSFUL;
|
||||
return _lastSetSDRBrightness;
|
||||
}
|
||||
i++;
|
||||
|
||||
_lastReadSDRBrightness = newBrightnessPercent;
|
||||
|
||||
return newBrightnessPercent;
|
||||
}
|
||||
Logger.Info($"Could not set refreshrate {refreshRate} on display {displayName} because EnumDisplaySettings did not report it as a valid refreshrate");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected List<uint> GetAvailableRefreshRatesInternal(string displayName, bool portrait, int horizontal, int vertical)
|
||||
{
|
||||
var list = new List<uint>();
|
||||
|
||||
uint i = 0;
|
||||
DEVMODEA devMode;
|
||||
while (NativeMethods.EnumDisplaySettingsA(displayName, i, out devMode))
|
||||
{
|
||||
if (((!portrait && devMode.dmPelsWidth == horizontal && devMode.dmPelsHeight == vertical) ||
|
||||
(portrait && devMode.dmPelsWidth == vertical && devMode.dmPelsHeight == horizontal)) &&
|
||||
!list.Contains(devMode.dmDisplayFrequency))
|
||||
{
|
||||
list.Add(devMode.dmDisplayFrequency);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
protected uint GetCurrentRefreshRate(string displayName)
|
||||
{
|
||||
DEVMODEA devMode;
|
||||
// NativeMethods defines modeNum as an 'uint' but we need to pass '-1'
|
||||
if (WinApi.EnumDisplaySettingsA(displayName, WinApi.ENUM_CURRENT_SETTINGS, out devMode))
|
||||
{
|
||||
return devMode.dmDisplayFrequency;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected DEVMODEA GetCurrentMode(string displayName)
|
||||
protected List<Rational> GetAvailableRefreshRatesV2(string displayName, int horizontal, int vertical)
|
||||
{
|
||||
DEVMODEA devMode;
|
||||
// NativeMethods defines modeNum as an 'uint' but we need to pass '-1'
|
||||
if (WinApi.EnumDisplaySettingsA(displayName, WinApi.ENUM_CURRENT_SETTINGS, out devMode))
|
||||
{
|
||||
return devMode;
|
||||
}
|
||||
return devMode;
|
||||
var dxWrapper = new DXWrapper();
|
||||
|
||||
var modes = dxWrapper.GetModes(displayName, (uint)horizontal, (uint)vertical);
|
||||
|
||||
var refreshRates = modes.Select(m => m.RefreshRate).DistinctBy(r => r.ToString())
|
||||
.Select(r => new Rational(r.Numerator, r.Denominator));
|
||||
|
||||
return refreshRates.ToList();
|
||||
}
|
||||
|
||||
protected List<DEVMODEA> GetAvailableResolutionsInternal(string displayName, bool portrait, uint refreshRate = 0)
|
||||
protected List<VirtualResolution> GetAvailableResolutionsInternalV2(string displayName, Rational refreshRate = null)
|
||||
{
|
||||
var list = new List<DEVMODEA>();
|
||||
var dxWrapper = new DXWrapper();
|
||||
|
||||
uint i = 0;
|
||||
DEVMODEA devMode;
|
||||
while (NativeMethods.EnumDisplaySettingsA(displayName, i, out devMode))
|
||||
{
|
||||
if ((portrait ? devMode.dmPelsWidth < devMode.dmPelsHeight : devMode.dmPelsWidth > devMode.dmPelsHeight) &&
|
||||
(refreshRate == 0 || devMode.dmDisplayFrequency == refreshRate) &&
|
||||
!list.Any(m => m.dmPelsWidth == devMode.dmPelsWidth && m.dmPelsHeight == devMode.dmPelsHeight))
|
||||
{
|
||||
list.Add(devMode);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
var modes = dxWrapper.GetModes(displayName);
|
||||
|
||||
list.Sort((a, b) => (int)(a.dmPelsWidth - b.dmPelsWidth));
|
||||
var refreshRates = modes.DistinctBy(m => $"{m.Resolution.width}x{m.Resolution.height}")
|
||||
.Select(m => new VirtualResolution(m.Resolution.width, m.Resolution.height));
|
||||
|
||||
return list;
|
||||
return refreshRates.ToList();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ColorControl.Services.Common;
|
||||
|
||||
public interface IServiceBase
|
||||
{
|
||||
List<string> GetInfo();
|
||||
void InstallEventHandlers();
|
||||
}
|
||||
Loaded 100 of 422 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user