Stop midi notes buffering in c# - c#

I have created a program in C# for my children to test them on reading music. It displays random notes at set intervals (determined by a timer) and then checks the currently displayed note against input from the keyboard to see if they got it right. It is working well, apart from the fact that if two notes are accidentally pressed at once, the second of them is taken to be the intended answer for the subsequent note, which hasn't even been displayed yet! I assume that the notes that are played on the musical keyboard are stored in a buffer and then used when next needed. I would like to be able to "wipe the slate clean" when a new note is displayed on the screen, so that any previous input is disregarded. I'd be grateful for any thoughts as to how I can do this please.
Some of the code is below:
using System;
using Midi;
using System.Media;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
// Create persistent delegates which we can add and remove to events.
noteOnHandler = new InputDevice.NoteOnHandler(this.NoteOn);
noteOffHandler = new InputDevice.NoteOffHandler(this.NoteOff);
InputDevice preferredInputDevice = InputDevice.InstalledDevices[0];
UseInputDevice(InputDevice.InstalledDevices[0]);
}
private void UseInputDevice(InputDevice newInputDevice)
{
if (newInputDevice == inputDevice)
{
return;
}
if (inputDevice != null)
{
if (inputDevice.IsOpen)
{
if (inputDevice.IsReceiving)
{
inputDevice.StopReceiving();
}
inputDevice.Close();
}
inputDevice.NoteOn -= noteOnHandler;
inputDevice.NoteOff -= noteOffHandler;
}
inputDevice = newInputDevice;
inputDevice.NoteOn += noteOnHandler;
inputDevice.NoteOff += noteOffHandler;
inputDevice.Open();
inputDevice.StartReceiving(null);
}
// Method called when the input device receives a NoteOn message. Updates
// the input status label. Respects GUI thread affinity by invoking to the
// GUI thread if necessary.
public void NoteOn(NoteOnMessage msg)
{
if (button1.Text == "STOP")
{
if (InvokeRequired)
{
BeginInvoke(noteOnHandler, msg);
return;
}
if (string.Equals(String.Format("{0}", msg.Pitch), notename)) { currentscore++; correct[numberofnotes] = true; using (SoundPlayer player = new SoundPlayer("chime_up.wav")) { player.PlaySync(); } }
else { using (SoundPlayer player = new SoundPlayer("klaxon_ahooga.wav")) { player.PlaySync(); } correct[numberofnotes] = false; }
outof++;
score.Text = String.Format("{0}", currentscore);
notesshown.Text = String.Format("{0}", outof);
numberofticks = 0;
if (outof < 20) { generate_note(); }
Redrawit();
Invalidate();
if (outof == 20) { reset_screen(); }
}
}
// Method called when the input device receives a NoteOff message. Updates
// the input status label. Respects GUI thread affinity by invoking to the
// GUI thread if necessary.
public void NoteOff(NoteOffMessage msg)
{
if (InvokeRequired)
{
BeginInvoke(noteOffHandler, msg);
return;
}
}
// Persistent delegate objects for the note handlers.
private InputDevice.NoteOnHandler noteOnHandler;
private InputDevice.NoteOffHandler noteOffHandler;
}
}

Related

Disable Text Scrolling when text is longer than the TextBox Width

I have a customTextBox1 on a Form.
customTextbox1 multiline is false and TextAlign is set to center.MaxLength is 23. And the customTextBox1 width is 92.customTextBox1 Font is set to "MS ゴシック", 12F.
When I type "12345678901234567890123" in the TextBox, the text is scrolling to the last character.Also,when I click on the text , the text is highlighted blue and I can drag to the left and right of the text.
.NetFramework 3.5
What I want is 2 things:
1)when the text is longer than TextBox width, I don't want to scroll to the last character.I want to stop scrolling at the right margin of the TextBox.
for example,
when I type "1234567890123456", I want to show "12345678901"and the rest of the overflow text should not be shown.
2)when I Click and Drag the text, I want to show "12345678901" only
And want to get rid of the blue highlighted selection too.
1)overflow text is showing
2)i can click and drag to the end of the text and beginning of the text
here is my code
CustomTextBox
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DisabledTextSelectForm
{
public partial class CustomTextBox : TextBox
{
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
public CustomTextBox()
{
InitializeComponent();
}
}
}
Form1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DisabledTextSelectForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
customTextBox1.AutoSize = true;
customTextBox1.Size = new Size(92,21);
customTextBox1.Multiline = false;
customTextBox1.TextAlign = HorizontalAlignment.Center;
customTextBox1.MaxLength = 23;
customTextBox1.Font = new Font("MS ゴシック", 12F);
}
}
}
Update1 :
I want to do this strange behavior of textBox because I am making a exact replica of an application written in other language which is not supported anymore. So we have to write it in C#. Both application will run on windows.
In the old application, there is a textBox in which user can type in ID numbers.
1)That textBox does not show overflow text.
If I type ("12345678901234567890123") ,it only show "12345678901" but if I click backspace [13]times, the text begins "1234567890". so I know the overflow text are there just not showing.
2)I can't click and drag the text right and left as in C# textBox.
I have manage to replicate No.1 behavior though.
Here is my code
CustomTextBox
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Runtime.InteropServices;
namespace DisabledTextSelectForm
{
public partial class CustomTextBox : TextBox
{
public override bool AutoSize
{
get { return base.AutoSize; }
set { base.AutoSize = value; }
}
public bool DisabledScrolling { get; set; }
int caretPos = 0;
public CustomTextBox()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
var isDigit = char.IsDigit(e.KeyChar);
var isBackSpace = e.KeyChar == (char)Keys.Back;
var diffWidth = 0;
if (Text.Length >= 2)
{
var firstChar = TextRenderer.MeasureText(Text[0].ToString(), Font);
var secondChar = TextRenderer.MeasureText(Text.Substring(0, 2).ToString(), Font);
diffWidth = secondChar.Width - firstChar.Width;
caretPos = Width / diffWidth;
}
if (caretPos != 0 && Text.Length >= caretPos && DisabledScrolling)
{
if (isDigit)
{
Text = Text.Length < MaxLength ? Text + e.KeyChar.ToString() : Text;
}
else if (isBackSpace)
{
Text = Text.Substring(0,Text.Length - 1);
}
ScrollTo(caretPos - 1);
e.Handled = true;
}
base.OnKeyPress(e);
}
private void ScrollTo(int scrollPosition)
{
if (Text.Length >= scrollPosition)
{
Select(scrollPosition, 0);
ScrollToCaret();
}
}
}
}
Form1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DisabledTextSelectForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
customTextBox1.DisabledScrolling = true;
customTextBox1.AutoSize = true;
customTextBox1.Size = new Size(92,21);
customTextBox1.Multiline = false;
customTextBox1.TextAlign = HorizontalAlignment.Center;
customTextBox1.MaxLength = 23;
customTextBox1.Font = new Font("MS ゴシック", 12F);
}
}
}
I know how to disable clicking and draging of Text in TextBox.
Add a Timer then set it Enable with 10 ms interval and in Tick event of your Timer put this code:
private void timer1_Tick(object sender, EventArgs e)
{
textBox1.SelectionLength = 0;
textBox1.SelectionStart = 0;
textBox1.ScrollToCaret();
}
In MouseMove event of your TextBox put this code:
private void textBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
textBox1.SelectionLength = 0;
textBox1.SelectionStart = 0;
textBox1.ScrollToCaret();
}
In KeyDown event of your TextBox put this code:
private void textBox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
textBox1.SelectionStart = textBox1.Text.Length;
}
Add this code in initialize block
public Form1()
{
InitializeComponent();
textBox1.HideSelection = true;
}

How can i count the number of keypress in the background in C#

I am using C# and .NET 4 to make a little program for my friend. I am a bengineer in coding.
I want to count the number of pressing X and Y on the keyboard. I managed to make it running in the background, but i have problem with counting. I tried searching for functions that may help me, but i didn't find anyting.
The program now running and if X or Y is pressed down, the counter just spinning.
Here's what i have:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Windows.Input;
namespace gombszamlalo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
bool fut = true;
private void Form1_Load(object sender, EventArgs e)
{
Thread TH = new Thread(billentyuzet);
CheckForIllegalCrossThreadCalls = false;
TH.SetApartmentState(ApartmentState.STA);
TH.Start();
}
public int x = 0;
public int y = 0;
void billentyuzet()
{
while (fut)
{
if ((Keyboard.GetKeyStates(Key.X) & KeyStates.Down) > 0)
{
x++;
label4.Text = x.ToString();
}
if ((Keyboard.GetKeyStates(Key.Y) & KeyStates.Down) > 0)
{
y++;
label5.Text = y.ToString();
}
if ((Keyboard.GetKeyStates(Key.F6) & KeyStates.Down) > 0)
{
fut = false;
}
}
}
I would be very happy, if somebody can help me to fix this code. Thank you very much!
Try this Global Mouse and Keyboard Library
I believe it contains all you need.
For counting Keypresses on Background you need Keyboard Hook. Have a look at these link:
https://www.codeproject.com/Articles/19004/A-Simple-C-Global-Low-Level-Keyboard-Hook
C# : Keyboard Hook

EventHandler is always null in C#

I'm writing a scheduler as a request for an exercise, so I can not use the windows's one.
The structure of my scheduler is almost complete, they're missing only a few secondary details.
As a request I need to use a main thread to control if there are tasks programmed in the time of execution, and if so, I have to start a secondary thread to execute the process. One of the requests is to use a limited number of threads, so I have a variable that counts the actual number of threads in execution. I want to use an event to signal to the main thread when a secondary thread is finished. I've searched a lot, here and in many other sites. Practically every site suggests the solution I've implemented, but in my case the EventHandler i've used is always null ... and I do not understand why. Could someone help me? Thanks a lot !!
Here is the code.
This is the class of the secondary thread:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace scheduler
{
public delegate void EventHandler(object sender, EventArgs e);
public class Thread_work
{
public event EventHandler ExecutionFinished;
Job job;
public Thread_work(Job j)
{
job = j;
LaunchCommandLineApp();
}
public void LaunchCommandLineApp()
{
// Use ProcessStartInfo class
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = job.process;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
var count = job.args.Count(c => c == ';');
startInfo.Arguments = "-f ";
while (count > 1)
{
startInfo.Arguments += job.args.Substring(0, job.args.IndexOf(';', 0));
job.args = job.args.Substring(job.args.IndexOf(';', 0) + 1, job.args.Length - 1);
count--;
}
if (count == 1) startInfo.Arguments += job.args.Substring(0, job.args.IndexOf(';', 0));
try
{
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
InvokeExecutionFinished(new EventArgs());
}
}
catch
{
// Log error.
}
}
protected virtual void InvokeExecutionFinished(EventArgs e)
{
if (ExecutionFinished != null)
ExecutionFinished(this, e);
}
}
}
This is the class of the scheduler:
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace scheduler
{
/// <summary>Custom TaskScheduler that processes work items in batches, where
/// each batch is processed by a ThreadPool thread, in parallel.</summary>
/// <remarks>
/// This is used as the default scheduler in several places in this solution, by,
/// for example, calling it directly in <see cref="TaskExtensions.ForEachAsync"/>,
/// or by accessing the relevant property of the static <see cref="TaskSchedulers"/>
/// class.</remarks>
public class ParallelTaskScheduler
{
public event EventHandler ExecutionFinished;
public bool stop_scheduler = false;
public int maxDegreeOfParallelism, active_thread;
public LinkedList<Job> jobs = new LinkedList<Job>();
public ParallelTaskScheduler(int maxDegreeOfParallelism)
{
if (maxDegreeOfParallelism < 1)
throw new ArgumentOutOfRangeException("maxDegreeOfParallelism");
this.maxDegreeOfParallelism = maxDegreeOfParallelism;
}
public ParallelTaskScheduler() : this(Environment.ProcessorCount) { }
public void QueueJob(Job task)
{
lock (jobs) jobs.AddLast(task);
}
private void MainThread() {
DateTime start, stop, now;
now = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, 00);
while (!stop_scheduler)
{
start = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 00);
now = now.AddMinutes(1);
stop = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 00);
foreach (Job j in jobs)
{
if (!j.mutex && j.date <= stop && j.date >= start)
{
if (active_thread < maxDegreeOfParallelism)
{
//Avvia thread esecuzione
j.mutex = true;
Thread_work th = new Thread_work(j);
th.ExecutionFinished += new EventHandler(this.th_executionFinished);
active_thread++;
//Al termine controlla se ricorrente
}
}
}
Thread.Sleep(20000);
}
}
private void th_executionFinished(object sender, EventArgs e) {
active_thread--;
}
void Connect() {
}
/// <summary>Runs the work on the ThreadPool.</summary>
/// <remarks>
/// This TaskScheduler is similar to the <see cref="LimitedConcurrencyLevelTaskScheduler"/>
/// sample implementation, until it reaches this method. At this point, rather than pulling
/// one Task at a time from the list, up to maxDegreeOfParallelism Tasks are pulled, and run
/// on a single ThreadPool thread in parallel.</remarks>
public void RunTasks()
{
active_thread = 0;
stop_scheduler = false;
Task.Factory.StartNew(MainThread);
}
public void StopTasks()
{
stop_scheduler = true;
}
}
/* [StructLayout(LayoutKind.Explicit)]
public class OverlapEvents
{
[FieldOffset(0)]
public Thread_work Source;
[FieldOffset(0)]
public ParallelTaskScheduler Target;
}*/
}
The problem is on the event ExecutionFinished in the class Thread_word, that is always null. It seems that my code is correct according to the researches I've done, but obviously is not. I have no more ideas of where the problem could be, so I hope someone can help me! Thanks!
You're calling LaunchCommandLineApp from the constructor; the EventHandler is null because you set it in the next line after new Thread_work(j), which is too late because the constructor already executed.
First, don't call in the constructor:
public Thread_work(Job j)
{
job = j;
}
Then call LaunchCommandLineApp after you set the delegate:
Thread_work th = new Thread_work(j);
th.ExecutionFinished += new EventHandler(this.th_executionFinished);
th.LaunchCommandLineApp();

Windows IoT Core reading value returned System.Threading.Tasks.Task`1[System.Single] instead of float

I am following Chris Pietschmann's Weather Station 3.0 tutorial for Raspberry Pi using the BME280 sensor at: https://www.hackster.io/23021/weather-station-v-3-0-b8b8bc.
In the MainPage he calls ReadTemperture (or any of the other registers of the sensor) to write out the returned values.
I get System.Threading.Tasks.Task`1[System.Single] in the Debug.Writeline() for all of the values... Temp, humidity, pressure and altitude.
I added a writeline inside the method and I get the correct value so I'm reading from the sensor... I just can't return it back to the mainpage and read it.
Looks like I'm missing something in the async side?
Here's the MainPage:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace IoT_BME280_Temp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
DispatcherTimer _timer;
const float seaLevelPressure = 1026.00f; //was 1022.00
BME280Sensor _bme280 = new BME280Sensor();
public MainPage()
{
this.InitializeComponent();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
await _bme280.Initialize();
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(5);
_timer.Tick += _timer_Tick;
_timer.Start();
}
private void _timer_Tick(object sender, object e)
{
try
{
var temp = _bme280.ReadTemperature();
Debug.WriteLine("Temp: {0} deg C", temp); // Results in: Temp: System.Threading.Tasks.Task`1[System.Single] deg C
var humidity = _bme280.ReadHumidity();
var pressure = _bme280.ReadPressure();
var altitude = _bme280.ReadAltitude(seaLevelPressure);
}
catch
{
Debug.WriteLine("Cannot read values from sensor...");
}
}
}
}
Here is ReadTemprature() from the BME280Sensor class:
public async Task<float> ReadTemperature()
{
//Make sure the I2C device is initialized
if (!init) await Begin();
//Read the MSB, LSB and bits 7:4 (XLSB) of the temperature from the BME280 registers
byte tmsb = ReadByte((byte)eRegisters.BME280_REGISTER_TEMPDATA_MSB);
byte tlsb = ReadByte((byte)eRegisters.BME280_REGISTER_TEMPDATA_LSB);
byte txlsb = ReadByte((byte)eRegisters.BME280_REGISTER_TEMPDATA_XLSB); // bits 7:4
//Combine the values into a 32-bit integer
Int32 t = (tmsb << 12) + (tlsb << 4) + (txlsb >> 4);
//Convert the raw value to the temperature in degC
double temp = BME280_compensate_T_double(t);
Debug.WriteLine("Temp: {0} deg C", temp); // This results in the correct temperature value...
//Return the temperature as a float value
return (float)temp;
}
Thanks in advance!
You're getting a Task because that's what ReadTemperature returns when you call it synchronously. To get the result of the task rather than the task itself, you need to call the method using await and change _timer_Tick to be async as well:
private async void _timer_Tick(object sender, object e)
{
try
{
var temp = await _bme280.ReadTemperature();
Debug.WriteLine("Temp: {0} deg C", temp);
var humidity = _bme280.ReadHumidity();
var pressure = _bme280.ReadPressure();
var altitude = _bme280.ReadAltitude(seaLevelPressure);
}
catch
{
Debug.WriteLine("Cannot read values from sensor...");
}
}

C# ColorLine not showing up in TChart

I currently have an TChart where I want to introduce a draggable horizontal line which changes the color of the points below the line. I have chosen to use ColorLine for this purpose but the line does not appear in the TChart. Am I using the right TChart tool for the job or am I missing something?
Below is the stripped down version of my current code.
public class testClass
{
private ColorLine line;
private double lineYVal = 5;
private TChart savedChart;
public testClass()
{
line = new Colorline();
line.AllowDrag = true;
line.Pen.Color = Color.Red;
line.EndDragLine += lineDragHandler;
}
public void foo(TChart chart) //chart is prepopulated with datapoints from 0->10
{
savedChart = chart;
//existing code which assigns colors
chart.Series[0].ColorRange(chart.Series[0].YValues, double.MinValue, lineYVal, Color.Red);
chart.Series[0].ColorRange(chart.Series[0].YValues, lineYVal, double.MaxValue, Color.Blue);
//my attempt to add a line
chart.Tools.Add(line);
line.Active = true;
line.Axis = chart.Axes.Left;
line.Value = lineYVal;
}
private void lineDragHandler(object sender)
{
lineYVal = line.Value;
savedChart.Tools.Clear(); //remove existing line from chart
foo(savedChart); //redo colors and re-add line
}
}
Code below works fine for me here. If your problem persists please send a Short, Self Contained, Correct (Compilable), Example project to reproduce the problem here. You can post your files at www.steema.net/upload.
using Steema.TeeChart;
using Steema.TeeChart.Styles;
using Steema.TeeChart.Tools;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializeChart();
}
private void InitializeChart()
{
testClass();
//existing code which assigns colors
tChart1.Series.Add(new Steema.TeeChart.Styles.Bar()).FillSampleValues();
tChart1.Series[0].ColorRange(tChart1.Series[0].YValues, double.MinValue, lineYVal, Color.Red);
tChart1.Series[0].ColorRange(tChart1.Series[0].YValues, lineYVal, double.MaxValue, Color.Blue);
//my attempt to add a line
tChart1.Tools.Add(line);
line.Active = true;
line.Axis = tChart1.Axes.Left;
line.Value = lineYVal;
}
private ColorLine line;
private double lineYVal = 5;
private TChart savedChart;
public void testClass()
{
line = new ColorLine();
line.AllowDrag = true;
line.Pen.Color = Color.Red;
line.EndDragLine += lineDragHandler;
}
public void foo(TChart chart) //chart is prepopulated with datapoints from 0->10
{
savedChart = chart;
//existing code which assigns colors
chart.Series[0].ColorRange(chart.Series[0].YValues, double.MinValue, lineYVal, Color.Red);
chart.Series[0].ColorRange(chart.Series[0].YValues, lineYVal, double.MaxValue, Color.Blue);
//my attempt to add a line
chart.Tools.Add(line);
line.Active = true;
line.Axis = chart.Axes.Left;
line.Value = lineYVal;
}
private void lineDragHandler(object sender)
{
lineYVal = line.Value;
if (savedChart != null)
{
savedChart.Tools.Clear(); //remove existing line from chart
foo(savedChart); //redo colors and re-add line
}
else
{
foo(tChart1);
}
}
}
}
It turns out that while the line was being added correctly, the code I was using to display the chart was not updating the chart properly and was displaying a version of the chart from before it was passed into my highlight function.

Categories