C#编程之串口(补充)滚动条至底部设计

这里补充一下上一章的内容,上一章我们将发送和接收的编辑框每收到一包数据后自动回车换行,并让滚动条处于最底部位置。

我们调用了 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>
XAML
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);
            }
        }
    }
}
XAML.CS

编译运行:

对于串口的设计,我们就讲到这里,下一章我们将开始讲解多媒体的学习与设计。

End.

谢谢.

原文地址:https://www.cnblogs.com/lumao1122-Milolu/p/12021210.html