■ 메트로 UI를 사용하는 방법을 보여준다.
▶ MetroStyle.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
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 } } |