src/GUI/UItools.ps1

# GDI+ 绘制类型(Graphics/Pen/Font/GraphicsPath)在 .NET Core 下位于 System.Drawing.Common(.NET 10 起再拆出 System.Private.Windows.*),Framework 下并进 System.Drawing。
try { Add-Type -AssemblyName System.Windows.Forms; Add-Type -AssemblyName System.Drawing } catch { }
$GUICSharpReferences = @('System.Windows.Forms', 'System.Drawing', 'System.Drawing.Primitives', 'System.Net.Primitives', 'System.ComponentModel.Primitives', 'Microsoft.Win32.Primitives')
if ($PSVersionTable.PSEdition -eq 'Core') {
    foreach ($optionalReference in @('System.Drawing.Common', 'System.Private.Windows.Core', 'System.Private.Windows.GdiPlus')) {
        try { [void][System.Reflection.Assembly]::Load($optionalReference); $GUICSharpReferences += $optionalReference } catch { }
    }
}

Add-Type @"
using System;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace ps12exeGUI {
    // 扁平圆角分组卡片:系统 GroupBox 的 3D 边框在深色下会露出亮线且无法换色,这里自绘边框与标题。
    public class FlatGroupBox : GroupBox {
        private Color borderColor = Color.FromArgb(0xD6, 0xD6, 0xD6);
        private Color titleColor = Color.FromArgb(0x5F, 0x5F, 0x5F);
        private int cornerRadius = 6;
 
        public Color BorderColor {
            get { return borderColor; }
            set { borderColor = value; Invalidate(); }
        }
        public Color TitleColor {
            get { return titleColor; }
            set { titleColor = value; Invalidate(); }
        }
        public int CornerRadius {
            get { return cornerRadius; }
            set { cornerRadius = value; Invalidate(); }
        }
 
        public FlatGroupBox() {
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true);
        }
 
        private static GraphicsPath RoundedRect(Rectangle bounds, int radius) {
            int diameter = radius * 2;
            GraphicsPath path = new GraphicsPath();
            if (diameter <= 0) {
                path.AddRectangle(bounds);
                return path;
            }
            path.AddArc(bounds.X, bounds.Y, diameter, diameter, 180, 90);
            path.AddArc(bounds.Right - diameter, bounds.Y, diameter, diameter, 270, 90);
            path.AddArc(bounds.Right - diameter, bounds.Bottom - diameter, diameter, diameter, 0, 90);
            path.AddArc(bounds.X, bounds.Bottom - diameter, diameter, diameter, 90, 90);
            path.CloseFigure();
            return path;
        }
 
        protected override void OnPaint(PaintEventArgs e) {
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.Clear(BackColor);
 
            int caption = Font.Height;
            int top = caption / 2;
            Rectangle rect = new Rectangle(0, top, Width - 1, Height - top - 1);
            if (rect.Width > 0 && rect.Height > 0) {
                using (GraphicsPath path = RoundedRect(rect, cornerRadius))
                using (Pen pen = new Pen(borderColor)) {
                    g.DrawPath(pen, path);
                }
            }
 
            using (Font titleFont = new Font(Font, FontStyle.Bold)) {
                TextRenderer.DrawText(g, Text, titleFont, new Point(12, 0), titleColor, TextFormatFlags.NoPadding | TextFormatFlags.SingleLine);
            }
        }
    }
 
    public class Dwm {
        [DllImport("dwmapi.dll")]
        public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
        public static void SetWindowAttribute(IntPtr hwnd, int attr, int attrValue)
        {
            DwmSetWindowAttribute(hwnd, attr, ref attrValue, sizeof(int));
        }
    }
    public class Win32 {
        [DllImport("Kernel32.dll", ExactSpelling = true)]
        public static extern IntPtr GetConsoleWindow();
        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("winmm.dll")]
        public static extern Int32 mciSendString(String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
        [DllImport("uxtheme.dll", CharSet=CharSet.Unicode)]
        public static extern int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList);
 
        [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
        private class MMDeviceEnumerator {}
 
        private enum EDataFlow { eRender, eCapture, eAll }
        private enum ERole { eConsole, eMultimedia, eCommunications }
 
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")]
        private interface IMMDeviceEnumerator {
            void NotNeeded();
            IMMDevice GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role);
        }
 
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D666063F-1587-4E43-81F1-B948E807363F")]
        private interface IMMDevice {
            [return: MarshalAs(UnmanagedType.IUnknown)]
            object Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams);
        }
 
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064")]
        private interface IAudioMeterInformation {
            float GetPeakValue();
        }
 
        public static bool IsPlayingSound() {
            IMMDeviceEnumerator enumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
            IMMDevice speakers = enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
            IAudioMeterInformation meter = (IAudioMeterInformation)speakers.Activate(typeof(IAudioMeterInformation).GUID, 0, IntPtr.Zero);
            float value = meter.GetPeakValue();
            return value > 1E-08;
        }
    }
}
"@
    -ReferencedAssemblies $GUICSharpReferences

#region Functions

function Update-ErrorLog {
    param(
        [System.Management.Automation.ErrorRecord]$ErrorRecord,
        [string]$Message,
        [switch]$Promote
    )

    if ( $Message -ne '' ) { [void][System.Windows.Forms.MessageBox]::Show($Message + $($ErrorRecord | Out-String), 'Exception Occurred') }

    Write-Error $ErrorRecord

    if ( $Promote ) { throw $ErrorRecord }
}

#endregion Functions


#region Environment Setup

try {
    Add-Type -AssemblyName System.Windows.Forms
    Add-Type -AssemblyName System.Drawing
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

    # 必须在创建任何控件之前调用。
    [System.Windows.Forms.Application]::EnableVisualStyles()
    [System.Windows.Forms.Application]::SetCompatibleTextRenderingDefault($false)
}
catch { Update-ErrorLog -ErrorRecord $_ -Message "Exception encountered during Environment Setup." }

#endregion Environment Setup