mirror of
https://github.com/jkocon/g-helper.git
synced 2026-02-23 13:00:52 +01:00
258 lines
9.1 KiB
C#
258 lines
9.1 KiB
C#
using System.ComponentModel;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace GHelper.UI
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public static GraphicsPath RoundedRect(Rectangle bounds, int radiusL, int radiusR)
|
|
{
|
|
int diameterL = radiusL * 2;
|
|
int diameterR = radiusR * 2;
|
|
|
|
Size sizeL = new Size(diameterL, diameterL);
|
|
Size sizeR = new Size(diameterR, diameterR);
|
|
|
|
Rectangle arcL = new Rectangle(bounds.Location, sizeL);
|
|
Rectangle arcR = new Rectangle(bounds.Location, sizeR);
|
|
|
|
GraphicsPath path = new GraphicsPath();
|
|
|
|
// top left arc
|
|
path.AddArc(arcL, 180, 90);
|
|
|
|
// top right arc
|
|
arcR.X = bounds.Right - diameterR;
|
|
arcR.Y = bounds.Top;
|
|
path.AddArc(arcR, 270, 90);
|
|
|
|
// bottom right arc
|
|
arcR.Y = bounds.Bottom - diameterR;
|
|
arcR.X = bounds.Right - diameterR;
|
|
path.AddArc(arcR, 0, 90);
|
|
|
|
// bottom left arc
|
|
arcL.X = bounds.Left;
|
|
arcL.Y = bounds.Bottom - diameterL;
|
|
path.AddArc(arcL, 90, 90);
|
|
|
|
path.CloseFigure();
|
|
return path;
|
|
}
|
|
|
|
public static void DrawRoundedRectangle(Graphics graphics, Pen pen, Rectangle bounds, int cornerRadiusL = 5, int cornerRadiusR = 5)
|
|
{
|
|
if (graphics == null)
|
|
throw new ArgumentNullException(nameof(graphics));
|
|
if (pen == null)
|
|
throw new ArgumentNullException(nameof(pen));
|
|
|
|
using (GraphicsPath path = RoundedRect(bounds, cornerRadiusL, cornerRadiusR))
|
|
{
|
|
graphics.DrawPath(pen, path);
|
|
}
|
|
}
|
|
|
|
public static void FillRoundedRectangle(Graphics graphics, Brush brush, Rectangle bounds, int cornerRadiusL = 5, int cornerRadiusR = 5)
|
|
{
|
|
if (graphics == null)
|
|
throw new ArgumentNullException(nameof(graphics));
|
|
if (brush == null)
|
|
throw new ArgumentNullException(nameof(brush));
|
|
|
|
using (GraphicsPath path = RoundedRect(bounds, cornerRadiusL, cornerRadiusR))
|
|
{
|
|
graphics.FillPath(brush, path);
|
|
}
|
|
}
|
|
|
|
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;
|
|
nint dc;
|
|
if (m.WParam == nint.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))
|
|
{
|
|
//FillRoundedRectangle(g, b, dropDownRect, 1, 3);
|
|
g.FillRectangle(b, dropDownRect);
|
|
}
|
|
using (var b = new SolidBrush(arrowColor))
|
|
{
|
|
g.FillPolygon(b, arrow);
|
|
}
|
|
using (var p = new Pen(innerBorderColor, 2))
|
|
{
|
|
DrawRoundedRectangle(g, p, innerBorder, 3, 1);
|
|
//DrawRoundedRectangle(g, p, innerInnerBorder, 3, 1);
|
|
|
|
//g.DrawRectangle(p, innerBorder);
|
|
//g.DrawRectangle(p, innerInnerBorder);
|
|
}
|
|
using (var p = new Pen(outerBorderColor))
|
|
{
|
|
DrawRoundedRectangle(g, p, outerBorder, 4, 4);
|
|
//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 nint 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 nint BeginPaint(nint hWnd,
|
|
[In, Out] ref PAINTSTRUCT lpPaint);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern bool EndPaint(nint hWnd, ref PAINTSTRUCT lpPaint);
|
|
|
|
[DllImport("gdi32.dll")]
|
|
public static extern int SelectClipRgn(nint hDC, nint hRgn);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern int GetUpdateRgn(nint hwnd, nint hrgn, bool fErase);
|
|
public enum RegionFlags
|
|
{
|
|
ERROR = 0,
|
|
NULLREGION = 1,
|
|
SIMPLEREGION = 2,
|
|
COMPLEXREGION = 3,
|
|
}
|
|
[DllImport("gdi32.dll")]
|
|
internal static extern bool DeleteObject(nint hObject);
|
|
|
|
[DllImport("gdi32.dll")]
|
|
private static extern nint CreateRectRgn(int x1, int y1, int x2, int y2);
|
|
}
|
|
}
|