158 lines
5.6 KiB
C#
158 lines
5.6 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
using Elfisa.UI.Theming;
|
|
|
|
namespace Elfisa.UI.Helpers
|
|
{
|
|
public static class WindowChromeHelper
|
|
{
|
|
private const int DwmwaUseImmersiveDarkMode = 20;
|
|
private const int DwmwaUseImmersiveDarkModeLegacy = 19;
|
|
private const int DwmwaCaptionColor = 35;
|
|
private const int DwmwaTextColor = 36;
|
|
|
|
private const uint SwpNomove = 0x0002;
|
|
private const uint SwpNosize = 0x0001;
|
|
private const uint SwpNozorder = 0x0004;
|
|
private const uint SwpFramechanged = 0x0020;
|
|
|
|
[DllImport("dwmapi.dll", PreserveSig = true)]
|
|
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, ref int pvAttribute, int cbAttribute);
|
|
|
|
[DllImport("dwmapi.dll", PreserveSig = true)]
|
|
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, ref uint pvAttribute, int cbAttribute);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
private static extern bool SetWindowPos(
|
|
IntPtr hWnd,
|
|
IntPtr hWndInsertAfter,
|
|
int x,
|
|
int y,
|
|
int cx,
|
|
int cy,
|
|
uint uFlags);
|
|
|
|
public static void ApplyTitleBarTheme(Form form, ThemeColors theme)
|
|
{
|
|
if (form == null || theme == null || !form.IsHandleCreated)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var isDark = theme.Mode == ThemeMode.Dark;
|
|
var useDarkMode = isDark ? 1 : 0;
|
|
TrySetInt(form.Handle, DwmwaUseImmersiveDarkMode, useDarkMode);
|
|
TrySetInt(form.Handle, DwmwaUseImmersiveDarkModeLegacy, useDarkMode);
|
|
|
|
var caption = theme.AccentPrimary;
|
|
var text = IsLightCaption(caption) ? Color.Black : Color.White;
|
|
|
|
TrySetUInt(form.Handle, DwmwaCaptionColor, ColorToDwm(caption));
|
|
TrySetUInt(form.Handle, DwmwaTextColor, ColorToDwm(text));
|
|
|
|
RefreshNonClientArea(form);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Обработка ресайза для FormBorderStyle.None (края окна).
|
|
/// </summary>
|
|
public static bool TryHandleNcHitTest(Form form, ref Message m, int border = 6)
|
|
{
|
|
const int wmNcHitTest = 0x84;
|
|
if (m.Msg != wmNcHitTest || form == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var screen = new Point(m.LParam.ToInt32() & 0xFFFF, (m.LParam.ToInt32() >> 16) & 0xFFFF);
|
|
// signed short for multi-monitor negative coords
|
|
screen = new Point((short)(m.LParam.ToInt32() & 0xFFFF), (short)((m.LParam.ToInt32() >> 16) & 0xFFFF));
|
|
var client = form.PointToClient(screen);
|
|
var w = form.ClientSize.Width;
|
|
var h = form.ClientSize.Height;
|
|
|
|
var left = client.X <= border;
|
|
var right = client.X >= w - border;
|
|
var top = client.Y <= border;
|
|
var bottom = client.Y >= h - border;
|
|
|
|
if (top && left) { m.Result = (IntPtr)13; return true; } // HTTOPLEFT
|
|
if (top && right) { m.Result = (IntPtr)14; return true; } // HTTOPRIGHT
|
|
if (bottom && left) { m.Result = (IntPtr)16; return true; } // HTBOTTOMLEFT
|
|
if (bottom && right) { m.Result = (IntPtr)17; return true; } // HTBOTTOMRIGHT
|
|
if (left) { m.Result = (IntPtr)10; return true; } // HTLEFT
|
|
if (right) { m.Result = (IntPtr)11; return true; } // HTRIGHT
|
|
if (top) { m.Result = (IntPtr)12; return true; } // HTTOP
|
|
if (bottom) { m.Result = (IntPtr)15; return true; } // HTBOTTOM
|
|
|
|
return false;
|
|
}
|
|
|
|
public static void ApplyThemedDialogHeader(Panel headerPanel, Label headerLabel, ThemeColors theme)
|
|
{
|
|
if (theme == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (headerPanel != null)
|
|
{
|
|
headerPanel.BackColor = theme.TitleBarTop;
|
|
}
|
|
|
|
if (headerLabel != null)
|
|
{
|
|
headerLabel.ForeColor = IsLightCaption(theme.TitleBarTop) ? Color.Black : Color.White;
|
|
}
|
|
}
|
|
|
|
private static bool IsLightCaption(Color color)
|
|
{
|
|
var luminance = (0.299 * color.R) + (0.587 * color.G) + (0.114 * color.B);
|
|
return luminance > 180;
|
|
}
|
|
|
|
public static void ApplyDialogChrome(Form form, Panel headerPanel = null, Label headerLabel = null)
|
|
{
|
|
if (form == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var theme = ThemeManager.Colors;
|
|
ApplyThemedDialogHeader(headerPanel, headerLabel, theme);
|
|
|
|
if (form.IsHandleCreated)
|
|
{
|
|
ApplyTitleBarTheme(form, theme);
|
|
}
|
|
else
|
|
{
|
|
form.HandleCreated += (_, __) => ApplyTitleBarTheme(form, ThemeManager.Colors);
|
|
}
|
|
}
|
|
|
|
private static uint ColorToDwm(Color color)
|
|
{
|
|
return (uint)(color.R | (color.G << 8) | (color.B << 16));
|
|
}
|
|
|
|
private static void RefreshNonClientArea(Form form)
|
|
{
|
|
SetWindowPos(form.Handle, IntPtr.Zero, 0, 0, 0, 0, SwpNomove | SwpNosize | SwpNozorder | SwpFramechanged);
|
|
}
|
|
|
|
private static void TrySetInt(IntPtr handle, int attribute, int value)
|
|
{
|
|
DwmSetWindowAttribute(handle, attribute, ref value, sizeof(int));
|
|
}
|
|
|
|
private static void TrySetUInt(IntPtr handle, int attribute, uint value)
|
|
{
|
|
DwmSetWindowAttribute(handle, attribute, ref value, sizeof(uint));
|
|
}
|
|
}
|
|
}
|