简体   繁体   中英

Is in C# WPF apps a possibility to do something as long as a button is pressed?

I'm pretty new to C# and WPF, so please forgive me if my question maybe stupid. I come from the C++ world

I have an application that has a button, as long as I press the button I want to record a sounde from the microphone and when I release the button then the recording should stop. Just like the voice message in WhatsApps. I added the events PreviewMouseDown="ButtonLiveDown" and PreviewMouseUp="ButtonLiveUp" to my button and I can see that they are fired:

My main class:

    m_MyLive = new AudioLive();
    m_MyLive.Init(this);

     private void ButtonLiveDown(object sender, MouseButtonEventArgs e)
    {

        m_MyLive.StartLive();

    }

    private void ButtonLiveUp(object sender, MouseButtonEventArgs e)
    {

        m_MyLive.EndLive();
    }

and my Live Class:

class AudioLive
{
    private MainWindow m_mainWindow;

    private WaveIn m_Recorder;
    private BufferedWaveProvider m_BufferedWaveProvider;
    private SavingWaveProvider m_SavingWaveProvider;
    private WaveOut m_Player;


    public void Dispose()
    {
        Dispose(true);

    }


    protected virtual void Dispose(bool disposing)
    {
        if (m_Recorder != null)
        {
            m_Recorder.Dispose();
        }


        m_Recorder = null;

        if (m_SavingWaveProvider != null)
        {
            m_SavingWaveProvider.Dispose();
        }


        m_SavingWaveProvider = null;

    }

    private void RecorderOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
    {
        m_BufferedWaveProvider.AddSamples(waveInEventArgs.Buffer, 0, waveInEventArgs.BytesRecorded);
    }


    public bool Init(MainWindow mainWindow)
    {
        m_mainWindow = mainWindow;

        m_Recorder = new WaveIn();
        m_Recorder.DataAvailable += RecorderOnDataAvailable;

        // set up our signal chain
        m_BufferedWaveProvider = new BufferedWaveProvider(m_Recorder.WaveFormat);
        m_SavingWaveProvider = new SavingWaveProvider(m_BufferedWaveProvider, "live.wav");

        // set up playback
        m_Player = new WaveOut();
        m_Player.Init(m_SavingWaveProvider);



        return true;
    }


    public void SetMicVolume(int nVol)
    {

        ....
    }



    public void StartLive()
    {



        SetMicVolume(100);

        // begin playback & record
        m_Player.Play();
        m_Recorder.StartRecording();


    }

    public void EndLive()
    {


        // stop recording
        m_Recorder.StopRecording();
        // stop playback
        m_Player.Stop();

    }
}

But this doesn't work, as long as I press the button down it seems that it stops working till I release the button. From C++ I know this, as long as I press the button the system is busy with the pressed Event and can't continue to work. Is it the same with C# & WPF? If yes, is there any other way to handle my feature wish?

If I understand your question, then yes, you will have to deal with UI blocking in this case. Use a background worker to kick the event on mouse down and background worker cancellation on mouse up. Example below shows with mouseup and mouse down event handelers as oppossed to the previewmouse up and down

Updated Example to help with understanding

XAML BUTTON:

        <Button x:Name="RecordBtn" Content="Button" HorizontalAlignment="Left" Margin="363,199,0,0" VerticalAlignment="Top" Width="75" MouseDown="Button_MouseDown" MouseUp="Button_MouseUp"/>

xaml code behind showing background worker kicking and holding the process:

public partial class MainWindow : Window
{
    private readonly BackgroundWorker worker = new BackgroundWorker();
    AudioLive m_MyLive = new AudioLive();
    Stopwatch stopWatch = new Stopwatch();



    public MainWindow()
    {
        InitializeComponent();
        AddHandler(FrameworkElement.MouseDownEvent, new MouseButtonEventHandler(Button_MouseDown), true);
        AddHandler(FrameworkElement.MouseUpEvent, new MouseButtonEventHandler(Button_MouseUp), true);
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.WorkerSupportsCancellation = true;
        m_MyLive.Init(this);
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {

        if (!m_MyLive.IsRecordinginProgress() && !worker.CancellationPending)
        {
            m_MyLive.StartLive();
            stopWatch.Reset();
            stopWatch.Start();
        }
        while (m_MyLive.IsRecordinginProgress() && !worker.CancellationPending)
        {

            this.Dispatcher.Invoke(() =>
            {
                updateLabel(String.Format("{0:0.#}", TimeSpan.FromMilliseconds(stopWatch.ElapsedMilliseconds).TotalSeconds) + " seconds");
            });
        }
    }

    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        m_MyLive.EndLive();
        stopWatch.Stop();
        updateLabel(String.Format("{0:0.#}", TimeSpan.FromMilliseconds(stopWatch.ElapsedMilliseconds).TotalSeconds) + " seconds");
    }

    private void updateLabel(string text)
    {
        RecordBtn.Content = text;
    }


    private void Button_MouseDown(object sender, MouseButtonEventArgs e)
    {
        worker.RunWorkerAsync();
    }

    private void Button_MouseUp(object sender, MouseButtonEventArgs e)
    {
        worker.CancelAsync();
    }

}

Updated AudioLive to add property isRecording to use in our background worker:

public class AudioLive
{
    private MainWindow m_mainWindow;

    private WaveIn m_Recorder;
    private BufferedWaveProvider m_BufferedWaveProvider;
    private SavingWaveProvider m_SavingWaveProvider;
    private WaveOut m_Player;
    private bool isRecording { get; set; }


    public bool IsRecordinginProgress()
    {
        return isRecording;
    }

    public void Dispose()
    {
        Dispose(true);

    }


    protected virtual void Dispose(bool disposing)
    {
        if (m_Recorder != null)
        {
            m_Recorder.Dispose();
        }


        m_Recorder = null;

        if (m_SavingWaveProvider != null)
        {
            m_SavingWaveProvider.Dispose();
        }


        m_SavingWaveProvider = null;

    }

    private void RecorderOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
    {
        m_BufferedWaveProvider.AddSamples(waveInEventArgs.Buffer, 0, waveInEventArgs.BytesRecorded);
    }


    public bool Init(MainWindow mainWindow)
    {
        m_mainWindow = mainWindow;

        m_Recorder = new WaveIn();
        m_Recorder.DataAvailable += RecorderOnDataAvailable;

        // set up our signal chain
        m_BufferedWaveProvider = new BufferedWaveProvider(m_Recorder.WaveFormat);
        m_SavingWaveProvider = new SavingWaveProvider(m_BufferedWaveProvider, "live.wav");

        // set up playback
        m_Player = new WaveOut();
        m_Player.Init(m_SavingWaveProvider);



        return true;
    }


    public void SetMicVolume(int nVol)
    {
    }



    public void StartLive()
    {



        SetMicVolume(100);

        // begin playback & record
        m_Player.Play();
        m_Recorder.StartRecording();
        isRecording = true;


    }

    public void EndLive()
    {


        // stop recording
        m_Recorder.StopRecording();
        // stop playback
        m_Player.Stop();
        isRecording = false;

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM