첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ GroupBox 클래스 : 커스텀 그룹 박스 만들기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


MainForm.cs

 

 

using System;

using System.ComponentModel;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 그룹 컨트롤

    /// </summary>

    public class GroupControl : GroupBox

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 그룹 테두리 그리기 여부

        /// </summary>

        private bool drawGroupBorder = true;

 

        /// <summary>

        /// 그룹 테두리 펜

        /// </summary>

        private Pen groupBorderPen;

 

        /// <summary>

        /// 그룹 배경 브러시

        /// </summary>

        private SolidBrush groupBackgroundBrush;

 

        /// <summary>

        /// 그룹 배경 이미지

        /// </summary>

        private Image groupBackgroundImage;

 

        /// <summary>

        /// 그룹 테두리 타입

        /// </summary>

        private GroupBorderType groupBorderType = GroupBorderType.ROUND_RECTANGLE;

 

        /// <summary>

        /// 그룹 헤더 테두리 색상

        /// </summary>

        private Pen groupHeaderBorderColor;

 

        /// <summary>

        /// 그룹 헤더 배경 색상

        /// </summary>

        private SolidBrush groupHeaderBackgroundColor;

 

        /// <summary>

        /// 그룹 헤더 텍스트 브러시

        /// </summary>

        private SolidBrush groupHeaderTextBrush;

 

        /// <summary>

        /// 문자열 포맷

        /// </summary>

        private StringFormat stringFormat;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 그룹 테두리 그리기 여부 - DrawGroupBorder

 

        /// <summary>

        /// 그룹 테두리 그리기 여부

        /// </summary>

        [Category("GroupControl")]

        [Description("그룹 테두리 그리기 여부를 가져오거나 설정합니다.")]

        [Browsable(true)]

        public bool DrawGroupBorder

        {

            get

            {

                return this.drawGroupBorder;

            }

            set

            {

                this.drawGroupBorder = value;

 

                Refresh();

            }

        }

 

        #endregion

        #region 그룹 테두리 색상 - GroupBorderColor

 

        [Category("GroupControl")]

        [Description("그룹 테두리 색상을 가져오거나 설정합니다.")]

        [Browsable(true)]

        public Color GroupBorderColor

        {

            get

            {

                return this.groupBorderPen.Color;

            }

            set

            {

                this.groupBorderPen.Color = value;

 

                Refresh();

            }

        }

 

        #endregion

        #region 그룹 배경 색상 - GroupBackgroundColor

 

        [Category("GroupControl")]

        [Description("그룹 배경 색상을 가져오거나 설정합니다.")]

        [Browsable(true)]

        public Color GroupBackgroundColor

        {

            get

            {

                return this.groupBackgroundBrush.Color;

            }

            set

            {

                this.groupBackgroundBrush.Color = value;

 

                Refresh();

            }

        }

 

        #endregion

        #region 그룹 배경 이미지 - GroupBackgroundImage

 

        [Category("GroupControl")]

        [Description("그룹 배경 이미지를 가져오거나 설정합니다.")]

        [Browsable(true)]

        public Image GroupBackgroundImage

        {

            get

            {

                return this.groupBackgroundImage;

            }

            set

            {

                this.groupBackgroundImage = value;

 

                Refresh();

            }

        }

 

        #endregion

        #region 그룹 테두리 타입 - GroupBorderType

 

        /// <summary>

        /// 그룹 테두리 타입

        /// </summary>

        [Category("GroupControl")]

        [Description("그룹 테두리 타입을 가져오거나 설정합니다")]

        [Browsable(true)]

        public GroupBorderType GroupBorderType

        {

            get

            {

                return this.groupBorderType;

            }

            set

            {

                this.groupBorderType = value;

 

                Refresh();

            }

        }

 

        #endregion

        #region 그룹 헤더 테두리 색상 - GroupHeaderBorderColor

 

        [Category("GroupControl")]

        [Description("그룹 헤더 테두리 색상을 가져오거나 설정합니다.")]

        [Browsable(true)]

        public Color GroupHeaderBorderColor

        {

            get

            {

                return this.groupHeaderBorderColor.Color;

            }

            set

            {

                this.groupHeaderBorderColor.Color = value;

 

                Refresh();

            }

        }

 

        #endregion

        #region 그룹 헤더 배경 색상 - GroupHeaderBackgroundColor

 

        [Category("GroupControl")]

        [Description("그룹 헤더 배경 색상을 가져오거나 설정합니다.")]

        [Browsable(true)]

        public Color GroupHeaderBackgroundColor

        {

            get

            {

                return this.groupHeaderBackgroundColor.Color;

            }

            set

            {

                this.groupHeaderBackgroundColor.Color = value;

 

                Refresh();

            }

        }

 

        #endregion

        #region 그룹 헤더 텍스트 색상 - GroupHeaderTextColor

 

        /// <summary>

        /// 그룹 헤더 텍스트 색상

        /// </summary>

        [Category("GroupControl")]

        [Description("그룹 헤더 텍스트 색상을 가져오거나 설정합니다.")]

        [Browsable(true)]

        public Color GroupHeaderTextColor

        {

            get

            {

                return this.groupHeaderTextBrush.Color;

            }

            set

            {

                this.groupHeaderTextBrush.Color = value;

 

                Refresh();

            }

        }

 

        #endregion

 

        #region 배경 색상 - BackColor

 

        [Browsable(false)] 

        [EditorBrowsable(EditorBrowsableState.Never)] 

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 

        [Obsolete("BackColor 속성은 구현되지 않습니다."true)] 

        public new Color BackColor 

        { 

            get

            {

                return base.BackColor;

            }

            set 

            { 

                throw new Exception("BackColor 속성은 구현되지 않습니다."); 

            }

        }

 

        #endregion

        #region 배경 이미지 - BackgroundImage

 

        [Browsable(false)]

        [EditorBrowsable(EditorBrowsableState.Never)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]

        [System.Obsolete("BackgroundImage 속성이 구현되지 않습니다.", true)]

        public new Image BackgroundImage

        {

            get

            {

                return base.BackgroundImage;

            }

            set

            {

                throw new Exception("BackgroundImage 속성이 구현되지 않습니다.");

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - GroupControl()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public GroupControl()

        {

            SetStyle(ControlStyles.SupportsTransparentBackColor, true);

            SetStyle(ControlStyles.UserPaint, true);

            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

 

            Size = new Size(200, 100);

 

            this.groupBorderPen             = new Pen(Color.Black);

            this.groupBackgroundBrush       = new SolidBrush(base.BackColor);

            this.groupHeaderBorderColor     = new Pen(Color.Black);

            this.groupHeaderBackgroundColor = new SolidBrush(Color.White);

            this.groupHeaderTextBrush       = new SolidBrush(Color.Black);

 

            base.BackColor = Color.Transparent;

 

            this.stringFormat = new StringFormat

            {

                Alignment     = StringAlignment.Center,

                LineAlignment = StringAlignment.Center,

                Trimming      = StringTrimming.EllipsisCharacter,

                FormatFlags   = StringFormatFlags.NoWrap

            };

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 텍스트 변경시 처리하기 - OnTextChanged(e)

 

        /// <summary>

        /// 텍스트 변경시 처리하기

        /// </summary>

        /// <param name="e">이벤트 인자</param>

        protected override void OnTextChanged(EventArgs e)

        {

            base.OnTextChanged(e);

 

            Refresh();

        }

 

        #endregion

        #region 페인트시 처리하기 - OnPaint(e)

 

        /// <summary>

        /// 페인트시 처리하기

        /// </summary>

        /// <param name="e">이벤트 인자</param>

        protected override void OnPaint(PaintEventArgs e)

        {

            Graphics graphis = e.Graphics;

 

            graphis.FillRectangle(this.groupBackgroundBrush, 0, 0, this.Width, this.Height);

 

            graphis.SmoothingMode = SmoothingMode.AntiAlias;

 

            int textWidth  = Convert.ToInt32(graphis.MeasureString(Text, Font).Width );

            int textHeight = Convert.ToInt32(graphis.MeasureString(Text, Font).Height);

 

            Rectangle groupBorderRectangle = new Rectangle

            (

                0,

                Convert.ToInt32(textHeight / 2),

                this.Width - 1,

                this.Height - 1 - Convert.ToInt32(textHeight / 2)

            );

 

            using(GraphicsPath graphicsPen = new GraphicsPath())

            {

                if(GroupBorderType == GroupBorderType.ROUND_RECTANGLE)

                {

                    int radius = 14;

 

                    graphicsPen.AddArc(groupBorderRectangle.Right - radius, groupBorderRectangle.Y              , radius, radius, 270, 90);

                    graphicsPen.AddArc(groupBorderRectangle.Right - radius, groupBorderRectangle.Bottom - radius, radius, radius, 0  , 90);

                    graphicsPen.AddArc(groupBorderRectangle.X             , groupBorderRectangle.Bottom - radius, radius, radius, 90 , 90);

                    graphicsPen.AddArc(groupBorderRectangle.X             , groupBorderRectangle.Y              , radius, radius, 180, 90);

 

                    graphicsPen.CloseFigure();

                }

                else

                {

                    graphicsPen.AddRectangle(groupBorderRectangle);

                }

 

                graphis.FillPath(this.groupBackgroundBrush, graphicsPen);

 

                if(GroupBackgroundImage != null)

                {

                    DrawBackgroundImage(e.Graphics, graphicsPen, Convert.ToInt32(textHeight / 2));

                }

 

                if(DrawGroupBorder)

                {

                    graphis.DrawPath(this.groupBorderPen, graphicsPen);

                }

            }

 

            if(textWidth > 0 & textHeight > 0)

            {

                Rectangle textRectangle = new Rectangle(7, 0, this.Width - 15, textHeight + 2);

 

                using(GraphicsPath graphicsPen = new GraphicsPath())

                {

                    int radius = 6;

 

                    graphicsPen.AddArc(textRectangle.Right - radius, textRectangle.Y              , radius, radius, 270, 90);

                    graphicsPen.AddArc(textRectangle.Right - radius, textRectangle.Bottom - radius, radius, radius, 0  , 90);

                    graphicsPen.AddArc(textRectangle.X             , textRectangle.Bottom - radius, radius, radius, 90 , 90);

                    graphicsPen.AddArc(textRectangle.X             , textRectangle.Y              , radius, radius, 180, 90);

 

                    graphicsPen.CloseFigure();

 

                    graphis.FillPath(this.groupHeaderBackgroundColor, graphicsPen);

 

                    graphis.DrawPath(this.groupHeaderBorderColor, graphicsPen);

                }

 

                graphis.DrawString(Text, Font, this.groupHeaderTextBrush, textRectangle, stringFormat);

            }

        }

 

        #endregion

 

        #region 처분하기 - Dispose(disposing)

 

        /// <summary>

        /// 처분하기

        /// </summary>

        /// <param name="disposing">처분 여부</param>

        protected override void Dispose(bool disposing)

        {

            this.groupBorderPen.Dispose();

            this.groupBackgroundBrush.Dispose();

            this.groupHeaderBorderColor.Dispose();

            this.groupHeaderBackgroundColor.Dispose();

 

            base.Dispose(disposing);

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 배경 이미지 그리기 - DrawBackgroundImage(graphics, graphicsPath, topOffset)

 

        /// <summary>

        /// 배경 이미지 그리기

        /// </summary>

        /// <param name="graphics">그래픽스</param>

        /// <param name="graphicsPath">그래픽스 패스</param>

        /// <param name="topOffset">위쪽 오프셋</param>

        private void DrawBackgroundImage(Graphics graphics, GraphicsPath graphicsPath, int topOffset)

        {

            using(Bitmap bitmap = new Bitmap(Width, Height - topOffset))

            {

                using(Graphics bitmapGraphics = Graphics.FromImage(bitmap))

                {

                    if(BackgroundImageLayout == ImageLayout.None)

                    {

                        bitmapGraphics.DrawImage(GroupBackgroundImage, 0, 0, GroupBackgroundImage.Width, GroupBackgroundImage.Height);

                    }

                    else if(BackgroundImageLayout == ImageLayout.Tile)

                    {

                        int tileCountX = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(bitmap.Width  / GroupBackgroundImage.Width )));

                        int tileCountY = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(bitmap.Height / GroupBackgroundImage.Height)));

 

                        for(int y = 0; y <= tileCountY; y++)

                        {

                            for(int x = 0; x <= tileCountX; x++)

                            {

                                bitmapGraphics.DrawImage

                                (

                                    GroupBackgroundImage,

                                    x * GroupBackgroundImage.Width,

                                    y * GroupBackgroundImage.Height,

                                    GroupBackgroundImage.Width,

                                    GroupBackgroundImage.Height

                                );

                            }

                        }

                    }

                    else if(BackgroundImageLayout == ImageLayout.Center)

                    {

                        int imageLeft = Convert.ToInt32((Width / 2) - (GroupBackgroundImage.Width / 2));

                        int imageTop  = Convert.ToInt32(((Height - topOffset) / 2) - (GroupBackgroundImage.Height / 2));

 

                        bitmapGraphics.DrawImage(GroupBackgroundImage, imageLeft, imageTop, GroupBackgroundImage.Width,

                            GroupBackgroundImage.Height);

                    }

                    else if(BackgroundImageLayout == ImageLayout.Stretch)

                    {

                        bitmapGraphics.DrawImage(GroupBackgroundImage, 0, 0, Width, Height - topOffset);

                    }

                    else if(BackgroundImageLayout == ImageLayout.Zoom)

                    {

                        double backgroundRatio = Width / (Height - topOffset);

                        double imageRatio      = GroupBackgroundImage.Width / GroupBackgroundImage.Height;

 

                        Rectangle backgroundRectangle = new Rectangle(0, 0, Width, Height - topOffset);

 

                        if(imageRatio > backgroundRatio)

                        {

                            backgroundRectangle.Width  = Width;

                            backgroundRectangle.Height = Convert.ToInt32(Width / imageRatio);

                        }

                        else if(imageRatio < backgroundRatio)

                        {

                            backgroundRectangle.Height = Height - topOffset;

                            backgroundRectangle.Width  = Convert.ToInt32((Height - topOffset) * imageRatio);

                        }

 

                        backgroundRectangle.X = Convert.ToInt32((Width / 2) - (backgroundRectangle.Width / 2));

                        backgroundRectangle.Y = Convert.ToInt32(((Height - topOffset) / 2) - (backgroundRectangle.Height / 2));

 

                        bitmapGraphics.DrawImage(GroupBackgroundImage, backgroundRectangle);

                    }

                }

                using(TextureBrush textureBrush = new TextureBrush(bitmap))

                {

                    if(BackgroundImageLayout != ImageLayout.Tile)

                    {

                        textureBrush.WrapMode = WrapMode.Clamp;

                    }

 

                    textureBrush.TranslateTransform(0, topOffset);

 

                    graphics.FillPath(textureBrush, graphicsPath);

                }

            }

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요