From 1a1c8e71fcd14858f595029f089b2d4a00202b32 Mon Sep 17 00:00:00 2001
From: ogi <Administrator@S-OGI-PC>
Date: Fri, 05 Dec 2025 09:24:16 +0900
Subject: [PATCH] プロジェクトファイルを追加。
---
HotelPms.Share.Windows/Component/PanelEx.cs | 499 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 499 insertions(+), 0 deletions(-)
diff --git a/HotelPms.Share.Windows/Component/PanelEx.cs b/HotelPms.Share.Windows/Component/PanelEx.cs
new file mode 100644
index 0000000..ef72941
--- /dev/null
+++ b/HotelPms.Share.Windows/Component/PanelEx.cs
@@ -0,0 +1,499 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Linq;
+using System.Drawing.Drawing2D;
+using System.Drawing.Text;
+using HotelPms.Share.Windows.Util;
+using HotelPms.Share.Windows.Animations;
+using HotelPms.Share.Windows.GraphicsApi;
+
+namespace HotelPms.Share.Windows.Component
+{
+ public class PanelEx : Panel
+ {
+ private int imgPadding = 5;
+
+ public int ArcWidth { get; set; } = 16;
+
+ public int OffsetX { get; set; } = 0;
+ public int OffsetY { get; set; } = 0;
+
+ /// <summary>
+ /// 模糊
+ /// </summary>
+ public int Blur { get; set; } = 15;
+
+ /// <summary>
+ /// 蔓延
+ /// </summary>
+ public int Spread { get; set; } = 15;
+
+ public bool UseTitleBookMark { get; set; } = true;
+
+ public Color TitleBookMarkColor { get; set; } = Color.Pink;
+
+ public string Title { get; set; } = string.Empty;
+
+ public Font TitleFont { get; set; } = DefaultFont;
+
+ public Font SignFont { get; set; } = DefaultFont;
+
+ public int TitleHeight { get; set; } = 0;
+
+ public Color TitleForeColor { get; set; } = Color.Black;
+
+ public Color TitleBackColor { get; set; } = Color.Gainsboro;
+
+ public int MaxHeight { get; set; } = -1;
+
+ private bool m_Expan = true;
+
+ /// <summary>
+ /// 拡張
+ /// </summary>
+ public bool Expan
+ {
+ get { return m_Expan; }
+ set
+ {
+ m_Expan = value;
+ if(!m_Expan && MaxHeight == -1) { MaxHeight = this.Height; }
+ //this.Height = m_Expan ? MaxHeight : MixHeight;
+ animationSelf.StartNewAnimation(m_Expan ? AnimationDirection.Out : AnimationDirection.In);
+ Invalidate();
+ }
+ }
+
+ private StringFormat m_StringFormat = new StringFormat();
+ private Rectangle m_TitleRect;
+
+ private string activeName = string.Empty;
+ public string ActiveName { get { return activeName; } set { activeName = value; Invalidate(); } }
+
+ private readonly Dictionary<Control, AnimationManager> animationDict = new Dictionary<Control, AnimationManager>();
+ private AnimationManager animationSelf;
+
+ public PanelEx()
+ {
+ SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true);
+ m_StringFormat.LineAlignment = StringAlignment.Center;
+ m_StringFormat.Alignment = StringAlignment.Near;
+
+ animationSelf = new AnimationManager
+ {
+ Increment = 0.03,
+ AnimationType = AnimationType.Linear,
+ InterruptAnimation = false,
+ };
+ animationSelf.OnAnimationProgress += _animationManager_OnAnimationProgress;
+ }
+
+ private void _animationManager_OnAnimationProgress(object sender)
+ {
+ Invalidate();
+ }
+
+ protected override void OnControlAdded(ControlEventArgs e)
+ {
+ if (e.Control is TextBox || e.Control is ComboBox)
+ {
+ e.Control.Enter += Control_Enter;
+ e.Control.Leave += Control_Leave;
+
+ IPanelEx child = e.Control as IPanelEx;
+ if (child != null)
+ {
+ System.Diagnostics.Debug.WriteLine($"{e.Control.Handle}:{e.Control.Name}:{child.PanelExEnabled}"); //←未設定
+ AnimationManager animationManager = new AnimationManager
+ {
+ Increment = 0.06,
+ AnimationType = AnimationType.EaseInOut,
+ InterruptAnimation = false,
+ };
+ animationManager.OnAnimationProgress += _animationManager_OnAnimationProgress;
+ animationDict.Add(e.Control, animationManager);
+ }
+ }
+ base.OnControlAdded(e);
+ }
+
+ private void Control_Leave(object sender, EventArgs e)
+ {
+ ActiveName = string.Empty;
+
+ IPanelEx child = sender as IPanelEx;
+ if (child != null && child.PanelExEnabled && (child.TitleStyle == CTextBox.ETitleStyle.Material || child.TitleStyle == CTextBox.ETitleStyle.Icon))
+ {
+ if (child.TitleStyle == CTextBox.ETitleStyle.Icon && (sender as Control).Text.Length > 0) { return; }
+ animationDict[child as Control].StartNewAnimation(AnimationDirection.Out);
+ }
+ }
+
+ private void Control_Enter(object sender, EventArgs e)
+ {
+ ActiveName = (sender as Control).Name;
+
+ IPanelEx child = sender as IPanelEx;
+ if (child != null && child.PanelExEnabled && (child.TitleStyle == CTextBox.ETitleStyle.Material || child.TitleStyle == CTextBox.ETitleStyle.Icon))
+ {
+ if (child.TitleStyle == CTextBox.ETitleStyle.Icon && (sender as Control).Text.Length > 0) { return; }
+ animationDict[child as Control].StartNewAnimation(AnimationDirection.In);
+ }
+ }
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ base.OnPaint(e);
+ e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+ e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
+ DrawShadow(Controls.OfType<Control>().Where(c => ActiveName.Length > 0 && ActiveName == c.Name), e.Graphics);
+ DrawStyle(Controls.OfType<CTextBox>().Where(c => c.BorderStyle == BorderStyle.None), e.Graphics);
+ DrawTitle(e);
+ SetHeight(e);
+ }
+
+ protected override void OnMouseMove(MouseEventArgs e)
+ {
+ base.OnMouseMove(e);
+ if (TitleHeight == 0) { return; }
+ Cursor = m_TitleRect.Contains(e.Location) ? Cursors.Hand : Cursors.Default;
+ }
+
+ protected override void OnMouseClick(MouseEventArgs e)
+ {
+ base.OnMouseClick(e);
+ if(!m_TitleRect.Contains(e.Location)) { return; }
+ Expan = !Expan;
+ }
+
+ private void DrawTitle(PaintEventArgs e)
+ {
+ if(TitleHeight == 0) { return; }
+ m_TitleRect = new Rectangle(UseTitleBookMark ? 5 : 0, 0, this.Width, TitleHeight);
+ using (SolidBrush backBrush = new SolidBrush(TitleBackColor))
+ {
+ e.Graphics.FillRectangle(backBrush, m_TitleRect);
+ }
+
+ if (UseTitleBookMark)
+ {
+ Rectangle markRect = new Rectangle(0, 0, 5, TitleHeight);
+ using (SolidBrush backBrush = new SolidBrush(TitleBookMarkColor))
+ {
+ e.Graphics.FillRectangle(backBrush, markRect);
+ }
+ }
+
+ //文言
+ using (SolidBrush foreBrush = new SolidBrush(TitleForeColor))
+ {
+ e.Graphics.DrawString(Title, TitleFont, foreBrush, m_TitleRect, m_StringFormat);
+ }
+
+ //矢印
+ int width = 30;
+ Rectangle signRect = new Rectangle(this.Width - width, 0, width, TitleHeight);
+ using (SolidBrush foreBrush = new SolidBrush(TitleForeColor))
+ {
+ e.Graphics.DrawString(m_Expan ? "▲" : "▼", SignFont, foreBrush, signRect, m_StringFormat);
+ }
+ }
+
+ private void SetHeight(PaintEventArgs e)
+ {
+ if (TitleHeight == 0 || MaxHeight <= 0) { return; }
+
+ if (!animationSelf.IsAnimating())
+ {
+ this.Height = m_Expan ? MaxHeight : TitleHeight;
+ System.Diagnostics.Debug.WriteLine($"animationSelf⇒END");
+ }
+ else
+ {
+ //Animate
+ int height = MaxHeight - TitleHeight;
+ int step = (int)(height * animationSelf.GetProgress());
+ if (m_Expan)
+ {
+ this.Height = TitleHeight + (height - step);
+ }
+ else
+ {
+ this.Height = MaxHeight - step;
+ }
+ System.Diagnostics.Debug.WriteLine($"animationSelf⇒{step}");
+ }
+ }
+
+ private void DrawShadow(IEnumerable<Control> controls, Graphics g)
+ {
+ foreach (var control in controls)
+ {
+ DrawOutsetShadow(g, control);
+ }
+ }
+
+ private void DrawStyle(IEnumerable<Control> controls, Graphics g)
+ {
+ foreach (var control in controls)
+ {
+ DrawControlStyle(g, control);
+ }
+ }
+
+ private Rectangle GetControlRect(Control control)
+ {
+ int titleWidth = 0;
+ if (control is IPanelEx)
+ {
+ IPanelEx child = control as IPanelEx;
+ if(child.PanelExEnabled)
+ {
+ if (child.TitleStyle == CTextBox.ETitleStyle.Label) { titleWidth = child.TitleWidth; }
+ else if (child.TitleStyle == CTextBox.ETitleStyle.Icon) { titleWidth = control.Height + imgPadding; }
+ }
+ }
+
+ int left = control.Left - ArcWidth / 2 - titleWidth;
+ int top = control.Top - ArcWidth / 2;
+ int width = control.Width + ArcWidth + titleWidth;
+ int height = control.Height + ArcWidth;
+ Rectangle r = new Rectangle(left, top, width, height);
+ return r;
+ }
+
+ /// <summary>
+ /// 枠線
+ /// </summary>
+ /// <param name="g"></param>
+ /// <param name="control"></param>
+ private void DrawControlStyle(Graphics g, Control control)
+ {
+ bool drawBorder = true;
+ Color borderColor = Color.FromArgb(255, 0, 120, 215); //255,0,120,215 (濃青) #7bc1f7 140, 123, 193, 247 (青) #22AC38 255, 34, 172, 56 (緑)
+ Rectangle r = GetControlRect(control);
+ if (control is IPanelEx)
+ {
+ IPanelEx child = control as IPanelEx;
+ if (child.PanelExEnabled)
+ {
+ borderColor = control.Focused ? child.BorderFocusColor : child.BorderColor;
+ if (child.TitleStyle == CTextBox.ETitleStyle.Material) { drawBorder = false; }
+ }
+ else
+ {
+ drawBorder = false;
+ }
+ }
+
+ if (drawBorder)
+ {
+ using (GraphicsPath path = new GraphicsPath())
+ {
+ path.AddArc(r.X, r.Y, ArcWidth, ArcWidth, 180, 90);
+ path.AddArc(r.X + r.Width - ArcWidth - 1, r.Y, ArcWidth, ArcWidth, -90, 90);
+ path.AddArc(r.X + r.Width - ArcWidth - 1, r.Y + r.Height - ArcWidth - 1, ArcWidth, ArcWidth, 0, 90);
+ path.AddArc(r.X, r.Y + r.Height - ArcWidth - 1, ArcWidth, ArcWidth, 90, 90);
+ path.CloseFigure();
+
+ using (Brush brush = new SolidBrush(control.BackColor))
+ {
+ g.FillPath(brush, path);
+ }
+ using (Pen pen = new Pen(borderColor)) //255,0,120,215 (濃青) #7bc1f7 140, 123, 193, 247 (青) #22AC38 255, 34, 172, 56 (緑)
+ {
+ g.DrawPath(pen, path);
+ }
+ }
+ }
+
+ //Labelを各
+ if (control is IPanelEx)
+ {
+ IPanelEx child = control as IPanelEx;
+ if (child.PanelExEnabled)
+ {
+ if (child.TitleStyle == CTextBox.ETitleStyle.Label)
+ {
+ int labelWidth = child.TitleWidth;
+ using (GraphicsPath path = new GraphicsPath())
+ {
+ path.AddArc(r.X, r.Y, ArcWidth, ArcWidth, 180, 90);
+ path.AddLine(new Point(r.X + labelWidth, r.Y), new Point(r.X + labelWidth, r.Y + r.Height - 1));
+ path.AddArc(r.X, r.Y + r.Height - ArcWidth - 1, ArcWidth, ArcWidth, 90, 90);
+ path.CloseFigure();
+
+ using (Brush brush = new SolidBrush(child.TitleBackColor))
+ {
+ g.FillPath(brush, path);
+ }
+ using (Pen pen = new Pen(borderColor)) //255,0,120,215 (濃青) #7bc1f7 140, 123, 193, 247 (青) #22AC38 255, 34, 172, 56 (緑) 255,122,122,122 gray
+ {
+ g.DrawPath(pen, path);
+ }
+ }
+
+ TextRenderer.DrawText(g, child.TitleText, child.TitleFont, new Rectangle(r.X, r.Y, child.TitleWidth, r.Height), child.TitleForeColor, TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter);
+ }
+ else if (child.TitleStyle == CTextBox.ETitleStyle.Icon)
+ {
+ if (child.ForeImage != null)
+ {
+ Rectangle imgRect = new Rectangle(control.Left - control.Height - imgPadding, control.Top, control.Width, control.Height);
+ GdiPlus.DrawImage(g, child.ForeImage as Bitmap, imgRect);
+ }
+
+ if (child is CTextBox)
+ {
+ CTextBox textBox = (child as CTextBox);
+ Size sizeText = TextRenderer.MeasureText(textBox.TipText, child.TitleFont);
+ int endX = r.X + 15; //タイトル文字最終的な位置 X
+ int endY = r.Y - sizeText.Height * 2 / 3; //タイトル文字最終的な位置 Y
+
+ if (animationDict.ContainsKey(control) && animationDict[control].IsAnimating())
+ {
+ double per = animationDict[control].GetProgress();
+ //位置、フォントサイズの変化 animationDict[control].GetProgress() in ⇒ enter ⇒ 増大, out ⇒ leave ⇒ 減少
+ float fontSize = textBox.Font.Size - (textBox.Font.Size - child.TitleFont.Size) * (float)per;
+ double curX = textBox.Left - (textBox.Left - endX) * per;
+ double curY = textBox.Top - (textBox.Top - endY) * per;
+ using (Font font = new Font(child.TitleFont.FontFamily, fontSize))
+ {
+ Rectangle textR = new Rectangle((int)curX, (int)curY, (int)(sizeText.Width * 1.2), sizeText.Height);
+ using (Brush brush = new SolidBrush(this.BackColor))
+ {
+ g.FillRectangle(brush, textR);
+ }
+ TextRenderer.DrawText(g, textBox.TipText, font, textR, borderColor, TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter);
+ }
+ }
+ else
+ {
+ if ((control.Focused || textBox.Text.Length > 0) && textBox.TipText.Length > 0)
+ {
+ Rectangle textR = new Rectangle(endX, endY, (int)(sizeText.Width * 1.2), sizeText.Height);
+ using (Brush brush = new SolidBrush(this.BackColor))
+ {
+ g.FillRectangle(brush, textR);
+ }
+ TextRenderer.DrawText(g, textBox.TipText, child.TitleFont, textR, borderColor, TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter);
+ }
+ }
+ }
+ }
+ else if (child.TitleStyle == CTextBox.ETitleStyle.Material && animationDict.ContainsKey(control))
+ {
+ var lineY = control.Bottom + 3;
+ if (!animationDict[control].IsAnimating())
+ {
+ using (Pen pen = new Pen(control.Focused ? child.ShadowColor : child.BorderColor, control.Focused ? 2F : 1F))
+ {
+ g.DrawLine(pen, control.Location.X, lineY, control.Location.X + control.Width, lineY);
+ }
+ }
+ else
+ {
+ //Animate
+ int animationWidth = (int)(control.Width * animationDict[control].GetProgress());
+ int halfAnimationWidth = animationWidth / 2;
+ int animationStart = control.Location.X + control.Width / 2;
+
+ using (Pen pen = new Pen(child.BorderColor, 1F))
+ {
+ g.DrawLine(pen, control.Location.X, lineY, control.Location.X + control.Width, lineY);
+ }
+
+ using (Pen pen = new Pen(child.ShadowColor, 2F))
+ {
+ g.DrawLine(pen, animationStart - halfAnimationWidth, lineY, animationStart - halfAnimationWidth + animationWidth, lineY);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ // drawing the loop on an image because of speed
+ private void DrawOutsetShadow(Graphics g, Control control)
+ {
+ Color shadowColor = Color.FromArgb(140, 123, 193, 247); //#7bc1f7 140, 123, 193, 247 (青) #22AC38 140, 34, 172, 56 (緑)
+ if (control is IPanelEx)
+ {
+ IPanelEx child = control as IPanelEx;
+ if (child.PanelExEnabled)
+ {
+ shadowColor = child.ShadowColor;
+ if (child.TitleStyle == CTextBox.ETitleStyle.Material) { return; }
+ }
+ }
+
+ var rOuter = control.Bounds;
+ var rInner = control.Bounds;
+ if (control is CTextBox && (control as CTextBox).BorderStyle == BorderStyle.None)
+ {
+ Rectangle r = GetControlRect(control);
+ rOuter = r;
+ rInner = r;
+ }
+
+ rInner.Offset(OffsetX, OffsetY);
+ rInner.Inflate(-Blur, -Blur);
+ rOuter.Inflate(Spread, Spread);
+ rOuter.Offset(OffsetX, OffsetY);
+ var originalOuter = rOuter;
+
+ using (var img = new Bitmap(originalOuter.Width, originalOuter.Height, g))
+ {
+ using (var g2 = Graphics.FromImage(img))
+ {
+ var currentBlur = 0;
+ do
+ {
+ var transparency = (rOuter.Height - rInner.Height) / (double)(Blur * 2 + Spread * 3);
+ transparency -= 0.02;
+ var color = Color.FromArgb(((int)(255 * (transparency * transparency))), shadowColor);
+ var rOutput = rInner;
+ rOutput.Offset(-originalOuter.Left, -originalOuter.Top);
+ DrawRoundedRectangle(g2, rOutput, currentBlur, Pens.Transparent, color);
+ rInner.Inflate(1, 1);
+ currentBlur = (int)((double)Blur * (1 - (transparency * transparency)));
+ } while (rOuter.Contains(rInner));
+ g2.Flush();
+ }
+ g.DrawImage(img, originalOuter);
+ }
+ }
+
+ private void DrawRoundedRectangle(Graphics gfx, Rectangle bounds, int cornerRadius, Pen drawPen, Color fillColor)
+ {
+ int strokeOffset = Convert.ToInt32(Math.Ceiling(drawPen.Width));
+ bounds = Rectangle.Inflate(bounds, -strokeOffset, -strokeOffset);
+
+ var gfxPath = new GraphicsPath();
+ if (cornerRadius > 0)
+ {
+ gfxPath.AddArc(bounds.X, bounds.Y, cornerRadius, cornerRadius, 180, 90);
+ gfxPath.AddArc(bounds.X + bounds.Width - cornerRadius, bounds.Y, cornerRadius, cornerRadius, 270, 90);
+ gfxPath.AddArc(bounds.X + bounds.Width - cornerRadius, bounds.Y + bounds.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90);
+ gfxPath.AddArc(bounds.X, bounds.Y + bounds.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90);
+ }
+ else
+ {
+ gfxPath.AddRectangle(bounds);
+ }
+ gfxPath.CloseAllFigures();
+
+ gfx.FillPath(new SolidBrush(fillColor), gfxPath);
+ if (drawPen != Pens.Transparent)
+ {
+ var pen = new Pen(drawPen.Color);
+ pen.EndCap = pen.StartCap = LineCap.Round;
+ gfx.DrawPath(pen, gfxPath);
+ }
+ }
+ }
+}
--
Gitblit v1.10.0