using System;
using System.Drawing;
using System.Windows.Forms;
namespace UI
{
///
/// Detecta automaticamente o perfil de tela (Monitor ou Notebook)
/// combinando resolução e DPI, e fornece fatores de escala para
/// dimensões e fontes de forma centralizada.
///
/// Base de referência do layout: 1920x1080 a 96 DPI = Scale 1.0
/// O layout base foi desenhado compacto (sem escalação excessiva),
/// então Monitor FHD usa 1.0 e os demais perfis sobem/descem a partir daí.
///
public static class ScreenProfile
{
// ─────────────────────────────────────────────
// Enum de perfil
// ─────────────────────────────────────────────
public enum ProfileType
{
NotebookHD, // ≤ 1366 x 768
NotebookHDPlus, // 1600 x 900
MonitorFHD, // 1920 x 1080 ← referência (Scale = 1.0)
MonitorQHD, // 2560 x 1440
MonitorUHD // 3840 x 2160 (4K)
}
// ─────────────────────────────────────────────
// Propriedades públicas
// ─────────────────────────────────────────────
/// Perfil detectado.
public static ProfileType Profile { get; private set; }
/// Fator de escala para dimensões e posições.
public static float Scale { get; private set; }
/// Fator de escala específico para fontes.
public static float FontScale { get; private set; }
/// DPI real da tela primária.
public static float Dpi { get; private set; }
/// Resolução da tela primária.
public static Size Resolution { get; private set; }
// ─────────────────────────────────────────────
// Inicialização estática
// ─────────────────────────────────────────────
static ScreenProfile() => Detect();
private static void Detect()
{
// 1. Resolução física
var screen = Screen.PrimaryScreen!;
int w = screen.Bounds.Width;
int h = screen.Bounds.Height;
Resolution = new Size(w, h);
// 2. DPI real (96 = 100%, 120 = 125%, 144 = 150%, 192 = 200%)
using var g = Graphics.FromHwnd(IntPtr.Zero);
Dpi = g.DpiX;
// 3. Correção: evita dupla escala quando Windows Scaling está ativo
float dpiCorrection = Dpi > 96f ? (96f / Dpi) : 1f;
// 4. Escala base por resolução
// Referência: Monitor FHD = 1.0 (layout desenhado para 1920x1080)
if (w >= 3840)
{
Profile = ProfileType.MonitorUHD;
Scale = 1.40f;
FontScale = 1.30f;
}
else if (w >= 2560)
{
Profile = ProfileType.MonitorQHD;
Scale = 1.20f;
FontScale = 1.15f;
}
else if (w >= 1920)
{
Profile = ProfileType.MonitorFHD;
Scale = 1.00f; // ← referência
FontScale = 1.00f;
}
else if (w >= 1600)
{
Profile = ProfileType.NotebookHDPlus;
Scale = 0.85f;
FontScale = 0.88f;
}
else
{
Profile = ProfileType.NotebookHD;
Scale = 0.72f;
FontScale = 0.76f;
}
// 5. Aplica correção de DPI
Scale *= dpiCorrection;
FontScale *= dpiCorrection;
// 6. Limita range seguro
Scale = Math.Clamp(Scale, 0.65f, 1.50f);
FontScale = Math.Clamp(FontScale, 0.70f, 1.40f);
}
// ─────────────────────────────────────────────
// Helpers de escala
// ─────────────────────────────────────────────
/// Escala um valor inteiro (dimensão ou posição).
public static int S(int value) => (int)Math.Round(value * Scale);
/// Escala um ponto.
public static Point P(int x, int y) => new(S(x), S(y));
/// Escala um tamanho.
public static Size Sz(int w, int h) => new(S(w), S(h));
/// Escala um retângulo.
public static Rectangle R(int x, int y, int w, int h)
=> new(S(x), S(y), S(w), S(h));
/// Escala um tamanho de fonte.
public static float F(float pt) => (float)Math.Round(pt * FontScale, 1);
// ─────────────────────────────────────────────
// Diagnóstico
// ─────────────────────────────────────────────
public static string Diagnostico()
=> $"Perfil: {Profile} | {Resolution.Width}x{Resolution.Height} | " +
$"DPI: {Dpi:F0} | Scale: {Scale:F2} | FontScale: {FontScale:F2}";
}
}