读出按下按钮的时间(串行通信C#,WPF)?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (99)

我写的程序,只是为了获得一个overviwev如何串行通信工作。

我的Commport课程:

class MyCommPort : INotifyPropertyChanged
{
    //Implementierung von "INotifyPropertyChanged"
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }


    //Felder
    private SerialPort _serialPort = null;
    private SolidColorBrush fillColor1 = Brushes.LightBlue;
    private SolidColorBrush fillColor2 = Brushes.LightBlue;
    private string text = null;


    //Eigenschaften
    public SerialPort SerialPort
    {
        get { return _serialPort; }
        set { _serialPort = value; }
    }

    public SolidColorBrush FillColor1
    {
        get { return fillColor1; }
        set
        {
            fillColor1 = value;
            OnPropertyChanged("FillColor1");
        }
    }

    public SolidColorBrush FillColor2
    {
        get { return fillColor2; }
        set
        {
            fillColor2 = value;
            OnPropertyChanged("FillColor2");
        }
    }

    public string Text
    {
        get { return text; }
        set
        {
            text = value;
            OnPropertyChanged("Text");
        }
    }

    //Konstruktor
    public MyCommPort()
    {
        //Neuer Port wird angelegt
        SerialPort = new SerialPort("COM3", 115200);

        //Port wird geöffnet
        SerialPort.Open();
        //Wenn Daten am Port ankommen wird Event gefeuert
        SerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
    }

    //Destruktor
    ~MyCommPort()
    {
        //Port wird geschlossen
        SerialPort.Close();
    }


    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        Thread.Sleep(10);
        //Neuer Port (Kopie von serialPort) wird angelegt ==> sender ist serialPort!
        SerialPort sp = (SerialPort)sender;

        //string DataIN = null;
        string DataIN = sp.ReadExisting();

        switch (DataIN)
        {
            case "(D07084)":
                FillColor1 = Brushes.Red;
                break;

            case "(D04081)":
                FillColor2 = Brushes.Red;
                break;

            default:                   
                break;
        }

        Text = DataIN;
        DataIN = null;

        Thread.Sleep(200);

        FillColor1 = Brushes.LightBlue;
        FillColor2 = Brushes.LightBlue;

    }
} 

我的看法:

    <Window x:Class="USB.MainWindow"
    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:local="clr-namespace:USB"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Grid Grid.Column="0">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Ellipse Grid.Row="0" Fill="{Binding Path=FillColor1}" />
        <Ellipse Grid.Row="1" Fill="{Binding Path=FillColor2}" />
    </Grid>

    <TextBox Grid.Column="1" Text="{Binding Text}" Height="50" Width="200"/>
</Grid>

视图的代码隐藏:

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MyCommPort();
    }

}
提问于
用户回答回答于

你需要定义一个间隔,该间隔对于人来说太小而无法按两次键,而对于机器来说太大而不能两次发送按下的键数据。在这个例子中,我假设你的密钥代码是int,我会将预定义的间隔视为75(毫秒)。

    private delegate void SerialPortKeyUpHandler(int keyCode, TimeSpan timeHeld);
    private event SerialPortKeyUpHandler SerialPortKeyUp;
    CancellationTokenSource cancellationTokenSource;
    private int keyCode;
    private const int accuracy = 75; //the interval I'm talking about

    private void StartCapturing(int keyCode)
    {
        this.keyCode = keyCode;
        DateTime start = DateTime.UtcNow;
        cancellationTokenSource.CancelAfter(accuracy);
        ParameterizedThreadStart threadStart = new ParameterizedThreadStart((object cancellationTokenObj) =>
        {
            CancellationToken cancellationToken = (CancellationToken)cancellationTokenObj;
            while (!cancellationToken.IsCancellationRequested) ; //wait until we make sure no more of the same key data is being sent
            SerialPortKeyUp?.Invoke(keyCode, DateTime.UtcNow.Subtract(start));
        });
        Thread thread = new Thread(threadStart);
        thread.Start(cancellationTokenSource.Token);
    }

    private void KeyDownCallback(object sender, KeyEventArgs e)
    {
        if (cancellationTokenSource == null || cancellationTokenSource.IsCancellationRequested)
        {
            cancellationTokenSource = new CancellationTokenSource();
            StartCapturing(e.KeyValue);
        }
        else
        {
            if (e.KeyValue == keyCode)
            {
                cancellationTokenSource.CancelAfter(accuracy);
            }
            else
            {
                cancellationTokenSource.Cancel();
                cancellationTokenSource.Dispose();
                cancellationTokenSource = new CancellationTokenSource();
                StartCapturing(e.KeyValue);
            }
        }
    }
    private void KeyUpCallback(int keyCode, TimeSpan heldTime)
    {
        Debug.WriteLine($"Key {keyCode} is up. The key was held for {heldTime.TotalSeconds.ToString("#.00")} second(s).");
    }

现在你有一个SerialPortKeyUp要注册的活动; 要这样做,请在某处输入

 SerialPortKeyUp += KeyUpCallback;

扫码关注云+社区

领取腾讯云代金券