如何在DateTimePicker控件中自定义日历?

时间:2016-03-22 10:33:30

标签: c# winforms winforms-interop

我认为这个问题很简单明了。下图是我目前的进展。

enter image description here

如您所见,自定义版本是我的扩展DateTimePicker控件。控件根据聚焦值更改按钮和边框颜色。下拉日历是我想要的下一个风格。

我只是不知道从哪里开始,因为没有接缝可以正常工作。我至少不会改变边框颜色,字体颜色等...

3 个答案:

答案 0 :(得分:5)

你有非常选项。下拉日历是MonthCalendar控件,当您单击用户解除它时再次单击下拉按钮时,由DTP动态创建。 MonthCalendar是Windows中内置的common controls之一,用C ++编写并存储在comctl32.dll中。您的应用程序使用v6.0版本,存储在并行缓存中(c:\ windows \ winsxs)。 .NET类只是一个包装器,它不会改变它的外观或工作方式。

值得注意的是,它在Windows版本之间发生了很大变化,总是需要注意的事项,它在Windows中非常明显的地方使用。它是用户在安装Windows时与之交互的第一个常用控件。并在任务栏上的时钟中使用。 Windows 10是第一个不再使用的版本,Win8的外观被冻结,不太可能再次改变。

如上所述,下拉列表是动态创建的。您可以通过发送DTM_GETMONTHCAL message获取MonthCalendar窗口的句柄,在DropDown事件的事件处理程序中执行此操作。此时窗口句柄有效,但日历尚未显示,是修补它的适当时间。

您可以发送MCM messages来配置日历。你可以看出,就造型而言,非常纤薄的选择。您有MCM_SETCALENDARBORDER来更改边框粗细,MCM_SETCOLOR可以更改颜色。后者仅在视觉样式渲染器被禁用时才有效,它不在您的应用程序中。从技术上讲,您可以调用SetWindowTheme()来禁用视觉样式渲染器,以便MCM_SETCOLOR再次起作用。但是,这将时钟转回到2000年,它看起来会非常恐怖。

这就是全部,不足以让任何人开心。考虑嵌入WPF DatePicker以获得对样式的更多控制。

答案 1 :(得分:1)

有许多属性会影响日历的显示,例如:

  • CalendarFont
  • CalendarForeColor
  • CalendarMonthBackground
  • CalendarTitleBackColor

有关详细信息,请参阅MSDN。

答案 2 :(得分:0)

有类似的问题。毕竟不是那么糟糕。我的DatePicker看起来有点不同,但根据您的需要调整它不会有问题 首先要做的是 - 创建一个资源字典并为项目添加所有必要的样式 在我的解决方案中,我使用了两种风格:

  • DatePicker的实际样式;
  • 使用自定义按钮的样式。

    以下是代码:

    <!-- The IconButtonStyle -->
    <Style x:Key="IconButtonStyle"
               TargetType="{x:Type Button}">
        <!-- set some default values -->
        <Setter Property="Background"
                    Value="Transparent" />
        <Setter Property="BorderBrush"
                    Value="Transparent" />
        <Setter Property="VerticalAlignment"
                Value="Center" />
        <!-- set the visual tree of the control -->
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <!-- here come the actual sub-controls -->
                    <Border x:Name="border"
                                Height="{TemplateBinding Height}"
                                Width="{TemplateBinding Width}"
                                SnapsToDevicePixels="True"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="1"
                                Padding="0"
                                CornerRadius="0,0,0,0">
                        <Border x:Name="innerBorder"
                                    SnapsToDevicePixels="True"
                                    BorderThickness="1"
                                    Padding="2"
                                    CornerRadius="0,0,0,0">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                                  RecognizesAccessKey="True"
                                                  Margin="{TemplateBinding Padding}">
                                <ContentPresenter.Effect>
                                    <!-- give the content a bit of shadow -->
                                    <DropShadowEffect x:Name="shadow"
                                                          ShadowDepth="0"
                                                          Opacity="0.7"
                                                          BlurRadius="0" />
                                </ContentPresenter.Effect>
                                <ContentPresenter.RenderTransform>
                                    <!-- push the content a bit to the left and the top -->
                                    <TranslateTransform x:Name="translation"
                                                            X="0"
                                                            Y="0" />
                                </ContentPresenter.RenderTransform>
                            </ContentPresenter>
                        </Border>
                    </Border>
                    <ControlTemplate.Triggers>
                        <!-- 
                                the triggers define the reactions to various state
                                changes
                            -->
                        <Trigger Property="IsKeyboardFocused"
                                     Value="true">
                            <Setter TargetName="innerBorder"
                                        Property="BorderBrush"
                                        Value="Transparent" />
                            <Setter Property="Background"
                                        Value="Transparent" />
                        </Trigger>
                        <Trigger Property="IsMouseOver"
                                     Value="true">
                            <Setter Property="Background"
                                        Value="Transparent" />
                        </Trigger>
    
                        <!-- when the control is disabled, just let the background shine through -->
                        <Trigger Property="IsEnabled"
                                     Value="false">
                            <Setter Property="Opacity"
                                        Value="0.5" />
                        </Trigger>
                        <Trigger Property="IsPressed"
                                     Value="True">
                            <!-- This Trigger manages the Animation of the button's content and its shadow -->
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0"
                                                             To="0"
                                                             Storyboard.TargetName="shadow"
                                                             Storyboard.TargetProperty="(DropShadowEffect.ShadowDepth)" />
                                        <DoubleAnimation Duration="0:0:0"
                                                             To="0"
                                                             Storyboard.TargetName="translation"
                                                             Storyboard.TargetProperty="(TranslateTransform.X)" />
                                        <DoubleAnimation Duration="0:0:0"
                                                             To="0"
                                                             Storyboard.TargetName="translation"
                                                             Storyboard.TargetProperty="(TranslateTransform.Y)" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0"
                                                             To="0"
                                                             Storyboard.TargetName="shadow"
                                                             Storyboard.TargetProperty="(DropShadowEffect.ShadowDepth)" />
                                        <DoubleAnimation Duration="0:0:0"
                                                             To="0"
                                                             Storyboard.TargetName="translation"
                                                             Storyboard.TargetProperty="(TranslateTransform.X)" />
                                        <DoubleAnimation Duration="0:0:0"
                                                             To="0"
                                                             Storyboard.TargetName="translation"
                                                             Storyboard.TargetProperty="(TranslateTransform.Y)" />
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
    
    <!-- Customized Datepicker -->
    <Style x:Key="DatePicker" TargetType="{x:Type DatePicker}">
        <Setter Property="Foreground" Value="{StaticResource DarkGrayBrush}" />
        <Setter Property="Focusable" Value="True" />
        <Setter Property="VerticalAlignment" Value="Top" />
        <Setter Property="VerticalContentAlignment" Value="Top" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="IsTodayHighlighted" Value="True" />
        <Setter Property="SelectedDateFormat" Value="Short" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <!--Set CalendarStyle to DatePickerCalendarStyle.-->
        <Setter Property="CalendarStyle"
          Value="{DynamicResource DatePickerCalendarStyle}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DatePicker}">
                    <Border BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}"
                            CornerRadius="0" 
                            Background="Transparent">
                        <Grid x:Name="PART_Root"
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="150" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Button x:Name="PART_Button"                                     
                                    Grid.Column="1"
                                    Foreground="{TemplateBinding Foreground}"                                                                        
                                    Focusable="True"
                                    HorizontalAlignment="Left"
                                    Margin="-24,0,0,0"
                                    Grid.Row="0"
                                    Panel.ZIndex="2" 
                                    Padding="0" >
                                <Button.Style>
                                    <Style TargetType="{x:Type Button}" BasedOn="{StaticResource IconButtonStyle}">
                                        <Setter Property="Height" Value="23" />
                                        <Setter Property="Background" Value="Transparent" />
                                        <Style.Triggers>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Background" Value="{StaticResource BlueFadedBrush}" />
                                            </Trigger>
                                        </Style.Triggers>
                                    </Style>
                                </Button.Style>
                                <Image Height="15" VerticalAlignment="Top" >
                                    <Image.Style>
                                        <Style TargetType="{x:Type Image}">
                                            <Setter Property="Source" Value="/img/calendarBlue.png"/>                                            
                                            <Style.Triggers>
                                                <DataTrigger Binding="{Binding ElementName=PART_Button, Path=IsMouseOver}" Value="True">
                                                    <Setter Property="Source" Value="/img/calendarWhite.png"/>
                                                </DataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </Image.Style>
                                </Image>
                            </Button>
                            <Border BorderBrush="{StaticResource BlueBrush}"
                                    BorderThickness="2"
                                    CornerRadius="0"
                                    Padding="0"
                                    Width="150"
                                    Height="23"
                                    Background="{StaticResource WhiteBrush}"
                                    Panel.ZIndex="1">
                                <DatePickerTextBox x:Name="PART_TextBox"                                               
                                                   Grid.Column="0"
                                                   Foreground="{TemplateBinding Foreground}"
                                                   Focusable="{TemplateBinding Focusable}"                                                   
                                                   HorizontalContentAlignment="Left"
                                                   Grid.Row="0"                                                                                                      
                                                   VerticalContentAlignment="Center" 
                                                   BorderThickness="0"
                                                   Background="Transparent"
                                                   Width="150" 
                                                   Padding="0">
                                    <!-- Watermark access -->
                                    <DatePickerTextBox.Style>
                                        <Style TargetType="DatePickerTextBox">
                                            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
                                            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
                                            <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
                                            <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
                                            <Setter Property="Template">
                                                <Setter.Value>
                                                    <ControlTemplate TargetType="{x:Type DatePickerTextBox}">
                                                        <Grid>
                                                            <Grid.Resources>
                                                                <SolidColorBrush x:Key="WatermarkBrush" Color="#FFAAAAAA"/>
                                                            </Grid.Resources>
                                                            <VisualStateManager.VisualStateGroups>
                                                                <VisualStateGroup x:Name="CommonStates">
                                                                    <VisualStateGroup.Transitions>
                                                                        <VisualTransition GeneratedDuration="0"/>
                                                                        <VisualTransition GeneratedDuration="0:0:0.1" To="MouseOver"/>
                                                                    </VisualStateGroup.Transitions>
                                                                    <VisualState x:Name="Normal"/>
                                                                    <VisualState x:Name="MouseOver">
                                                                        <Storyboard>
                                                                            <ColorAnimation Duration="0" To="Transparent" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="ContentElement"/>
                                                                            <ColorAnimation Duration="0" To="Transparent" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="watermark_decorator"/>
                                                                        </Storyboard>
                                                                    </VisualState>
                                                                </VisualStateGroup>
                                                                <VisualStateGroup x:Name="WatermarkStates">
                                                                    <VisualStateGroup.Transitions>
                                                                        <VisualTransition GeneratedDuration="0"/>
                                                                    </VisualStateGroup.Transitions>
                                                                    <VisualState x:Name="Unwatermarked"/>
                                                                    <VisualState x:Name="Watermarked">
                                                                        <Storyboard>
                                                                            <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentElement"/>
                                                                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Watermark"/>
                                                                        </Storyboard>
                                                                    </VisualState>
                                                                </VisualStateGroup>
                                                                <VisualStateGroup x:Name="FocusStates">
                                                                    <VisualStateGroup.Transitions>
                                                                        <VisualTransition GeneratedDuration="0"/>
                                                                    </VisualStateGroup.Transitions>
                                                                    <VisualState x:Name="Unfocused"/>
                                                                    <VisualState x:Name="Focused">
                                                                        <Storyboard>
                                                                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="FocusVisual"/>
                                                                        </Storyboard>
                                                                    </VisualState>
                                                                </VisualStateGroup>
                                                            </VisualStateManager.VisualStateGroups>
                                                            <Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="1" Opacity="1" Padding="{TemplateBinding Padding}">
                                                                <Grid x:Name="WatermarkContent" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                                                    <Border x:Name="ContentElement" BorderBrush="#FFFFFFFF" BorderThickness="0"/>
                                                                    <Border x:Name="watermark_decorator" BorderBrush="#FFFFFFFF" BorderThickness="0">
                                                                        <ContentControl x:Name="PART_Watermark" Focusable="False" IsHitTestVisible="False" Opacity="0" Padding="0">
                                                                            <ContentControl.Template>
                                                                                <ControlTemplate>
                                                                                    <TextBlock Text="dd/mm/aaaa" Margin="2,0,0,0"/>
                                                                                </ControlTemplate>
                                                                            </ContentControl.Template>
                                                                        </ContentControl>
                                                                    </Border>
                                                                    <ScrollViewer x:Name="PART_ContentHost" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                                                    <Border x:Name="FocusVisual" BorderBrush="#FF45D6FA" CornerRadius="1" IsHitTestVisible="False" Opacity="0"/>
                                                                </Grid>
                                                            </Border>
                                                        </Grid>
                                                    </ControlTemplate>
                                                </Setter.Value>
                                            </Setter>
                                        </Style>
                                    </DatePickerTextBox.Style>
                                    <!-- Watermark access Ends -->
                                </DatePickerTextBox>
                            </Border>
                            <Grid x:Name="PART_DisabledVisual"
                                  Grid.ColumnSpan="2"
                                  Grid.Column="0"
                                  IsHitTestVisible="False"
                                  Opacity="0"
                                  Grid.Row="0">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Rectangle Grid.Column="0"
                                        Fill="#A5FFFFFF"
                                        RadiusY="1"
                                        Grid.Row="0"
                                        RadiusX="1" />
                                <Rectangle Grid.Column="1"
                                         Fill="#A5FFFFFF"
                                         Height="18"
                                         Margin="3,0,3,0"
                                         RadiusY="1"
                                         Grid.Row="0"
                                         RadiusX="1"
                                         Width="19" />                                
                                <Popup x:Name="PART_Popup"                                       
                                         AllowsTransparency="True"                                       
                                         Placement="Bottom"
                                         PlacementTarget="{Binding ElementName=PART_TextBox}"
                                         StaysOpen="False" />                                
                            </Grid>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    用法如下:

    <DatePicker Style="{StaticResource DatePicker}" />