Where to declare queues in separate event handlers - c#

Hi I am trying to use the queue function in my program for a mini game that receives X,Y,Z acceleration from an accelerometer.
However I don't know where I should or how I should declare the queue to make it accessible in two separate event handler.
As you can see I tried multiple attempts and declaring it in both the private event handlers was my last attempt.
Any help is appreciated. Thanks!
Here's my current code:
public Form1()
{
InitializeComponent();
ConnectedComPortUpdate();
serialPort1.DataReceived += DataReceivedHandler;
comboBox1.DropDown += comboBox1_DropDown;
}
private void comboBox1_DropDown(object sender, EventArgs e)
{
ConnectedComPortUpdate();
}
private void Clock_Tick(object sender, EventArgs e)
{
int xAccel;
int yAccel;
int zAccel;
Queue<int> myXQueue = new Queue<int>();
Queue<int> myYQueue = new Queue<int>();
Queue<int> myZQueue = new Queue<int>();
while( myXQueue.Count!=0 && myYQueue.Count!=0 && myZQueue.Count!=0 );
{
xAccel = myXQueue.Dequeue();
yAccel = myYQueue.Dequeue();
zAccel = myZQueue.Dequeue();
this.BeginInvoke(new EventHandler(delegate
{
XAccel.Text = xAccel.ToString("000");
YAccel.Text = yAccel.ToString("000");
ZAccel.Text = zAccel.ToString("000");
}));
}
}
private void ConnectedComPortUpdate()
{
//Clears COM List
comboBox1.Items.Clear();
//Accesses System Port Information and Adds it to the ComboBox
comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames().ToArray());
//Selects the last and "first" device
try
{
comboBox1.SelectedIndex = 0;
}
catch (ArgumentOutOfRangeException)
{
MessageBox.Show("Please plug in your tiny stick");
comboBox1.Text = (" ");
}
}
private void button1_Click(object sender, EventArgs e)
{
if (!serialPort1.IsOpen)
{
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.Open();
comboBox1.Enabled = false;
butPortState.Text = "Disconnect";
MessageBox.Show(String.Format("You selected port '{0}'", serialPort1.PortName));
}
catch
{
MessageBox.Show("Please select a serial port from the drop down list");
}
}
else
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
comboBox1.Enabled = true;
butPortState.Text = "Connect";
}
}
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
int currentDataByte = 0;
int byteToRead;
int xAccel = 0;
int yAccel = 0;
int zAccel = 0;
Queue<int> myXQueue = new Queue<int>();
Queue<int> myYQueue = new Queue<int>();
Queue<int> myZQueue = new Queue<int>();
while (serialPort1.IsOpen && serialPort1.BytesToRead != 0)
{
try
{
byteToRead = serialPort1.ReadByte();
}
catch
{
byteToRead = 0;
}
if (byteToRead == 255)
{
currentDataByte = 0;
}
else
{
currentDataByte++;
switch (currentDataByte)
{
case 1:
myXQueue.Enqueue(byteToRead);
xAccel = byteToRead;
break;
case 2:
myYQueue.Enqueue(byteToRead);
yAccel = byteToRead;
break;
case 3:
myZQueue.Enqueue(byteToRead);
zAccel = byteToRead;
break;
}
}
}
}
}
}

You would need the queues to be declared at the class/instance level:
// These can now be used in all event handlers...
Queue<int> myXQueue = new Queue<int>();
Queue<int> myYQueue = new Queue<int>();
Queue<int> myZQueue = new Queue<int>();
public Form1()
{
InitializeComponent();
ConnectedComPortUpdate();
serialPort1.DataReceived += DataReceivedHandler;
comboBox1.DropDown += comboBox1_DropDown;
}
private void comboBox1_DropDown(object sender, EventArgs e)
{
ConnectedComPortUpdate();
}
private void Clock_Tick(object sender, EventArgs e)
{
int xAccel;
int yAccel;
int zAccel;

I don't think the answer to this question (or even the question itself) is C# specific necessarily. Consider the question "Where should I declare variable X" The answer is almost always "In the narrowest scope possible that's accessible every place that needs to use variable X"
In your case, the answer may be "At the class level"
Alternatively, if you were to program in a more functional style the answer may be "Reconsider the structure of the program so that X can be passed as a parameter to the functions that need it". Most C# event handler have a place where you can stick a "user state" object so that it can be passed along from event source to event handler.
The answer would be the same in C, C++, java, etc.
(Perhaps this should be a comment, but I'm afraid it's a bit long)

Related

How to use check a Button in another Button statement? c#

I am having a problem . I want to use if statement to check if a button is clicked. For Example:
public void button1_Click(object sender, EventArgs e)
{
while (1)
{
...
...
...
if (Button2 == clicked)
{
break;
}
}
}
But it's not working like this, because the ".click" can only be on the left side of "+=" or "-=". Any idea how i can check if Button2 is clicked?
the code is loking like this: and i want to check button2 to stop the "programm".
the check for the Button2 is nearly at the end of the code ;)
public void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
int EmFilterPos;
int ExFilterPos;
string String1;
int[] EmLB = new int[126];
int[] ExLB = new int[126];
int LBEmAnzahl = 0;
int LBEmTot = 0;
int LBExAnzahl = 0;
int LBExTot = 0;
UInt32 C_Zyklen;
UInt32 Zyklen;
Roche.DetectionControl2.Device_Filterwheels.ELBPowerState LB_On = Roche.DetectionControl2.Device_Filterwheels.ELBPowerState.LBOn;
Roche.DetectionControl2.Device_Filterwheels.ELBPowerState LB_Off = Roche.DetectionControl2.Device_Filterwheels.ELBPowerState.LBOff;
Roche.DetectionControl2.Device_Filterwheels.fiweGetLBResponse LightBarrier;
string Text = String.Format("Filterrad-Dauertest\r\nGestart am {0:d} um {0:t}\r\n\r\n", DateTime.Now);
System.IO.File.WriteAllText(#"TestLogFile\Filterrad_Dauertest1.txt", Text);
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweInitFilter();
System.Threading.Thread.Sleep(50);
while (Zyklen <= 20)
{
for (int q=1;q<8;q++)
{
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweMove(q,q);
System.Threading.Thread.Sleep(50);
Zyklen++;
}
for (int w=0;w<7;w++)
{
ExFilterPos = rnd.Next(1,8);
EmFilterPos = rnd.Next(1,8);
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweMove(ExFilterPos,EmFilterPos);
System.Threading.Thread.Sleep(50);
Zyklen++;
}
C_Zyklen = Zyklen;
if ((C_Zyklen % 2) < 14)
{
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweInitFilter();
System.Threading.Thread.Sleep(50);
using (System.IO.StreamWriter file = new System.IO.StreamWriter (#"TestLogFile\Filterrad_Dauertest1.txt", true))
{
file.Write("Init bei: ");
String1 = String.Format("{0,7}",Zyklen);
file.Write(String1);
file.Write(file.NewLine);
}
ExFilterPos = 60;
EmFilterPos = 60;
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweRawMove(ExFilterPos,EmFilterPos);
System.Threading.Thread.Sleep(50);
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweSetLB(LB_On);
while (EmFilterPos != -60)
{
LightBarrier = Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweGetLB();
if (LightBarrier.LBEm == Roche.DetectionControl2.Device_Filterwheels.ELBState.LBbright)
{
LBEmAnzahl++;
LBEmTot += EmFilterPos;
}
if (LightBarrier.LBEx == Roche.DetectionControl2.Device_Filterwheels.ELBState.LBbright)
{
LBExAnzahl++;
LBExTot += ExFilterPos;
}
ExFilterPos--;
EmFilterPos--;
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweRawMove(ExFilterPos,EmFilterPos);
}
EmFilterPos = LBEmTot / LBEmAnzahl;
ExFilterPos = LBExTot / LBExAnzahl;
using (System.IO.StreamWriter file = new System.IO.StreamWriter (#"TestLogFile\Filterrad_Dauertest1.txt", true))
{
file.Write("Nullstelle Mittelposition Em-Filter: ");
file.Write(EmFilterPos);
file.Write(file.NewLine);
file.Write("Nullstelle Mittelposition Ex-Filter: ");
file.Write(ExFilterPos);
file.Write(file.NewLine);
file.Write(file.NewLine);
}
Instrument.N1_DetectionControl2_1_Device_Filterwheels.fiweSetLB(LB_Off);
}
if (Button2 == clicked) // or something like this
break;
}
using (System.IO.StreamWriter file = new System.IO.StreamWriter (#"TestLogFile\Filterrad_Dauertest1.txt", true))
{
file.Write("Beendet am {0:d} um {0:t}\r\n", DateTime.Now);
}*/
}
Hm...
bool b1clicked = false, b2clicked = false;
public void button2_Click(object sender, EventArgs e)
{
b2clicked = true;
}
public void button1_Click(object sender, EventArgs e)
{
b1clicked = true;
if (b1clicked && b2clicked)
{
//...
}
}
Beside the weird behavior you want..and since you are not using Threads, you have the following options:
Local functions (.Net > 4.7)
private void B_Click(object sender, EventArgs e)
{
bool clickFlag = false;
void Click(object sender2, EventArgs e2)
{
clickFlag = true;
}
b2.Click += Click;
while (!clickFlag)
{
Thread.Sleep(1);
}
b2.Click -= Click;
//Continue with your stuff
}
Threads
Thread newThread;
private void Button1_Click()
{
newThread = new Thread(YourBreakableProcess);
newThread.Start();
}
private void Button2_Click()
{
newThread.Join();
}
private void YourBreakableProcess()
{
//Your breakable process
}
Async methods.
I hope you find a solution. Cheers.
Edit:
Since what you want is to interrupt the process of whatever you are doing, the only option you have is Local fuctions as shown above, if you are not tied to a specific framework version.
BackgroundWorker and check in every step if the button 2 was pressed with the flag thing mentioned in other answer.
Threads, and make a thread.Join when the button 2 is pressed.
Edit 2:
Updated answer with Threads, I will recommend that if you go with this option it is much better to use a BackgroundWorker instead as you will have the whole control of the process breaking it only in the place where it would be fine to break it.
You can achieve this using a flag variable. Declare and initialize flag value to false.On button2 click change flag value to true as follows,
private bool flag= false;
private void button2_Click(object sender, EventArgs e)
{
flag= true;
}
public void button1_Click(object sender, EventArgs e)
{
//Use flag to check whether button 2 has clicked or not
if (flag)
{
}
else
{
}
}

How to print my score on another Winform? [duplicate]

This question already has an answer here:
Interaction between forms — How to change a control of a form from another form?
(1 answer)
Closed 6 years ago.
On one Form, the Quiz form, I have an integer score which keeps track of the user's score. On another Form, the Game Over form, I need to print out the score of the user, but even after hours of me attempting to do so, I still can't manage to do it. I know my code could be improved by A LOT but I just need help to solve this problem and would appreciate it. I just started out on C# and I just wanted to experiment on things.
namespace Quiz_Application
{
public partial class Quiz : Form
{
static Random gen = new Random();
int[] rand = Enumerable.Range(1, 5).OrderBy(q => gen.Next()).ToArray();
int i = 0;
int score = 0;
int[] goArray = new int[1];
public void Question1()
{
questionText.Text = "What is the capital city of Spain?";
optionA.Text = "Barcelona";
optionB.Text = "Madrid";
optionC.Text = "Seville";
optionD.Text = "Zarazoga";
}
public void Question2()
{
questionText.Text = "What is the biggest island on Earth?";
optionA.Text = "Luzon";
optionB.Text = "Singapore";
optionC.Text = "Greenland";
optionD.Text = "Hawaii";
}
public void Question3()
{
questionText.Text = "What is the world's longest river?";
optionA.Text = "Nile";
optionB.Text = "Amazon";
optionC.Text = "Mississipi";
optionD.Text = "Congo";
}
public void Question4()
{
questionText.Text = "Which country is Prague in?";
optionA.Text = "Czech Republic";
optionB.Text = "Slovakia";
optionC.Text = "Austria";
optionD.Text = "Poland";
}
public void Question5()
{
questionText.Text = "What is the diameter of Earth?";
optionA.Text = "6,779km";
optionB.Text = "3,474km";
optionC.Text = "12,742km";
optionD.Text = "8,721km";
}
static void Wait(double sec)
{
Task.Delay(TimeSpan.FromSeconds(sec)).Wait();
}
public Quiz()
{
InitializeComponent();
}
private void Quiz_Load(object sender, EventArgs e)
{
}
public void label1_Click(object sender, EventArgs e)
{
scoreNum.ResetText();
score = 0;
int goScore = goArray[0];
this.Hide();
Form1 f1 = new Form1();
f1.ShowDialog();
this.Close();
}
private void optionClick(object sender, EventArgs e)
{
startButton.Enabled = false;
Button l = (Button)sender;
int[] goArray = new int[1];
goArray[0] = score;
if (l.Text == "Madrid" || l.Text == "Greenland" || l.Text == "Amazon" || l.Text == "Czech Republic" || l.Text == "12,742km")
{
score++;
scoreNum.Text = score.ToString();
correctOrWrong.Image = Resources.correct; Wait(1); correctOrWrong.Image = null;
}
else
{
correctOrWrong.Image = Resources.wrong; Wait(1); correctOrWrong.Image = null;
}
l.BackColor = System.Drawing.Color.Maroon;
optionA.Enabled = false; optionB.Enabled = false; optionC.Enabled = false; optionD.Enabled = false;
startButton.Enabled = true;
}
private void startButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
optionA.Enabled = true; optionB.Enabled = true; optionC.Enabled = true; optionD.Enabled = true;
if (i == 5)
{
scoreNum.ResetText();
score = 0;
int goScore = goArray[0];
b.Text = "Finish";
this.Hide();
Game_Over go = new Game_Over();
go.ShowDialog();
this.Close();
}
try
{
switch (rand[i])
{
case 1:
Question1();
i++;
break;
case 2:
Question2();
i++;
break;
case 3:
Question3();
i++;
break;
case 4:
Question4();
i++;
break;
case 5:
Question5();
i++;
break;
case 6:
Wait(2);
this.Hide();
Game_Over go = new Game_Over();
go.ShowDialog();
this.Close();
break;
}
if (i == 5)
{
b.Text = "Finish";
}
}
catch { }
if (i != 5)
b.Text = "Next";
b.Enabled = false;
}
private void mouseEnter(object sender, EventArgs e)
{
this.Cursor = Cursors.Hand;
}
private void mouseLeave(object sender, EventArgs e)
{
this.Cursor = Cursors.Default;
}
public int get(int i)
{
return i;
}
}
and my Game Over form
namespace Quiz_Application
{
public partial class Game_Over : Form
{
public Game_Over()
{
InitializeComponent();
}
private void Game_Over_Load(object sender, EventArgs e)
{
Quiz q = new Quiz();
}
private void playAgain_Click(object sender, EventArgs e)
{
Quiz q = new Quiz();
this.Hide();
q.ShowDialog();
this.Close();
}
private void mainMenu_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
this.Hide();
f1.ShowDialog();
this.Close();
}
}
Create a public class and store the value in it, you can access the value across the code.
class Globals
{
public static int Score = 0;
}
// In the window you can assign value for the variable like below
Globals.Score=<Your score>;
In the Game_Over form, add a label to display the score if you haven't done so already. I will call it myScoreLabel Then, when you show the form i.e. here:
case 6:
Wait(2);
this.Hide();
Game_Over go = new Game_Over();
go.ShowDialog();
this.Close();
break;
add this line before go.ShowDialog:
go.yourScoreLabel.Text = "Score: " + score.ToString();

How to capture Enter key in a ListBox control?

I read articles over the internet but I think I'm missing something here. I tried following the answer to this SO question, but nothing has happened.
I wanted to trigger the usePort_Click method whenever I press the Enter/Return key. Also, I don't know how to get around the EventArgs parameter of usePort_Click whenever I do try calling it from the ports_Keydown method.
Note: ports is a ListBox control.
private void usePort_Click(object sender, EventArgs e)
{
try
{
port = new SerialPort((string)ports.SelectedItem, 9600);
portUsedLabel.Text = (string)ports.SelectedItem;
String buffer = "";
String tellArduino = "food"; // test value
port.Open();
port.WriteLine(tellArduino);
for (int x = 0; x < tellArduino.Length; x++)
{
buffer += port.ReadLine();
}
ports.Items.Add(buffer);
port.Close();
}
catch { //stuff }
}
private void ports_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
//code here
}
}
A good solution would be to move the code you want to execute into a separate method (I called it someStuff, replace the name with something better) and call that method from both event handlers:
private void usePort_Click(object sender, EventArgs e)
{
someStuff();
}
private void ports_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
someStuff();
}
}
private void someStuff()
{
try
{
port = new SerialPort((string)ports.SelectedItem, 9600);
portUsedLabel.Text = (string)ports.SelectedItem;
String buffer = "";
String tellArduino = "food"; // test value
port.Open();
port.WriteLine(tellArduino);
for (int x = 0; x < tellArduino.Length; x++)
{
buffer += port.ReadLine();
}
ports.Items.Add(buffer);
port.Close();
}
catch { //stuff }
}

BackgroundWorker for implementing "Search as you type" Combobox

I have created a code for my combobox, that can search addresses in a very large table on Sql Server with the help of stored procedure (i'm working with Entity framework). My stored procedure returns 10 hits and my code fills the combobox with search results. For doing this I'm using BackgroundWorker.
But here I'm now having big problems:
- although the combobox is filled with my search results, it always has the first item selected. Even if I type in only a letter, the whole text gets selected;
After that searching for the address doesn't work anymore. It searches only among these 10 results and I'm having no idea how to solve this. Here is my whole code, that causes me problems:
public String searchedItem = "";
public delegate void DelegateUpdateComboboxSelection(ComboBox myCombo,string value,int count);
BackgroundWorker m_bgworker = new BackgroundWorker();
static AutoResetEvent resetWorker = new AutoResetEvent(false);
m_bgworker.WorkerSupportsCancellation = true;
m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
BindingList<spIskalnikNaslovi_Result1> m_addresses = new BindingList<SP_Result1>();
void m_bgworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int count = (int)((object[])e.Result)[0];
string value = (string)((object[])e.Result)[1];
ComboBox myCombo = (ComboBox)((object[])e.Result)[2];
DelegateUpdateComboboxSelection ndelegate = new DelegateUpdateComboboxSelection(UpdateComboSelection);
if (this.InvokeRequired)
{
Invoke(ndelegate, new object[] {myCombo, value, count});
return;
}
else
{
UpdateComboSelection(myCombo, value, count);
return;
}
}
private void UpdateComboSelection(ComboBox myCombo, String value, int count)
{
myCombo = comboBox9;
myCombo.DataSource = m_addresses;
searchedItem = myCombo.Text;
if (count > 0)
{
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
}
}
public void FillComboboxBindingList(object sender, DoWorkEventArgs e)
{
if (m_bgworker.CancellationPending)
{
resetWorker.Set();
e.Cancel = true;
return;
}
else
{
string value = (String)((Object[])e.Argument)[0];
List<SP_Result1> result;
result = _vsebina.SP_searcher(value).ToList<SP_Result1>();
m_addresses = new BindingList<SP_Result1>();
foreach (SP_Result1 rez in result)
{
if (m_addresses.Contains(rez))
{
continue;
}
else
{
m_addresses.Add(rez);
}
}
foreach (SP_Result1 r in m_addresses.ToArray())
{
if (!result.Contains(r))
{
m_addresses.Remove(r);
}
}
e.Result = new object[] { rezultat.Count, vrednost, null };
return;
}
}
private void comboBox9_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
int searchStart = comboBox9.SelectionStart;
if (searchStart > 0)
{
searchStart--;
if (searchStart == 0)
{
comboBox9.Text = "";
}
else
{
comboBox9.Text = comboBox9.Text.Substring(0, searchStart + 1);
}
}
else
{
searchStart = 0;
}
e.Handled = true;
}
}
private void comboBox9_Enter(object sender, EventArgs e)
{
comboBox9.SelectionStart = 0;
comboBox9.SelectionLength = 0;
}
private void comboBox9_Click(object sender, EventArgs e)
{
comboBox9.Text = "";
}
private void comboBox9_KeyPress(object sender, KeyPressEventArgs e)
{
Search();
}
public void Search()
{
if (comboBox9.Text.Length < 4)
{
return;
}
else
{
if (m_bgworker.IsBusy)
{
m_bgworker.CancelAsync();
m_bgworker = new BackgroundWorker();
m_bgworker.WorkerSupportsCancellation = true;
m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
}
m_bgworker.RunWorkerAsync(new object[] { comboBox9.Text, comboBox9 });
}
}
Maybe can someone enlighten me, what I'm doing wrong. This is first time, that I'm using BackgroundWorker. I have no idea, how
to achieve "search as you type" with combobox in any other way, because my datatable with addresses is quite large (million records).
Thanks in advance for any kind of help or code example.
Vladimir
Edit 1:
Ok, here is my code, before I have used BackGroundWorker. It worked, but it searches very very slow (it can take up to 10 seconds):
private void comboBox9_TextChanged(object sender, EventArgs e)
{
if (comboBox9.Text.Length < 4)
{
return;
}
else
{
FillCombobox(comboBox9.Text, comboBox9);
}
}
public void FillCombobox(string value, ComboBox myCombo)
{
List<spIskalnikNaslovi_Result1> result;
result = _vsebina.spIskalnikNaslovi1(value).ToList();
if (result.Count() > 0)
{
myCombo.DataSource = result;
myCombo.ValueMember = "HS_MID";
myCombo.DisplayMember = "NASLOV1";
var searchedItem = myCombo.Items[0].ToString();
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
}
return;
}
Is there a way to speed this up without having backgroundworker?
make a button you will call searchbutton
and in click_event of this button call your search() method that run your backgroundworker
that fill the combobox
clear you key_press event of your combobox and it will work
the mistake is you key_press event that call every key stroke happening your search method
so retrieve it
You should get your items in a list, use that list to populate your combobox.
then set AutoCompleteMode property value to Suggest or Append or SuggestAppend and set AutoCompleteSoucre property value to ListItems.
For "Search as you Type", which is actually "Filter as you Type" more than search, you need to implement the OnKeyDown or KeyPressed event.
What you would do is take the search string, which is the current text at the time of the event, then filter the master list using that string. Normally one would use "Starts With" for the filtering, but you could also simply use "Contains". Then you live update the contents of the box with the results from the filter. This is accomplished by changing and refreshing the Datasource.
Here is my final solution without BackGroundWorker. It works quick with my large table, and is upgraded for using a stored procedure on SQL Server (if you use Entity Framework). I use Timer to make sure the user can find a value, that he is searching.
Here you can see the original solution, that I found on this site (thanks to Max Lambertini and algreat for the idea and working concept):
C# winforms combobox dynamic autocomplete
My solution:
private bool _canUpdate = true;
private bool _needUpdate = false;
List<spIskalnikNaslovi_Result1> dataFound;
private void comboBox12_TextChanged(object sender, EventArgs e)
{
if (_needUpdate)
{
if (_canUpdate)
{
_canUpdate = false;
refreshData();
}
else
{
restartTimer();
}
}
}
private void comboBox12_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
int searchStart = comboBox12.SelectionStart;
if (searchStart > 0)
{
searchStart--;
if (searchStart == 0)
{
comboBox12.Text = "";
}
else
{
comboBox12.Text = comboBox12.Text.Substring(0, searchStart + 1);
}
}
else
{
searchStart = 0;
}
e.Handled = true;
}
}
private void comboBox12_TextUpdate(object sender, EventArgs e)
{
_needUpdate = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
_canUpdate = true;
timer1.Stop();
refreshData();
}
private void refreshData()
{
if (comboBox12.Text.Length > 1)
{
FillCombobox(comboBox12.Text, comboBox12);
}
}
private void restartTimer()
{
timer1.Stop();
_canUpdate = false;
timer1.Start();
}
private void FillCombobox(string value, ComboBox myCombo)
{
dataFound = _vsebina.spIskalnikNaslovi1(value).ToList();
if (dataFound.Count() > 0)
{
myCombo.DataSource = dataFound;
myCombo.ValueMember = "HS_MID";
myCombo.DisplayMember = "NASLOV1";
var searchedItem = myCombo.Items[0].ToString();
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
return;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
return;
}
}

Mouse Click Loops using buttons (C#)

I'm a tad new to C# so please bear with me!
I am writing a program to send code via RS232 to a home made telescope mount.
The issues I have at the moment is hopefully very simple (But quite difficult for me!)
As an example say I have a button, I want to execute a loop when the left mouse button is held down, (which will be a continuous stream of 232 data), then when the left mouse button is released I need the loop to stop and to execute another line of code.
I sincerely hope that information I have given is enough and somebody is kind enough to help me along (I have searched the internet for answers believe me!)
Many thanks.
Hook into the MouseDown and MouseUp events on the button. The MouseDown event should spawn a thread, or signal to the thread to begin executing the loop. The MouseUp event should signal to the thread to stop executing the loop.
Something like this:
public class InterruptibleLoop
{
private volatile bool stopLoop;
private Thread loopThread;
public void Start() {
// If the thread is already running, do nothing.
if (loopThread != null) {
return;
}
// Reset the "stop loop" signal.
stopLoop = false;
// Create and start the new thread.
loopThread = new Thread(LoopBody);
loopThread.Start();
}
public void Stop() {
// If the thread is not running, do nothing.
if (loopThread == null) {
return;
}
// Signal to the thread that it should stop looping.
stopLoop = true;
// Wait for the thread to terminate.
loopThread.Join();
loopThread = null;
}
private void LoopBody() {
while (!stopLoop) {
// Do your work here
}
}
}
Method 1:
First create a timer with the interval set to the frequency you want it to send the data. And send the data in the tick event. Create an event for the button's mouse down event and the buttons' mouse up event. In the mouse down event, start the timer. In the mouse up event, stop the timer.
Method 2:
Instead of starting a timer on the mouse down event, start a new thread where you do a continuous loop of data sending. Stop the thread on the mouse up event.
namespace Scope_Project_Ver_2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// *** Output data timer ***
otimer.Interval = 50;
// otimer.Interval = isendFreq;
otimer.Tick += new EventHandler(otimer_Tick);
// *** Input data timer ***
// itimer.Interval = 601; <- to be unchecked
// itimer.Tick += new EventHandler(itimer_Tick); <- to be unchecked
}
public int b1,b2,b3,b4,b5;
public string sb1, sb2, sb3, sb4, sb5;
public int ivorSpeed;
public string svorSpeed;
public int ihorSpeed;
public string shorSpeed;
public int isendFreq;
private void sendDataB_Click(object sender, MouseEventArgs e)
{
if (sendDataCB.Checked)
{
sendDataCB.Checked = false;
if (otimer.Enabled)
otimer.Stop();
}
else
{
sendDataCB.Checked = true;
if (!otimer.Enabled)
otimer.Start();
}
}
void otimer_Tick(object sender, EventArgs e)
{
SerialPort port = new SerialPort(
"COM1", 9600, Parity.None, 8, StopBits.One);
port.Open();
port.Write("Q"); // Q
port.Write(sb1); // 1
port.Write(sb2); // 2
// Binary stuff // Ver Speed Binary 3
byte[] bverbinary = new byte[1];
byte verbinary = 0;
verbinary = Byte.Parse(svorSpeed);
bverbinary[0] = verbinary;
port.Write(bverbinary, 0, bverbinary.Length);
// End of Binary stuff for Ver Speed
// Binary stuff // Hor Speed Binary 4
byte[] bhorbinary = new byte[1];
byte horbinary = 0;
horbinary = Byte.Parse(shorSpeed);
bhorbinary[0] = horbinary;
port.Write(bhorbinary, 0, bhorbinary.Length);
port.Write(sb5); // Movement 5
port.Close();
}
private void vorSpeed_ValueChanged(object sender, EventArgs e)
{
// MessageBox.Show((this.vorSpeed.Value).ToString());
this.Text = "You changed the Vertical Speed to " + vorSpeed.Value;
ivorSpeed = (int)vorSpeed.Value;
svorSpeed = ivorSpeed.ToString();
}
private void horSpeed_ValueChanged(object sender, EventArgs e)
{
// MessageBox.Show((this.horSpeed.Value).ToString());
this.Text = "You changed the Horizontal Speed to " + horSpeed.Value;
ihorSpeed = (int)horSpeed.Value;
shorSpeed = ihorSpeed.ToString();
}
private void scopeUp_MouseDown(object sender, MouseEventArgs e) // Scope Up On
{
b1 = 2;
b2 = 0;
b5 = 1;
sb1 = b1.ToString();
sb2 = b2.ToString();
sb3 = b3.ToString();
sb4 = b4.ToString();
sb5 = b5.ToString();
}
private void scopeUp_MouseUp(object sender, MouseEventArgs e) // Scope Up Off
{
}
private void scopeRight_MouseDown(object sender, MouseEventArgs e)
{
b1 = 1;
b2 = 2;
b5 = 1;
sb1 = b1.ToString();
sb2 = b2.ToString();
sb3 = b3.ToString();
sb4 = b4.ToString();
sb5 = b5.ToString();
}
private void scopeRight_MouseUp(object sender, MouseEventArgs e)
{
}
private void scopeDown_MouseDown(object sender, MouseEventArgs e)
{
b1 = 2;
b2 = 1;
b5 = 1;
sb1 = b1.ToString();
sb2 = b2.ToString();
sb3 = b3.ToString();
sb4 = b4.ToString();
sb5 = b5.ToString();
}
private void scopeDown_MouseUp(object sender, MouseEventArgs e)
{
}
private void scopeLeft_MouseDown(object sender, MouseEventArgs e)
{
b1 = 0;
b2 = 2;
b5 = 1;
sb1 = b1.ToString();
sb2 = b2.ToString();
sb3 = b3.ToString();
sb4 = b4.ToString();
sb5 = b5.ToString();
}
private void scopeLeft_MouseUp(object sender, MouseEventArgs e)
{
}
private void scopeStop_Click(object sender, EventArgs e)
{
b1 = 0;
b2 = 0;
b5 = 0;
sb1 = b1.ToString();
sb2 = b2.ToString();
sb3 = b3.ToString();
sb4 = b4.ToString();
sb5 = b5.ToString();
}
private void sendFreq_ValueChanged(object sender, EventArgs e)
{
this.Text = "You changed the send Freq to " + sendFreq.Value + " m/s";
isendFreq = (int)sendFreq.Value;
}
}
}

Categories