首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >读出按钮被按下的时间(串行通信C#,WPF)

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

Stack Overflow用户
提问于 2018-07-25 07:07:35
回答 1查看 42关注 0票数 0

我刚开始学习C#中的串行通信,所以这可能是一个很简单的问题,但我花了三天时间在谷歌上搜索,我的问题仍然没有解决,所以我希望你能帮助我。

我有一个设备(这是一种特殊的手风琴),上面有很多按钮。当我按下一个按钮时,获取数据是没有问题的。对于每个按钮,我会收到不同的ASCII代码。

我的问题是:我需要知道时间,我按下按钮多长时间。但我只有在按下按钮时才会获得数据(而不是在释放按钮时)。

有没有可能发现这一点?

下面你可以看到我写的程序,只是为了了解串行通信是如何工作的。

我的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();
    }

}
EN

回答 1

Stack Overflow用户

发布于 2018-07-25 09:31:56

我将要写的答案可能看起来很不可靠;然而,这是你得到的,直到有人想出一些聪明的想法。

由于您无法到达按钮释放的时刻,因此如果(且仅当)您的设备在按住按键的情况下一直发送相同的按键数据,那么就有一个技巧可以完成。

您需要定义一个时间间隔,该时间间隔对于人类按下两次键来说太小,对于机器不发送两次按键数据来说太大。在本例中,我假设您的关键代码是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;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51508756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档