첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
다운로드

▶ generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestProject">
    <Style x:Key="SliderRepeatButtonStyleKey" TargetType="{x:Type RepeatButton}">
        <Setter Property="OverridesDefaultStyle" Value="true"        />
        <Setter Property="IsTabStop"             Value="false"       />
        <Setter Property="Focusable"             Value="false"       />
        <Setter Property="Background"            Value="Transparent" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type RepeatButton}">
                    <Border Background="{TemplateBinding Background}" />
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="{x:Type local:ColorThumb}" TargetType="{x:Type local:ColorThumb}">
        <Setter Property="PointerOutlineBrush"     Value="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" />
        <Setter Property="PointerOutlineThickness" Value="2"                                                                 />
        <Setter Property="Foreground"              Value="{x:Null}"                                                          />
        <Setter Property="ThumbColor"              Value="Transparent"                                                       />
        <Setter Property="Background"              Value="Transparent"                                                       />
        <Setter Property="Height"                  Value="5"                                                                 />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ColorThumb}">
                    <Border
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}">
                        <Polygon Name="arrowPolygon"
                            Stroke="{TemplateBinding PointerOutlineBrush}" 
                            StrokeThickness="{TemplateBinding PointerOutlineThickness}"
                            Stretch="Fill"
                            Points="100 20 80 50 100 80">
                            <Polygon.Fill>
                                <SolidColorBrush 
                                    Color="{Binding ThumbColor, RelativeSource={RelativeSource TemplatedParent}}" />
                            </Polygon.Fill>
                        </Polygon>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsDragging" Value="False">
                            <Setter TargetName="arrowPolygon" Property="BitmapEffect">
                                <Setter.Value>
                                    <BitmapEffectGroup>
                                        <BevelBitmapEffect BevelWidth="5" Relief="0.5" />
                                        <DropShadowBitmapEffect />
                                    </BitmapEffectGroup>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="{x:Type local:SpectrumSlider}" TargetType="{x:Type local:SpectrumSlider}">
        <Setter Property="Orientation"                  Value="Vertical"                                                      />
        <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"                                                         />
        <Setter Property="Background"                   Value="Transparent"                                                   />
        <Setter Property="Foreground"                   Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
        <Setter Property="Minimum"                      Value="0"                                                             />
        <Setter Property="Maximum"                      Value="100"                                                           />
        <Setter Property="TickFrequency"                Value="0.001"                                                         />
        <Setter Property="IsSnapToTickEnabled"          Value="True"                                                          />
        <Setter Property="IsDirectionReversed"          Value="False"                                                         />
        <Setter Property="Value"                        Value="1"                                                             />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:SpectrumSlider}">
                    <Border
                        Height="{TemplateBinding Height}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"                                              />
                                <ColumnDefinition Width="Auto" MinWidth="{TemplateBinding Slider.MinWidth}" />
                                <ColumnDefinition Width="Auto"                                              />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <Border x:Name="PART_TrackBackground" Grid.Column="1"
                                Margin="10 0 10 0"
                                Width="20">
                                <Rectangle x:Name="PART_SpectrumDisplay"
                                    Stretch="Fill"
                                    VerticalAlignment="Stretch" />
                                <Border.BitmapEffect>
                                    <BevelBitmapEffect
                                        BevelWidth="3"
                                        EdgeProfile="BulgedUp"
                                        Relief="0.3" />
                                </Border.BitmapEffect>
                            </Border>
                            <Canvas Grid.Column="1"
                                HorizontalAlignment="Center"
                                Width="4">
                                <Rectangle x:Name="PART_SelectionRange" Canvas.Left="1"
                                    Width="2.0"
                                    Fill="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"
                                    Visibility="Hidden" />
                            </Canvas>
                            <Track Name="PART_Track" Grid.Column="1">
                                <Track.DecreaseRepeatButton>
                                    <RepeatButton
                                        Style="{StaticResource SliderRepeatButtonStyleKey}"
                                        Command="Slider.DecreaseLarge" />
                                </Track.DecreaseRepeatButton>
                                <Track.IncreaseRepeatButton>
                                    <RepeatButton
                                        Style="{StaticResource SliderRepeatButtonStyleKey}"
                                        Command="Slider.IncreaseLarge" />
                                </Track.IncreaseRepeatButton>
                                <Track.Thumb>
                                    <local:ColorThumb x:Name="Thumb"
                                        Height="20"
                                        ThumbColor="{Binding SelectedColor, RelativeSource={RelativeSource TemplatedParent}}" />
                                </Track.Thumb>
                            </Track>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelectionRangeEnabled" Value="true">
                            <Setter TargetName="PART_SelectionRange" Property="Visibility" Value="Visible" />
                        </Trigger>
                        <Trigger Property="Width" Value="Auto">
                            <Setter Property="MinWidth" Value="21" />
                        </Trigger>
                        <Trigger Property="Height" Value="Auto">
                            <Setter Property="MinHeight" Value="104" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

 

728x90

 

▶ SpectrumSlider.cs

using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls;

namespace TestProject
{
    /// <summary>
    /// 스펙트럼 슬라이더
    /// </summary>
    public class SpectrumSlider : Slider
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// DependencyProperty
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 선택 색상 속성 - SelectedColorProperty

        /// <summary>
        /// 선택 색상 속성
        /// </summary>
        private static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register
        (
            "SelectedColor",
            typeof(Color),
            typeof(SpectrumSlider),
            new PropertyMetadata(Colors.Transparent)
        );

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 스펙트럼 표시명
        /// </summary>
        private static string SPECTRUN_DISPLAY_NAME = "PART_SpectrumDisplay";

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 스펙트럼 표시 사각형
        /// </summary>
        private Rectangle spectrumDisplayRectangle;

        /// <summary>
        /// 색상 초기화 여부
        /// </summary>
        private bool colorInitialized = false;

        /// <summary>
        /// 선택기 브러시
        /// </summary>
        private LinearGradientBrush pickerBrush;

        #endregion

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

        #region 선택 색상 - SelectedColor

        /// <summary>
        /// 선택 색상
        /// </summary>
        public Color SelectedColor
        {
            get
            {
                return (Color)GetValue(SelectedColorProperty);
            }
            set
            {
                SetValue(SelectedColorProperty, value);
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Static

        #region 생성자 - SpectrumSlider()

        /// <summary>
        /// 생성자
        /// </summary>
        static SpectrumSlider()
        {
            DefaultStyleKeyProperty.OverrideMetadata
            (
                typeof(SpectrumSlider),
                new FrameworkPropertyMetadata(typeof(SpectrumSlider))
            );
        }

        #endregion

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

        #region 템플리트 적용시 처리하기 - OnApplyTemplate()

        /// <summary>
        /// 템플리트 적용시 처리하기
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.spectrumDisplayRectangle = GetTemplateChild(SPECTRUN_DISPLAY_NAME) as Rectangle;

            if(!this.colorInitialized)
            {
                UpdateColorSpectrum();

                OnValueChanged(0, 0);
            }
        }

        #endregion

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

        #region 값 변경시 처리하기 - OnValueChanged(previousValue, newValue)

        /// <summary>
        /// 값 변경시 처리하기
        /// </summary>
        /// <param name="previousValue">이전 값</param>
        /// <param name="newValue">신규 값</param>
        protected override void OnValueChanged(double previousValue, double newValue)
        {
            base.OnValueChanged(previousValue, newValue);

            Color? color = ColorHelper.GetColor(360 - newValue, 1, 1);
            
            SetValue(SelectedColorProperty, color);
        }

        #endregion

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

        #region 스펙트럼 생성하기 - CreateSpectrum()

        /// <summary>
        /// 스펙트럼 생성하기
        /// </summary>
        private void CreateSpectrum()
        {
            this.pickerBrush = new LinearGradientBrush();

            this.pickerBrush.ColorInterpolationMode = ColorInterpolationMode.SRgbLinearInterpolation;
            this.pickerBrush.StartPoint             = new Point(0.5, 0);
            this.pickerBrush.EndPoint               = new Point(0.5, 1);

            List<Color> colorList = ColorHelper.GetHSVColorList();

            double stopIncrement = (double)1 / colorList.Count;

            int i;

            for(i = 0; i < colorList.Count; i++)
            {
                this.pickerBrush.GradientStops.Add(new GradientStop(colorList[i], i * stopIncrement));
            }

            this.pickerBrush.GradientStops[i - 1].Offset = 1.0;

            this.spectrumDisplayRectangle.Fill = pickerBrush;
        }

        #endregion
        #region 색상 스펙트럼 업데이트하기 - UpdateColorSpectrum()

        /// <summary>
        /// 색상 스펙트럼 업데이트하기
        /// </summary>
        private void UpdateColorSpectrum()
        {
            if(this.spectrumDisplayRectangle != null)
            {
                this.colorInitialized = true;

                CreateSpectrum();
            }
            else
            {
                this.colorInitialized = false;
            }
        }

        #endregion
    }
}

 

300x250

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestProject"
    Width="800"
    Height="600"
    Title="FrameworkElement 클래스 : DefaultStyleKeyProperty 속성을 사용해 컨트롤 테마 스타일 설정하기"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <StackPanel
            HorizontalAlignment="Center"
            VerticalAlignment="Center">
            <local:SpectrumSlider x:Name="slider"
                Width="40"
                Height="300"
                IsMoveToPointEnabled="True"
                IsSnapToTickEnabled="False"
                Maximum="360"
                Value="0" />
            <Label
                HorizontalAlignment="Center"
                Content="{Binding ElementName=slider, Path=Value}" />
        </StackPanel>
    </Grid>
</Window>
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요