WPF:重写Slider滑动条模板,美化样式设计

默认的Slider

看一下默认的Slider样式

<Style x:Key="BaseSliderStyle" TargetType="Slider">
    <Setter Property="Width" Value="500"/>
    <Setter Property="Margin" Value="20"/>
    <Setter Property="Maximum" Value="10"/>
    <Setter Property="IsSnapToTickEnabled" Value="True"/>
    <Setter Property="TickPlacement" Value="Both"/>
    <Setter Property="TickFrequency" Value="1"/>
    <Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>

在这里插入图片描述
设置了最大值是10,上下的Tick指针都显示,间隔是1。
上图从上往下分析一下结构就是:上TickBar + 包含Thumb、RepeatButton的Track + 下TickBar,即
在这里插入图片描述
MSDN上面是这样的:
在这里插入图片描述

RepeatButton就是点击Thumb两侧空白(实际是RepeatButton背景色是透明色)的实现移动Thumb的效果。

重新设计Slider

由上面的结构分析,不难写出Template样式

<Style x:Key="DefaultSliderStyle" TargetType="Slider" BasedOn="{StaticResource BaseSliderStyle}">
   <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Slider">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <TickBar Name="TopTick"
                             Grid.Row="0"
                             Placement="Top"
                             Height="4"
                             Visibility="Visible"
                             Fill="Red"/>
                    <Border Name="TrackBackground" 
                            Grid.Row="1"
                            Height="4"
                            Background="Green"/>
                    <Track Name="PART_Track" Grid.Row="1">
                        <Track.DecreaseRepeatButton>
                            <RepeatButton Style="{StaticResource DefaultRepeatButtonStyle}" Command="Slider.DecreaseLarge"/>
                        </Track.DecreaseRepeatButton>
                        <Track.Thumb>
                            <Thumb Style="{StaticResource DefaultSliderThumbStyle}"/>
                        </Track.Thumb>
                        <Track.IncreaseRepeatButton>
                            <RepeatButton Style="{StaticResource DefaultRepeatButtonStyle}" Command="Slider.IncreaseLarge"/>
                        </Track.IncreaseRepeatButton>
                    </Track>
                    <TickBar Name="BottomTick"
                             Grid.Row="2"
                             Placement="Bottom"
                             Height="4"
                             Visibility="Visible"
                             Fill="Red"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

模板包括三行,分别放上TickBar、Track、下TickBar

1、用一个Border做背景色;
2、TickBar都设置了可见(为了演示),一开始可设置都不可见;然后添加Trigger,判断TickPlacement的值取设置那个可见;
3、Thumb 是一个圆形按钮;
4、RepeatButton设置成透明;
5、Track的Name一定要设置为PART_Track,不然就不能拖动Thumb了。(在其他地方看到的解释了,微软写内部模板,这类命名方式不能改,个人经验是类似PART_XXX这类名称。)

Thumb的样式是,一个圆:

<Style x:Key="DefaultSliderThumbStyle" TargetType="Thumb">
    <Setter Property="Width" Value="15"/>
    <Setter Property="Height" Value="15"/>
    <Setter Property="Background" Value="Blue"/>
    <Setter Property="SnapsToDevicePixels" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Thumb">
                <Ellipse Width="{TemplateBinding Width}" 
                         Height="{TemplateBinding Height}"
                         Fill="{TemplateBinding Background}"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

RepeateButton透明:

<Style x:Key="DefaultRepeatButtonStyle" TargetType="RepeatButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="RepeatButton">
                <Border Background="Transparent"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

效果图:

在这里插入图片描述

美化Slider

样式:

<Window.Resources>
    <DropShadowEffect x:Key="UnhoverThumbEffect" BlurRadius="5" ShadowDepth="0" Opacity="0.3" Color="RoyalBlue"/>
    <DropShadowEffect x:Key="HoverThumbEffect" BlurRadius="5" ShadowDepth="0" Opacity="0.5" Color="RoyalBlue"/>
    <DropShadowEffect x:Key="DragThumbEffect" BlurRadius="8" ShadowDepth="0" Opacity="1" Color="RoyalBlue"/>
    <Style x:Key="DefaultSliderThumbStyle" TargetType="Thumb">
        <Setter Property="Width" Value="15"/>
        <Setter Property="Height" Value="15"/>
        <Setter Property="Background" Value="White"/>
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Thumb">
                    <Ellipse Width="{TemplateBinding Width}" 
                             Height="{TemplateBinding Height}"
                             Fill="{TemplateBinding Background}"
                             Effect="{StaticResource UnhoverThumbEffect}">
                    </Ellipse>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Effect" Value="{StaticResource HoverThumbEffect}"/>
                            <Setter Property="Cursor" Value="Hand"/>
                        </Trigger>
                        <Trigger Property="IsDragging" Value="True">
                            <Setter Property="Effect" Value="{StaticResource DragThumbEffect}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="DefaultLeftRepeatButtonStyle" TargetType="RepeatButton">
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="RepeatButton">
                	<Border Background="RoyalBlue" Height="4"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="DefaultRightRepeatButtonStyle" TargetType="RepeatButton">
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="RepeatButton">
                    <Border Background="Transparent"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="BaseSliderStyle" TargetType="Slider">
        <Setter Property="Width" Value="500"/>
        <Setter Property="MinHeight" Value="30"/>
        <Setter Property="Margin" Value="20"/>
        <Setter Property="Maximum" Value="100"/>
        <Setter Property="IsSnapToTickEnabled" Value="True"/>
        <!--移到鼠标点击的指定刻度点-->
        <Setter Property="IsMoveToPointEnabled" Value="True"/>
        <!--移动的最大最小距离。
            由于设置了IsMoveToPointEnabled=True,下面两个属性就没发挥作用了。
            点击RepeatButton时直接就移动到了指定位置。
            如果为False,那么由于RepeatButton绑定了Slider.DecreaseLarge命令,
            那点击左右的RepeatButton一次,就移动10个单位距离。
            同样的还有Slider.DecreaseSmall命令,移动1个单位距离-->
        <Setter Property="LargeChange" Value="10"/>
        <Setter Property="SmallChange" Value="1"/>
        <Setter Property="Background" Value="LightGray"/>
        <Setter Property="Foreground" Value="RoyalBlue"/>
        <Setter Property="SnapsToDevicePixels" Value="True"/>
    </Style>
    <Style x:Key="BeautifySliderStyle" TargetType="Slider" BasedOn="{StaticResource BaseSliderStyle}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Slider">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition MinHeight="{TemplateBinding MinHeight}" Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <TickBar Name="TopTick"
                                 Grid.Row="0"
                                 Placement="Top"
                                 Height="4"
                                 Visibility="Collapsed"
                                 Fill="{TemplateBinding Foreground}"/>
                        <Border Name="TrackBackground" 
                                Grid.Row="1"
                                Height="4"
                                Background="{TemplateBinding Background}"/>
                        <Track Name="PART_Track" Grid.Row="1">
                            <Track.DecreaseRepeatButton>
                                <RepeatButton Style="{StaticResource DefaultLeftRepeatButtonStyle}" Command="Slider.DecreaseLarge"/>
                            </Track.DecreaseRepeatButton>
                            <Track.Thumb>
                                <Thumb Style="{StaticResource DefaultSliderThumbStyle}"/>
                            </Track.Thumb>
                            <Track.IncreaseRepeatButton>
                                <RepeatButton Style="{StaticResource DefaultRightRepeatButtonStyle}" Command="Slider.IncreaseLarge"/>
                            </Track.IncreaseRepeatButton>
                        </Track>
                        <TickBar Name="BottomTick"
                                 Grid.Row="2"
                                 Placement="Bottom"
                                 Height="4"
                                 Visibility="Collapsed"
                                 Fill="{TemplateBinding Foreground}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="TickPlacement" Value="Both">
                            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
                            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
                        </Trigger>
                        <Trigger Property="TickPlacement" Value="BottomRight">
                            <Setter TargetName="BottomTick" Property="Visibility" Value="Visible"/>
                        </Trigger>
                        <Trigger Property="TickPlacement" Value="TopLeft">
                            <Setter TargetName="TopTick" Property="Visibility" Value="Visible"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid Background="White">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center">
        <Slider Style="{StaticResource BaseSliderStyle}"/>
        <Slider Name="slider" Style="{StaticResource BeautifySliderStyle}" TickPlacement="BottomRight"/>
        <TextBlock Text="{Binding ElementName=slider, Path=Value}"/>
    </StackPanel>
</Grid>

效果图:
在这里插入图片描述

有个问题

我不想要下面那共101个刻度线,我只想要11个代表0、10、20、30、40、50、60、70、80、90、100的刻度线就行了。虽然可以设置

<Setter Property="TickFrequency" Value="10"/>
或者
<Setter Property="Ticks" Value="0,10,20,30,40,50,60,70,80,90,100"/>

但是,此时移动一次的最小单位距离就不是1了,而是10。可我还是希望最小移动单位是1,不然怎么得到如63这样的值呢。不知道有没有人有简单解决方法,欢迎交流!!!

抱歉,我不是一个可以编写代码的AI。不过,我可以为您提供相关信息和资源,希望能帮到您。 Ascon是一种轻量级加密算法,它的设计目标是在资源受限的环境中提供高度的安全性和性能。Ascon有四种不同的配置:Ascon-128、Ascon-128a、Ascon-HASH、Ascon-HASHa。 Ascon的实现可以使用数字电路技术,这种实现方式可以提供更高的性能和更低的功耗。以下是一个使用数字电路方式实现Ascon-128的代码示例: ```verilog module Ascon128(clk, rst, mode, key, nonce, plaintext, ciphertext, tag, valid); parameter ROUNDS = 12; parameter BLOCK_SIZE = 64; input clk, rst; input [1:0] mode; input [127:0] key, nonce, plaintext; output [127:0] ciphertext, tag; output valid; // Round constants parameter [127:0] RC[0:11] = '{128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000, 128'h0000000000000000}; // S-box function [7:0] SBox(input [7:0] x); case (x) 8'h00: SBox = 8'h63; 8'h01: SBox = 8'h7c; 8'h02: SBox = 8'h77; 8'h03: SBox = 8'h7b; 8'h04: SBox = 8'hf2; 8'h05: SBox = 8'h6b; 8'h06: SBox = 8'h6f; 8'h07: SBox = 8'hc5; 8'h08: SBox = 8'h30; 8'h09: SBox = 8'h01; 8'h0a: SBox = 8'h67; 8'h0b: SBox = 8'h2b; 8'h0c: SBox = 8'hfe; 8'h0d: SBox = 8'hd7; 8'h0e: SBox = 8'hab; 8'h0f: SBox = 8'h76; 8'h10: SBox = 8'hca; 8'h11: SBox = 8'h82; 8'h12: SBox = 8'hc9; 8'h13: SBox = 8'h7d; 8'h14: SBox = 8'hfa; 8'h15: SBox = 8'h59; 8'h16: SBox = 8'h47; 8'h17: SBox = 8'hf0; 8'h18: SBox = 8'had; 8'h19: SBox = 8'hd4; 8'h1a: SBox = 8'ha2; 8'h1b: SBox = 8'haf; 8'h1c: SBox = 8'h9c; 8'h1d: SBox = 8'ha4; 8'h1e: SBox = 8'h72; 8'h1f: SBox = 8'hc0; 8'h20: SBox = 8'hb7; 8'h21: SBox = 8'hfd; 8'h22: SBox = 8'h93; 8'h23: SBox = 8'h26; 8'h24: SBox = 8'h36; 8'h25: SBox = 8'h3f; 8'h26: SBox = 8'hf7; 8'h27: SBox = 8'hcc; 8'h28: SBox = 8'h34; 8'h29: SBox = 8'ha5; 8'h2a: SBox = 8'he5; 8'h2b: SBox = 8'hf1; 8'h2c: SBox = 8'h71; 8'h2d: SBox = 8'hd8; 8'h2e: SBox = 8'h31; 8'h2f: SBox = 8'h15; 8'h30: SBox = 8'h04; 8'h31: SBox = 8'hc7; 8'h32: SBox = 8'h23; 8'h33: SBox = 8'hc3; 8'h34: SBox = 8'h18; 8'h35: SBox = 8'h96; 8'h36: SBox = 8'h05; 8'h37: SBox = 8'h9a; 8'h38: SBox = 8'h07; 8'h39: SBox = 8'h12; 8'h3a: SBox = 8'hab; 8'h3b: SBox = 8'h80; 8'h3c: SBox = 8'he2; 8'h3d: SBox = 8'heb; 8'h3e: SBox = 8'h27; 8'h3f: SBox = 8'hb2; 8'h40: SBox = 8'h75; 8'h41: SBox = 8'h09; 8'h42: SBox = 8'h83; 8'h43: SBox = 8'h2c; 8'h44: SBox = 8'h1a; 8'h45: SBox = 8'h1b; 8'h46: SBox = 8'h6e; 8'h47: SBox = 8'h5a; 8'h48: SBox = 8'ha0; 8'h49: SBox = 8'h52; 8'h4a: SBox = 8'h3b; 8'h4b: SBox = 8'hd6; 8'h4c: SBox = 8'hb3; 8'h4d: SBox = 8'h29; 8'h4e: SBox = 8'he3; 8'h4f: SBox = 8'h2f; 8'h50: SBox = 8'h84; 8'h51: SBox = 8'hd2; 8'h52: SBox = 8'h1f; 8'h53: SBox = 8'hb5; 8'h54: SBox = 8'h0b; 8'h55: SBox = 8'h8f; 8'h56: SBox = 8'h0e; 8'h57: SBox = 8'hab; 8'h58: SBox = 8'h16; 8'h59: SBox = 8'hc6; 8'h5a: SBox = 8'hb4; 8'h5b: SBox = 8'hc2; 8'h5c: SBox = 8'h3e; 8'h5d: SBox = 8'h5e; 8'h5e: SBox = 8'h27; 8'h5f: SBox = 8'h46; 8'h60: SBox = 8'h58; 8'h61: SBox = 8'hdf; 8'h62: SBox = 8'hd0; 8'h63: SBox = 8'hef; 8'h64: SBox = 8'haa; 8'h65: SBox = 8'hfb; 8'h66: SBox = 8'h43; 8'h67: SBox = 8'h4d; 8'h68: SBox = 8'h33; 8'h69: SBox = 8'hd9; 8'h6a: SBox = 8'h98; 8'h6b: SBox = 8'hc1; 8'h6c: SBox = 8'h8c; 8'h6d: SBox = 8'h9d; 8'h6e: SBox = 8'h5d; 8'h6f: SBox = 8'h65; endcase endfunction // Permutation function function [127:0] P(input [127:0] state); reg [127:0] out; reg [127:0] x, y, z; integer i; out = state; for (i = 0; i < ROUNDS; i = i + 1) begin x = out[127:64]; y = out[63:32]; z = out[31:0]; // Add round constant y = y ^ RC[i]; // S-box x = {SBox(x[7:0]), SBox(x[15:8]), SBox(x[23:16]), SBox(x[31:24]), SBox(x[39:32]), SBox(x[47:40]), SBox(x[55:48]), SBox(x[63:56])}; y = {SBox(y[7:0]), SBox(y[15:8]), SBox(y[23:16]), SBox(y[31:24]), SBox(y[39:32]), SBox(y[47:40]), SBox(y[55:48]), SBox(y[63:56])}; z = {SBox(z[7:0]), SBox(z[15:8]), SBox(z[23:16]), SBox(z[31:24]), SBox(z[39:32]), SBox(z[47:40]), SBox(z[55:48]), SBox(z[63:56])}; // Linear diffusion layer out = {x[0]^y[0]^z[0], x[8]^y[8]^z[8], x[16]^y[16]^z[16], x[24]^y[24]^z[24], x[32]^y[32]^z[32], x[40]^y[40]^z[40], x[48]^y[48]^z[48], x[56]^y[56]^z[56], x[1]^y[1]^z[1], x[9]^y[9]^z[9], x[17]^y[17]^z[17], x[25]^y[25]^z[25], x[33]^y[33]^z[33], x[41]^y[41]^z[41], x[49]^y[49]^z[49], x[57]^y[57]^z[57], x[2]^y[2]^z[2], x[10]^y[10]^z[10], x[18]^y[18]^z[18], x[26]^y[26]^z[26], x[34]^y[34]^z[34], x[42]^y[42]^z[42], x[50]^y[50]^z[50], x[58]^y[58]^z[58], x[3]^y[3]^z[3], x[11]^y[11]^z[11], x[19]^y[19]^z[19], x[27]^y[27]^z[27], x[35]^y[35]^z[35], x[43]^y[43]^z[43], x[51]^y[51]^z[51], x[59]^y[59]^z[59], x[4]^y[4]^z[4], x[12]^y[12]^z[12], x[20]^y[20]^z[20], x[28]^y[28]^z[28], x[36]^y[36]^z[36], x[44]^y[44]^z[44], x[52]^y[52]^z[52], x[60]^y[60]^z[60], x[5]^y[5]^z[5], x[13]^y[13]^z[13], x[21]^y[21]^z[21], x[29]^y[29]^z[29], x[37]^y[37]^z[37], x[45]^y[45]^z[45], x[53]^y[53]^z[53], x[61]^y[61]^z[61], x[6]^y[6]^z[6], x[14]^y[14]^z[14], x[22]^y[22]^z[22], x[30]^y[30]^z[30], x[38]^y[38]^z[38], x[46]^y[46]^z[46], x[54]^y[54]^z[54], x[62]^y[62]^z[62], x[7]^y[7]^z[7], x[15]^y[15]^z[15], x[23]^y[23]^z[23], x[31]^y[31]^z[31], x[39]^y[39]^z[39], x[47]^y[47]^z[47], x[55]^y[55]^z[55], x[63]^y[63]^z[63]}; end P = out; endfunction // Encryption function function [127:0] Encrypt(input [127:0] plaintext, input [127:0] key, input [127:0] nonce); reg [127:0] state, out, k, n; integer i; // Initial state state = {nonce, 128'h0000000000000000}; // Key and nonce setup k = key; n = nonce; // Absorb key state[127:64] = state[127:64] ^ k; state = P(state); k = k ^ state[127:64]; // Absorb nonce state[127:64] = state[127:64] ^ n; state = P(state); n = n ^ state[127:64]; // Absorb associated data (mode != 0) if (mode != 0) begin for (i = 0; i < $size(plaintext)/BLOCK_SIZE; i = i + 1) begin state[127:64] = state[127:64] ^ plaintext[i*BLOCK_SIZE +: BLOCK_SIZE]; state = P(state); end end // Encrypt plaintext (mode == 0 or 1) out = 128'h0000000000000000; for (i = 0; i < $size(plaintext)/BLOCK_SIZE; i = i + 1) begin state[127:64] = state[127:64] ^ plaintext[i*BLOCK_SIZE +: BLOCK_SIZE]; out[i*BLOCK_SIZE +: BLOCK_SIZE] = state[127:64] ^ plaintext[i*BLOCK_SIZE +: BLOCK_SIZE]; state = P(state); end // Generate tag (mode == 0 or 2) tag = state[127:64] ^ k ^ (mode == 0 ? 128'h0000000000000000 : n); Encrypt = out; endfunction reg [127:0] ciphertext_reg, tag_reg; reg valid_reg; always @(posedge clk) begin if (rst) begin ciphertext_reg <= 128'h0000000000000000; tag_reg <= 128'h0000000000000000; valid_reg <= 0; end else begin case (mode) 2'b00: begin // Encryption mode ciphertext_reg <= Encrypt(plaintext, key, nonce); tag_reg <= 128'h0000000000000000; valid_reg <= 1; end 2'b01: begin // Encryption mode with authentication ciphertext_reg <= Encrypt(plaintext, key, nonce); tag_reg <= Encrypt(128'h0000000000000000, key, nonce); valid_reg <= 1; end 2'b10: begin // Authentication mode ciphertext_reg <= 128'h0000000000000000; tag_reg <= Encrypt(plaintext, key, nonce); valid_reg <= 1; end 2'b11: begin // Authentication only mode ciphertext_reg <= 128'h0000000000000000; tag_reg <= Encrypt(128'h0000000000000000, key, nonce); valid_reg <= 1; end endcase end end assign ciphertext = ciphertext_reg; assign tag = tag_reg; assign valid = valid
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值