Function call only works when MessageBox.Show() is included? - vb.net

In my current project I have a self-made audioplayer which is operated trough my musictimer() function. Below is a sub which orders the audioplayer to go to the next song when someone has clicked on a picture. This works perfectly.
Private Sub PictureBox4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox4.Click
If (ListBox1.Items.Count - 1 > songBeingPlayed) Then
musictimer("next")
Else
musictimer("stop")
End If
End Sub
Below there is a sub which orders the player to play the next song when a song is finished playing. This sub also works but only when I have the MessageBox.Show("blabla") line in there. Otherwise it simply ignores the musictimer("next"). Obviously its quite annoying to have popup messages the entire times so I want it gone. Does anyone know whats going on? Im clueless.
Private Sub AxWindowsMediaPlayer1_PlayStateChange(ByVal sender As System.Object, ByVal e As AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) Handles AxWindowsMediaPlayer1.PlayStateChange
If AxWindowsMediaPlayer1.playState = WMPLib.WMPPlayState.wmppsStopped Then
musictimer("next")
MessageBox.Show("blabla")
End If
End Sub
My very messy musictimer function.
Function musictimer(ByVal action)
If action Is "initial" Then
TextBox1.Text = "0:00"
Timer1.Stop()
secondsCounter = 1
doubledigitsecondCounter = 0
minuteCounter = 0
End If
If action Is "reset" Then
TextBox1.Text = "0:00"
Timer1.Stop()
secondsCounter = 1
doubledigitsecondCounter = 0
minuteCounter = 0
Me.AxWindowsMediaPlayer1.URL = ""
changePlayButton("play")
End If
If action Is "start" Then
If (ListBox1.Items.Count > 0) Then
Me.AxWindowsMediaPlayer1.URL = directoryPath + listboxpl(songBeingPlayed)
AxWindowsMediaPlayer1.Ctlcontrols.play()
Timer1.Start()
changePlayButton("pause")
End If
End If
If action Is "pause" Then
Timer1.Stop()
AxWindowsMediaPlayer1.Ctlcontrols.pause()
changePlayButton("play")
End If
If action Is "next" Then
If (ListBox1.Items.Count - 1 > songBeingPlayed) Then
songBeingPlayed += 1
musictimer("reset")
musictimer("start")
changePlayButton("pause")
Else
musictimer("pause")
End If
End If
If action Is "previous" Then
If (songBeingPlayed > 0) Then
songBeingPlayed -= 1
musictimer("reset")
musictimer("start")
End If
End If
End Function

The PlayStateChanged event is quite notorious. It was really meant to just update a UI element that shows the state. Doing anything with the player in that event is very troublesome. A call to MessagBox can have an affect because it pumps a message loop, always a big deal for ActiveX controls.
The best way to stay out of trouble is by delaying your code, making it run after the event was fired and the player is back into a quiescent state. Elegantly done by using the Control.BeginInvoke() method. Like this:
Private Sub AxWindowsMediaPlayer1_PlayStateChange(ByVal sender As System.Object, ByVal e As AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) Handles AxWindowsMediaPlayer1.PlayStateChange
If e.newState = WMPLib.WMPPlayState.wmppsStopped Then
Me.BeginInvoke(New Action(AddressOf NextSong))
End If
End Sub
Private Sub NextSong()
musictimer("next")
End Sub

Related

How can i make a subroutine click a picture box?

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...

Changing typing behavior of ListBox

When typing into a listbox the listbox scrolls to the next item with first letter matching the input character. I want to disable/change this behavior.
I implemented a handler for the keypress event and implemented my new behavior, but I don't see any way to remove the old behavior.
How can I disable the default behavior?
Here is the event handler for the keypress event:
Private Sub FooListBox_KeyPress(sender As Object, e As KeyPressEventArgs) Handles FooListBox.KeyPress
If SearchResetTimer.Enabled Then
SearchResetTimer.Stop()
SearchTimer.Stop()
Else
BeginUpdate()
SearchedString = ""
End If
SearchedString = SearchedString & e.KeyChar
SearchResetTimer.Start()
SearchTimer.Start()
End Sub
Private Function SearchFor(listbox As ListBox, target As String) As Integer
For i As Integer = listbox.SelectedIndex To listbox.Items.Count - 1
If listbox.Items(i).ToString().ToLower().StartsWith(target) Then
Return i
End If
Next
For i As Integer = 0 To listbox.SelectedIndex - 1
If listbox.Items(i).ToString().ToLower().StartsWith(target) Then
Return i
End If
Next
Return -1
End Function
Private Sub SearchTimer_Tick(sender As Object, e As EventArgs) Handles SearchTimer.Tick
SearchTimer.Stop()
Dim Found As Integer = SearchFor(FooListBox, SearchedString)
If Found <> -1 Then
FooListBox.SelectedIndex = Found
End If
EndUpdate()
End Sub
Private Sub SearchResetTimer_Tick(sender As Object, e As EventArgs) Handles SearchResetTimer.Tick
SearchResetTimer.Stop()
End Sub
Quick overview: there are two timers, searchTimer that when ticked searches for the string and updates the control, searchResetTimer which resets the searched string and marks the beginning of a new user input.
Note that I am not releasing this code under CC, it is for illustration purposes only

Vb.Net Background Worker Updating UI Not Working

I have a background worker that is supposed to be updating a ToolStripLabel with some status messages. However, the updating is not happening, but no errors are being thrown. Here's the code I am using:
Private Sub BackgroundWorker3_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker3.DoWork
BackgroundWorker3.WorkerReportsProgress = True
Dim Counter As Integer = 0
Do Until BW1Running = False
Counter = Counter + 1
Threading.Thread.Sleep(1000)
Incident_Form.BackgroundWorker3.ReportProgress(Counter)
If Counter >= 100 Then
e.Result = False
Return
End If
Loop
If BW1Running = False Then
Counter = 100
Incident_Form.BackgroundWorker3.ReportProgress(Counter)
End If
End Sub
Private Sub BackgroundWorker3_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker3.ProgressChanged
Me.ToolStripStatusLabel1.Text = e.ProgressPercentage.ToString
End Sub
Nothing happens when the ProgressChanged is fired. I've debugged it and it'll print a line to the output window, but it will not update that label. Any ideas on what I'm missing?
You're calling:
Incident_Form.BackgroundWorker3.ReportProgress()
instead of just:
BackgroundWorker3.ReportProgress()
Your BackgroundWorker3_ProgressChanged method is subscribed to the ProgressChanged event of the BackgroundWorker located in the current form, not in the Incident_Form form.
Remove Incident_Form from the beginning of the BackgroundWorker3.ReportProgress() calls and you should be good to go.

windows media player stops of playing the song when PlayStateChange changed to play

this is my code:
Private Sub AxWindowsMediaPlayer1_PlayStateChange(ByVal sender As System.Object, ByVal e As AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) Handles AxWindowsMediaPlayer1.PlayStateChange
If AxWindowsMediaPlayer1.playState = WMPPlayState.wmppsMediaEnded Then
Dim str As Integer
'the original lblPlayItemIndex.Text = 0 : the index of the first item in the listview
str = lblPlayItemIndex.Text + 1
AxWindowsMediaPlayer1.URL = fmPlaylist.lstPlaylist.Items(str).Tag
AxWindowsMediaPlayer1.Ctlcontrols.play()
MsgBox("str: " & str)
End If
End Sub
I have a listview as a playlist for media player....
the .tag of each item in the listview is the path for the song
the "lblPlayItemIndex.Text" is the index of the listviewitem and when the song end ... it will make the "lblPlayItemIndex.Text" +1 to get the next item in the listview
actually I made it good....but the problem when I close the message the song stops of playing....
is there anything wrong in my code .... or should I make it with another way??!!
When the player state changes, it changes many many times as you can see if you print them to the console window. You need to allow time for these to stop before you try to play the next one. This will show 3 ways to do that.
All three remedies need a method (Sub) to play the next song which is not part of an event:
Private Sub PlayNextItem()
' however you figure out what to play next...example
If chkRandom.Checked Then
NextIndex = RNG.Next(0, SongList.Length)
Else
NextIndex = If(NextIndex + 1 > SongList.Count - 1, 0, NextIndex + 1)
End If
AxWMP.URL = SongList(NextIndex)
lblNowPlaying.Text = SongList(NextIndex)
AxWMP.Ctlcontrols.play()
End Sub
Method 1
You see this a lot because it is easily understood. From thePlayStateChange event, activate a Timer; then from the Timer_Tick event, call your new method. An interval of 500 should be enough time for it to transition:
Playstate change event:
If AxWindowsMediaPlayer1.playState = WMPPlayState.wmppsMediaEnded Then
Timer2.Enabled = True
End If
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
PlayNextItem()
' be sure to turn off the timer
Timer1.Enabled = False
End Sub
Method 2 is simpler - use a delegate:
Delegate Sub PlayNextDelegate()
Dim PlayNext As PlayNextDelegate = AddressOf PlayNextItem
Then from the playstate changed event:
Me.BeginInvoke(PlayNext)
Perhaps simpler is Method 3 from this answer which includes an explanation of whats going on.
Me.BeginInvoke(New MethodInvoker(AddressOf PlayNextItem))
It still relies on a separate method (Sub) to play the next song, but you dont need to declare and setup a delegate, that is woven into the call.

Creating Timer Countdown VB.Net?

i am creating a minigame where when the use clicks a button, it "attacks" the monster causing it to lose 5 hp, displayed using a progressbar. then at the same time the monster also attacks making the player lose hp. but the problem is these events happen at the exact same time, and i would like a 2 second interval between the events. ive been trying to get a timer event to work since this morning, but it just wouldnt work here is my code
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If Tick = 0 Then
Timer1.Stop()
Timer1.Enabled = False
Else
Tick -= 1
End If
End Sub
and here is the attack button event
Private Sub btnAttack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAttack.Click
PlayerAttacks(mhealth, attack)
textShiftUp(numlines)
HPBarsAlter(mhealth, health)
Tick = 2
Timer1.Start()
MonsterAttacks(health, mattack, CritRate)
HPBarsAlter(mhealth, health)
MobDeath(mhealth, MobNumber)
Timer1.Stop()
End Sub
please tell me if you need any more information thank you :)
Basically, move your monster attack to the timer
Private Sub btnAttack_Click(...)
btnAttack.Enabled = False ' disable more attacks
PlayerAttacks(mhealth, attack)
textShiftUp(numlines)
HPBarsAlter(mhealth, health)
MonsterTimer.Interval = 2000
MonsterTimer.Start()
End Sub
Private Sub MonsterTimer_Tick(...
' not sure what the old code was doing
MonsterTimer.Stop ' stop the attacks
MonsterAttacks(health, mattack, CritRate)
HPBarsAlter(mhealth, health)
MobDeath(mhealth, MobNumber)
btnAttack.Enabled = True ' allow more attacks
End Sub
EDIT
Added 2 lines to toggle the ability to attack while waiting.