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