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

■ Color 클래스 : 색상 그리드 사용하기

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


TestProject.zip


ColorCell.cs

 

 

using System;

using System.Windows;

using System.Windows.Media;

 

namespace TestProject

{

    /// <summary>

    /// 색상 셀

    /// </summary>

    public class ColorCell : FrameworkElement

    {

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

        ////////////////////////////////////////////////////////////////////////////////////////// Static

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

 

        #region Field

 

        /// <summary>

        /// 선택 여부 속성

        /// </summary>

        public static readonly DependencyProperty IsSelectedProperty;

 

        /// <summary>

        /// 하이라이트 여부 속성

        /// </summary>

        public static readonly DependencyProperty IsHighlightedProperty;

 

        #endregion

 

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

 

        #region Field

 

        /// <summary>

        /// 셀 크기

        /// </summary>

        private static readonly Size _cellSize = new Size(20, 20);

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

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

 

        #region Field

 

        /// <summary>

        /// 색상 드로잉 비주얼

        /// </summary>

        private DrawingVisual colorDrawingVisual;

 

        /// <summary>

        /// 브러시

        /// </summary>

        private Brush brush;

 

        #endregion

 

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

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

 

        #region 선택 여부 - IsSelected

 

        /// <summary>

        /// 선택 여부

        /// </summary>

        public bool IsSelected

        {

            set

            {

                SetValue(IsSelectedProperty, value);

            }

            get

            {

                return (bool)GetValue(IsSelectedProperty);

            }

        }

 

        #endregion

        #region 하이라이트 여부 - IsHighlighted

 

        /// <summary>

        /// 하이라이트 여부

        /// </summary>

        public bool IsHighlighted

        {

            set

            {

                SetValue(IsHighlightedProperty, value);

            }

            get

            {

                return (bool)GetValue(IsHighlightedProperty);

            }

        }

 

        #endregion

        #region 브러시 - Brush

 

        /// <summary>

        /// 브러시

        /// </summary>

        public Brush Brush

        {

            get

            {

                return this.brush;

            }

        }

 

        #endregion

 

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

 

        #region 비주얼 자식 수 - VisualChildrenCount

 

        /// <summary>

        /// 비주얼 자식 수

        /// </summary>

        protected override int VisualChildrenCount

        {

            get

            {

                return 1;

            }

        }

 

        #endregion

 

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

        ////////////////////////////////////////////////////////////////////////////////////////// Static

 

        #region 생성자 - ColorCell()

 

        /// <summary>

        /// 생성자

        /// </summary>

        static ColorCell()

        {

            IsSelectedProperty = DependencyProperty.Register

            (

                "IsSelected",

                typeof(bool),

                typeof(ColorCell),

                new FrameworkPropertyMetadata

                (

                    false,

                    FrameworkPropertyMetadataOptions.AffectsRender

                )

            );

 

            IsHighlightedProperty = DependencyProperty.Register

            (

                "IsHighlighted",

                typeof(bool),

                typeof(ColorCell),

                new FrameworkPropertyMetadata

                (

                    false,

                    FrameworkPropertyMetadataOptions.AffectsRender

                )

            );

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

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

 

        #region 생성자 - ColorCell(color)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="color">색상</param>

        public ColorCell(Color color)

        {

            this.colorDrawingVisual = new DrawingVisual();

 

            DrawingContext drawingContext = this.colorDrawingVisual.RenderOpen();

 

            Rect rect = new Rect(new Point(0, 0), _cellSize);

 

            rect.Inflate(-4, -4);

 

            Pen pen = new Pen(SystemColors.ControlTextBrush, 1);

 

            this.brush = new SolidColorBrush(color);

 

            drawingContext.DrawRectangle(this.brush, pen, rect);

 

            drawingContext.Close();

 

            AddVisualChild(this.colorDrawingVisual);

 

            AddLogicalChild(this.colorDrawingVisual);

        }

 

        #endregion

 

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

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

 

        #region 비주얼 자식 구하기 - GetVisualChild(index)

 

        /// <summary>

        /// 비주얼 자식 구하기

        /// </summary>

        /// <param name="index">인덱스</param>

        /// <returns>비주얼 자식</returns>

        protected override Visual GetVisualChild(int index)

        {

            if(index > 0)

            {

                throw new ArgumentOutOfRangeException("index");

            }

 

            return this.colorDrawingVisual;

        }

 

        #endregion

        #region 측정하기 (오버라이딩) - MeasureOverride(availableSize)

 

        /// <summary>

        /// 측정하기 (오버라이딩)

        /// </summary>

        /// <param name="availableSize">이용 가능한 크기</param>

        /// <returns>측정 크기</returns>

        protected override Size MeasureOverride(Size availableSize)

        {

            return _cellSize;

        }

 

        #endregion

        #region 렌더링 처리하기 - OnRender(drawingContext)

 

        /// <summary>

        /// 렌더링 처리하기

        /// </summary>

        /// <param name="drawingContext">DrawingContext</param>

        protected override void OnRender(DrawingContext drawingContext)

        {

            Rect rect = new Rect(new Point(0, 0), RenderSize);

 

            rect.Inflate(-1, -1);

 

            Pen pen = new Pen(SystemColors.HighlightBrush, 1);

 

            if(IsHighlighted)

            {

                drawingContext.DrawRectangle(SystemColors.ControlDarkBrush, pen, rect);

            }

            else if(IsSelected)

            {

                drawingContext.DrawRectangle(SystemColors.ControlLightBrush, pen, rect);

            }

            else

            {

                drawingContext.DrawRectangle(Brushes.Transparent, null, rect);

            }

        }

 

        #endregion

    }

}

 

 

ColorGrid.cs

 

 

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Controls.Primitives;

using System.Windows.Input;

using System.Windows.Media;

 

namespace TestProject

{

    /// <summary>

    /// 색상 그리드

    /// </summary>

    public class ColorGrid : Control

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Event

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

 

        #region 선택 색상 변경시 - SelectedColorChanged

 

        /// <summary>

        /// 선택 색상 변경시

        /// </summary>

        public event EventHandler SelectedColorChanged;

 

        #endregion

 

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

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

 

        #region Field

 

        /// <summary>

        /// 행 수

        /// </summary>

        private const int ROW_COUNT = 5;

 

        /// <summary>

        /// 컬럼 수

        /// </summary>

        private const int COLUMN_COUNT = 8;

 

        /// <summary>

        /// 색상 문자열 배열

        /// </summary>

        private string[,] colorStringArray = new string[ROW_COUNT, COLUMN_COUNT]

        {

            { "Black"    , "Brown"    , "DarkGreen"  , "MidnightBlue", "Navy"     , "DarkBlue"    , "Indigo"   , "DimGray"   },

            { "DarkRed"  , "OrangeRed", "Olive"      , "Green"       , "Teal"     , "Blue"        , "SlateGray", "Gray"      },

            { "Red"      , "Orange"   , "YellowGreen", "SeaGreen"    , "Aqua"     , "LightBlue"   , "Violet"   , "DarkGray"  },

            { "Pink"     , "Gold"     , "Yellow"     , "Lime"        , "Turquoise", "SkyBlue"     , "Plum"     , "LightGray" },

            { "LightPink", "Tan"      , "LightYellow", "LightGreen"  , "LightCyan", "LightSkyBlue", "Lavender" , "White"     }

        };

 

        /// <summary>

        /// 색상 셀 배열

        /// </summary>

        private ColorCell[,] colorCellArray = new ColorCell[ROW_COUNT, COLUMN_COUNT];

 

        /// <summary>

        /// 선택 색상 셀

        /// </summary>

        private ColorCell selectedColorCell;

 

        /// <summary>

        /// 하이라이트 색상 셀

        /// </summary>

        private ColorCell highlightedColorCell;

 

        /// <summary>

        /// 테두리

        /// </summary>

        private Border border;

 

        /// <summary>

        /// 유니폼 그리드

        /// </summary>

        private UniformGrid uniformGrid;

 

        /// <summary>

        /// 선택 색상

        /// </summary>

        private Color selectedColor = Colors.Black;

 

        #endregion

 

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

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

 

        #region 선택 색상 - SelectedColor

 

        /// <summary>

        /// 선택 색상

        /// </summary>

        public Color SelectedColor

        {

            get

            {

                return this.selectedColor;

            }

        }

 

        #endregion

        #region 비주얼 자식 수 - VisualChildrenCount

 

        /// <summary>

        /// 비주얼 자식 수

        /// </summary>

        protected override int VisualChildrenCount

        {

            get

            {

                return 1;

            }

        }

 

        #endregion

 

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

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

 

        #region 생성자 - ColorGrid()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public ColorGrid()

        {

            this.border = new Border();

 

            this.border.BorderBrush     = SystemColors.ControlDarkDarkBrush;

            this.border.BorderThickness = new Thickness(1);

 

 

            AddVisualChild(this.border);

 

            AddLogicalChild(this.border);

 

 

            this.uniformGrid = new UniformGrid();

 

            this.uniformGrid.Background = SystemColors.WindowBrush;

            this.uniformGrid.Columns    = COLUMN_COUNT;

 

            this.border.Child = this.uniformGrid;

 

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

            {

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

                {

                    Color color = (Color)typeof(Colors).GetProperty(colorStringArray[y, x]).GetValue(null, null);

 

                    this.colorCellArray[y, x] = new ColorCell(color);

 

                    this.uniformGrid.Children.Add(this.colorCellArray[y, x]);

 

                    if(color == SelectedColor)

                    {

                        this.selectedColorCell = this.colorCellArray[y, x];

 

                        this.colorCellArray[y, x].IsSelected = true;

                    }

 

                    ToolTip toolTip = new ToolTip();

 

                    toolTip.Content = colorStringArray[y, x];

 

                    this.colorCellArray[y, x].ToolTip = toolTip;

                }

            }

        }

 

        #endregion

 

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

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

 

        #region 비주얼 자식 구하기 - GetVisualChild(index)

 

        /// <summary>

        /// 비주얼 자식 구하기

        /// </summary>

        /// <param name="index">인덱스</param>

        /// <returns></returns>

        protected override Visual GetVisualChild(int index)

        {

            if(index > 0)

            {

                throw new ArgumentOutOfRangeException("index");

            }

 

            return this.border;

        }

 

        #endregion

        #region 측정하기 (오버라이딩) - MeasureOverride(availableSize)

 

        /// <summary>

        /// 측정하기 (오버라이딩)

        /// </summary>

        /// <param name="availableSize">이용 가능한 크기</param>

        /// <returns>측정 크기</returns>

        protected override Size MeasureOverride(Size availableSize)

        {

            this.border.Measure(availableSize);

 

            return this.border.DesiredSize;

        }

 

        #endregion

        #region 배열하기 (오버라이딩) - ArrangeOverride(finalSize)

 

        /// <summary>

        /// 배열하기 (오버라이딩)

        /// </summary>

        /// <param name="finalSize">최종 크기</param>

        /// <returns>최종 크기</returns>

        protected override Size ArrangeOverride(Size finalSize)

        {

            this.border.Arrange(new Rect(new Point(0, 0), finalSize));

 

            return finalSize;

        }

 

        #endregion

 

        #region 마우스 ENTER 처리하기 - OnMouseEnter(e)

 

        /// <summary>

        /// 마우스 ENTER 처리하기

        /// </summary>

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

        protected override void OnMouseEnter(MouseEventArgs e)

        {

            base.OnMouseEnter(e);

 

            if(this.highlightedColorCell != null)

            {

                this.highlightedColorCell.IsHighlighted = false;

 

                this.highlightedColorCell = null;

            }

        }

 

        #endregion

        #region 마우스 이동시 처리하기 - OnMouseMove(e)

 

        /// <summary>

        /// 마우스 이동시 처리하기

        /// </summary>

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

        protected override void OnMouseMove(MouseEventArgs e)

        {

            base.OnMouseMove(e);

 

            ColorCell colorCell = e.Source as ColorCell;

 

            if(colorCell != null)

            {

                if(this.highlightedColorCell != null)

                {

                    this.highlightedColorCell.IsHighlighted = false;

                }

 

                this.highlightedColorCell = colorCell;

 

                this.highlightedColorCell.IsHighlighted = true;

            }

        }

 

        #endregion

        #region 마우스 DOWN 처리하기 - OnMouseDown(e)

 

        /// <summary>

        /// 마우스 DOWN 처리하기

        /// </summary>

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

        protected override void OnMouseDown(MouseButtonEventArgs e)

        {

            base.OnMouseDown(e);

 

            ColorCell colorCell = e.Source as ColorCell;

 

            if(colorCell != null)

            {

                if(this.selectedColorCell != null)

                {

                    this.selectedColorCell.IsSelected = false;

                }

 

                this.selectedColorCell = colorCell;

 

                this.selectedColorCell.IsSelected = true;

            }

 

            Focus();

        }

 

        #endregion

        #region 마우스 UP 처리하기 - OnMouseUp(e)

 

        /// <summary>

        /// 마우스 UP 처리하기

        /// </summary>

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

        protected override void OnMouseUp(MouseButtonEventArgs e)

        {

            base.OnMouseUp(e);

 

            ColorCell colorCell = e.Source as ColorCell;

 

            if(colorCell != null)

            {

                if(this.selectedColorCell != null)

                {

                    this.selectedColorCell.IsSelected = false;

                }

 

                this.selectedColorCell = colorCell;

 

                this.selectedColorCell.IsSelected = true;

 

                this.selectedColor = (this.selectedColorCell.Brush as SolidColorBrush).Color;

 

                OnSelectedColorChanged(EventArgs.Empty);

            }

        }

 

        #endregion

        #region 마우스 LEAVE 처리하기 - OnMouseLeave(e)

 

        /// <summary>

        /// 마우스 LEAVE 처리하기

        /// </summary>

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

        protected override void OnMouseLeave(MouseEventArgs e)

        {

            base.OnMouseLeave(e);

 

            if(this.highlightedColorCell != null)

            {

                this.highlightedColorCell.IsHighlighted = false;

 

                this.highlightedColorCell = null;

            }

        }

 

        #endregion

 

        #region 키보드 포커스 획득시 처리하기 - OnGotKeyboardFocus(e)

 

        /// <summary>

        /// 키보드 포커스 획득시 처리하기

        /// </summary>

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

        protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)

        {

            base.OnGotKeyboardFocus(e);

 

            if(this.highlightedColorCell == null)

            {

                if(this.selectedColorCell != null)

                {

                    this.highlightedColorCell = this.selectedColorCell;

                }

                else

                {

                    this.highlightedColorCell = this.colorCellArray[0, 0];

                }

 

                this.highlightedColorCell.IsHighlighted = true;

            }

        }

 

        #endregion

        #region 키 DOWN 처리하기 - OnKeyDown(e)

 

        /// <summary>

        /// 키 DOWN 처리하기

        /// </summary>

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

        protected override void OnKeyDown(KeyEventArgs e)

        {

            base.OnKeyDown(e);

 

            int index = this.uniformGrid.Children.IndexOf(this.highlightedColorCell);

            int y     = index / COLUMN_COUNT;

            int x     = index % COLUMN_COUNT;

 

            switch(e.Key)

            {

                case Key.Home :

 

                    y = 0;

                    x = 0;

 

                    break;

 

                case Key.End :

 

                    y = ROW_COUNT    - 1;

                    x = COLUMN_COUNT + 1;

 

                    break;

 

                case Key.Down :

 

                    if((y = (y + 1) % ROW_COUNT) == 0)

                    {

                        x++;

                    }

 

                    break;

 

                case Key.Up :

 

                    if((y = (y + ROW_COUNT - 1) % ROW_COUNT) == ROW_COUNT - 1)

                    {

                        x--;

                    }

 

                    break;

 

                case Key.Right :

 

                    if((x = (x + 1) % COLUMN_COUNT) == 0)

                    {

                        y++;

                    }

 

                    break;

 

                case Key.Left :

 

                    if((x = (x + COLUMN_COUNT - 1) % COLUMN_COUNT) == COLUMN_COUNT - 1)

                    {

                        y--;

                    }

 

                    break;

 

                case Key.Enter :

                case Key.Space :

 

                    if(this.selectedColorCell != null)

                    {

                        this.selectedColorCell.IsSelected = false;

                    }

 

                    this.selectedColorCell = this.highlightedColorCell;

 

                    this.selectedColorCell.IsSelected = true;

 

                    this.selectedColor = (this.selectedColorCell.Brush as SolidColorBrush).Color;

 

                    OnSelectedColorChanged(EventArgs.Empty);

 

                    break;

 

                default :

 

                    return;

            }

 

            if(x >= COLUMN_COUNT || y >= ROW_COUNT)

            {

                MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

            }

            else if(x < 0 || y < 0)

            {

                MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));

            }

            else

            {

                this.highlightedColorCell.IsHighlighted = false;

 

                this.highlightedColorCell = this.colorCellArray[y, x];

 

                this.highlightedColorCell.IsHighlighted = true;

            }

 

            e.Handled = true;

        }

 

        #endregion

        #region 키보드 포커스 상실시 처리하기 - OnLostKeyboardFocus(e)

 

        /// <summary>

        /// 키보드 포커스 상실시 처리하기

        /// </summary>

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

        protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e)

        {

            base.OnGotKeyboardFocus(e);

 

            if(this.highlightedColorCell != null)

            {

                this.highlightedColorCell.IsHighlighted = false;

 

                this.highlightedColorCell = null;

            }

        }

 

        #endregion

 

        #region 선택 색상 변경시 처리하기 - OnSelectedColorChanged(e)

 

        /// <summary>

        /// 선택 색상 변경시 처리하기

        /// </summary>

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

        protected virtual void OnSelectedColorChanged(EventArgs e)

        {

            if(SelectedColorChanged != null)

            {

                SelectedColorChanged(this, e);

            }

        }

 

        #endregion

    }

}

 

 

MainWindow.cs

 

 

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

 

namespace TestProject

{

    /// <summary>

    /// 메인 윈도우

    /// </summary>

    public class MainWindow : Window

    {

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

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

 

        #region 생성자 - MainWindow()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainWindow()

        {

            SizeToContent = SizeToContent.WidthAndHeight;

            Padding       = new Thickness(10);

            FontFamily    = new FontFamily("나눔고딕코딩");

            FontSize      = 16;

            Title         = "Control 클래스 : 색상 그리드 사용하기";

 

            StackPanel stackPanel = new StackPanel();

 

            stackPanel.Orientation = Orientation.Horizontal;

 

            Content = stackPanel;

 

            Button button1 = new Button();

 

            button1.Content             = "테스트 버튼";

            button1.Margin              = new Thickness(24);

            button1.HorizontalAlignment = HorizontalAlignment.Center;

            button1.VerticalAlignment   = VerticalAlignment.Center;

 

            stackPanel.Children.Add(button1);

 

            ColorGrid colorGrid = new ColorGrid();

 

            colorGrid.Margin              = new Thickness(24);

            colorGrid.HorizontalAlignment = HorizontalAlignment.Center;

            colorGrid.VerticalAlignment   = VerticalAlignment.Center;

 

            colorGrid.SelectedColorChanged += colorGrid_SelectedColorChanged;

 

            stackPanel.Children.Add(colorGrid);

 

            Button button2 = new Button();

 

            button2.Content             = "테스트 버튼";

            button2.Margin              = new Thickness(24);

            button2.HorizontalAlignment = HorizontalAlignment.Center;

            button2.VerticalAlignment   = VerticalAlignment.Center;

 

            stackPanel.Children.Add(button2);

        }

 

        #endregion

 

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

        ////////////////////////////////////////////////////////////////////////////////////////// Static

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

 

        #region 프로그램 시작하기 - Main()

 

        /// <summary>

        /// 프로그램 시작하기

        /// </summary>

        [STAThread]

        private static void Main()

        {

            Application application = new Application();

 

            application.Run(new MainWindow());

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

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

 

        #region 색상 그리드 선택 색상 변경시 처리하기 - colorGrid_SelectedColorChanged(sender, e)

 

        /// <summary>

        /// 색상 그리드 선택 색상 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

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

        private void colorGrid_SelectedColorChanged(object sender, EventArgs e)

        {

            ColorGrid colorGrid = sender as ColorGrid;

 

            Background = new SolidColorBrush(colorGrid.SelectedColor);

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요