'**********************************************
'Written By.................R. S. Percy
'CodeProject user name......rspercy60
'e-mail.....................rspercy60@yahoo.com
'Date Started...............11/14/2010
'Date Finished..............11/14/2010
'**********************************************
#Region "System and 3rd-party libraries."
Imports System.IO.Path
Imports System.IO
Imports System.Threading
Imports System.Environment
Imports Microsoft.DirectX.AudioVideoPlayback
Imports ComponentFactory.Krypton.Toolkit
#End Region
Public Class frmPlayer
#Region "Variables."
'File Paths Used.
Dim pathAudio As String = GetFolderPath(SpecialFolder.MyMusic) & "\" 'MP3's path.
Dim pathPlaylist As String = GetFolderPath(SpecialFolder.MyMusic) & "\Playlists\" 'Playlists path.
'Listbox Variables.
Dim fileNameMP3 As String
Dim FileNameShow As String
Dim FileNamePath As String
Dim fileIndex As Integer
'Shuffle Variables.
Private mySongs As New ArrayList()
Private boolShuffle As Boolean
'OpenFileDialog.Filter.
Dim AudioFiles As String = "Audio Files (*.mp3)|*.mp3" 'MP3's Only
'Booleans for Audio.
Dim b_PlayState As Boolean 'For Audio
Dim b_EndOfMedia As Boolean 'For Audio
'DirectX Variables.
Dim myAudio As Audio
Dim thisAudio As Audio
Dim intData As String
'DropShadow Constant.
Private Const CS_DROPSHADOW As Integer = 131072
#End Region
#Region "frmPlayer - Load and Closing Events!"
Private Sub frmPlayer_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
audioTimer.Dispose()
End Sub
Private Sub frmPlayer_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
b_PlayState = False
b_EndOfMedia = True
kbtnLoadAllPlayLists.PerformClick()
End Sub
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ClassStyle = cp.ClassStyle Or CS_DROPSHADOW
Return cp
End Get
End Property
#End Region
#Region "Subs and Functions!"
Private Sub Load_Files(ByVal MediaType As String)
Dim supportedFiles As String
klstSongs.Items.Clear()
Select Case MediaType
Case "Audio"
supportedFiles = AudioFiles
Case Else 'Added protection
supportedFiles = AudioFiles
End Select
With ofd
.InitialDirectory = pathAudio
.Filter = supportedFiles
.CheckFileExists = True
.CheckPathExists = True
.Multiselect = True
.RestoreDirectory = True
End With
If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
For Each Me.fileNameMP3 In ofd.FileNames
FileNameShow = GetFileName(fileNameMP3)
Me.klstSongs.Items.Add(FileNameShow)
Next
Else
'User pressed the Cancel button.
fileIndex = Nothing
Exit Sub
End If
fileIndex = 0
klstSongs.SetSelected(fileIndex, True)
FileNameShow = klstSongs.SelectedItem.ToString()
myAudio = New Audio(pathAudio & FileNameShow)
'Continue the button checking
kbtnPlay.Enabled = True
kbtnPause.Enabled = True
kbtnStop.Enabled = True
End Sub
Private Sub Check_Next_Media()
If fileIndex >= Me.klstSongs.Items.Count - 1 Then 'Exception prevention
klstSongs.Items.Clear()
b_PlayState = False
b_EndOfMedia = True
audioTimer.Enabled = False
klblStatus.Text = "Waiting..."
klblTime.Text = "00:00 / 00:00"
klblPctDone.Text = "0%"
fileIndex = Nothing
gtbPosition.Value = 0
Exit Sub
End If
If krbRandom.Checked = True Then
Dim r As Random = New Random()
b_EndOfMedia = False
b_PlayState = True
klstSongs.SetSelected(fileIndex, False)
klstSongs.Items.RemoveAt(fileIndex) 'Prevents being played again.
fileIndex = r.Next(0, Me.klstSongs.Items.Count - 1)
klstSongs.SetSelected(fileIndex, True)
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
myAudio = New Audio(pathAudio & FileNameShow)
myAudio.Play()
audioTimer.Enabled = True
gtbPosition.MaxValue = myAudio.Duration
klblStatus.Text = "Playing"
Exit Sub
End If
If krbRepeat.Checked = True Then
b_EndOfMedia = False
b_PlayState = True
klstSongs.SetSelected(fileIndex, True)
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
myAudio = New Audio(pathAudio & FileNameShow)
myAudio.Play()
audioTimer.Enabled = True
gtbPosition.MaxValue = myAudio.Duration
klblStatus.Text = "Playing"
Exit Sub
End If
'Normal or Sequential play
If krbSequential.Checked Then
b_PlayState = True
b_EndOfMedia = False
Me.klstSongs.SetSelected(fileIndex, False)
fileIndex += 1
Me.klstSongs.SetSelected(fileIndex, True)
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
myAudio = New Audio(pathAudio & FileNameShow)
myAudio.Play()
audioTimer.Enabled = True
gtbPosition.MaxValue = myAudio.Duration
klblStatus.Text = "Playing"
End If
End Sub
Public Shared Sub ShufflePlayList(ByVal source As ArrayList)
Try
Dim rnd As New Random()
Dim inx As Integer = source.Count - 1
While inx > 0
Dim position As Integer = rnd.[Next](inx)
Dim temp As Object = source(inx)
source(inx) = source(position)
source(position) = temp
System.Threading.Interlocked.Decrement(inx)
End While
Catch generatedExceptionName As Exception
End Try
End Sub
#End Region
#Region "Open, Play, Pause and Stop Click Events!"
Private Sub kbtnOpen_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kbtnOpen.Click
Load_Files("Audio")
End Sub
Private Sub kbtnPlay_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kbtnPlay.Click
If b_PlayState = False Then
FileNameShow = klstSongs.SelectedItem.ToString()
myAudio = New Audio(pathAudio & FileNameShow)
b_PlayState = True
b_EndOfMedia = False
gtbPosition.Value = myAudio.CurrentPosition
gtbPosition.MaxValue = myAudio.Duration
audioTimer.Enabled = True
myAudio.Play()
klblStatus.Text = "Playing"
Else
'b_PlayState = True
b_EndOfMedia = False
gtbPosition.Value = myAudio.CurrentPosition
gtbPosition.MaxValue = myAudio.Duration
audioTimer.Enabled = True
myAudio.Play()
klblStatus.Text = "Playing"
End If
End Sub
Private Sub kbtnPause_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kbtnPause.Click
If Not myAudio.Paused Then
b_PlayState = True
b_EndOfMedia = False
myAudio.Pause()
gtbPosition.Value = myAudio.CurrentPosition
gtbPosition.MaxValue = myAudio.Duration
audioTimer.Enabled = False
klblStatus.Text = "Paused"
End If
End Sub
Private Sub kbtnStop_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kbtnStop.Click
myAudio.Stop()
audioTimer.Enabled = False
klblTime.Text = "00:00 / 00:00"
klblPctDone.Text = "0%"
gtbPosition.Value = 0
b_PlayState = False
b_EndOfMedia = True
klblStatus.Text = "Stopped"
End Sub
#End Region
#Region "Clear, Previous, Next, Shuffle, Load and Create Click Events!"
Private Sub kbtnClearListBoxes_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles kbtnClearListBoxes.Click
klstPlaylist.Items.Clear()
klstSongs.Items.Clear()
b_PlayState = False
b_EndOfMedia = True
boolShuffle = False
fileIndex = Nothing
klblStatus.Text = "Waiting..."
klblTime.Text = "00:00 / 00:00"
klblPctDone.Text = "0%"
gtbPosition.Value = 0
End Sub
Private Sub kbtnPrevious_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles kbtnPrevious.Click
If (klstSongs.Items.Count - 1) < 0 Then Exit Sub 'If listbox is empty, then we exit the sub.
myAudio.Stop()
If fileIndex = 0 Then Exit Sub 'Exception prevention
b_PlayState = True
b_EndOfMedia = False
Me.klstSongs.SetSelected(fileIndex, False)
fileIndex -= 1
Me.klstSongs.SetSelected(fileIndex, True)
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
myAudio = New Audio(pathAudio & FileNameShow)
myAudio.Play()
audioTimer.Enabled = True
gtbPosition.MaxValue = myAudio.Duration
klblStatus.Text = "Playing"
End Sub
Private Sub kbtnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles kbtnNext.Click
If (klstSongs.Items.Count - 1) < 0 Then Exit Sub 'If listbox is empty, then we exit the sub.
myAudio.Stop()
If fileIndex = Me.klstSongs.Items.Count - 1 Then Exit Sub 'Exception prevention
b_PlayState = True
b_EndOfMedia = False
Me.klstSongs.SetSelected(fileIndex, False)
fileIndex += 1
Me.klstSongs.SetSelected(fileIndex, True)
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
myAudio = New Audio(pathAudio & FileNameShow)
myAudio.Play()
audioTimer.Enabled = True
gtbPosition.MaxValue = myAudio.Duration
klblStatus.Text = "Playing"
End Sub
Private Sub kbtnShuffle_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kbtnShuffle.Click
If b_PlayState Then Exit Sub 'If a song is playing, then we exit the sub.
If (klstSongs.Items.Count - 1) < 0 Then Exit Sub 'If listbox is empty, then we exit the sub.
For k As Integer = 0 To klstSongs.Items.Count - 1
mySongs.Add(klstSongs.Items.Item(k).ToString())
Next
If boolShuffle Then
klstSongs.Items.Clear()
ShufflePlayList(mySongs)
For i As Integer = 0 To mySongs.Count - 1
Dim fileName As String = mySongs(i).ToString()
klstSongs.Items.Add(fileName)
Next
Else
klstSongs.Items.Clear()
ShufflePlayList(mySongs)
For j As Integer = 0 To mySongs.Count - 1
Dim fileName As String = mySongs(j).ToString()
klstSongs.Items.Add(fileName)
Next
boolShuffle = True
End If
mySongs.Clear()
fileIndex = 0
klstSongs.SetSelected(fileIndex, True)
End Sub
Private Sub kbtnLoadAllPlayLists_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles kbtnLoadAllPlayLists.Click
If b_PlayState Then Exit Sub 'If a song is playing, then we exit the sub.
klstPlaylist.Items.Clear()
Try
Dim di As New DirectoryInfo(pathPlaylist)
Dim fName As FileInfo
Dim fNames() As FileInfo = di.GetFiles("*.m3u")
If (fNames IsNot Nothing) Then
For Each fName In fNames
klstPlaylist.Items.Add(fName.Name)
Next
End If
Catch ex As Exception
MessageBox.Show("Error, You must first create a playlist.", "No PlayLists Found!")
End Try
End Sub
Private Sub kbtnCreataPlaylist_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kbtnCreataPlaylist.Click
If (klstSongs.Items.Count - 1) < 0 Then
MessageBox.Show("SongList area must have at least 1" & vbCrLf _
& "item in it to create a playlist.", "Info to the Rescue!", MessageBoxButtons.OK, MessageBoxIcon.Information)
Exit Sub 'If listbox is empty, display message and exit the sub.
End If
Dim opl As New OpenFileDialog
With opl
.CheckPathExists = False
.CheckFileExists = False
.Filter = "Playlists |*.m3u"
.InitialDirectory = pathPlaylist
.RestoreDirectory = True
.Title = "Create Playlist file."
End With
If opl.ShowDialog = Windows.Forms.DialogResult.OK Then
If System.IO.Path.GetExtension(opl.FileName) <> ".m3u" Then
opl.FileName = opl.FileName & ".m3u"
End If
Dim sr As StreamWriter = File.CreateText(opl.FileName)
For i As Integer = 0 To klstSongs.Items.Count() - 1
sr.WriteLine(klstSongs.Items.Item(i).ToString())
Next
'Clean Up.
sr.Close()
sr = Nothing
End If
End Sub
Private Sub klstPlaylist_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles klstPlaylist.SelectedIndexChanged
If (klstPlaylist.Items.Count - 1) < 0 Then Exit Sub 'Exception prevention
If (b_PlayState = True) Then Exit Sub
klstSongs.Items.Clear() 'Clear the listbox.
Try
'Create a Reader and set it to the selected item.
Dim sr As StreamReader = New StreamReader(pathPlaylist & klstPlaylist.SelectedItem.ToString) '& ".m3u")
'Start reading and add each line to the listbox.
Do While sr.Peek() >= 0
FileNamePath = sr.ReadLine
Me.klstSongs.Items.Add(FileNamePath)
Loop
'Clean up the mess.
sr.Close()
sr = Nothing
'Set the listbox's selected fileindex to zero.
fileIndex = 0
klstSongs.SetSelected(fileIndex, True)
Catch ex As Exception 'Self-Explanetory.
MessageBox.Show("Error : " & ex.Message)
End Try
End Sub
#End Region
#Region "audioTimer Tick Event!"
Private Sub audioTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles audioTimer.Tick
If myAudio IsNot Nothing Then
Dim s As Integer = CInt(myAudio.CurrentPosition)
Dim h As Integer = s \ 3600
Dim m As Integer = (s - (h * 3600)) \ 60
s = s - (h * 3600 + m * 60)
Dim ss As Integer = CInt(myAudio.Duration)
Dim hh As Integer = ss \ 3600
Dim mm As Integer = (ss - (hh * 3600)) \ 60
ss = ss - (hh * 3600 + mm * 60)
gtbPosition.Value = myAudio.CurrentPosition
klblTime.Text = [String].Format("{0:D2}:{1:D2} / {2:D2}:{3:D2}", m, s, mm, ss)
klblPctDone.Text = Int((gtbPosition.Value / gtbPosition.MaxValue) * 100).ToString() & "%"
Else
klblTime.Text = "00:00 / 00:00"
klblPctDone.Text = "0%"
klblStatus.Text = "Stopped"
End If
If myAudio.CurrentPosition = myAudio.Duration Then
myAudio.SeekStopPosition(myAudio.Duration, SeekPositionFlags.AbsolutePositioning)
Check_Next_Media()
End If
End Sub
#End Region
#Region "gTrackbar Events!'"
Private Sub gtbPosition_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles gtbPosition.MouseDown
myAudio.Pause()
audioTimer.Enabled = False
End Sub
Private Sub gtbPosition_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles gtbPosition.MouseUp
myAudio.CurrentPosition = gtbPosition.Value
myAudio.Play()
audioTimer.Enabled = True
End Sub
Private Sub gtbVolume_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles gtbVolume.MouseDown
thisAudio = myAudio
End Sub
Private Sub gtbVolume_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles gtbVolume.MouseUp
'thisAudio = myAudio
thisAudio.Volume = gtbVolume.Value
End Sub
#End Region
#Region "frmTagInfo Subs!"
Private Sub kbtnTagInfo_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kbtnTagInfo.Click
Dim frm As New frmTagInfo
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
Dim fileInfo As New clsID3v1Reader(pathAudio & FileNameShow)
frm.lblTitle.Text &= fileInfo.TrackTitle
frm.lblArtist.BackColor = Color.LightGray
frm.lblArtist.Text &= fileInfo.Artist
frm.lblGenre.Text &= GetGenre(fileInfo.Genre)
Dim ss As Integer = CInt(myAudio.Duration)
Dim hh As Integer = ss \ 3600
Dim mm As Integer = (ss - (hh * 3600)) \ 60
ss = ss - (hh * 3600 + mm * 60)
frm.lblLength.BackColor = Color.LightGray
frm.lblLength.Text &= [String].Format("{0:D2}:{1:D2}:{2:D2}", hh, mm, ss)
frm.lblSize.Text &= GetFileLengthMP3(intData)
frm.lblYear.BackColor = Color.LightGray
frm.lblYear.Text &= fileInfo.Year
frm.txtComment.Text = fileInfo.Comment
frm.Show()
End Sub
Public Function GetGenre(ByVal strGenre As String)
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
Dim fileInfo As New clsID3v1Reader(pathAudio & FileNameShow)
Select Case fileInfo.Genre
Case 0
strGenre = "Blues"
Case 1
strGenre = "Classic Rock"
Case 2
strGenre = "Country"
Case 3
strGenre = "Dance"
Case 4
strGenre = "Disco"
Case 5
strGenre = "Funk"
Case 6
strGenre = "Grundge"
Case 7
strGenre = "HipHop"
Case 8
strGenre = "Jazz"
Case 9
strGenre = "Metal"
Case 10
strGenre = "NewAge"
Case 11
strGenre = "Oldies"
Case 12
strGenre = "Other"
Case 13
strGenre = "Pop"
Case 14
strGenre = "RnB"
Case 15
strGenre = "Rap"
Case 16
strGenre = "Reggae"
Case 17
strGenre = "Rock"
Case 18
strGenre = "Techno"
Case 19
strGenre = "Industrial"
Case 20
strGenre = "Alternative"
Case 21
strGenre = "Ska"
Case 22
strGenre = "Death Metal"
Case 23
strGenre = "Pranks"
Case 24
strGenre = "Soundtrack"
Case 25
strGenre = "EuroTechno"
Case 26
strGenre = "Ambient"
Case 27
strGenre = "Triphop"
Case 28
strGenre = "Vocal"
Case 29
strGenre = "JazzFunk"
Case 30
strGenre = "Fusion"
Case 31
strGenre = "Trance"
Case 32
strGenre = "Classical"
Case 33
strGenre = "Instrumental"
Case 34
strGenre = "Acid"
Case 35
strGenre = "House"
Case 36
strGenre = "Game"
Case 37
strGenre = "Sound Clip"
Case 38
strGenre = "Gospel"
Case 39
strGenre = "Noise"
Case 40
strGenre = "AlternRock"
Case 41
strGenre = "Bass"
Case 42
strGenre = "Soul"
Case 43
strGenre = "Punk"
Case 44
strGenre = "Space"
Case 45
strGenre = "Meditative"
Case 46
strGenre = "InstrumentalPop"
Case 47
strGenre = "InstrumentalRock"
Case 48
strGenre = "Ethnic"
Case 49
strGenre = "Gothic"
Case 50
strGenre = "Darkwave"
Case 51
strGenre = "TechnoIndustrial"
Case 52
strGenre = "Electronic"
Case 53
strGenre = "PopFolk"
Case 54
strGenre = "Eurodance"
Case 55
strGenre = "Dream"
Case 56
strGenre = "SouthernRock"
Case 57
strGenre = "Comedy"
Case 58
strGenre = "Cult"
Case 59
strGenre = "Gangsta"
Case 60
strGenre = "Top 40"
Case 61
strGenre = "ChristainRap"
Case 62
strGenre = "PopFunk"
Case 63
strGenre = "Jungle"
Case 64
strGenre = "NativeAmerican"
Case 65
strGenre = "Cabaret"
Case 66
strGenre = "NewWave"
Case 67
strGenre = "Psychadelic"
Case 68
strGenre = "Rave"
Case 69
strGenre = "Showtunes"
Case 70
strGenre = "Trailer"
Case 71
strGenre = "LoFi"
Case 72
strGenre = "Tribal"
Case 73
strGenre = "AcidPunk"
Case 74
strGenre = "AcidJazz"
Case 75
strGenre = "Polka"
Case 76
strGenre = "Retro"
Case 77
strGenre = "Musical"
Case 78
strGenre = "RocknRoll"
Case 79
strGenre = "Hardrock"
Case 80
strGenre = "Folk"
Case 81
strGenre = "FolkRock"
Case 82
strGenre = "NationalFolk"
Case 83
strGenre = "Swing"
Case 84
strGenre = "FastFusion"
Case 85
strGenre = "Bebob"
Case 86
strGenre = "Latin"
Case 87
strGenre = "Revival"
Case 88
strGenre = "Celtic"
Case 89
strGenre = "Bluegrass"
Case 90
strGenre = "Avantgarde"
Case 91
strGenre = "GothicRock"
Case 92
strGenre = "ProgressiveRock"
Case 93
strGenre = "PsychedelicRock"
Case 94
strGenre = "SymphonicRock"
Case 95
strGenre = "SlowRock"
Case 96
strGenre = "BigBand"
Case 97
strGenre = "Chorus"
Case 98
strGenre = "EasyListening"
Case 99
strGenre = "Acoustic"
Case 100
strGenre = "Humour"
Case 101
strGenre = "Speech"
Case 102
strGenre = "Chanson"
Case 103
strGenre = "Opera"
Case 104
strGenre = "ChamberMusic"
Case 105
strGenre = "Sonata"
Case 106
strGenre = "Symphony"
Case 107
strGenre = "BootyBass"
Case 108
strGenre = "Primus"
Case 109
strGenre = "PornGroove"
Case 110
strGenre = "Satire"
Case 111
strGenre = "SlowJam"
Case 112
strGenre = "Club"
Case 113
strGenre = "Tango"
Case 114
strGenre = "Samba"
Case 115
strGenre = "Folklure"
Case 116
strGenre = "Ballad"
Case 117
strGenre = "PowerBallad"
Case 118
strGenre = "RhythmicSoul"
Case 119
strGenre = "Freestyle"
Case 120
strGenre = "Duet"
Case 121
strGenre = "PunkRock"
Case 122
strGenre = "DrumSolo"
Case 123
strGenre = "ACappella"
Case 124
strGenre = "EuroHouse"
Case 125
strGenre = "DanceHall"
Case 126
strGenre = "Goa"
Case 127
strGenre = "DrumBass"
Case 128
strGenre = "ClubHouse"
Case 129
strGenre = "Hardcore"
Case 130
strGenre = "Terror"
Case 131
strGenre = "Indie"
Case 132
strGenre = "BritPop"
Case 133
strGenre = "Negerpunk"
Case 134
strGenre = "PolskPunk"
Case 135
strGenre = "Beat"
Case 136
strGenre = "ChristianGangsta"
Case 137
strGenre = "HeavyMetal"
Case 138
strGenre = "BlackMetal"
Case 139
strGenre = "Crossover"
Case 140
strGenre = "ContemporaryChristian"
Case 141
strGenre = "ChristianRock"
Case 142
strGenre = "Merengue"
Case 143
strGenre = "Salsa"
Case 144
strGenre = "ThrashMetal"
Case 145
strGenre = "Anime"
Case 146
strGenre = "JPop"
Case 147
strGenre = "SynthPop"
Case 255
strGenre = "None"
End Select
Return strGenre
End Function
Private Function GetFileLengthMP3(ByVal fileLength As String) As String
Dim myFile As FileInfo
FileNameShow = CStr(klstSongs.SelectedItem.ToString())
myFile = New FileInfo(pathAudio & FileNameShow)
Dim length As Long = myFile.Length
fileLength = Format(Int(length / 1024), "0,000") & " KB"
Return fileLength
End Function
#End Region
#Region "frmAbout!"
Private Sub kbtnAbout_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles kbtnAbout.Click
Dim frm As New frmAbout
frm.Show()
End Sub
#End Region
End Class