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}"; } }