첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ CheckButton.cs

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 체크 버튼
    /// </summary>
    [DefaultEvent("CheckedChanged")]
    public class CheckButton : UserControl
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Event
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 클릭시 이벤트 - Clicked

        /// <summary>
        /// 클릭시 이벤트
        /// </summary>
        public event EventHandler Clicked;

        #endregion
        #region 체크 변경시 이벤트 - CheckedChanged

        /// <summary>
        /// 체크 변경시 이벤트
        /// </summary>
        public event EventHandler CheckedChanged;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Enumeration
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 이미지 버튼 스타일 - CheckButtonStyle

        /// <summary>
        /// 이미지 버튼 스타일
        /// </summary>
        public enum CheckButtonStyle
        {
            /// <summary>
            /// DEFAULT
            /// </summary>
            Default,

            /// <summary>
            /// FLAT
            /// </summary>
            Flat
        };

        #endregion

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

        #region 이미지 버튼 상태 - CheckButtonState

        /// <summary>
        /// 이미지 버튼 상태
        /// </summary>
        private enum CheckButtonState { None, Hover, Pressed };

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 컨테이너
        /// </summary>
        private Container container = null;

        /// <summary>
        /// 버튼 스타일
        /// </summary>
        private CheckButtonStyle buttonStyle = CheckButtonStyle.Default;

        /// <summary>
        /// 버튼 상태
        /// </summary>
        private CheckButtonState buttonState = CheckButtonState.None;

        /// <summary>
        /// 코너 반지름
        /// </summary>
        private int cornerRadius = 8;

        /// <summary>
        /// 외부 테두리 경로
        /// </summary>
        private GraphicsPath outerBorderPath = null;

        /// <summary>
        /// 내부 테두리 경로
        /// </summary>
        private GraphicsPath innerBorderPath = null;

        /// <summary>
        /// 하이라이트 경로
        /// </summary>
        private GraphicsPath highlightPath = null;

        /// <summary>
        /// 버튼 색상 1
        /// </summary>
        private Color buttonColor1 = Color.Gray;

        /// <summary>
        /// 버튼 색상 브러시 1
        /// </summary>
        private SolidBrush buttonColorBrush1 = new SolidBrush(Color.Gray);

        /// <summary>
        /// 버튼 색상 2
        /// </summary>
        private Color buttonColor2 = Color.Gray;

        /// <summary>
        /// 버튼 색상 펜 2
        /// </summary>
        private Pen buttonColorPen2 = new Pen(Color.Gray);

        /// <summary>
        /// 하이라이트 색상
        /// </summary>
        private Color highlightColor = Color.White;

        /// <summary>
        /// 하이라이트 색상 펜
        /// </summary>
        private Pen highlightColorPen = new Pen(Color.White);

        /// <summary>
        /// 배경 이미지
        /// </summary>
        private Image backgroundImage = null;

        /// <summary>
        /// 체크 박스 표시 여부
        /// </summary>
        private bool showCheckBox = true;

        /// <summary>
        /// 체크 박스 표시 위치
        /// </summary>
        private Point checkBoxLocation = new Point(8, 8);

        /// <summary>
        /// 체크 여부
        /// </summary>
        private bool isChecked = false;

        /// <summary>
        /// 이미지 정렬
        /// </summary>
        private ContentAlignment imageAlignment = ContentAlignment.MiddleLeft;

        /// <summary>
        /// 이미지 크기
        /// </summary>
        private Size imageSize = new Size(24, 24);

        /// <summary>
        /// 이미지 사각형
        /// </summary>
        private Rectangle imageRectangle = new Rectangle(8, 8, 24, 24);

        /// <summary>
        /// 이미지
        /// </summary>
        private Image image = null;

        /// <summary>
        /// 제목 정렬
        /// </summary>
        private ContentAlignment titleAlignment = ContentAlignment.MiddleCenter;

        /// <summary>
        /// 제목 사각형
        /// </summary>
        private Rectangle titleRectangle;

        /// <summary>
        /// 제목 문자열 포맷
        /// </summary>
        private StringFormat titleStringFormat = null;

        /// <summary>
        /// 제목 색상
        /// </summary>
        private Color titleColor = Color.White;

        /// <summary>
        /// 제목
        /// </summary>
        private string title;

        /// <summary>
        /// FADE IN 타이머
        /// </summary>
        private Timer fadeInTimer = null;

        /// <summary>
        /// FADE OUT 타이머
        /// </summary>
        private Timer fadeOutTimer = null;

        /// <summary>
        /// 반짝임 투명도
        /// </summary>
        private int glowAlpha = 0;

        /// <summary>
        /// 반짝임 색상
        /// </summary>
        private Color glowColor = Color.White;

        /// <summary>
        /// 키로 호출 여부
        /// </summary>
        private bool calledByKey = false;

        /// <summary>
        /// 클릭 여부
        /// </summary>
        private bool isClicked = false;

        /// <summary>
        /// 대화 상자 결과
        /// </summary>
        private DialogResult dialogResult = DialogResult.None;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 버튼 스타일 - ButtonStyle

        /// <summary>
        /// 버튼 스타일
        /// </summary>
        [Category("CheckButton")]
        public CheckButtonStyle ButtonStyle
        {
            get
            {
                return this.buttonStyle;
            }
            set
            {
                this.buttonStyle = value;
                
                Invalidate();
            }
        }

        #endregion
        #region 코너 반지름 - CornerRadius

        /// <summary>
        /// 코너 반지름
        /// </summary>
        [Category("CheckButton")]
        public int CornerRadius
        {
            get
            {
                return this.cornerRadius;
            }
            set
            {
                this.cornerRadius = value;

                SetOuterBorderPath(ClientRectangle, this.cornerRadius);
                
                Invalidate();
            }
        }

        #endregion
        #region 버튼 색상 1 - ButtonColor1

        /// <summary>
        /// 버튼 색상 1
        /// </summary>
        [Category("CheckButton")]
        public Color ButtonColor1
        {
            get
            {
                return this.buttonColor1;
            }
            set
            {
                this.buttonColor1 = value;

                this.buttonColorBrush1 = new SolidBrush(this.buttonColor1);
                
                Invalidate();
            }
        }

        #endregion
        #region 버튼 색상 2 - ButtonColor2

        /// <summary>
        /// 버튼 색상 2
        /// </summary>
        [Category("CheckButton")]
        public Color ButtonColor2
        {
            get
            {
                return this.buttonColor2;
            }
            set
            {
                this.buttonColor2 = value;

                this.buttonColorPen2 = new Pen(this.buttonColor2);
                
                Invalidate();
            }
        }

        #endregion
        #region 하이라이트 색상 - HighlightColor

        /// <summary>
        /// 하이라이트 색상
        /// </summary>
        [Category("CheckButton")]
        public Color HighlightColor
        {
            get
            {
                return this.highlightColor;
            }
            set
            {
                this.highlightColor = value;

                this.highlightColorPen = new Pen(this.highlightColor);
                
                Invalidate();
            }
        }

        #endregion
        #region 배경 이미지 - BackgroundImage

        /// <summary>
        /// 배경 이미지
        /// </summary>
        [Category("CheckButton")]
        public override Image BackgroundImage
        {
            get
            {
                return this.backgroundImage;
            }
            set
            {
                this.backgroundImage = value;
                
                Invalidate();
            }
        }

        #endregion
        #region 체크 박스 표시 여부 - ShowCheckBox

        /// <summary>
        /// 체크 박스 표시 여부
        /// </summary>
        [Category("CheckButton")]
        public bool ShowCheckBox
        {
            get
            {
                return this.showCheckBox;
            }
            set
            {
                this.showCheckBox = value;
                
                Invalidate();
            }
        }

        #endregion
        #region 체크 박스 표시 위치 - CheckBoxLocation

        /// <summary>
        /// 체크 박스 표시 위치
        /// </summary>
        [Category("CheckButton")]
        public Point CheckBoxLocation
        {
            get
            {
                return this.checkBoxLocation;
            }
            set
            {
                this.checkBoxLocation = value;

                Invalidate();
            }
        }

        #endregion
        #region 이미지 정렬 - ImageAlignment

        /// <summary>
        /// 이미지 정렬
        /// </summary>
        [Category("CheckButton")]
        public ContentAlignment ImageAlignment
        {
            get
            {
                return this.imageAlignment;
            }
            set
            {
                this.imageAlignment = value;
                
                Invalidate();
            }
        }

        #endregion
        #region 이미지 크기 - ImageSize

        /// <summary>
        /// 이미지 크기
        /// </summary>
        [Category("CheckButton")]
        public Size ImageSize
        {
            get
            {
                return this.imageSize;
            }
            set
            {
                this.imageSize = value;

                SetImageRectangle(this.imageSize);
                
                Invalidate();
            }
        }

        #endregion
        #region 이미지 - Image

        /// <summary>
        /// 이미지
        /// </summary>
        [Category("CheckButton")]
        public Image Image
        {
            get
            {
                return this.image;
            }
            set
            {
                this.image = value;
                
                Invalidate();
            }
        }

        #endregion
        #region 제목 정렬 - TitleAlignment

        /// <summary>
        /// 제목 정렬
        /// </summary>
        [Category("CheckButton")]
        public ContentAlignment TitleAlignment
        {
            get
            {
                return this.titleAlignment;
            }
            set
            {
                this.titleAlignment = value;

                SetTitleStringFormat(this.titleAlignment);
                
                Invalidate();
            }
        }

        #endregion
        #region 제목 색상 - TitleColor

        /// <summary>
        /// 제목 색상
        /// </summary>
        [Category("CheckButton")]
        public Color TitleColor
        {
            get
            {
                return this.titleColor;
            }
            set
            {
                this.titleColor = value;
                
                Invalidate();
            }
        }

        #endregion
        #region 제목 - Title

        /// <summary>
        /// 제목
        /// </summary>
        [Category("CheckButton")]
        public String Title
        {
            get
            {
                return this.title;
            }
            set
            {
                this.title = value;

                Invalidate();
            }
        }

        #endregion
        #region 반짝임 색상 - GlowColor

        /// <summary>
        /// 반짝임 색상
        /// </summary>
        [Category("CheckButton")]
        public Color GlowColor
        {
            get
            {
                return this.glowColor;
            }
            set
            {
                this.glowColor = value;
                
                Invalidate();
            }
        }

        #endregion
        #region 대화 상자 결과 - DialogResult

        /// <summary>
        /// 대화 상자 결과
        /// </summary>
        [Category("CheckButton")]
        public DialogResult DialogResult
        {
            get
            {
                return this.dialogResult;
            }
            set
            {
                this.dialogResult = value;
                
                Invalidate();
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - CheckButton()

        /// <summary>
        /// 생성자
        /// </summary>
        public CheckButton()
        {
            Name      = "CheckButton";
            Size      = new Size(100, 32);
            BackColor = Color.Transparent;

            SetHighlightPath(ClientRectangle, this.cornerRadius);

            SetOuterBorderPath(ClientRectangle, this.cornerRadius);

            SetInnerBorderPath(ClientRectangle, this.cornerRadius);

            SetTitleRectangle(ClientRectangle);

            SetTitleStringFormat(this.titleAlignment);

            this.SetStyle(ControlStyles.AllPaintingInWmPaint        , true);
            this.SetStyle(ControlStyles.DoubleBuffer                , true);
            this.SetStyle(ControlStyles.ResizeRedraw                , true);
            this.SetStyle(ControlStyles.Selectable                  , true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint                   , true);

            this.fadeInTimer = new Timer();

            this.fadeInTimer.Interval  = 30;

            this.fadeOutTimer = new Timer();

            this.fadeOutTimer.Interval = 30;

            Resize                 += UserControl_Resize;
            Paint                  += UserControl_Paint;
            KeyDown                += UserControl_KeyDown;
            KeyUp                  += UserControl_KeyUp;
            MouseEnter             += UserControl_MouseEnter;
            MouseDown              += UserControl_MouseDown;
            MouseUp                += UserControl_MouseUp;
            MouseLeave             += UserControl_MouseLeave;
            this.fadeInTimer.Tick  += fadeInTimer_Tick;
            this.fadeOutTimer.Tick += fadeOutTimer_Tick;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 클릭시 이벤트 발생시키기 - FireClickedEvent()

        /// <summary>
        /// 클릭시 이벤트 발생시키기
        /// </summary>
        protected void FireClickedEvent()
        {
            Clicked?.Invoke(this, EventArgs.Empty);
        }

        #endregion
        #region 체크 변경시 이벤트 발생시키기 - FireCheckedChangedEvent()

        /// <summary>
        /// 체크 변경시 이벤트 발생시키기
        /// </summary>
        protected void FireCheckedChangedEvent()
        {
            CheckedChanged?.Invoke(this, EventArgs.Empty);
        }

        #endregion
        #region 리소스 해제하기 - Dispose(disposing)

        /// <summary>
        /// 리소스 해제하기
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if(disposing)
            {
                if(this.container != null)
                {
                    this.container.Dispose();

                    this.outerBorderPath?.Dispose();

                    this.innerBorderPath?.Dispose();

                    this.highlightPath?.Dispose();

                    this.buttonColorPen2?.Dispose();

                    this.highlightColorPen?.Dispose();

                    this.buttonColorBrush1?.Dispose();
                }
            }

            base.Dispose(disposing);
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 사용자 컨트롤 크기 변경시 처리하기 - UserControl_Resize(sender, e)

        /// <summary>
        /// 사용자 컨트롤 크기 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_Resize(object sender, EventArgs e)
        {
            Rectangle rectangle = ClientRectangle;

            rectangle.X -= 1;
            rectangle.Y -= 1;

            rectangle.Width  += 2;
            rectangle.Height += 2;

            using
            (
                GraphicsPath graphicsPath = GetShapePath
                (
                    rectangle,
                    this.cornerRadius,
                    this.cornerRadius,
                    this.cornerRadius,
                    this.cornerRadius
                )
            )
            {
                Region = new Region(graphicsPath);
            }

            SetOuterBorderPath(ClientRectangle, this.cornerRadius);

            SetInnerBorderPath(ClientRectangle, this.cornerRadius);

            SetHighlightPath(ClientRectangle, this.cornerRadius);

            SetTitleRectangle(ClientRectangle);
        }

        #endregion
        #region 사용자 컨트롤 키 DOWN시 처리하기 - UserControl_KeyDown(sender, e)

        /// <summary>
        /// 사용자 컨트롤 키 DOWN시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Enter)
            {
                MouseEventArgs mouseEventArgs = new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0);

                UserControl_MouseDown(sender, mouseEventArgs);
            }
        }

        #endregion
        #region 사용자 컨트롤 키 UP시 처리하기 - UserControl_KeyUp(sender, e)

        /// <summary>
        /// 사용자 컨트롤 키 UP시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_KeyUp(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Enter)
            {
                if(!this.isClicked)
                {
                    return;
                }

                MouseEventArgs mouseEventArgs = new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0);

                this.calledByKey = true;

                UserControl_MouseUp(sender, mouseEventArgs);
            }
        }

        #endregion
        #region 사용자 컨트롤 마우스 진입시 처리하기 - UserControl_MouseEnter(sender, e)

        /// <summary>
        /// 사용자 컨트롤 마우스 진입시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_MouseEnter(object sender, EventArgs e)
        {
            this.buttonState = CheckButtonState.Hover;

            this.fadeOutTimer.Stop();

            this.fadeInTimer.Start();
        }

        #endregion
        #region 사용자 컨트롤 마우스 이탈시 처리하기 - UserControl_MouseLeave(sender, e)

        /// <summary>
        /// 사용자 컨트롤 마우스 이탈시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_MouseLeave(object sender, EventArgs e)
        {
            this.buttonState = CheckButtonState.None;

            if(this.buttonStyle == CheckButtonStyle.Flat)
            {
                this.glowAlpha = 0;
            }

            this.fadeInTimer.Stop();

            this.fadeOutTimer.Start();

            this.isClicked = false;
        }

        #endregion
        #region 사용자 컨트롤 마우스 DOWN시 처리하기 - UserControl_MouseDown(sender, e)

        /// <summary>
        /// 사용자 컨트롤 마우스 DOWN시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_MouseDown(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                if(this.isClicked)
                {
                    return;
                }

                this.isClicked = true;

                this.buttonState = CheckButtonState.Pressed;

                if(this.buttonStyle != CheckButtonStyle.Flat)
                {
                    this.glowAlpha = 255;
                }

                this.fadeInTimer.Stop();

                this.fadeOutTimer.Stop();

                Invalidate();
            }
        }

        #endregion
        #region 사용자 컨트롤 마우스 UP시 처리하기 - UserControl_MouseUp(sender, e)

        /// <summary>
        /// 사용자 컨트롤 마우스 UP시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_MouseUp(object sender, MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                this.buttonState = CheckButtonState.Hover;

                this.fadeInTimer.Stop();

                this.fadeOutTimer.Stop();

                Invalidate();

                if(this.calledByKey == true)
                {
                    OnClick(EventArgs.Empty);
                    
                    this.calledByKey = false;
                }

                this.isClicked = false;

                FireClickedEvent();

                this.isChecked = !this.isChecked;

                if(this.showCheckBox)
                {
                    FireCheckedChangedEvent();
                }
            }
        }

        #endregion
        #region 사용자 컨트롤 페인트시 처리하기 - UserControl_Paint(sender, e)

        /// <summary>
        /// 사용자 컨트롤 페인트시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void UserControl_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode     = SmoothingMode.AntiAlias;
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

            DrawBackgroundImage(e.Graphics);
            DrawHighlight(e.Graphics);
            DrawImage(e.Graphics);
            DrawTitle(e.Graphics);
            DrawGlow(e.Graphics);
            DrawInnerBorder(e.Graphics);
            DrawOuterBorder(e.Graphics);
            DrawCheckBox(e.Graphics);
        }

        #endregion
        #region FADE IN 타이머 틱 처리하기 - fadeInTimer_Tick(sender, e)

        /// <summary>
        /// FADE IN 타이머 틱 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void fadeInTimer_Tick(object sender, EventArgs e)
        {
            if(this.buttonStyle == CheckButtonStyle.Flat)
            {
                this.glowAlpha = 0;
            }

            if(this.glowAlpha + 30 >= 255)
            {
                this.glowAlpha = 255;

                this.fadeInTimer.Stop();
            }
            else
            {
                this.glowAlpha += 30;
            }

            Invalidate();
        }

        #endregion
        #region FADE OUT 타이머 틱 처리하기 - fadeOutTimer_Tick(sender, e)

        /// <summary>
        /// FADE OUT 타이머 틱 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void fadeOutTimer_Tick(object sender, EventArgs e)
        {
            if(this.buttonStyle == CheckButtonStyle.Flat)
            {
                this.glowAlpha = 0;
            }

            if(this.glowAlpha - 30 <= 0)
            {
                this.glowAlpha = 0;

                this.fadeOutTimer.Stop();
            }
            else
            {
                this.glowAlpha -= 30;
            }

            this.Invalidate();
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 도형 패스 구하기 - GetShapePath(rectangle, r1, r2, r3, r4)

        /// <summary>
        /// 도형 패스 구하기
        /// </summary>
        /// <param name="rectangle">사각형</param>
        /// <param name="r1">R1</param>
        /// <param name="r2">R2</param>
        /// <param name="r3">R3</param>
        /// <param name="r4">R4</param>
        /// <returns>도형 패스</returns>
        private GraphicsPath GetShapePath(RectangleF rectangle, float r1, float r2, float r3, float r4)
        {
            float x      = rectangle.X;
            float y      = rectangle.Y;
            float width  = rectangle.Width;
            float height = rectangle.Height;

            GraphicsPath graphicsPath = new GraphicsPath();

            graphicsPath.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);

            graphicsPath.AddLine(x + r1, y, x + width - r2, y);

            graphicsPath.AddBezier(x + width - r2, y, x + width, y, x + width, y + r2, x + width, y + r2);

            graphicsPath.AddLine(x + width, y + r2, x + width, y + height - r3);

            graphicsPath.AddBezier
            (
                x + width,
                y + height - r3,
                x + width,
                y + height,
                x + width - r3,
                y + height,
                x + width - r3,
                y + height
            );

            graphicsPath.AddLine(x + width - r3, y + height, x + r4, y + height);

            graphicsPath.AddBezier(x + r4, y + height, x, y + height, x, y + height - r4, x, y + height - r4);

            graphicsPath.AddLine(x, y + height - r4, x, y + r1);

            return graphicsPath;
        }

        #endregion
        #region 하이라이트 경로 설정하기 - SetHighlightPath(clientRectangle, cornerRadius)

        /// <summary>
        /// 하이라이트 경로 설정하기
        /// </summary>
        /// <param name="clientRectangle">클라이언트 사각형</param>
        /// <param name="cornerRadius">코너 반지름</param>
        private void SetHighlightPath(Rectangle clientRectangle, int cornerRadius)
        {
            Rectangle rectangle = new Rectangle(0, 0, clientRectangle.Width, clientRectangle.Height / 2);

            GraphicsPath highlightPath = GetShapePath(rectangle, cornerRadius, cornerRadius, 0, 0);

            this.highlightPath?.Dispose();

            this.highlightPath = highlightPath;
        }

        #endregion
        #region 내부 테두리 경로 설정하기 - SetInnerBorderPath(clientRectangle, cornerRadius)

        /// <summary>
        /// 내부 테두리 경로 설정하기
        /// </summary>
        /// <param name="clientRectangle">클라이언트 사각형</param>
        /// <param name="cornerRadius">코너 반지름</param>
        private void SetInnerBorderPath(Rectangle clientRectangle, int cornerRadius)
        {
            Rectangle rectangle = clientRectangle;

            rectangle.X++;
            rectangle.Y++;

            rectangle.Width  -= 3;
            rectangle.Height -= 3;

            GraphicsPath innerBorderPath = GetShapePath
            (
                rectangle,
                cornerRadius,
                cornerRadius,
                cornerRadius,
                cornerRadius
            );

            this.innerBorderPath?.Dispose();

            this.innerBorderPath = innerBorderPath;
        }

        #endregion
        #region 외부 테두리 경로 설정하기 - SetOuterBorderPath(clientRectangle, cornerRadius)

        /// <summary>
        /// 외부 테두리 경로 설정하기
        /// </summary>
        /// <param name="clientRectangle">클라이언트 사각형</param>
        /// <param name="cornerRadius">코너 반지름</param>
        private void SetOuterBorderPath(Rectangle clientRectangle, float cornerRadius)
        {
            Rectangle rectangle = clientRectangle;

            rectangle.Width  -= 1;
            rectangle.Height -= 1;

            GraphicsPath outerBorderPath = GetShapePath
            (
                rectangle,
                cornerRadius,
                cornerRadius,
                cornerRadius,
                cornerRadius
            );

            this.outerBorderPath?.Dispose();

            this.outerBorderPath = outerBorderPath;
        }

        #endregion
        #region 이미지 사각형 설정하기 - SetImageRectangle(imageSize)

        /// <summary>
        /// 이미지 사각형 설정하기
        /// </summary>
        /// <param name="imageSize">이미지 크기</param>
        private void SetImageRectangle(Size imageSize)
        {
            Rectangle imageRectangle = new Rectangle(8, 8, imageSize.Width, imageSize.Height);

            switch(this.imageAlignment)
            {
                case ContentAlignment.TopCenter :

                    imageRectangle = new Rectangle
                    (
                        Width / 2 - imageSize.Width / 2,
                        8,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;

                case ContentAlignment.TopRight :

                    imageRectangle = new Rectangle
                    (
                        Width - 8 - imageSize.Width,
                        8,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;

                case ContentAlignment.MiddleLeft :

                    imageRectangle = new Rectangle
                    (
                        8,
                        Height / 2 - imageSize.Height / 2,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;

                case ContentAlignment.MiddleCenter :

                    imageRectangle = new Rectangle
                    (
                        Width  / 2 - imageSize.Width  / 2,
                        Height / 2 - imageSize.Height / 2,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;

                case ContentAlignment.MiddleRight :

                    imageRectangle = new Rectangle
                    (
                        Width  - 8 - imageSize.Width,
                        Height / 2 - imageSize.Height / 2,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;

                case ContentAlignment.BottomLeft :

                    imageRectangle = new Rectangle
                    (
                        8,
                        Height - 8 - imageSize.Height,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;

                case ContentAlignment.BottomCenter :

                    imageRectangle = new Rectangle
                    (
                        Width  / 2 - imageSize.Width / 2,
                        Height - 8 - imageSize.Height,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;

                case ContentAlignment.BottomRight :

                    imageRectangle = new Rectangle
                    (
                        Width  - 8 - imageSize.Width,
                        Height - 8 - imageSize.Height,
                        imageSize.Width,
                        imageSize.Height
                    );

                    break;
            }

            this.imageRectangle = imageRectangle;
        }

        #endregion
        #region 제목 사각형 설정하기 - SetTitleRectangle(clientRectangle)

        /// <summary>
        /// 제목 사각형 설정하기
        /// </summary>
        /// <param name="clientRectangle">클라이언트 사각형</param>
        private void SetTitleRectangle(Rectangle clientRectangle)
        {
            this.titleRectangle = new Rectangle(8, 4, clientRectangle.Width - 8, clientRectangle.Height - 8);

            //Rectangle rectangle = new Rectangle(8, 8, Width - 17, Height - 17);
        }

        #endregion
        #region 제목 문자열 포맷 설정하기 - SetTitleStringFormat(titleAlignment)

        /// <summary>
        /// 제목 문자열 포맷 설정하기
        /// </summary>
        /// <param name="titleAlignment">제목 정렬</param>
        private void SetTitleStringFormat(ContentAlignment titleAlignment)
        {
            StringFormat stringFormat = new StringFormat();

            stringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.LineLimit;

            switch(titleAlignment)
            {
                case ContentAlignment.TopLeft   :
                case ContentAlignment.TopCenter :
                case ContentAlignment.TopRight  :

                    stringFormat.LineAlignment = StringAlignment.Near;

                    break;

                case ContentAlignment.MiddleLeft   :
                case ContentAlignment.MiddleCenter :
                case ContentAlignment.MiddleRight  :

                    stringFormat.LineAlignment = StringAlignment.Center;

                    break;

                case ContentAlignment.BottomLeft   :
                case ContentAlignment.BottomCenter :
                case ContentAlignment.BottomRight  :

                    stringFormat.LineAlignment = StringAlignment.Far;
                    break;
            }

            switch(titleAlignment)
            {
                case ContentAlignment.TopLeft    :
                case ContentAlignment.MiddleLeft :
                case ContentAlignment.BottomLeft :

                    stringFormat.Alignment = StringAlignment.Near;

                    break;

                case ContentAlignment.TopCenter    :
                case ContentAlignment.MiddleCenter :
                case ContentAlignment.BottomCenter :

                    stringFormat.Alignment = StringAlignment.Center;

                    break;

                case ContentAlignment.TopRight    :
                case ContentAlignment.MiddleRight :
                case ContentAlignment.BottomRight :

                    stringFormat.Alignment = StringAlignment.Far;

                    break;
            }

            this.titleStringFormat = stringFormat;
        }

        #endregion

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

        /// <summary>
        /// 배경 이미지 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawBackgroundImage(Graphics graphics)
        {
            if(this.buttonStyle == CheckButtonStyle.Flat && this.buttonState == CheckButtonState.None)
            {
                return;
            }

            int alpha = (this.buttonState == CheckButtonState.Pressed) ? 204 : 127;

            graphics.FillPath(this.buttonColorBrush1, this.outerBorderPath);

            graphics.SetClip(this.innerBorderPath);

            if(this.backgroundImage != null)
            {
                graphics.DrawImage(this.backgroundImage, ClientRectangle);
            }

            graphics.ResetClip();

            using(SolidBrush solidBrush = new SolidBrush(Color.FromArgb(alpha, this.buttonColor2)))
            {
                graphics.FillPath(solidBrush, this.outerBorderPath);
            }
        }

        #endregion
        #region 하이라이트 그리기 - DrawHighlight(graphics)

        /// <summary>
        /// 하이라이트 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawHighlight(Graphics graphics)
        {
            if(!Enabled)
            {
                return;
            }

            if(this.buttonStyle == CheckButtonStyle.Flat && this.buttonState == CheckButtonState.None)
            {
                return;
            }

            int alpha = (buttonState == CheckButtonState.Pressed) ? 60 : 150;

            LinearGradientBrush highlightColorBrush = new LinearGradientBrush
            (
                this.highlightPath.GetBounds(),
                Color.FromArgb(alpha, this.highlightColor),
                Color.FromArgb(alpha / 3, this.highlightColor),
                LinearGradientMode.Vertical
            );

            graphics.FillPath(highlightColorBrush, this.highlightPath);
        }

        #endregion
        #region 이미지 그리기 - DrawImage(graphics)

        /// <summary>
        /// 이미지 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawImage(Graphics graphics)
        {
            if(this.image == null)
            {
                return;
            }

            graphics.DrawImage(this.image, this.imageRectangle);
        }

        #endregion
        #region 제목 그리기 - DrawTitle(graphics)

        /// <summary>
        /// 제목 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawTitle(Graphics graphics)
        {
            graphics.DrawString
            (
                this.title,
                Font,
                new SolidBrush(this.titleColor),
                this.titleRectangle,
                this.titleStringFormat
            );
        }

        #endregion
        #region 내부 테두리 그리기 - DrawInnerBorder(graphics)

        /// <summary>
        /// 내부 테두리 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawInnerBorder(Graphics graphics)
        {
            if(this.buttonStyle == CheckButtonStyle.Flat && this.buttonState == CheckButtonState.None)
            {
                return;
            }

            graphics.DrawPath(this.highlightColorPen, this.innerBorderPath);
        }

        #endregion
        #region 외부 테두리 그리기 - DrawOuterBorder(graphics)

        /// <summary>
        /// 외부 테두리 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawOuterBorder(Graphics graphics)
        {
            if(this.buttonStyle == CheckButtonStyle.Flat && this.buttonState == CheckButtonState.None)
            {
                return;
            }

            graphics.DrawPath(this.buttonColorPen2, this.outerBorderPath);
        }

        #endregion
        #region 체크 박스 그리기 - DrawCheckBox(graphics)

        /// <summary>
        /// 체크 박스 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawCheckBox(Graphics graphics)
        {
            if(this.showCheckBox)
            {
                System.Windows.Forms.VisualStyles.CheckBoxState state;

                if(this.isChecked)
                {
                    state = System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal;
                }
                else
                {
                    state = System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
                }

                CheckBoxRenderer.DrawCheckBox
                (
                    graphics,
                    this.checkBoxLocation,
                    state
                );
            }
        }

        #endregion
        #region GLOW 그리기 - DrawGlow(graphics)

        /// <summary>
        /// GLOW 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        private void DrawGlow(Graphics graphics)
        {
            if(this.buttonState == CheckButtonState.Pressed || this.buttonState == CheckButtonState.None)
            {
                return;
            }

            graphics.SetClip(this.innerBorderPath);

            using(GraphicsPath graphicsPath = new GraphicsPath())
            {
                graphicsPath.AddEllipse(-5, this.Height / 2 - 10, Width + 11, Height + 11);

                using(PathGradientBrush pathGradientBrush = new PathGradientBrush(graphicsPath))
                {
                    pathGradientBrush.CenterColor    = Color.FromArgb(this.glowAlpha, this.glowColor);
                    pathGradientBrush.SurroundColors = new Color[] { Color.FromArgb(0, this.glowColor) };

                    graphics.FillPath(pathGradientBrush, graphicsPath);
                }
            }

            graphics.ResetClip();
        }

        #endregion
    }
}
728x90
반응형
그리드형
Posted by 사용자 icodebroker

댓글을 달아 주세요