Circulate playing audio with MediaElement in WPF - wpf

I am developing a video player with WPF.(in VB)
I have already created a MediaElement ,ListBox, "Next" button,
then start playing through reading ListBox,
and use "Next" to skip to next audio/video.
In "MediaEnded" event, i just copy all code in "Next" button.
Now, problem is coming,
Assume the Listbox has four audios(.mp3), "test1.mp3", "test2.mp3", ......
now playing is "test1.mp3", i push "Next" button, then now playing is "test2.mp3".
However, when i just let "test1.mp3" play completed, my player will not play "test2.mp3",
it plays "test3.mp3" or others in random.
This situation like "MediaEnded" event was processed for many times.
Private Sub MediaElement1_MediaEnded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MediaElement1.MediaEnded
nextmedia()
End Sub
Private Sub nextmedia()
Try
'pi is play index, start from 1, 0 is non playing
If pi <> 0 Then
If pi = ListBox_temp.Items.Count Then
Dim filename As String = ListBox_temp.Items.Item(0).ToString
MediaElement1.Source = New Uri(filename)
pi = 1
Else
Dim filename As String = ListBox_temp.Items.Item(pi).ToString
MediaElement1.Source = New Uri(filename)
pi = pi + 1
End If
End If
Catch ex As Exception
End Try
Window1.Title = "Video Sampler - " + CStr(pi) + ". " + CStr(ListBox1.Items.Item(pi - 1))
End Sub
Who can help me....

I haven't tested it, but try the following.
Try
pi = If(pi < ListBox_temp.Items.Count - 1, pi + 1, 0)
Dim filename As String = ListBox_temp.Items.Item(pi).ToString
MediaElement1.Source = New Uri(filename)
Catch ex As Exception
End Try
This increments pi unless the last ListBoxItem is selected, in which case it sets it to zero.

Related

How to monitor array's and reset when limit is reached. VB.net

I have a VB.Net program that loops through array's to try to figure out where bottles are on a "conveyor". The point of this program is to visually show staff, how the conveyor works using VB.net and Labels. It's extremely difficult to explain, so I’ll do my best.
Bottle_Number(10) Bottle_Position(128)
There are 10 bottles that I want to track at all 128 stops on the conveyor.
We have a conveyor that can only fit 10 bottles. I need to track the position of each of the 10 bottles. Once bottle 11 comes on - That means bottle 1 is completed and off the conveyor. So, bottle 11 becomes bottle 1, so I need to reset the position of bottle1 to 0, and continue tracking bottles 2-9 while also tracking bottle 11(Not bottle 1). Once bottle 12 comes on it becomes bottle 2, and I need to reset the position of bottle 2 to '0' and continue tracking all bottles.
Any help would be appreciated.
Here is my code:
Public Class frmMain
Dim Product_Position(10) As Integer
Dim Inches_Per_Pulse As Integer
Dim PulseNumber As Integer
Dim Product_Counter As Integer
Dim Product_Location(10) As Integer
Dim Function1 As Integer
Dim Function2 As Integer
Dim Function3 As Integer
Dim Function4 As Integer
Dim Function5 As Integer
Dim Function6 As Integer
Dim Function7 As Integer
Dim Function8 As Integer
Dim Function9 As Integer
Dim Function10 As Integer
Dim Product_in_Tunel As Integer
Dim test As Integer
Dim Roll_OVer As Boolean
Dim Product_Counter_Test As Integer
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
lblStatus.BackColor = Color.Green
lblStatus.Text = "Conveyor Status: Running"
End Sub
Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
lblStatus.BackColor = Color.Red
lblStatus.Text = "Conveyor Status: Off"
End Sub
Private replace_next As Integer
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
If Product_Counter = 10 Then
replace_next += 1
If replace_next > 10 Then
replace_next = 1 ' replace them in turn 1..10, then loop back to 1
Product_Position(replace_next) = 0 ' put initial position here
End If
End If
Product_Counter = Product_Counter + 1
If Product_Counter > 10 Then
Product_Counter = 1
Roll_over = True
End If
'MsgBox(Product_Counter)
'MsgBox(replace_next)
End Sub
Private Sub btnPulse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPulse.Click
Get_Location()
End Sub
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
PulseNumber = "0"
Inches_Per_Pulse = "1"
Roll_OVer = False
'MsgBox("Test")
End Sub
Public Sub Get_Location()
'MsgBox(Product_Counter)
If Roll_OVer = True Then
Product_Counter_Test = 10
'MsgBox("i'm stuck here")
End If
If Roll_OVer = False Then
Product_Counter_Test = Product_Counter
End If
'MsgBox(Product_Counter_Test)
'MsgBox("am I here - Yes")
For test = 1 To Product_Counter_Test
'MsgBox("This works")
Product_Position(test) = Product_Position(test) + Inches_Per_Pulse
Next
PulseNumber = PulseNumber + 1
ClearLabels()
lblProduct1Position.Text = Product_Position(1)
lblProduct2Position.Text = Product_Position(2)
lblProduct3Position.Text = Product_Position(3)
lblProduct4Position.Text = Product_Position(4)
lblProduct5Position.Text = Product_Position(5)
lblProduct6Position.Text = Product_Position(6)
lblProduct7Position.Text = Product_Position(7)
lblProduct8Position.Text = Product_Position(8)
lblProduct9Position.Text = Product_Position(9)
lblProduct10Position.Text = Product_Position(10)
End Sub
Public Sub ClearLabels()
lblProduct1Position.Text = ""
lblProduct2Position.Text = ""
lblProduct3Position.Text = ""
lblProduct4Position.Text = ""
lblProduct5Position.Text = ""
lblProduct6Position.Text = ""
lblProduct7Position.Text = ""
lblProduct8Position.Text = ""
lblProduct9Position.Text = ""
lblProduct10Position.Text = ""
End Sub
The Pulse button is what is actually driving the conveyor, each pulse (click of the button) means the conveyor is moving forward.
Right now once the program gets to bottle 11, it resets and only moves forward the "new" bottle (bottle1). It should continue incrementing the remaining bottles until they reach the end and do the same for them - Reset the position to 0 and begin counting again.
As far as I understand it, once you have 11 bottles, you don't want to reset to only one bottle, but instead still have 10 bottles, and replace one of them. You'll need a second variable to keep track of which is to be replaced.
So instead of :
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
Product_Counter = Product_Counter + 1
If Product_Counter > 10 Then Product_Counter = 1
End Sub
It would be something like:
Private Replace_Next as Integer = 0
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
If Product_Counter = 10 Then
Replace_Next += 1
If Replace_Next > 10 Then Replace_Next = 1 ' replace them in turn 1..10, then loop back to 1
Product_Position(Replace_Next) = .... ' put initial position here
Else
Product_Counter = Product_Counter + 1
End If
End Sub
Your conveyor is FIFO (first-in, first-out), so rather than constantly shifting, reindexing and/or rebuilding (=reset?) an array to make it seem like it is FIFO, Net includes the Queue(Of T) collection which is FIFO.
A LinkedList(Of T) could also be used. A plain List(Of T) would also work, but if the add/remove frequency is high, that will result in the same inefficient shifting taking place under the hood that you have with an array.
The only issue is enforcement of the size limit, which is easily handled with a small class wrapper. I assume there is something interesting or identifiable about the bottles other than their position. The test code uses a sequence ID and the contents.
Friend Class Bottle
Public Property Contents As String
Public Property SequenceID As Int32
' etc
Public Overrides Function ToString() As String
Return String.Format("{0}: ({1})", SequenceID.ToString("00"), Contents)
End Function
End Class
You likely have more relevant information to show. The, the collection class:
Friend Class BottleQueue
Private mcol As Queue(Of Bottle)
Private lbls As Label()
Private MaxSize As Int32 = 10 ' default
Public Sub New(size As Int32)
MaxSize = size
mcol = New Queue(Of Bottle)
End Sub
Public Sub New(size As Int32, l As Label())
Me.New(size)
lbls = l
End Sub
Public Sub Add(b As Bottle)
mcol.Enqueue(b)
Do Until mcol.Count <= MaxSize
mcol.Dequeue()
Loop
UpdateDisplay()
End Sub
Public Function Peek() As Bottle
Return mcol.ElementAtOrDefault(0)
End Function
Public ReadOnly Property Count() As Int32
Get
Return mcol.Count
End Get
End Property
Public Function Remove() As Bottle
Dim b As Bottle = Nothing
If mcol.Count > 0 Then
b = mcol.Dequeue
UpdateDisplay()
End If
Return b
End Function
Private Sub UpdateDisplay()
Dim n As Int32
If lbls Is Nothing OrElse lbls.Count = 0 Then
Return
End If
For n = 0 To mcol.Count - 1
lbls(n).Text = mcol.ElementAtOrDefault(n).ToString
Next
For n = n To lbls.Count - 1
lbls(n).Text = "(empty)"
Next
End Sub
Public ReadOnly Property GetQueue As Bottle()
Get
Return mcol.ToArray()
End Get
End Property
End Class
The class has 2 display means built in. One updates a set of labels. Since it is a collection, it also provides a way to get the current collection in order for a collection type control such as a Listbox. An even better way would be if the collection itself was "observable", so it could be used as a datasource.
It also provides a way to Removethe next bottle manually. Removing from a specific index (e.g. Remove(3)) is antithetical to a Queue, so it isnt implemented.
test code:
' form level vars:
Private BottleQ As BottleQueue
Private BottleID As Int32 = 7
' form load, passing the labels to use
' using a queue size of FIVE for test
BottleQ = New BottleQueue(5, New Label() {Label1, Label2, Label3, Label4, Label5})
Adding an item:
Dim material = {"Napalm", "Beer", "Perfume", "Pepsi", "Cyanide", "Wine"}
' add new bottle with something in it
BottleQ.Add(New Bottle With {.Contents = material(RNG.Next(0, material.Count)),
.SequenceID = BottleID})
BottleID += 1
' clear and show the contents in a listbox:
lbQueView.Items.Clear()
lbQueView.Items.AddRange(BottleQ.GetQueue)
The BottleId arbitrarily starts at 7, the contents are random. BTW, material shows just about the only way I ever use an array: when the contents are fixed and known ahead of time. In almost all other cases, a NET collection of one sort or another, is probably a better choice.
Because it is not an observable collection (and that is a little at odds with the FIFO nature), the listbox needs to be cleared each time. That could be internal to the class like the label display is. Results:
On the right, the first 5 are shown in order; 3 clicks later, the result is on the left: everything moved up 3 and 3 new items have been added.
Note: If the code using this needs to know when/which Bottle is removed from the conveyor, the class could include a ItemRemoved event which provides the item/Bottle just removed when adding forces one out. That is probably the case, but the question doesnt mention it.

Datagridviewcell Tooltip doesn't display after modifying image of any cell

In my winforms application, I loop through the cells of a datagridview and add a tooltip for specific cells based on values in other columns. I do this in the cellformatting event handler, and it worked perfectly. Here is the code:
Private Sub dgvResults_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles dgvResults.CellFormatting
Select Case dgvResults.Columns(e.ColumnIndex).Name
Case "TradeInValue"
DirectCast(dgvResults.Rows(e.RowIndex).Cells("TradeInValue"), DataGridViewTextBoxCell).ToolTipText = "Min = " & CDec(dgvResults.Item("BB_Min", e.RowIndex).FormattedValue).ToString("$#####.##") & ", Max = " & CDec(dgvResults.Item("BB_Max", e.RowIndex).FormattedValue).ToString("$#####.##")
If Not IsNothing(dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue) AndAlso dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue.ToString.Trim.Length > 0 AndAlso CInt(dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue.ToString) <> -1 Then
If dgvResults.Item("ValueList", e.RowIndex).FormattedValue.ToString.Length > 0 Then
Dim ValueParts() As String = dgvResults.Item("ValueList", e.RowIndex).FormattedValue.ToString.Split("|")
'Dim selectedTrim As String = ValueParts(dgvResults.Item("SelectedTrimIndex", e.RowIndex).FormattedValue)
End If
End If
End Select
End Sub
Then, I added code in the cellpainting event handler to hide specific images, again based on values in the datagridview. Here is that code.
Private Sub dgvResults_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles dgvResults.CellPainting
If e.ColumnIndex >= 0 AndAlso e.RowIndex >= 0 Then
Select Case dgvResults.Columns(e.ColumnIndex).Name
Case "VIN_Pic"
If dgvResults.Rows(e.RowIndex).Cells("VIN_Value").FormattedValue = "" Then
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = New Bitmap(1, 1)
End If
Case "EmailDisplayImage"
If dgvResults.Rows(e.RowIndex).Cells("ListingContactEmail").FormattedValue = "" Then
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = New Bitmap(1, 1)
End If
End Select
End If
End Sub
When this code as added, the tooltips no longer display. The CellToolTipTextNeeded event fires, and it shows the correct text in the argument, but it never displays. Comment out the lines that assign a new image to the datagridviewimagecells, and the tooltips start displaying again.
I hope this explanation was sufficient. Any ideas?
With the below code, you will run into memory and GDI object leaks very easily as a new Bitmap instance is created every time the cell is painted. Also this is causing your ToolTip to be not displayed.
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = New Bitmap(1, 1)
Define the empty bitmap in class level or add as embedded resource and use it.
Dim emptyBitmap As New Bitmap(1, 1);
DirectCast(dgvResults.Item(e.ColumnIndex, e.RowIndex), DataGridViewImageCell).Value = emptyBitmap

Object reference not set to an instance of an object

The purpose of this program is to run through a range of pictureboxes and set it's .image property to a particular image. I keep getting the error "Object reference not set to an instance of an object". Coming from the line that shows "DirectCast(Me.Controls(pic(i)), PictureBox).Image = My.Resources.glass_buttonred"....Whats weird is if i move that code outside of the for loop it runs just fine.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim pic(2) As Object
For i = 0 To 2
pic(i) = "picturebox" + Convert.ToString(i)
DirectCast(Me.Controls(pic(i)), PictureBox).Image = My.Resources.glass_buttonred
Next
Label1.Text = pic(1)
End Sub
HERE IS THE WORKING CODE. THANKS! Hope it will help others wanting to convert string to control object
Dim pic(2) As Object
For i = 0 To 2
pic(i) = "picturebox" + Convert.ToString(i + 1)
DirectCast(Me.Controls(pic(i)), PictureBox).Image = My.Resources.glass_buttonred
Next
Label1.Text = pic(1)
The problem may be that Me.Controls is case sensitive. If you're using the designer to build these, you likely need:
' Note the upper case letters below
pic(i) = "PictureBox" + (i + 1).ToString()
DirectCast(Me.Controls(pic(i)), PictureBox).Image ' ...
The designer, by default, will name the controls "PictureBox1" (for the first), and "PictureBox2" for the second, with the case being relevant.

How can I get my code to stop in Visual Basic?

I am creating a game where the player answers a question and then if they answer correctly, then they get to flip two cards over to see if they match (bit like pairs game). However, I am struggling to figure out how I can stop the input box (how the user enters their answer), if the player gets the question right, from appearing for a period of time until the player has selected two cards.
I am using two arrays, one for holding the questions and the other for holding the answers. P.s. Excuse the last few questions, trying to get it to work before I finish them all.
Private Sub Questions()
strQuestions(0) = "A common noun refers to the name of things."
strQuestions(1) = "A pronoun is a word that takes the place of nouns."
strQuestions(2) = "'She' is a pronoun that would replace a woman's name."
strQuestions(3) = "The days of the week are proper nouns."
strQuestions(4) = "'He', 'She' and 'them' are all pronouns."
strQuestions(5) = "Spain is a proper noun."
strQuestions(6) = "Proper nouns always start with a capital letter."
strQuestions(7) = "The place 'England' is referred to as a proper noun."
strQuestions(8) = "A 'camera' is a common noun."
strQuestions(9) = "FE"
strQuestions(10) = "GR"
strAnswers(0) = "TRUE"
strAnswers(1) = "TRUE"
strAnswers(2) = "TRUE"
strAnswers(3) = "TRUE"
strAnswers(4) = "TRUE"
strAnswers(5) = "TRUE"
strAnswers(6) = "TRUE"
strAnswers(7) = "TRUE"
strAnswers(8) = "TRUE"
strAnswers(9) = "TRUE"
strAnswers(10) = "TRUE"
Dim userAnswer As String
For i = 0 To UBound(strQuestions)
userAnswer = InputBox(strQuestions(i))
If userAnswer <> strAnswers(i) Then
MsgBox("Incorrect. Try again.")
Else
MsgBox("Correct! Make your move.")
WHAT GOES HERE?
End If
Next i
End Sub
Private Sub label_click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Label9.Click, Label8.Click, Label7.Click, Label6.Click, Label5.Click,
Label4.Click, Label3.Click, Label2.Click, Label16.Click, Label15.Click, Label14.Click, Label13.Click, Label12.Click,
Label11.Click, Label10.Click, Label1.Click
' The timer is only on after two non-matching
' icons have been shown to the player,
' so ignore any clicks if the timer is running
If Timer1.Enabled Then Exit Sub
Dim clickedLabel = TryCast(sender, Label)
If clickedLabel IsNot Nothing Then
End If
' If the clicked label is black, the player clicked
' an icon that's already been revealed --
' ignore the click
If clickedLabel.ForeColor = Color.Black Then Exit Sub
' If firstClicked is Nothing, this is the first icon
' in the pair that the player clicked,
' so set firstClicked to the label that the player
' clicked, change its color to black, and return
If firstClicked Is Nothing Then
firstClicked = clickedLabel
firstClicked.ForeColor = Color.Black
Exit Sub
End If
' If the player gets this far, the timer isn't
' running and firstClicked isn't Nothing,
' so this must be the second icon the player clicked
' Set its color to black
secondClicked = clickedLabel
secondClicked.ForeColor = Color.Black
CheckForWinner()
' If the player clicked two matching icons, keep them
' black and reset firstClicked and secondClicked
' so the player can click another icon
If firstClicked.Text = secondClicked.Text Then
firstClicked = Nothing
secondClicked = Nothing
Questions()
Exit Sub
End If
' If the player gets this far, the player
' clicked two different icons, so start the
' timer (which will wait three quarters of
' a second, and then hide the icons)
Timer1.Start()
Questions()
Exit Sub
You need to restructure your program so that the part where the questions are asked is not in a loop. Instead consider using a sub which asks for the next answer. If the correct answer is given, the sub exits and the application waits for the user to pick a card.
Once the cards are selected, you call the ask a question sub again. The position through the list of questions is stored as a variable in the form. Each time the ask a question sub is executed, it checks if the end of the list has been reached and if so ends the game.
Something like this (although its been a while since I wrote any VB!)
Private CurrentQuestion As Integer
Private Sub Questions()
CurrentQuestion = 0
...
AskQuestion
End Sub
Private Sub AskQuestion
If CurrentQuestion = UBound(strQuestions)
EndGame
Else
userAnswer = InputBox(strQuestions(CurrentQuestion))
If userAnswer <> strAnswers(CurrentQuestion) Then
MsgBox("Incorrect. Try again.")
AskQuestion
Else
CurrentQuestion = CurrentQuestion + 1
MsgBox("Correct! Make your move.")
End If
End If
End Sub
Private Sub label_click(ByVal sender As System.Object,
....
AskQuestion
End Sub

Upload Progressbar with FtpWebRequest

I have a program that uploads files to our server when they are dropped over the form, to make it easy for our customers to get large files to us.
I have it mostly working, but I want to have a progress bar so that the user knows it's working, instead of having it just sit there for 5 minutes while the files upload quietly in the background.
I would be happy to just have the progress bar pulse so it looks the program is working, and not frozen. If I can show actual status then that would be better.
My code:
Private Sub Grid1_Drop(sender As System.Object, e As System.Windows.DragEventArgs) Handles Grid1.Drop
Dim sFileInfo As System.IO.FileInfo
Dim sStatus As String = ""
If e.Data.GetDataPresent("FileDrop") Then
Try
Dim theFiles() As String = CType(e.Data.GetData("FileDrop", True), String())
For Each file As String In theFiles
sFileInfo = New System.IO.FileInfo(file)
If UploadFile(txtUsername.Text, sFileInfo) Then
lstFileList.Items.Add(file & " - Uploaded")
Else
lstFileList.Items.Add(file & " - Upload Failed")
End If
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End Sub
Public Function UploadFile(ByVal User As String, ByVal oFile As FileInfo) As Boolean
Dim ftpRequest As FtpWebRequest
Dim ftpResponse As FtpWebResponse
Try
ftpRequest = CType(FtpWebRequest.Create(Base + User + "/" + oFile.Name), FtpWebRequest)
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile
ftpRequest.Proxy = Nothing
ftpRequest.UseBinary = True
ftpRequest.Credentials = Cred
ftpRequest.KeepAlive = KeepAlive
ftpRequest.EnableSsl = UseSSL
If UseSSL Then ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
Dim fileContents(oFile.Length) As Byte
Using fr As FileStream = oFile.OpenRead
fr.Read(fileContents, 0, Convert.ToInt32(oFile.Length))
End Using
Using writer As Stream = ftpRequest.GetRequestStream
writer.Write(fileContents, 0, fileContents.Length)
End Using
ftpResponse = CType(ftpRequest.GetResponse, FtpWebResponse)
ftpResponse.Close()
ftpRequest = Nothing
Return True
Catch ex As WebException
Return False
End Try
End Function
Have a look at the background worker class. http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx which will free up your ui so you can add in a progress bar control and have it animate while your files are being uploaded

Resources