这里补充一下上一章的内容,上一章我们将发送和接收的编辑框每收到一包数据后自动回车换行,并让滚动条处于最底部位置。
我们调用了 TextBoxBase.ScrollToEnd(); 方法类来实现。
但是我们很容易就会发现,当焦点处于编辑框时,这个功能就会失常了。为了解决这个问题,我们可以用强行聚焦的方式解决这个问题:
1 m_textBox1.ScrollToEnd(); 2 m_textBox2.ScrollToEnd(); 3 if (myBtn.IsFocused != true) 4 { 5 myBtn.Focus(); 6 }
将焦点实时处于按键聚焦状态。
那么出现这个问题的原因是什么呢? 其实是当我选择textbox控件后,该控件处于聚焦状态,而每次写入数据后,其光标都要返回到起始位置处,这就导致了当执行 ScrollToEnd(); 操作后,滚动条立马又回到了起始位置。
那么知道这个原因之后,我们就不难解决这个问题了,我们只需在执行 ScrollToEnd 之后,将光标设置到文字的末尾,即可解决 这问题了。
m_textBox1.ScrollToEnd(); m_textBox2.ScrollToEnd(); if (m_textBox1.IsFocused == true) { m_textBox1.SelectionStart = m_textBox1.Text.Length; } else if(m_textBox2.IsFocused==true) { m_textBox2.SelectionStart = m_textBox2.Text.Length; }
首先判断是否聚焦,如果编辑框聚焦,那么将光标设置到文本末尾。
最后我们重新整理一下,当串口开启时,禁止重配端口号和波特率。当串口关闭时,允许配置串口端口号和波特率,完整代码如下:
<Window x:Class="SearilPort.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Background="LightSkyBlue"> <Window.Resources> <!--define glass gradient stop resource--> <GradientStopCollection x:Key="myGradientStopResource"> <GradientStop Color="WhiteSmoke" Offset="0.2"/> <GradientStop Color="Transparent" Offset="0.4"/> <GradientStop Color="WhiteSmoke" Offset="0.5"/> <GradientStop Color="Transparent" Offset=" 0.75"/> <GradientStop Color="WhiteSmoke" Offset="0.9"/> <GradientStop Color="Transparent" Offset=" 1.0"/> </GradientStopCollection> <!--define gradient brush resource--> <LinearGradientBrush x:Key="myGlassBrushResource" StartPoint="0,0" EndPoint=" 1,1" Opacity="0.75" GradientStops="{StaticResource myGradientStopResource }"/> <!--background brush resource--> <LinearGradientBrush x:Key="grayBlueGradientBrush" StartPoint=" 0,0" EndPoint="1,1"> <GradientStop Color="Gray" Offset="0"/> <GradientStop Color="Cyan" Offset="0.5"/> <GradientStop Color="Gold" Offset="1.0"/> </LinearGradientBrush> <!--define button options--> <Style TargetType="Button"> <!--define button background--> <Setter Property="Background" Value="{StaticResource grayBlueGradientBrush}"/> <!--define button template--> <Setter Property="Template"> <Setter.Value> <!--target type is button--> <ControlTemplate TargetType="{x:Type Button}"> <Grid Margin="-1,0,-10,1"> <!--outline rectangle--> <Rectangle x:Name="outerRectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="{TemplateBinding Background}" RadiusX="10" RadiusY="10" StrokeThickness="5" Fill="Transparent"/> <!--inner rectangle--> <Rectangle x:Name="innerRectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Stroke="Transparent" StrokeThickness="5" Fill="{TemplateBinding Background}" RadiusX="10" RadiusY="10"/> <!--glass rectangle--> <Rectangle x:Name="glassCube" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" StrokeThickness="1" RadiusX="5" RadiusY="5" Opacity="0" Fill="{StaticResource myGlassBrushResource}" RenderTransformOrigin="0.5,0.5"> <!--rectangle stroke--> <Rectangle.Stroke> <LinearGradientBrush StartPoint=" 0.5,0" EndPoint="0.5,1"> <LinearGradientBrush.GradientStops> <GradientStop Color="LightBlue" Offset="0.0"/> <GradientStop Color="Gray" Offset="1.0"/> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Rectangle.Stroke> <!--glass rectangle render transform--> <Rectangle.RenderTransform> <TransformGroup> <!--To stretch or contact horizontally or vertially--> <ScaleTransform/> <!--rotate transform by angles--> <RotateTransform/> </TransformGroup> </Rectangle.RenderTransform> </Rectangle> <!--dock panel--> <DockPanel Name="myContentPresenterDockPanel"> <ContentPresenter x:Name="myContentPresent" HorizontalAlignment="Center" Margin="0,20" Content="{TemplateBinding Content}" TextBlock.Foreground="Black" TextBlock.FontWeight="Bold"/> </DockPanel> </Grid> <!--control template--> <ControlTemplate.Triggers> <!--mouse over trigger--> <Trigger Property="IsMouseOver" Value="True"> <!--rectangle stroke--> <Setter Property="Rectangle.Stroke" TargetName="outerRectangle" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube"/> </Trigger> <!--Mouse focused trigger--> <Trigger Property="IsFocused" Value="True"> <Setter Property="Rectangle.Stroke" TargetName="innerRectangle" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/> <Setter Property="Rectangle.Opacity" Value="1" TargetName="glassCube"/> </Trigger> <!--Event trigger mouse enter--> <EventTrigger RoutedEvent="Mouse.MouseEnter"> <!--actions--> <EventTrigger.Actions> <!--begin story board--> <BeginStoryboard Name="mouseEnterBeginStoryboard"> <Storyboard> <!--animation--> <DoubleAnimation Storyboard.TargetName="glassCube" Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" By="-0.2" Duration="0:0:0.5" /> <DoubleAnimation Storyboard.TargetName="glassCube" Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" By="-0.2" Duration="0:0:0.5" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> <!--event trigger mouse leave--> <EventTrigger RoutedEvent="Mouse.MouseLeave"> <EventTrigger.Actions> <StopStoryboard BeginStoryboardName="mouseEnterBeginStoryboard"/> </EventTrigger.Actions> </EventTrigger> <!--event trigger button click--> <EventTrigger RoutedEvent="Button.Click"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="glassCube" Storyboard.TargetProperty= "(Rectangle.RenderTransform).(TransformGroup.Children)[1].(RotateTransform.Angle)" By="360" Duration="0:0:0.5"/> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="Label"> <Setter Property="FontWeight" Value="Bold"/> </Style> <Style TargetType="TextBox"> <Setter Property="Background" Value="LightCyan"/> </Style> </Window.Resources> <Grid Margin="0,-2,0,2"> <TextBox HorizontalAlignment="Left" VerticalAlignment="Top" VerticalScrollBarVisibility="Auto" Width="324" Height="119" Name="m_textBox1" Margin="10,40,0,0" IsReadOnly="True" /> <TextBox Name="m_textBox2" HorizontalAlignment="Left" VerticalScrollBarVisibility="Auto" Height="106" Margin="10,195,0,0" VerticalAlignment="Top" Width="324" IsReadOnly="True"/> <ComboBox Name="myCOM" Margin="0,58,38,0" VerticalAlignment="Top" HorizontalAlignment="Right" Background="LightBlue" Width="90" Height="22"/> <ComboBox Name="myBaudRate" Margin="0,116,38,0" VerticalAlignment="Top" HorizontalAlignment="Right" Background="LightBlue" Width="90" Height="22"/> <Label Name="m_Com" Content="COM" HorizontalAlignment="Left" Margin="389,27,0,0" VerticalAlignment="Top" Width="62"/> <Label Name="m_Baud" Content="BaudRate" HorizontalAlignment="Left" Margin="389,85,0,0" VerticalAlignment="Top"/> <Label Name="m_DateReceived" Content="Received Data" HorizontalAlignment="Left" Margin="15,10,0,0" VerticalAlignment="Top" Width="97"/> <Label Name="m_DataSend" Content="Transmit Data" HorizontalAlignment="Left" Margin="15,164,0,0" VerticalAlignment="Top" Width="97"/> <Button Content="Clear" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="51" Margin="0,0,24,40" Click="Btn2_Click" Height="58"/> <Button Content="Open" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="51" Margin="0,0,98,40" Click="Btn1_Click" Name="myBtn" RenderTransformOrigin="0.5,0.5" Height="57"/> </Grid> </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.IO.Ports; using System.Security.Cryptography; namespace SearilPort { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { SerialPort myPort = new SerialPort(); bool serialState; private int counter = 0; public MainWindow() { InitializeComponent(); myComboxs(); myPort.DataReceived += DataReceived; } private void myComboxs() { myCOM.Items.Add("COM0"); myCOM.Items.Add("COM1"); myCOM.Items.Add("COM2"); myCOM.Items.Add("COM3"); myCOM.Items.Add("COM4"); myCOM.SelectedIndex = myCOM.Items.IndexOf("COM1"); myBaudRate.Items.Add("2400"); myBaudRate.Items.Add("4800"); myBaudRate.Items.Add("9600"); myBaudRate.Items.Add("38400"); myBaudRate.Items.Add("115200"); myBaudRate.SelectedIndex = myBaudRate.Items.IndexOf("9600"); serialState = false; } private void Btn1_Click(object sender, RoutedEventArgs e) { try { if (serialState == false) { if(myPort.IsOpen) { myPort.Close(); } myPort.BaudRate = int.Parse(myBaudRate.Text); myPort.DataBits = 8; myPort.PortName = myCOM.Text; myPort.Open(); serialState = true; m_DateReceived.Foreground = new SolidColorBrush(Colors.Green); m_DataSend.Foreground = new SolidColorBrush(Colors.Green); m_Baud.Foreground = new SolidColorBrush(Colors.DarkGray); m_Com.Foreground = new SolidColorBrush(Colors.DarkGray); myBtn.Content = "Closed"; myCOM.IsEnabled = false; myBaudRate.IsEnabled = false; } else { if (myPort.IsOpen) { myPort.Close(); } serialState = false; //myBtn.Background = Brushes.Green; myBtn.Content = "Open"; m_DateReceived.Foreground = new SolidColorBrush(Colors.DarkGray); m_DataSend.Foreground = new SolidColorBrush(Colors.DarkGray); m_Baud.Foreground = new SolidColorBrush(Colors.Green); m_Com.Foreground = new SolidColorBrush(Colors.Green); myBaudRate.IsEnabled = true; myCOM.IsEnabled = true; } } catch(Exception ex) { MessageBox.Show(ex.Message); } } private void Btn2_Click(object sender, RoutedEventArgs e) { m_textBox1.Text = ""; m_textBox2.Text = ""; } private void DataReceived(object sender,SerialDataReceivedEventArgs e) { try { byte[] inbuf = new byte[8]; byte[] output = new byte[16]; myPort.Read(inbuf, 0, inbuf.Length); string str = System.Text.Encoding.Default.GetString(inbuf); this.Dispatcher.Invoke(new Action(() => { m_textBox1.Text += (++counter).ToString()+"Pcs: "; foreach (byte i in inbuf) { m_textBox1.Text += i.ToString("X2"); } m_textBox1.Text += " "; using (var aes = new RijndaelManaged()) { aes.Key = new byte[] { 0x1F, 0x54, 0x52, 0x6A, 0x73, 0x93, 0x58, 0x9E, 0x4B, 0xCF, 0xFB, 0xAE, 0xFC, 0x97, 0x59, 0x3E }; aes.IV = new byte[16]; aes.Padding = PaddingMode.None; for (int i = 0; i < 8; i++) { output[i] = inbuf[i]; } for (byte i = 8; i < 16; i++) { output[i] = (byte)(output[i - 8] ^ output[i - 4]); } var cryptoTransform = aes.CreateEncryptor(); byte[] resultBuffer = cryptoTransform.TransformFinalBlock(output, 0, output.Length); m_textBox2.Text += counter.ToString() + "ID= "; foreach (byte i in resultBuffer) { m_textBox2.Text += i.ToString("X2"); } m_textBox2.Text += " "; } myPort.Write(output,0,output.Length); m_textBox1.ScrollToEnd(); m_textBox2.ScrollToEnd(); if (m_textBox1.IsFocused == true) { m_textBox1.SelectionStart = m_textBox1.Text.Length; } else if(m_textBox2.IsFocused==true) { m_textBox2.SelectionStart = m_textBox2.Text.Length; } /// if (myBtn.IsFocused != true) /// { ///myBtn.Focus(); /// } })); } catch(Exception ex) { MessageBox.Show(ex.Message); } } } }
编译运行:
对于串口的设计,我们就讲到这里,下一章我们将开始讲解多媒体的学习与设计。
End.
谢谢.