using LYFZ.OtherExpansion.Win32; using LYFZ.OtherExpansion.Win32.Struct; using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace LYFZ.OtherExpansion.SkinControl { [ToolboxBitmap(typeof(NumericUpDown))] public class SkinNumericUpDown : NumericUpDown { private class UpDownButtonNativeWindow : NativeWindow, IDisposable { private const int WM_PAINT = 15; private const int VK_LBUTTON = 1; private const int VK_RBUTTON = 2; private SkinNumericUpDown _owner; private Control _upDownButton; private IntPtr _upDownButtonWnd; private bool _bPainting; private static readonly IntPtr TRUE = new IntPtr(1); public UpDownButtonNativeWindow(SkinNumericUpDown owner) { this._owner = owner; this._upDownButton = owner.UpDownButton; this._upDownButtonWnd = this._upDownButton.Handle; if (Environment.OSVersion.Version.Major > 5 && NativeMethods.IsAppThemed()) { NativeMethods.SetWindowTheme(this._upDownButtonWnd, "", ""); } base.AssignHandle(this._upDownButtonWnd); } private bool LeftKeyPressed() { if (SystemInformation.MouseButtonsSwapped) { return NativeMethods.GetKeyState(2) < 0; } return NativeMethods.GetKeyState(1) < 0; } private void DrawUpDownButton() { bool mousePress = this.LeftKeyPressed(); Rectangle clipRect = this._upDownButton.ClientRectangle; RECT windowRect = default(RECT); NativeMethods.Point cursorPoint = default(NativeMethods.Point); NativeMethods.GetCursorPos(ref cursorPoint); NativeMethods.GetWindowRect(this._upDownButtonWnd, ref windowRect); bool mouseOver = NativeMethods.PtInRect(ref windowRect, cursorPoint); cursorPoint.x -= windowRect.Left; cursorPoint.y -= windowRect.Top; bool mouseInUpButton = cursorPoint.y < clipRect.Height / 2; using (Graphics g = Graphics.FromHwnd(this._upDownButtonWnd)) { UpDownButtonPaintEventArgs e = new UpDownButtonPaintEventArgs(g, clipRect, mouseOver, mousePress, mouseInUpButton); this._owner.OnPaintUpDownButton(e); } } protected override void WndProc(ref Message m) { int msg = m.Msg; if (msg != 15) { base.WndProc(ref m); return; } if (!this._bPainting) { this._bPainting = true; PAINTSTRUCT ps = default(PAINTSTRUCT); NativeMethods.BeginPaint(m.HWnd, ref ps); this.DrawUpDownButton(); NativeMethods.EndPaint(m.HWnd, ref ps); this._bPainting = false; m.Result = SkinNumericUpDown.UpDownButtonNativeWindow.TRUE; return; } base.WndProc(ref m); } public void Dispose() { this._owner = null; this._upDownButton = null; base.ReleaseHandle(); } } private SkinNumericUpDown.UpDownButtonNativeWindow _upDownButtonNativeWindow; private Color _baseColor = Color.FromArgb(166, 222, 255); private Color _borderColor = Color.FromArgb(23, 169, 254); private Color _arrowColor = Color.FromArgb(0, 95, 152); private static readonly object EventPaintUpDownButton = new object(); public event UpDownButtonPaintEventHandler PaintUpDownButton { add { base.Events.AddHandler(SkinNumericUpDown.EventPaintUpDownButton, value); } remove { base.Events.RemoveHandler(SkinNumericUpDown.EventPaintUpDownButton, value); } } [Category("Skin"), DefaultValue(typeof(Color), "166, 222, 255"), Description("色调")] public Color BaseColor { get { return this._baseColor; } set { this._baseColor = value; this.UpDownButton.Invalidate(); } } [Category("Skin"), DefaultValue(typeof(Color), "23, 169, 254"), Description("边框颜色")] public Color BorderColor { get { return this._borderColor; } set { this._borderColor = value; base.Invalidate(true); } } [Category("Skin"), DefaultValue(typeof(Color), "0, 95, 152"), Description("箭头颜色")] public Color ArrowColor { get { return this._arrowColor; } set { this._arrowColor = value; this.UpDownButton.Invalidate(); } } public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; base.Invalidate(true); } } public Control UpDownButton { get { return base.Controls[0]; } } protected virtual void OnPaintUpDownButton(UpDownButtonPaintEventArgs e) { Graphics g = e.Graphics; Rectangle rect = e.ClipRectangle; Color upButtonBaseColor = this._baseColor; Color upButtonBorderColor = this._borderColor; Color upButtonArrowColor = this._arrowColor; Color downButtonBaseColor = this._baseColor; Color downButtonBorderColor = this._borderColor; Color downButtonArrowColor = this._arrowColor; Rectangle upButtonRect = rect; upButtonRect.Y++; upButtonRect.Width -= 2; upButtonRect.Height = rect.Height / 2 - 2; Rectangle downButtonRect = rect; downButtonRect.Y = upButtonRect.Bottom + 2; downButtonRect.Height = rect.Height - upButtonRect.Bottom - 4; downButtonRect.Width -= 2; if (base.Enabled) { if (e.MouseOver) { if (e.MousePress) { if (e.MouseInUpButton) { upButtonBaseColor = this.GetColor(this._baseColor, 0, -35, -24, -9); } else { downButtonBaseColor = this.GetColor(this._baseColor, 0, -35, -24, -9); } } else { if (e.MouseInUpButton) { upButtonBaseColor = this.GetColor(this._baseColor, 0, 35, 24, 9); } else { downButtonBaseColor = this.GetColor(this._baseColor, 0, 35, 24, 9); } } } } else { upButtonBaseColor = SystemColors.Control; upButtonBorderColor = SystemColors.ControlDark; upButtonArrowColor = SystemColors.ControlDark; downButtonBaseColor = SystemColors.Control; downButtonBorderColor = SystemColors.ControlDark; downButtonArrowColor = SystemColors.ControlDark; } g.SmoothingMode = SmoothingMode.AntiAlias; Color backColor = base.Enabled ? base.BackColor : SystemColors.Control; using (SolidBrush brush = new SolidBrush(backColor)) { rect.Inflate(1, 1); g.FillRectangle(brush, rect); } this.RenderButton(g, upButtonRect, upButtonBaseColor, upButtonBorderColor, upButtonArrowColor, ArrowDirection.Up); this.RenderButton(g, downButtonRect, downButtonBaseColor, downButtonBorderColor, downButtonArrowColor, ArrowDirection.Down); UpDownButtonPaintEventHandler handler = base.Events[SkinNumericUpDown.EventPaintUpDownButton] as UpDownButtonPaintEventHandler; if (handler != null) { handler(this, e); } } protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); if (this._upDownButtonNativeWindow == null) { this._upDownButtonNativeWindow = new SkinNumericUpDown.UpDownButtonNativeWindow(this); } } protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed(e); if (this._upDownButtonNativeWindow != null) { this._upDownButtonNativeWindow.Dispose(); this._upDownButtonNativeWindow = null; } } protected override void WndProc(ref Message m) { int msg = m.Msg; if (msg != 15) { if (msg != 133) { base.WndProc(ref m); return; } } else { base.WndProc(ref m); if (base.BorderStyle == BorderStyle.None) { return; } Color borderColor = base.Enabled ? this._borderColor : SystemColors.ControlDark; using (Graphics g = Graphics.FromHwnd(m.HWnd)) { ControlPaint.DrawBorder(g, base.ClientRectangle, borderColor, ButtonBorderStyle.Solid); return; } } if (base.BorderStyle != BorderStyle.None) { Color backColor = base.Enabled ? base.BackColor : SystemColors.Control; Rectangle rect = new Rectangle(0, 0, base.Width, base.Height); IntPtr hdc = NativeMethods.GetWindowDC(m.HWnd); if (hdc == IntPtr.Zero) { throw new Win32Exception(); } try { using (Graphics g2 = Graphics.FromHdc(hdc)) { using (Brush brush = new SolidBrush(backColor)) { g2.FillRectangle(brush, rect); } } } finally { NativeMethods.ReleaseDC(m.HWnd, hdc); } } m.Result = IntPtr.Zero; } public void RenderArrowInternal(Graphics g, Rectangle dropDownRect, ArrowDirection direction, Brush brush) { Point point = new Point(dropDownRect.Left + dropDownRect.Width / 2, dropDownRect.Top + dropDownRect.Height / 2); Point[] points; switch (direction) { case ArrowDirection.Left: points = new Point[] { new Point(point.X + 2, point.Y - 3), new Point(point.X + 2, point.Y + 3), new Point(point.X - 1, point.Y) }; break; case ArrowDirection.Up: points = new Point[] { new Point(point.X - 3, point.Y + 1), new Point(point.X + 3, point.Y + 1), new Point(point.X, point.Y - 1) }; break; default: if (direction != ArrowDirection.Right) { points = new Point[] { new Point(point.X - 3, point.Y - 1), new Point(point.X + 3, point.Y - 1), new Point(point.X, point.Y + 1) }; } else { points = new Point[] { new Point(point.X - 2, point.Y - 3), new Point(point.X - 2, point.Y + 3), new Point(point.X + 1, point.Y) }; } break; } g.FillPolygon(brush, points); } public void RenderButton(Graphics g, Rectangle rect, Color baseColor, Color borderColor, Color arrowColor, ArrowDirection direction) { this.RenderBackgroundInternal(g, rect, baseColor, borderColor, 0.45f, true, LinearGradientMode.Vertical); using (SolidBrush brush = new SolidBrush(arrowColor)) { this.RenderArrowInternal(g, rect, direction, brush); } } public void RenderBackgroundInternal(Graphics g, Rectangle rect, Color baseColor, Color borderColor, float basePosition, bool drawBorder, LinearGradientMode mode) { using (LinearGradientBrush brush = new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, mode)) { Color[] colors = new Color[] { this.GetColor(baseColor, 0, 35, 24, 9), this.GetColor(baseColor, 0, 13, 8, 3), baseColor, this.GetColor(baseColor, 0, 68, 69, 54) }; brush.InterpolationColors = new ColorBlend { Positions = new float[] { 0f, basePosition, basePosition + 0.05f, 1f }, Colors = colors }; g.FillRectangle(brush, rect); } if (baseColor.A > 80) { Rectangle rectTop = rect; if (mode == LinearGradientMode.Vertical) { rectTop.Height = (int)((float)rectTop.Height * basePosition); } else { rectTop.Width = (int)((float)rect.Width * basePosition); } using (SolidBrush brushAlpha = new SolidBrush(Color.FromArgb(80, 255, 255, 255))) { g.FillRectangle(brushAlpha, rectTop); } } if (drawBorder) { using (Pen pen = new Pen(borderColor)) { g.DrawRectangle(pen, rect); } } } private Color GetColor(Color colorBase, int a, int r, int g, int b) { int a2 = (int)colorBase.A; int r2 = (int)colorBase.R; int g2 = (int)colorBase.G; int b2 = (int)colorBase.B; if (a + a2 > 255) { a = 255; } else { a = Math.Max(a + a2, 0); } if (r + r2 > 255) { r = 255; } else { r = Math.Max(r + r2, 0); } if (g + g2 > 255) { g = 255; } else { g = Math.Max(g + g2, 0); } if (b + b2 > 255) { b = 255; } else { b = Math.Max(b + b2, 0); } return Color.FromArgb(a, r, g, b); } } }