用Silverlight打造位运算器(3)--完成

      上一回我们说到,使用模板制作的SpeedButton无法在载入浏览器时处于按下状态,这个缺点是我无法忍受的,没办法,只好使用用户控件的方式重写SpeedButton以解决这个问题。所有控件完成后,位移运算器就变得十分简单了。没想到当年要3000行代码完成的东西,变得如此简单,有些超出我的预期。
好,先看看位移运算器的完整效果,请首先安装Silverlight3.0
最新发现不登录博客园的用户无法直接看到Silverlight,如果是这样,请移步到以下网址观看动画:

http://www.bbniu.com/matrix/ShowApplication.aspx?id=147



     界面做成这样,主要是考虑到可以用它来上课做演示,很多计算机课程都需要讲到位运算。
制作步骤:
一、 重写SpeedButton
1、 在BitLibrary中删除Theme文件夹及SpeedButton.cs文件。
2、 在【BitLibrary】项目上单击鼠标右键,选择【添加】【新建项】,添加一个Silverlight用户控件,并命名为“SpeedButton.xaml”。更改SpeedButton.xaml文件如下:

<UserControl x:Class="BitLibrary.SpeedButton"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml">
    
<UserControl.Resources>
        
<LinearGradientBrush x:Key="BorderNormalBrush">
            
<GradientStop Color="#FFA3AEB9" Offset="0"/>
            
<GradientStop Color="#FF8399A9" Offset="0.375"/>
            
<GradientStop Color="#FF718597" Offset="0.375"/>
            
<GradientStop Color="#FF617584" Offset="1"/>
        
</LinearGradientBrush>
        
<SolidColorBrush x:Key="BorderBgPressedBrush" Color="#FF6DBDD1"/>
        
<SolidColorBrush x:Key="BorderBgNormaldBrush" Color="White"/>
        
<LinearGradientBrush x:Key="RectNormalBrush" StartPoint=".7,0" EndPoint=".7,1">
            
<GradientStop Color="#FFFFFFFF" Offset="0" />
            
<GradientStop Color="#F1FFFFFF" Offset="0.375" />
            
<GradientStop Color="#DCFFFFFF" Offset="0.625" />
            
<GradientStop Color="#8FFFFFFF" Offset="1" />
        
</LinearGradientBrush>
        
<LinearGradientBrush x:Key="RectMouseOverBrush" StartPoint=".7,0" EndPoint=".7,1">
            
<GradientStop Color="#FFFFFFFF" Offset="0" />
            
<GradientStop Color="#C2FFFFFF" Offset="0.375" />
            
<GradientStop Color="#8CFFFFFF" Offset="0.625" />
            
<GradientStop Color="#C8FFFFFF" Offset="1" />
        
</LinearGradientBrush>
        
<LinearGradientBrush x:Key="RectPressedBrush" StartPoint=".7,0" EndPoint=".7,1">
            
<GradientStop Color="#D8FFFFFF" Offset="0" />
            
<GradientStop Color="#C6FFFFFF" Offset="0.375" />
            
<GradientStop Color="#8CFFFFFF" Offset="0.625" />
            
<GradientStop Color="#3FFFFFFF" Offset="1" />
        
</LinearGradientBrush>
    
</UserControl.Resources>
    
<Grid x:Name="LayoutRoot" Background="Transparent" Width="30" Height="30">
        
<Border x:Name="Bd" CornerRadius="3" Background="{StaticResource BorderBgNormaldBrush}" BorderThickness="1" 
            BorderBrush
="{StaticResource BorderNormalBrush}">
            
<Grid Background="Transparent" Margin="1">
                
<Border x:Name="BackgroundAnimation" Background="#FF448DCA"/>
                
<Rectangle x:Name="BackgroundGradient" Fill="{StaticResource RectNormalBrush}"/>
            
</Grid>
        
</Border>
        
<ContentPresenter x:Name="contentPresenter" VerticalAlignment="Center"
                          HorizontalAlignment
="Center" Margin="0"/>
    
</Grid>
</UserControl>

 

      在这个SpeedButton里使用了跟之前模板里一样的外观,不同之处是在控件的资源内添加了6种画刷,这些静态资源不但可以直接在xaml文件中使用StaticResource关键字进行引用,也可以在cs文件中使用this. Resources["资源名称"]进行引用,从而可以很方便地改变控件外观。
3、 打开SpeedButton.xaml.cs文件,更改代码如下:

 

 1 public partial class SpeedButton : UserControl
 2     {
 3         public SpeedButton()
 4         {
 5             InitializeComponent();
 6             this.MouseEnter += new MouseEventHandler(SpeedButton_MouseEnter);
 7             this.MouseLeave += new MouseEventHandler(SpeedButton_MouseLeave);
 8             this.MouseLeftButtonDown += new MouseButtonEventHandler(SpeedButton_MouseLeftButtonDown);
 9         }
10         //声明依赖属性Text
11         public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
12             "Text"typeof(string), typeof(SpeedButton), null);
13         public string Text
14         {
15             get { return (string)contentPresenter.Content; }
16             set { contentPresenter.Content = value; }
17         }
18         public SystemState State
19         {
20             get;
21             set;
22         }
23         private Boolean isPress = false//指示按钮是否处于按下状态
24         public Boolean IsPress
25         {
26             get
27             {
28                 return isPress;
29             }
30             set
31             {
32                 if (IsPress == value) return;
33                 isPress = value;
34                 if (isPress)
35                 {
36                     Bd.Background = (SolidColorBrush)Resources["BorderBgPressedBrush"];
37                     BackgroundGradient.Fill = (LinearGradientBrush)Resources["RectPressedBrush"];
38                 }
39                 else
40                 {
41                     Bd.Background = (SolidColorBrush)Resources["BorderBgNormaldBrush"];
42                     BackgroundGradient.Fill = (LinearGradientBrush)Resources["RectNormalBrush"]; 
43                 }
44             }
45         }
46         void SpeedButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
47         {
48             if (!isPress)
49             {
50                 IsPress = true;
51             }
52         }
53 
54         void SpeedButton_MouseLeave(object sender, MouseEventArgs e)
55         {
56             if (!isPress)
57             {
58                 BackgroundGradient.Fill = (LinearGradientBrush)Resources["RectNormalBrush"];
59             }
60         }
61 
62         void SpeedButton_MouseEnter(object sender, MouseEventArgs e)
63         {
64             if (!isPress)
65             {
66                 BackgroundGradient.Fill = (LinearGradientBrush)Resources["RectMouseOverBrush"];
67             }
68         }
69 }

 

大家应该也会注意到,之前在模板中,外观的改变使用的是动画,但所有的动画时间(Duration)都为0。而在现在这个SpeedButton控件中,通过直接更改画刷来改变控件外观,这些更改都是在鼠标事件中实现的。虽然实现不同,但效果是一样的。运行程序,我们发现OCT按钮是处于按下状态的。终于解决了这个大bug。
大家可以对比相同控件两种不同的做法,使用模板控件从ContentControl控件继承,而使用用户控件需要从UserControl进行继承,这样很多放在UserControl里的控件的属性就会被屏敝掉,从而不能再调用Content属性对按钮上显示的文字进行设置。如本例所示,声明了一个依赖属性Text来对按钮上的文字进行设置。
经过以上努力,终于可以开始写位移运算器了,当然,没遇到任何困难,如砍瓜切菜般,迅速完成。唯一不爽的地方是VS2008里使用SL3没有界面设计窗口,要不停地运行程序来看控件位置,有点郁闷。

 二、位运算器主程序
1、更改MainPage.xaml代码如下:

 

<UserControl x:Class="BitCalculator.MainPage"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d
="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:src
="clr-namespace:BitLibrary;assembly=BitLibrary"
    mc:Ignorable
="d" d:DesignWidth="569" d:DesignHeight="195">
    
<Canvas x:Name="LayoutRoot" Background="SkyBlue" Loaded="LayoutRoot_Loaded">
        
<src:ToolBar x:Name="tbTop" Grid.Row="1" SelectionChange="tb_SelectionChange"
                     Canvas.Left
="10" Canvas.Top="17"/>
        
<src:BitTextBox x:Name="btxtTop" Text="20091122" Canvas.Left="132" Canvas.Top="0"/>
        
<Button x:Name="btnTopSHL" Content="&lt;&lt;" Canvas.Left="469" Canvas.Top="17" Width="30" Height="30" ToolTipService.ToolTip="左移" Click="SHL_Click" />
        
<Button x:Name="btnTopSHR" Content=">>" Canvas.Left="499" Canvas.Top="17" Width="30" Height="30" ToolTipService.ToolTip="右移" Click="SHR_Click"/>
        
<Button x:Name="btnTopNOT" Content="~" Canvas.Left="529" Canvas.Top="17" Width="30" Height="30" ToolTipService.ToolTip="求补" Click="NOT_Click"/>

        
<src:ToolBar x:Name="tbMid" Grid.Row="1" SelectionChange="tb_SelectionChange"
                     Canvas.Left
="10" Canvas.Top="49"/>
        
<src:BitTextBox x:Name="btxtMid" Text="20091122" Canvas.Left="132" Canvas.Top="32"/>
        
<Button x:Name="btnMidSHL" Content="&lt;&lt;" Canvas.Left="469" Canvas.Top="49" Width="30" Height="30" ToolTipService.ToolTip="左移" Click="SHL_Click"/>
        
<Button x:Name="btnMidSHR" Content=">>" Canvas.Left="499" Canvas.Top="49" Width="30" Height="30" ToolTipService.ToolTip="右移" Click="SHR_Click"/>
        
<Button x:Name="btnMidNOT" Content="~" Canvas.Left="529" Canvas.Top="49" Width="30" Height="30" ToolTipService.ToolTip="求补" Click="NOT_Click"/>

        
<Button x:Name="btnAnd" Content="AND" Canvas.Left="235" Canvas.Top="81" Width="30" Height="30" ToolTipService.ToolTip="与运算" Click="btnAnd_Click"/>
        
<Button x:Name="btnOr" Content="OR" Canvas.Left="265" Canvas.Top="81" Width="30" Height="30" ToolTipService.ToolTip="或运算" Click="btnOr_Click"/>
        
<Button x:Name="btnXor" Content="XOR" Canvas.Left="295" Canvas.Top="81" Width="30" Height="30" ToolTipService.ToolTip="异或运算" Click="btnXor_Click"/>
        
<Button x:Name="btnMod" Content="MOD" Canvas.Left="325" Canvas.Top="81" Width="30" Height="30" ToolTipService.ToolTip="取模" Click="btnMod_Click"/>
        
<Button x:Name="btnClear" Content="CLR" Canvas.Left="355" Canvas.Top="81" Width="30" Height="30" ToolTipService.ToolTip="清空文框" Click="btnClear_Click"/>
        
        
<src:ToolBar x:Name="tbBottom" Grid.Row="1" SelectionChange="tb_SelectionChange"
                     Canvas.Left
="10" Canvas.Top="113"/>
        
<src:BitTextBox x:Name="btxtBottom" Text="20091122" Canvas.Left="132" Canvas.Top="96"/>
        
<Button x:Name="btnBottomSHL" Content="&lt;&lt;" Canvas.Left="469" Canvas.Top="113" Width="30" Height="30" ToolTipService.ToolTip="左移" Click="SHL_Click"/>
        
<Button x:Name="btnBottomSHR" Content=">>" Canvas.Left="499" Canvas.Top="113" Width="30" Height="30" ToolTipService.ToolTip="右移" Click="SHR_Click"/>
        
<Button x:Name="btnBottomNOT" Content="~" Canvas.Left="529" Canvas.Top="113" Width="30" Height="30" ToolTipService.ToolTip="求补" Click="NOT_Click"/>
        
        
<CheckBox x:Name="cbFillZero" Content="二进制数字不足32位补0" IsChecked="true"
                  Canvas.Left
="10" Canvas.Top="150" Click="cbFillZero_Click"/>
        
<CheckBox x:Name="cbAllCtrl" Content="统一进制控制" IsChecked="false"
                  Canvas.Left
="165" Canvas.Top="150" Click="cbAllCtrl_Click"/>
        
<TextBlock Text="http://www.cnblogs.com/abatei" Canvas.Top="168" Canvas.Left="10"/>
    
</Canvas>
</UserControl>

2、打开MainPage.xaml.cs文件,更改代码如下:

 

  1 using BitLibrary;
  2 
  3 namespace BitCalculator
  4 {
  5     public partial class MainPage : UserControl
  6     {
  7         public MainPage()
  8         {
  9             InitializeComponent();
 10         }
 11 
 12 
 13         private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
 14         {
 15             tbTop.Tag = btxtTop;
 16             tbMid.Tag = btxtMid;
 17             tbBottom.Tag = btxtBottom;
 18             btnTopSHL.Tag = btxtTop;
 19             btnTopSHR.Tag = btxtTop;
 20             btnTopNOT.Tag = btxtTop;
 21             btnMidSHL.Tag = btxtMid;
 22             btnMidSHR.Tag = btxtMid;
 23             btnMidNOT.Tag = btxtMid;
 24             btnBottomSHL.Tag = btxtBottom;
 25             btnBottomSHR.Tag = btxtBottom;
 26             btnBottomNOT.Tag = btxtBottom;
 27         }
 28 
 29         private void cbFillZero_Click(object sender, RoutedEventArgs e)
 30         {
 31             btxtTop.FillZero = (bool)cbFillZero.IsChecked;
 32             btxtMid.FillZero = (bool)cbFillZero.IsChecked;
 33             btxtBottom.FillZero = (bool)cbFillZero.IsChecked;
 34         }
 35 
 36         private void tb_SelectionChange(object sender, RoutedEventArgs e)
 37         {
 38             SystemState state=((ToolBar)sender).ToolState;
 39             if ((bool)cbAllCtrl.IsChecked)
 40             {
 41                 btxtTop.State = state;
 42                 btxtMid.State = state;
 43                 btxtBottom.State = state;
 44             }
 45             else
 46             {
 47                 ((BitTextBox)((ToolBar)sender).Tag).State = state;
 48             }
 49         }
 50 
 51         private void SHL_Click(object sender, RoutedEventArgs e)
 52         {
 53             BitTextBox btxt = (BitTextBox)((Button)sender).Tag;
 54             btxt.Value = btxt.Value << 1;
 55         }
 56 
 57         private void SHR_Click(object sender, RoutedEventArgs e)
 58         {
 59             BitTextBox btxt = (BitTextBox)((Button)sender).Tag;
 60             btxt.Value = btxt.Value >> 1;
 61         }
 62 
 63         private void NOT_Click(object sender, RoutedEventArgs e)
 64         {
 65             BitTextBox btxt = (BitTextBox)((Button)sender).Tag;
 66             btxt.Value = ~btxt.Value;
 67         }
 68 
 69         private void btnAnd_Click(object sender, RoutedEventArgs e)
 70         {
 71             btxtBottom.Value = btxtTop.Value & btxtMid.Value;
 72         }
 73 
 74         private void btnOr_Click(object sender, RoutedEventArgs e)
 75         {
 76             btxtBottom.Value = btxtTop.Value | btxtMid.Value;
 77         }
 78 
 79         private void btnXor_Click(object sender, RoutedEventArgs e)
 80         {
 81             btxtBottom.Value = btxtTop.Value ^ btxtMid.Value;
 82         }
 83 
 84         private void btnMod_Click(object sender, RoutedEventArgs e)
 85         {
 86             btxtBottom.Value = btxtTop.Value % btxtMid.Value;
 87         }
 88 
 89         private void btnClear_Click(object sender, RoutedEventArgs e)
 90         {
 91             btxtTop.Clear();
 92             btxtMid.Clear();
 93             btxtBottom.Clear();
 94         }
 95 
 96         private void cbAllCtrl_Click(object sender, RoutedEventArgs e)
 97         {
 98             if ((bool)cbAllCtrl.IsChecked)
 99             {
100                 tbTop.Visibility = Visibility.Collapsed;
101                 btxtTop.State = tbMid.ToolState;
102                 tbBottom.Visibility = Visibility.Collapsed;
103                 btxtBottom.State = tbMid.ToolState;
104             }
105             else
106             {
107                 tbTop.Visibility = Visibility.Visible;
108                 tbTop.ToolState = btxtTop.State;
109                 tbBottom.Visibility = Visibility.Visible;
110                 tbBottom.ToolState = btxtBottom.State;
111             }
112         }
113     }
114 }
      界面上的按钮虽然很多,但很多按钮的事件是共用的,使用按钮的Tag属性来存放所控制的按钮,这样点击相应按钮时,只需通过Tag属性找到所控制的编辑框即可。
      位运算器完成后,我马上把成果用在了其他地方,在之前做的Hashtable动态演示程序中加入了位运算编辑框,这样在选中一个结点时,可以通过这个编辑框查看结点哈希码的不同进制的数字。
      演示地址:http://www.cnblogs.com/abatei/archive/2009/06/23/1509790.html

 

posted @ 2009-11-27 13:00  abatei  阅读(2327)  评论(1编辑  收藏  举报