using Microsoft.Win32; using System.ComponentModel; using System.Drawing.Drawing2D; using System.Runtime.InteropServices; namespace CustomControls { public class RForm : Form { public static Color colorEco = Color.FromArgb(255, 6, 180, 138); public static Color colorStandard = Color.FromArgb(255, 58, 174, 239); public static Color colorTurbo = Color.FromArgb(255, 255, 32, 32); public static Color buttonMain; public static Color buttonSecond; public static Color formBack; public static Color foreMain; public static Color borderMain; public static Color chartMain; public static Color chartGrid; [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")] public static extern bool CheckSystemDarkModeStatus(); [DllImport("DwmApi")] //System.Runtime.InteropServices private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, int[] attrValue, int attrSize); public bool darkTheme = false; public static void InitColors(bool darkTheme) { if (darkTheme) { buttonMain = Color.FromArgb(255, 55, 55, 55); buttonSecond = Color.FromArgb(255, 38, 38, 38); formBack = Color.FromArgb(255, 28, 28, 28); foreMain = Color.FromArgb(255, 240, 240, 240); borderMain = Color.FromArgb(255, 50, 50, 50); chartMain = Color.FromArgb(255, 35, 35, 35); chartGrid = Color.FromArgb(255, 70, 70, 70); } else { buttonMain = SystemColors.ControlLightLight; buttonSecond = SystemColors.ControlLight; formBack = SystemColors.Control; foreMain = SystemColors.ControlText; borderMain = Color.LightGray; chartMain = SystemColors.ControlLightLight; chartGrid = Color.LightGray; } } private static bool IsDarkTheme() { using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"); var registryValueObject = key?.GetValue("AppsUseLightTheme"); if (registryValueObject == null) return false; return (int)registryValueObject <= 0; } public bool InitTheme(bool setDPI = false) { bool newDarkTheme = CheckSystemDarkModeStatus(); bool changed = (darkTheme != newDarkTheme); darkTheme = newDarkTheme; InitColors(darkTheme); if (setDPI) ControlHelper.Resize(this); if (changed) { DwmSetWindowAttribute(this.Handle, 20, new[] { darkTheme ? 1 : 0 }, 4); ControlHelper.Adjust(this, changed); } return changed; } } public class RCheckBox : CheckBox { } public class RComboBox : ComboBox { private Color borderColor = Color.Gray; [DefaultValue(typeof(Color), "Gray")] public Color BorderColor { get { return borderColor; } set { if (borderColor != value) { borderColor = value; Invalidate(); } } } private Color buttonColor = Color.FromArgb(255, 255, 255, 255); [DefaultValue(typeof(Color), "255, 255, 255")] public Color ButtonColor { get { return buttonColor; } set { if (buttonColor != value) { buttonColor = value; Invalidate(); } } } private Color arrowColor = Color.Black; [DefaultValue(typeof(Color), "Black")] public Color ArrowColor { get { return arrowColor; } set { if (arrowColor != value) { arrowColor = value; Invalidate(); } } } protected override void WndProc(ref Message m) { if (m.Msg == WM_PAINT && DropDownStyle != ComboBoxStyle.Simple) { var clientRect = ClientRectangle; var dropDownButtonWidth = SystemInformation.HorizontalScrollBarArrowWidth; var outerBorder = new Rectangle(clientRect.Location, new Size(clientRect.Width - 1, clientRect.Height - 1)); var innerBorder = new Rectangle(outerBorder.X + 1, outerBorder.Y + 1, outerBorder.Width - dropDownButtonWidth - 2, outerBorder.Height - 2); var innerInnerBorder = new Rectangle(innerBorder.X + 1, innerBorder.Y + 1, innerBorder.Width - 2, innerBorder.Height - 2); var dropDownRect = new Rectangle(innerBorder.Right + 1, innerBorder.Y, dropDownButtonWidth, innerBorder.Height + 1); if (RightToLeft == RightToLeft.Yes) { innerBorder.X = clientRect.Width - innerBorder.Right; innerInnerBorder.X = clientRect.Width - innerInnerBorder.Right; dropDownRect.X = clientRect.Width - dropDownRect.Right; dropDownRect.Width += 1; } var innerBorderColor = Enabled ? BackColor : SystemColors.Control; var outerBorderColor = Enabled ? BorderColor : SystemColors.ControlDark; var buttonColor = Enabled ? ButtonColor : SystemColors.Control; var middle = new Point(dropDownRect.Left + dropDownRect.Width / 2, dropDownRect.Top + dropDownRect.Height / 2); var arrow = new Point[] { new Point(middle.X - 3, middle.Y - 2), new Point(middle.X + 4, middle.Y - 2), new Point(middle.X, middle.Y + 2) }; var ps = new PAINTSTRUCT(); bool shoulEndPaint = false; IntPtr dc; if (m.WParam == IntPtr.Zero) { dc = BeginPaint(Handle, ref ps); m.WParam = dc; shoulEndPaint = true; } else { dc = m.WParam; } var rgn = CreateRectRgn(innerInnerBorder.Left, innerInnerBorder.Top, innerInnerBorder.Right, innerInnerBorder.Bottom); SelectClipRgn(dc, rgn); DefWndProc(ref m); DeleteObject(rgn); rgn = CreateRectRgn(clientRect.Left, clientRect.Top, clientRect.Right, clientRect.Bottom); SelectClipRgn(dc, rgn); using (var g = Graphics.FromHdc(dc)) { using (var b = new SolidBrush(buttonColor)) { g.FillRectangle(b, dropDownRect); } using (var b = new SolidBrush(arrowColor)) { g.FillPolygon(b, arrow); } using (var p = new Pen(innerBorderColor)) { g.DrawRectangle(p, innerBorder); g.DrawRectangle(p, innerInnerBorder); } using (var p = new Pen(outerBorderColor)) { g.DrawRectangle(p, outerBorder); } } if (shoulEndPaint) EndPaint(Handle, ref ps); DeleteObject(rgn); } else base.WndProc(ref m); } private const int WM_PAINT = 0xF; [StructLayout(LayoutKind.Sequential)] public struct RECT { public int L, T, R, B; } [StructLayout(LayoutKind.Sequential)] public struct PAINTSTRUCT { public IntPtr hdc; public bool fErase; public int rcPaint_left; public int rcPaint_top; public int rcPaint_right; public int rcPaint_bottom; public bool fRestore; public bool fIncUpdate; public int reserved1; public int reserved2; public int reserved3; public int reserved4; public int reserved5; public int reserved6; public int reserved7; public int reserved8; } [DllImport("user32.dll")] private static extern IntPtr BeginPaint(IntPtr hWnd, [In, Out] ref PAINTSTRUCT lpPaint); [DllImport("user32.dll")] private static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT lpPaint); [DllImport("gdi32.dll")] public static extern int SelectClipRgn(IntPtr hDC, IntPtr hRgn); [DllImport("user32.dll")] public static extern int GetUpdateRgn(IntPtr hwnd, IntPtr hrgn, bool fErase); public enum RegionFlags { ERROR = 0, NULLREGION = 1, SIMPLEREGION = 2, COMPLEXREGION = 3, } [DllImport("gdi32.dll")] internal static extern bool DeleteObject(IntPtr hObject); [DllImport("gdi32.dll")] private static extern IntPtr CreateRectRgn(int x1, int y1, int x2, int y2); } public class RButton : Button { //Fields private int borderSize = 5; private int borderRadius = 5; public int BorderRadius { get { return borderRadius; } set { borderRadius = value; } } private Color borderColor = Color.Transparent; public Color BorderColor { get { return borderColor; } set { borderColor = value; } } private bool activated = false; public bool Activated { get { return activated; } set { if (activated != value) this.Invalidate(); activated = value; } } private bool secondary = false; public bool Secondary { get { return secondary; } set { secondary = value; } } public RButton() { DoubleBuffered = true; FlatStyle = FlatStyle.Flat; FlatAppearance.BorderSize = 0; } private GraphicsPath GetFigurePath(Rectangle rect, int radius) { GraphicsPath path = new GraphicsPath(); float curveSize = radius * 2F; path.StartFigure(); path.AddArc(rect.X, rect.Y, curveSize, curveSize, 180, 90); path.AddArc(rect.Right - curveSize, rect.Y, curveSize, curveSize, 270, 90); path.AddArc(rect.Right - curveSize, rect.Bottom - curveSize, curveSize, curveSize, 0, 90); path.AddArc(rect.X, rect.Bottom - curveSize, curveSize, curveSize, 90, 90); path.CloseFigure(); return path; } protected override void OnPaint(PaintEventArgs pevent) { base.OnPaint(pevent); float ratio = pevent.Graphics.DpiX / 192.0f; int border = (int)(ratio * borderSize); Rectangle rectSurface = this.ClientRectangle; Rectangle rectBorder = Rectangle.Inflate(rectSurface, -border, -border); Color borderDrawColor = activated ? borderColor : Color.Transparent; using (GraphicsPath pathSurface = GetFigurePath(rectSurface, borderRadius + border)) using (GraphicsPath pathBorder = GetFigurePath(rectBorder, borderRadius)) using (Pen penSurface = new Pen(this.Parent.BackColor, border)) using (Pen penBorder = new Pen(borderDrawColor, border)) { penBorder.Alignment = PenAlignment.Outset; pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias; this.Region = new Region(pathSurface); pevent.Graphics.DrawPath(penSurface, pathSurface); pevent.Graphics.DrawPath(penBorder, pathBorder); } if (!Enabled && ForeColor != SystemColors.ControlText) { var rect = pevent.ClipRectangle; if (Image is not null) { rect.Y += Image.Height; rect.Height -= Image.Height; } TextFormatFlags flags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak; TextRenderer.DrawText(pevent.Graphics, this.Text, this.Font, rect, Color.Gray, flags); } } } }