How can i make a subroutine click a picture box? - vb.net

I have the sub routine for when the picture box is clicked.
Public Sub PictureBox5_Click(sender As Object, e As EventArgs) Handles PictureBox5.Click
If player = "p1" Then
PictureBox5.BackgroundImage = My.Resources.cross
pic5 = 1
End If
If player = "p2" Then
PictureBox5.BackgroundImage = My.Resources.nought
pic5 = 2
End If
blnFlag = True
PictureBox5.Update()
End Sub
I want to create a subroutine that clicks the picture box to change the image to a nought.
Does anyone have any idea on how i would go about doing this.

There are a couple ways you can accomplish this:
Call the click event PictureBox5_Click() inside a sub:
Private Sub AnotherClick_Click(sender as Object, e as EventArgs) handles AnotherClick.Click
~Do Stuff
PictureBox5_Click(sender, e)
End Sub
Use PerformClick():
Me.PictureBox5.PerformClick()
Edit: I updated option 1 to include the full click event sub. Should add that this is not really an "acceptable" way of writing code, you shouldn't call these event handlers directly, but rather put your logic in another sub/function and call it from there whenever you need. However, if there is some reason you need to specifically call this event handler, option 1 is the way to go.

Private Sub SetPicture(PicBox as PictureBox)\
If player = "p1" Then
PicBox.BackgroundImage = My.Resources.cross
pic5 = 1
End If
If player = "p2" Then
PickBox.BackgroundImage = My.Resources.nought
pic5 = 2
End If
blnFlag = True
PicBox.Update()
End Sub
Public Sub PictureBox5_Click(sender As Object, e As EventArgs) Handles PictureBox5.Click
SetPicture(PictureBox5)
End Sub
That's how it should be done... now you can also call SetPicture from anywhere else, passing in any other picture box you want...

Related

Infinite loop is causing the form to not show up vb

I have an infinite loop in this sub because I want the program to keep testing this process to see if the variable has changed. When I run the program in the debugger, nothing shows up, including the form however when I removed the infinite loop from the program, the form showed up again. Does anyone know why this is happening? I should also mention I've tried a DO LOOP as well. Can anyone help?
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim greenCount As Integer
Dim looptest As Boolean = True
While looptest = True
For Each control In Me.Controls.OfType(Of Button)
If control.BackColor = Color.Lime Then
greenCount += 1
End If
Next
txtFielder.Text = greenCount.ToString
End While
End Sub
You need to get rid of all that code regardless. Depending on how you're changing the BackColor of those Buttons in the first place, updating the lime count might be best done there. Otherwise, you should be handling the appropriate event, e.g.
Private limeButtonCount As Integer = 0
Private Sub Buttons_BackColorChanged(sender As Object, e As EventArgs) Handles Button3.BackColorChanged,
Button2.BackColorChanged,
Button1.BackColorChanged
If DirectCast(sender, Button).BackColor = Color.Lime Then
limeButtonCount += 1
Else
limeButtonCount -= 1
End If
TextBox1.Text = limeButtonCount.ToString()
End Sub
Note that this code assumes that there are only two possible BackColor values and that all Buttons are not lime by default. If your scenario is a bit more complex than that then you may need to change a code a little, e.g.
Private limeButtonCount As Integer = 0
Private Sub Buttons_BackColorChanged(sender As Object, e As EventArgs) Handles Button3.BackColorChanged,
Button2.BackColorChanged,
Button1.BackColorChanged
limeButtonCount = Controls.OfType(Of Button)().Count(Function(b) b.BackColor = Color.Lime)
TextBox1.Text = limeButtonCount.ToString()
End Sub
Form.Load occurs before a form is displayed for the first time.
This means that you'll never see your form as long as you loop in this event. You probably want to use the Shown event instead.

Visual Basic web application call function from multiple objects

I have a Visual Basic web application where I will have a 5x5 grid displayed on the web page. Each grid box will contain a button. I want to be able to access the button attributes when any button is clicked. I would assume I would create a private function to handle each button click (I would create 25 functions), but I want each private function to call a public function which will receive the object and the grid coordinates.
My buttons on the web pages are called btn_column1_row1, btn_column2_row1, btn_column3_row1, btn_column4_row1, btn_column5_row1, btn_column1_row2, etc.
I want to code the private functions like this:
Private Sub btn_column1_row1_Click(sender As Object, e As EventArgs) Handles btn_column1_row1.Click
inspectButton(e,100,1,1)
End Sub
Private Sub btn_column2_row1_Click(sender as Object, e As EventArgs) Handles btn_column2_row1.Click
inspectButton(e,100,2,1)
End Sub
Private Sub btn_column5_row5_Click(sender as Object, e As EventArgs) Handles btn_column5_row5.Click
inspectButton(e,500,5,5)
End Sub
Then, the function inspectButton should look something like this:
Function inspectButton(ByVal e as EventArgs, textvalue, column, row)
Dim Question as string = Session("question")
Dim Answer as string = Session("answer")
if e.text = textvalue then
e.text = Question(column, row)
else
e.text = Answer(column, row)
end if
return
End Function
Is this the correct way to pass the button object to the inspectButton function?
Private Sub btn_Click(sender as Object, e As EventArgs) Handles btn_column1_row1.Click, btn_column1_row2.Click, btn_column3_row5.Click, btn_column5_row5.Click, btn_column5_row1.Click 'etc
inspectButton(sender)
End Sub
Function inspectButton(ByVal btn as Object)
Dim Question as string = Session("question")
Dim Answer as string = Session("answer")
if btn.Text = btn.Text then
btn.Text = Question(btn.column, btn.row)
else
btn.Text = Answer(btn.column, btn.row)
end if
return
End Function
Maybe this can be a solution... i can't understand the textvalue,column and row parameters passed...
You can handle multiple events with a single sub.

How to degrade similar tool strip button procedures to a single in VB.NET

I'm using ToolStrip and it's buttons to change GUI structure with an example code how i change GUIs with tool strip buttons. Are there any methods to use them more easy way like when clicked event of ToolStripButton handled it can call a single procedure etc.? In current case it seems i'm coding in a bad way.
For example if user click the Home button it highlights the button as selected and hides other panel elements and make visible Home's panel.
Private Sub tsbHome_Click(sender As Object, e As EventArgs) Handles tsbHome.Click
tsbHome.Checked = True
tsbTools.Checked = False
tsbReport.Checked = False
tsbAnalyze.Checked = False
'... Tool Strip Button lists continues...
pnlHome.Visible = True
pnlTools.Visible = False
pnlReport.Visible = False
pnlAnalyze.Visible = False
' ... Panel lists continues...
End Sub
if user click the Tools button it highlights the button as selected and hides other panel elements and make visible Tool's panel.
Private Sub tsbTools_Click(sender As Object, e As EventArgs) Handles tsbTools.Click
tsbHome.Checked = False
tsbTools.Checked = True
tsbReport.Checked = False
tsbAnalyze.Checked = False
'... Tool Strip Button lists continues...
pnlHome.Visible = False
pnlTools.Visible = True
pnlReport.Visible = False
pnlAnalyze.Visible = False
' ... Panel lists continues...
End Sub
There are two tricks to making this code much simpler. The first is knowing you can have more than one item in the Handles clause of an event method declaration. (You can also omit that clause, and use AddHandler to set up event handlers for a lot of controls to one method.) The other trick is knowing how to use the sender argument to determine which of the several controls connected to this method was used.
Put those together, and you get one method that will work to change to any of your views.
Private Sub NavigationMenuItem_Click(sender As Object, e As EventArgs) Handles tsbHome.Click, tsbTools.Click, tsbReport.Click, tsbAnalyzer.Click
'First Suspend Layout, to avoid extra screen re-draws
Me.SuspendLayout()
'Set your checkboxes
tsbHome.Checked = sender Is tsbHome
tsbTools.Checked = sender Is tsbTools
tsbReport.Checked = sender Is tsbReport
tsbAnalyze.Checked = sender Is tsbAnalyze
'Then De-select EVERYTHING
pnlHome.Visible = sender Is tsbHome
pnlTools.Visible = sender Is tsbTools
pnlReport.Visible = sender Is tsbReport
pnlAnalyze.Visible = sender Is tsbAnalyze
' ... lists continues...
'Finally, resume layout so all changes draw to the screen at once
Me.ResumeLayout()
End Sub
We can make this simpler if you add code to the Form Load or InitializeComponent() method to put the panels and toolstrip buttons into lists:
Private ViewButtons As List(Of ToolStripButton)
Private ViewPanels As List(Of Panel)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ViewButtons = New List(Of ToolStripButton) From {tsbHome, tsbTools, tsbReport, tsbAnalyze}
ViewPanels = New List(Of Panel) From {pnlHome, pnlTools, pnlReport, pnlAnalyze}
For Each b In ViewButtons
AddHandler b.Click, AddressOf NavigationMenuItem_Click
Next
End Sub
Private Sub NavigationMenuItem_Click(sender As Object, e As EventArgs)
Me.SuspendLayout()
For i As Integer = 0 To ViewButtons.Length - 1
Dim selected As Boolean = ViewButtons(i) Is sender
ViewButtons(i).Checked = selected
ViewPanels(i).Visible = selected
Next
Me.ResumeLayout()
End Sub

Refresh Chart Every Second

Have a question. I think it must be quite easy to implement but for some reason I can't do it. Right now the charts are updated if I click on them. I wish that they were updated every time I change a value (just like in Excel), for must be easier to implement a timer.
For some reason I can't implement it and I have already tried a few things that I have found online.
I have two charts and I want the charts to update the values every second (or the interval suitable for the program).
I am working on a Windows form and have the following VB code:
Private Sub Chart1_Click(sender As Object, e As EventArgs) Handles Chart1.MouseClick
AutoSize = False
Chart1.ChartAreas(0).AxisX.Interval = 0.05
Chart1.ChartAreas(0).AxisY.Interval = 200
With Chart1
.Series(0).Points.Clear()
.Series(1).Points.Clear()
.Series(2).Points.Clear()
End With
With Chart1
.Series(0).Points.AddXY(TOCGLong, TOSumMassValues)
.Series(1).Points.AddXY(LandCGLong, LandSumMassValues)
.Series(2).Points.AddXY(ZFWCGLong, ZFWSumMassValues)
End With
With Chart1.ChartAreas
With .Max
.AxisX.Maximum = 3.55
.AxisY.Maximum = 2300
End With
With .Min
.AxisX.Minimum = 3.15
.AxisY.Minimum = 1200
End With
End With
Chart1.Series(3).Points.Clear()
For i As Integer = 0 To 5
Chart1.Series(3).Points.AddXY(CGLimitX(i), CGLimitY(i))
Next
End Sub
Private Sub Chart3_Click(sender As Object, e As EventArgs) Handles Chart3.MouseClick
Dim FuelX() As Integer = {80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180}
Dim ISA() As Double = {27171.16, 24053.39, 21011, 18043.99, 15152.36, 12336.11, 9595.24, 6929.75, 4339.64, 1824.91, -614.44}
Dim ISA20() As Double = {25421.84, 21987.56, 18644, 15409.16, 12277.04, 9247.64, 6320.96, 3497, 775.76, -1842.76, -4358.56}
Dim ISA35() As Double = {23726.04, 19793.81, 16041, 12467.61, 9073.64, 5859.09, 2823.96, -31.75, -2708.04, -5204.91, -7522.36}
AutoSize = False
Chart3.ChartAreas(0).AxisX.Interval = 10
Chart3.ChartAreas(0).AxisY.Interval = 5000
With Chart3
.Series(0).Points.Clear()
'.Series(1).Points.Clear()
'.Series(2).Points.Clear()
End With
With Chart3
.Series(0).Points.AddXY(FuelConsuption, SDaltitude.Value)
For i As Integer = 0 To 10
.Series(1).Points.AddXY(FuelX(i), ISA(i))
.Series(2).Points.AddXY(FuelX(i), ISA20(i))
.Series(3).Points.AddXY(FuelX(i), ISA35(i))
Next
End With
With Chart3.ChartAreas
With .Max
.AxisX.Maximum = 180
.AxisY.Maximum = 23000
End With
With .Min
.AxisX.Minimum = 80
.AxisY.Minimum = 0
End With
End With
End Sub
Take the code out of the Chart1.MouseClick handler and put it in a Sub of its own with a descriptive name. Do the same for the Chart3.MouseClick handler.
In the Chart1.MouseClick handler, call that first Sub.
In the Chart3.MouseClick handler, call that second method.
For the question in the question:
I wish that they were updated everytime I change a value
In the appropriate textbox leave handlers, call the appropriate method(s), something like this:
Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave
UpdateChart1()
UpdateChart2()
End Sub
I suggest using the Leave event so that it doesn't keep changing while the user is in the middle of typing.
For the question in the title:
You should put the chart updating code in its own methods, as written above. Then you can easily call it from a timer's tick event. The essential parts of the code are like this:
Public Class Form1
Dim tim As Timer
Sub UpdateMpgChart()
' ... code here to update the chart
End Sub
Sub UpdateOtherChart()
' ... code here to update the other chart
End Sub
Sub TimerTickHandler(sender As Object, e As EventArgs)
UpdateMpgChart()
UpdateOtherChart()
End Sub
Sub InitialiseTimer()
tim = New Timer With {.Interval = 1000}
AddHandler tim.Tick, AddressOf TimerTickHandler
tim.Start()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
InitialiseTimer()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
tim.Dispose()
End If
End Sub
End Class
I wish that they were updated every time I change a value (just like in Excel), for must be easier to implement a timer.
You can use the ReactiveProperty nuget.
You declare a ReactiveProperty for each value you want to "react":
public ReactiveProperty<int> Prop1 = new ReactiveProperty(0);
public ReactiveProperty<int> Prop2 = new ReactiveProperty(0);
In the constructor (or load event) just tell the property to update the chart:
Prop1.Subscribe(value => Chart1_Click(this, null));
Here I'm telling to Prop1 to execute the Chart1_Click method, but you can create an specific method for updating the charts and put this in the subscribe method instead the Chart1_Click.
And for change the Prop1 or Prop2 values just:
Prop1.Value = 5; // this line will run the specified method
Prop2.Value = 10;

Button Array - how to pass a parameter to shared handler

I have a bit of code where i have a dynamically created array or buttons with staff pictures on them, as well as the staff's name. I've added one handler to handle any button click from any of the buttons. where i am stuck is, if you look at the code below, it all works fine, and if you click any of the buttons you get the "aha" test message. but i want the name of the staff clicked on (so btnArray(i).Text) to be passed to the handler for further processing. I tried adding a ByVal parameter to the handler but that caused an error. what's the correct way to do this? As i said, the code below works for me, i just am at a loss as to how to add the extra functionality.
Dim btnArray(staffcount) As System.Windows.Forms.Button
For i As Integer = 1 To staffcount - 1
btnArray(i) = New System.Windows.Forms.Button
btnArray(i).Visible = True
btnArray(i).Width = 80
btnArray(i).Height = 101
btnArray(i).BackgroundImage = Image.FromFile(picloc(i))
btnArray(i).BackgroundImageLayout = ImageLayout.Stretch
btnArray(i).Text = staffname(i)
Dim who As String
who = btnArray(i).Text
AddHandler btnArray(i).Click, AddressOf Me.theButton_Click
btnArray(i).ForeColor = Color.White
btnArray(i).TextAlign = ContentAlignment.BottomCenter
Dim fnt As Font
fnt = btnArray(i).Font
btnArray(i).Font = New Font(fnt.Name, 10, FontStyle.Bold)
FlowLayoutPanel1.Controls.Add(btnArray(i))
Next i
End Sub
Private Sub theButton_Click()
MsgBox("aha")
End Sub
First, correct the signature of your shared handler.
Private Sub theButton_Click(sender As Object, e As EventArgs)
End Sub
Once that is done getting the text of the button clicked is a simple matter.
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim textOfButtonClicked As String = DirectCast(sender, Button).Text
MessageBox.Show(textOfButtonClicked)
End Sub
The sender is the button that was clicked. Since signatures use objects for the sender the DirectCast 'changes' it to button and you then can access the .Text property of the button.
If there are more manipulations you want to perform on the clicked button you could do it this way
Private Sub theButton_Click(sender As Object, e As EventArgs)
Dim whBtn As Button = DirectCast(sender, Button) ' get reference to button clicked
Dim textOfButtonClicked As String = whBtn.Text
MessageBox.Show(textOfButtonClicked)
'e.g. change the color
whBtn.BackColor = Color.LightYellow
End Sub