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

728x90
반응형
728x170

TestProject.zip
다운로드

▶ MetroStyle.cs

using System.ComponentModel;
using System.Drawing;

namespace TestProject
{
    /// <summary>
    /// 메트로 스타일
    /// </summary>
    public class MetroStyle : INotifyPropertyChanged
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Event
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 속성 변경시 - PropertyChanged

        /// <summary>
        /// 속성 변경시
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

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

        #region Field

        /// <summary>
        /// 베이스 폰트
        /// </summary>
        private Font baseFont;

        /// <summary>
        /// 볼드체 폰트
        /// </summary>
        private Font boldFont;

        /// <summary>
        /// 라이트 폰트
        /// </summary>
        private Font lightFont;

        /// <summary>
        /// 배경색
        /// </summary>
        private Color backColor;

        /// <summary>
        /// 전경색
        /// </summary>
        private Color foreColor;

        /// <summary>
        /// 강조색
        /// </summary>
        private Color accentColor;

        /// <summary>
        /// 강조 전경색
        /// </summary>
        private Color accentForeColor;

        /// <summary>
        /// 비활성화 색
        /// </summary>
        private Color disabledColor;

        /// <summary>
        /// 다크 스타일 여부
        /// </summary>
        private bool isDarkStyle;

        #endregion

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

        #region 베이스 폰트 - BaseFont

        /// <summary>
        /// 베이스 폰트
        /// </summary>
        public Font BaseFont
        {
            get
            {
                return this.baseFont;
            }
            set
            {
                if(value.Equals(this.baseFont) == false)
                {
                    this.baseFont = value;

                    FirePropertyChanged("BaseFont");
                }
            }
        }

        #endregion
        #region 볼드체 폰트 - BoldFont

        /// <summary>
        /// 볼드체 폰트
        /// </summary>
        public Font BoldFont
        {
            get
            {
                return this.boldFont;
            }
            set
            {
                if(value.Equals(this.boldFont) == false)
                {
                    this.boldFont = value;

                    FirePropertyChanged("BoldFont");
                }
            }
        }

        #endregion
        #region 라이트 폰트 - LightFont

        /// <summary>
        /// 라이트 폰트
        /// </summary>
        public Font LightFont
        {
            get
            {
                return this.lightFont;
            }
            set
            {
                if(value.Equals(this.lightFont) == false)
                {
                    this.lightFont = value;

                    FirePropertyChanged("LightFont");
                }
            }
        }

        #endregion
        #region 배경색 - BackColor

        /// <summary>
        /// 배경색
        /// </summary>
        public Color BackColor
        {
            get
            {
                return this.backColor;
            }
            set
            {
                if(value.Equals(this.backColor) == false)
                {
                    this.backColor = value;

                    FirePropertyChanged("BackColor");
                }
            }
        }

        #endregion
        #region 전경색 - ForeColor

        /// <summary>
        /// 전경색
        /// </summary>
        public Color ForeColor
        {
            get
            {
                return this.foreColor;
            }
            set
            {
                if(value.Equals(this.foreColor) == false)
                {
                    this.foreColor = value;

                    FirePropertyChanged("ForeColor");
                }
            }
        }

        #endregion
        #region 강조색 - AccentColor

        /// <summary>
        /// 강조색
        /// </summary>
        public Color AccentColor
        {
            get
            {
                return this.accentColor;
            }
            set
            {
                if(value.Equals(this.accentColor) == false)
                {
                    this.accentColor = value;

                    FirePropertyChanged("AccentColor");
                }
            }
        }

        #endregion
        #region 강조 전경색 - AccentForeColor

        /// <summary>
        /// 강조 전경색
        /// </summary>
        public Color AccentForeColor
        {
            get
            {
                return this.accentForeColor;
            }
            set
            {
                if(value.Equals(this.accentForeColor) == false)
                {
                    this.accentForeColor = value;

                    FirePropertyChanged("AccentForeColor");
                }
            }
        }

        #endregion
        #region 비활성화 색 - DisabledColor

        /// <summary>
        /// 비활성화 색
        /// </summary>
        public Color DisabledColor
        {
            get
            {
                return this.disabledColor;
            }
            set
            {
                if(value.Equals(this.disabledColor) == false)
                {
                    this.disabledColor = value;

                    FirePropertyChanged("DisabledColor");
                }
            }
        }

        #endregion
        #region 다크 스타일 여부 - IsDarkStyle

        /// <summary>
        /// 다크 스타일 여부
        /// </summary>
        public bool IsDarkStyle
        {
            get
            {
                return this.isDarkStyle;
            }
            set
            {
                if(value != this.isDarkStyle)
                {
                    this.isDarkStyle = value;

                    if(this.isDarkStyle)
                    {
                        BackColor       = Color.FromArgb(51, 51, 51);
                        ForeColor       = Color.White;
                        AccentColor     = Color.DarkOrange;
                        AccentForeColor = Color.FromArgb(51, 51, 51);
                        DisabledColor   = Color.DimGray;
                    }
                    else
                    {
                        BackColor       = Color.White;
                        ForeColor       = Color.FromArgb(51, 51, 51);
                        AccentColor     = Color.FromArgb(0, 114, 198);
                        AccentForeColor = Color.White;
                        DisabledColor   = Color.DimGray;
                    }

                    FirePropertyChanged("IsDarkStyle");
                }
            }
        }

        #endregion

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

        #region 생성자 - MetroStyle()

        /// <summary>
        /// 생성자
        /// </summary>
        public MetroStyle()
        {
            BaseFont  = new Font("Segoe UI"      , 11.25f                   );
            BoldFont  = new Font("Segoe UI"      , 11.25f, FontStyle.Bold   );
            LightFont = new Font("Segoe UI Light", 11.25f, FontStyle.Regular);

            IsDarkStyle = false;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 속성 변경시 이벤트 발생시키기 - FirePropertyChanged(propertyName)

        /// <summary>
        /// 속성 변경시 이벤트 발생시키기
        /// </summary>
        /// <param name="propertyName">property name</param>
        public void FirePropertyChanged(string propertyName)
        {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}

 

▶ MetroUI.cs

using System.Diagnostics;

namespace TestProject
{
    /// <summary>
    /// 메트로 UI
    /// </summary>
    public static class MetroUI
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private
        
        #region Field

        /// <summary>
        /// 메트로 스타일
        /// </summary>
        private static MetroStyle _metroStyle;

        /// <summary>
        /// 디자인 모드 여부
        /// </summary>
        private static bool _idDesignMode;

        /// <summary>
        /// 초기화 여부
        /// </summary>
        private static bool _isInitialized;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 디자인 모드 여부 - IsDesignMode

        /// <summary>
        /// 디자인 모드 여부
        /// </summary>
        public static bool IsDesignMode
        {
            get
            {
                if(_isInitialized == false)
                {
                    Initialize();
                }
                
                return _idDesignMode;
            }
        }

        #endregion
        #region 스타일 - Style

        /// <summary>
        /// 스타일
        /// </summary>
        public static MetroStyle Style
        {
            get
            {
                if(_metroStyle == null)
                {
                    _metroStyle = new MetroStyle();
                }

                return _metroStyle;
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 초기화 하기 - Initialize()

        /// <summary>
        /// 초기화 하기
        /// </summary>
        private static void Initialize()
        {
            _idDesignMode = (Process.GetCurrentProcess().ProcessName == "devenv");

            _isInitialized = true;
        }

        #endregion
    }
}

 

▶ MetroToolStripRenderer.cs

using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메트로 툴 스트립 렌더러
    /// </summary>
    public class MetroToolStripRenderer : ToolStripProfessionalRenderer
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MetroToolStripRenderer()

        /// <summary>
        /// 생성자
        /// </summary>
        public MetroToolStripRenderer() : base(new MetroColorTable())
        {
        }

        #endregion

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

        #region 항목 텍스트 렌더링시 처리하기 - OnRenderItemText(e)

        /// <summary>
        /// 항목 텍스트 렌더링시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
        {
            if(e.Item.Selected && e.Item.Pressed == false)
            {
                e.TextColor = MetroUI.Style.AccentForeColor;
            }
            else
            {
                e.TextColor = MetroUI.Style.ForeColor;
            }

            base.OnRenderItemText(e);
        }

        #endregion
        #region 항목 이미지 렌더링시 처리하기 - OnRenderItemImage(e)

        /// <summary>
        /// 항목 이미지 렌더링시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e)
        {
            if(e.Item.Selected && e.Item.Pressed == false)
            {
                e.Graphics.DrawImageUnscaled(e.Item.Image.AdjustRGBGamma(1f, 1f, 1f, 0.01f), e.ImageRectangle);
            }
            else
            {
                if(MetroUI.Style.IsDarkStyle)
                {
                    e.Graphics.DrawImageUnscaled(e.Item.Image.AdjustRGBGamma(1f, 1f, 1f, 0.01f), e.ImageRectangle);
                }
                else
                {
                    base.OnRenderItemImage(e);
                }
            }
        }

        #endregion
    }
}

 

▶ MetroMenuStrip.cs

using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메트로 메뉴 스트립
    /// </summary>
    public class MetroMenuStrip : MenuStrip
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MetroMenuStrip()

        /// <summary>
        /// 생성자
        /// </summary>
        public MetroMenuStrip() : base()
        {
            Renderer  = new MetroToolStripRenderer();
            Font      = MetroUI.Style.BaseFont;
            ForeColor = MetroUI.Style.ForeColor;
        }

        #endregion

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

        #region 항목 추가시 처리하기 - OnItemAdded(e)

        /// <summary>
        /// 항목 추가시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnItemAdded(ToolStripItemEventArgs e)
        {
            base.OnItemAdded(e);

            e.Item.Font      = MetroUI.Style.BaseFont;
            e.Item.ForeColor = MetroUI.Style.ForeColor;
        }

        #endregion
    }
}

 

▶ MetroToolbar.cs

using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메뉴 툴 스트립
    /// </summary>
    public class MetroToolStrip : ToolStrip
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MetroToolStrip()

        /// <summary>
        /// 생성자
        /// </summary>
        public MetroToolStrip() : base()
        {
            Renderer  = new MetroToolStripRenderer();
            Font      = MetroUI.Style.BaseFont;
            ForeColor = MetroUI.Style.ForeColor;
        }

        #endregion

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

        #region 항목 추가시 처리하기 - OnItemAdded(e)

        /// <summary>
        /// 항목 추가시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnItemAdded(ToolStripItemEventArgs e)
        {
            e.Item.Font      = MetroUI.Style.BaseFont;
            e.Item.ForeColor = MetroUI.Style.ForeColor;

            base.OnItemAdded(e);
        }

        #endregion
    }
}

 

▶ ImageExtension.cs

using System.Drawing;
using System.Drawing.Imaging;

namespace TestProject
{
    /// <summary>
    /// 이미지 확장
    /// </summary>
    public static class ImageExtension
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region RGB 감마 조정하기 - AdjustRGBGamma(sourceImage, red, green, blue, gamma)

        /// <summary>
        /// RGB 감마 조정하기
        /// </summary>
        /// <param name="sourceImage">소스 이미지</param>
        /// <param name="red">빨강색</param>
        /// <param name="green">녹색</param>
        /// <param name="blue">파랑색</param>
        /// <param name="gamma">감마</param>
        /// <returns>RGB 감마 조정 이미지</returns>
        /// <remarks>
        /// blue (metro) : 0f, 1f, 3f, 0.55f
        /// light grey   : 1f, 1f, 1f, 0.35f
        /// white        : 1f, 1f, 1f, 0.01f
        /// green        : 0f, 2f, 0f, 0.75f
        /// red          : 2f, 0f, 0f, 0.75f
        /// </remarks>
        public static Image AdjustRGBGamma(this Image sourceImage, float red, float green, float blue, float gamma)
        {
            Bitmap targetBitmap = new Bitmap(sourceImage.Width, sourceImage.Height);

            ImageAttributes imgAttributes = new ImageAttributes();

            ColorMatrix colorMatrix = new ColorMatrix
            (
                new float[][]
                {
                    new float[] { red, 0f   , 0f  , 0f, 0f },
                    new float[] { 0f , green, 0f  , 0f, 0f },
                    new float[] { 0f , 0f   , blue, 0f, 0f },
                    new float[] { 0f , 0f   , 0f  , 1f, 0f },
                    new float[] { 0f , 0f   , 0f  , 0f, 1f },
                }
            );

            imgAttributes.ClearColorMatrix();

            imgAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            imgAttributes.SetGamma(gamma, ColorAdjustType.Bitmap);

            using(Graphics graphics = Graphics.FromImage(targetBitmap))
            {
                graphics.DrawImage
                (
                    sourceImage,
                    new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
                    0,
                    0,
                    sourceImage.Width,
                    sourceImage.Height,
                    GraphicsUnit.Pixel,
                    imgAttributes
                );
            }

            return (Image)targetBitmap;
        }

        #endregion
    }
}

 

▶ MainForm.cs

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

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            if(MetroUI.IsDesignMode == false)
            {
                MetroUI.Style.PropertyChanged += Style_PropertyChanged;

                MetroUI.Style.IsDarkStyle = true;
            }

            this.exitApplicationMenuItem.Click += exitApplicationMenuItem_Click;
            this.switchStyleButton.Click       += switchStyleButton_Click;
        }

        #endregion

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

        #region 윈도우 메시지 처리하기 - WndProc(message)

        /// <summary>
        /// 윈도우 메시지 처리하기
        /// </summary>
        /// <param name="message">메시지</param>
        protected override void WndProc(ref Message message)
        {
            if(message.Msg == 0x84) // WM_NCHITTEST
            {
                message.Result = (IntPtr)0x02;  // HTCAPTION
            }
            else
            {
                base.WndProc(ref message);
            }
        }

        #endregion
        #region 크기 조정시 처리하기 - OnResize(e)

        /// <summary>
        /// 크기 조정시 처리하기
        /// </summary>
        /// <param name="e">이벤트 인자</param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            Invalidate();
        }

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

        /// <summary>
        /// 페인트시 처리하기
        /// </summary>
        /// <param name="e">이벤트인자</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            using(Pen pen = new Pen(MetroUI.Style.AccentColor))
            {
                e.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
            }

            using(SolidBrush brush = new SolidBrush(MetroUI.Style.AccentColor))
            {
                e.Graphics.DrawString(Text.ToUpper(), MetroUI.Style.LightFont, brush, 10, 8);
            }
        }

        #endregion

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

        #region 스타일 속성 변경시 처리하기 - Style_PropertyChanged(sender, e)

        /// <summary>
        /// 스타일 속성 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Style_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if(e.PropertyName == "IsDarkStyle")
            {
                BackColor = MetroUI.Style.BackColor;

                Refresh();
            }
        }

        #endregion
        #region Exit Application 메뉴 항목 클릭시 처리하기 - exitApplicationMenuItem_Click(sender, e)

        /// <summary>
        /// Exit Application 메뉴 항목 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void exitApplicationMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        #endregion
        #region Switch Style 버튼 클릭시 처리하기 - switchStyleButton_Click(sender, e)

        /// <summary>
        /// Switch Style 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void switchStyleButton_Click(object sender, EventArgs e)
        {
            MetroUI.Style.IsDarkStyle = !(MetroUI.Style.IsDarkStyle);
        }

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

댓글을 달아 주세요