重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
这是一个有趣的问题 我保证某些聪明的编程好手会建议我使用委托 在这种事情发生之前 让我们 先探究一下这个问题的几种解决方案 假定我有两个窗体 每个窗体都有两个 textbox 控件 txt stData 和 txt ndData 我怎样才能保持这两个窗体中的控件同步呢?对于我们讨论的问题来说 有两个或十个窗体都不重要 问题是相同的 第一个办法相对简单 事实上 它甚至比我们直接使用委托更为简单 我想委托有时会给人用牛刀杀鸡的感觉 首先 我建立一个类它包含我希望与应用程序中的所有窗体共享的属性(参见 Figure ) 例如 MyData 和 MoreData 拥有每个窗体都能显示的数据 我将很快回到这个类来 第二 正如我早先提到的我用相同的控件(txt stData 和 txt ndData)建立了两个窗体 你可以参考 Figure 的布局 两个窗体都有完全相同的数据 并且我将很快解释为什么 下面 我建立一个名为 modGeneral 的模块并加入下面一行代码 Friend DataStuff As DataClass 这一行代码为我的新类 DataClass 创建了一个友元变量 使你可以完全访问程序集 对这个简单例子来说 也就是指完整的应用程序 然后我添加了下面的代码到 Form 的 Load 事件 DataStuff = New DataClass Me txt stData DataBindings Add( Text DataStuff MyData ) Me txt ndData DataBindings Add( Text DataStuff MoreData ) 第一行建立一个 DataClass 新实例 下面两行代码将数据绑定到 textbox 控件 对这个窗体而言 就这么些操作! 现在 你怎样让它们与 Form 和其它窗体上的数据同步呢?将下面两行加入到 Form 的窗体load 事件中去 Me txt stData DataBindings Add( Text DataStuff MyData ) Me txt ndData DataBindings Add( Text DataStuff Moredata ) 这个方法容易确保所有窗体上的几乎任何类型的数据处于同步状态 你可以简单地将控件绑定到某个类的相同实例上 这就行了 现在来看另一个方法 我创建了一个名为 frmBase 的新窗体 这时我在上面放一个 textbox (txtNextData)和 label 我想 让应用程序的每个窗体都共享这个 textbox 和 label 并且我希望它们互相之间保持同步 于是我重建这个工程 通过从新的 frmBase 中的继承 我创建了 Form 和Form 因此它们继承了所有新的控件 但是我怎样能保持这些控件同步呢?这时必须写一点代码去达到此效果 这些代码在单个的类中 通过简单地调用一个函数而被复用 Figure 中的代码展示了这个称为 modGeneral 模块 它的第一个任务是定义两个变量 MyForms 和 localNextData MyForms 是一个 集合 它将包含我想要同步的窗体列表 localNextData变量将储存所有我想要在窗体里显示的数据 注意这些变量可以驻留于某个类中而不是某个模块里 AddForm 过程来自 modGeneral 带一个窗体实例参数 并将其加入 MyForms 集合中 我将在UpdateControlsNextData 过程中使用这个 集合以决定哪些窗体要更新 AddForm 也调用UpdateControlsNextData 来确保一个新窗体是用正确的数据更新的 modGeneral 中的其它代码是 NextData 属性 这些属性的 set 存取器更新 localNextData 并也调用 UpdateControlsNextData 去同步所有窗体 这时所有我需要做的是 在想要改变它时设置 NextData 通过调用 UpdateControlsNextData 所有窗体将被更新 第三个方法是定制链接 它是第二个方法的精华版 我创建它以获得多一些窗体控件处理的灵活性 例如 我只想跟踪和处理某些窗体 这些窗体包含必须同步的控件 这个方法 还可以让我自己定义拟同步的控件 并且只处理这些控件的窗体 我为这个办法添加了另一个模块 (modGeneralv ) 如 Figure 所示 该模块包括一个集合(MyFormsToUpdate) 其中包含所有我想要同步的窗体 这个模块 还有一个新的数组 (ControlsToUpdate) 它提供一个我要同步的控件列表 该数组的定义如下 Private ControlsToUpdate() As String = { txtCustomer txtAddress txtName } 这个模块里有一个新的替代 AddForm 的改良版本 叫做 AddFormToUpdate 该方法工作方式与AddForm 类似 但现在它只添加拥有一个或多 个 ControlsToUpdate 数组中控件的窗体 因此只有那些含有特定控件的窗体在更新集合中 它使我可以从每个窗体中调用该函数 如果我决定以后添加某个特定的控件 它将会被自动添加到窗体列表 我只需对窗体代码做细小的改动便可以实现 这个模块还包含 UpdateControlsOnAllForms 过程 它执行更新 代替上一个方法中使用的一个应用程序级变量 我现在使用主窗体的概念 因此我可以将那个窗体的值拷贝到集合中的所有其它窗体 UpdateControlsOnAllForms 其实就是一组简单的 For Nexts 循环遍历某个窗体的所有控件 找到需要更新的控体 并更新它们 为了在我的窗体中实现这一功能 我在窗体的 Load 事件中加入了这一行代码 AddFormToUpdate(Me) 另外一种可选的方法 我可以将它添加到构造函数 这一行代码将把当前窗体实例添加到集合进行更新 现在让我们考察单个事件过程 Private Sub txt_Leave(ByVal sender As Object _ ByVal e As System EventArgs) Handles txtAddress Leave _ txtCustomer Leave txtName Leave UpdateControlsOnAllForms(Me) End Sub 这段代码将我想要同步的所有三个控件 (txtAddress txtCustomer 和 txtName)的 Leave 事件捆绑到一个事件句柄上 这时我可以添加一行代码 来调用 UpdateControlsOnAllForms Me 被传递到该过程调用 从而导致其它窗体与该窗体同步 现在我有三个版本的代码 它们都可以同步窗体中控件 因此我可以进行选择 我可能已经使用了自定义事件 在 DataClass 中定义某个事件并让每个窗体都预订它 然后当这个事件触发时 这些窗体可以从每个事件句柄中获取新的数据并设置适当的控件 但是这样做所需的代码量一点也不会比第一种方法中将控件绑定到类来得少 我可以构建单个实现更新的过程 并将该过程放到某个模块中 我需要向该过程传递窗体实例来实现更新 我可以用类中的某个事件句柄触发这个过程 此过程看起来就像这样 Sub UpdateControls(ByVal ThisForm As frmBase) With ThisForm txtNextData Text = localNextData End With End Sub ThisForm 参数被定义为 frmBase 类型 以便它可以访问 IntelliSense 并获得窗体的自定义属性 简单地将它写成 Form 将无法显示 frmBase 中的属性及其派生窗体 另一选择是使用委托 当然 委托可以让我将委托调用重定向到每个窗体的方法上 如果我使用多播机制 那么我可以让每个窗体都处理该事件并更新相应的控件 用委托建立这样的功能听起来确实简单 但 对我来说它更麻烦且没有实践价值 此外 与第三个方法中的 For Next 循环嵌套相比 这个代码并不难理解 毕竟 一个应用程序花费最大的部分仍然是它的维护 lishixinzhi/Article/program/net/201311/11593
网站建设哪家好,找成都创新互联公司!专注于网页设计、网站建设、微信开发、微信小程序定制开发、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了安顺免费建站欢迎大家使用!
思路很简单可以定义一个结构LyricStructure Lyric
Dim Time As Single
Dim Content As String
End Structure声明一个列表 Private Lyrics As New List(Of Lyric)然后以文本方式把歌词文件读入一个变量 并对它进行分析 分别把时间和歌词内容存入一个Lyric,并加入Lyrics中。代码如下:(假设歌曲文件的路径为path)Dim LrcPath As String== IO.Path.GetDirectoryName(cPath) "/" IO.Path.GetFileNameWithoutExtension(cPath) ".lrc"If IO.File.Exists(LrcPath= True Then AnalysisLyric() Private Sub AnalysisLyric()
Lyrics.Clear() '先清空列表
Dim tm As Byte
Dim sr As New IO.StreamReader(LrcPath, System.Text.Encoding.Default) '读取歌词文件
Do While sr.EndOfStream = False '判断是否处于文件流末尾
Dim tmpStr As String = sr.ReadLine '读取一行
If tmpStr.Length 5 Then Continue Do '长度小于5则跳过,进行下一次循环
Select Case Mid(tmpStr, 2, 2) '判断第2-3个字符 因为歌词里的注释都是[ti:***]类似的结构
Case "ti"
lTitle = Mid(tmpStr, 5, tmpStr.Length - 5)
Case "ar"
lArtist = Mid(tmpStr, 5, tmpStr.Length - 5)
Case "al"
lAlbum = Mid(tmpStr, 5, tmpStr.Length - 5)
Case "by"
lAuthor = Mid(tmpStr, 5, tmpStr.Length - 5)
Case Else '如果不为以上的内容 则为歌词正文,进行以下操作
If Not Mid(tmpStr, 1, 6) Like "?##:##" Then Continue Do
Dim time(-1) As String '因为有时歌词是以[00:00.00][00:00.00]**** 这样歌词把多个时间存放在一起的 ,所以定义一个数组来存放歌词
Do '因为不确定时间的个数,所以此处必须循环判断
tm = InStr(tmpStr, "]") '因为歌词时间有时是[00:00.00]形式,有时是[00:00]形式,所以不能单纯的截取第几个字符 ,我是根据查找']'字符来进行判断的
ReDim Preserve time(time.GetUpperBound(0) + 1) 为time数组重新分配大小
time(time.GetUpperBound(0)) = Mid(tmpStr, 1, tm) 'time.GetUpperBound(0)返回数组的第一维的最大下标
tmpStr = IIf(tmpStr.Length = tm, " ", Mid(tmpStr, tm + 1)) '歌词内容
Loop While Mid(tmpStr, 1, 6) Like "?##:##" '如果截取剩下的部分依然匹配的话继续循环
For Each t In time '为每个时间都创建一个Lyric变量
Dim ln As Lyric
ln.Time = SwitchTime(Mid(t, 2, t.Length - 2))
ln.Content = tmpStr
Lyrics.Add(ln)
Next
End Select
Loop
sr.Close() 关闭流
Sort() '把所有Lyric按时间顺序排序
End Sub Private Function SwitchTime(ByVal time As String) As Single ‘这个函数是用来把00:00.00格式的时间转化成以秒数显示的数值
Dim tm As Single
Dim minute As Single = Val(Mid(time, 1, 2))
Dim second As Single = Val(Mid(time, 4, 5))
tm = minute * 60 + second
Return tm
End Function Private Sub Sort()
For i = 0 To Lyrics.Count - 2
For j = i To Lyrics.Count - 1
If Lyrics(i).Time Lyrics(j).Time Then
Dim tm As Lyric = Lyrics(i)
Lyrics(i) = Lyrics(j)
Lyrics(j) = tm
End If
Next
Next
End Sub 接下来是显示歌词的问题了 ,只要有每句歌词和对应的时间,那么问题就好办了。你可以用Windows Media Player控件返回的时间和每句歌词的时间做比较,来判断应该显示那一句。代码是很久前写的 ,那时没加注释,都是刚刚加上去的哟,你可以根据你的实际情况自己修改,有什么不懂的地方可以继续问我哈~~
可以稍微改下,预读两句歌词的时间范围,时间大于第一句的起始点,小于第二句的起始点,那么显示第一句,
Public Class Form1
Dim soundname As String()
Dim i As Integer
Dim j, l As Boolean
Dim k As Integer
Dim filename As String '取歌曲的名字
Dim path As String()
Dim s, m As Integer
Dim luj As String
Dim count As Integer '用来声明选择歌曲的数目
Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
selectsound()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim g As Graphics
g = Graphics.FromHwnd(Me.Handle)
Dim mfont As New Font("宋体", 20)
Dim mstringformat As New StringFormat
mstringformat.Alignment = StringAlignment.Center
mstringformat.LineAlignment = StringAlignment.Center
g.DrawString("X071616", mfont, Brushes.Black, 75, 328, mstringformat)
If ListBox1.Items.Count = 0 Then selectsound() : Exit Sub
playsound()
End Sub
Private Sub TrackBar1_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar1.Scroll
Me.AxWindowsMediaPlayer1.settings.volume = TrackBar1.Value
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
If Timer1.Enabled = False Then
Timer1.Enabled = True
Else
Timer1.Enabled = False
End If
If i = 0 Then
Me.AxWindowsMediaPlayer1.Ctlcontrols.pause()
i = 1
Button3.Text = "继续"
Exit Sub
End If
If i = 1 Then
Me.AxWindowsMediaPlayer1.Ctlcontrols.play()
Button3.Text = "暂停"
i = 0
Exit Sub
End If
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
j = True
playsound()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.AxWindowsMediaPlayer1.Ctlcontrols.stop()
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim string1, ss, sss As String
string1 = ListBox1.SelectedItem.ToString.Substring(ListBox1.SelectedItem.ToString.LastIndexOf("\") + 1)
filename = string1.Substring(0, string1.LastIndexOf("."))
luj = ListBox1.SelectedItem.ToString.Substring(0, ListBox1.SelectedItem.ToString.LastIndexOf(".")) + ".lrc"
Me.HScrollBar1.Value = Me.AxWindowsMediaPlayer1.Ctlcontrols.currentPosition / (Me.AxWindowsMediaPlayer1.currentMedia.duration + 0.001) * 1000
ss = Me.AxWindowsMediaPlayer1.Ctlcontrols.currentPositionString
Me.Label1.Text = ss
If Dir(luj) Nothing Then
Dim fr As System.IO.StreamReader = New System.IO.StreamReader(luj, System.Text.Encoding.Default)
sss = fr.ReadLine '我们读取的第一行歌词
While (sss "")
If (sss.LastIndexOf(ss) -1) Then '时间匹配了歌词中的时间
Me.TextBox1.Text = sss.Substring(sss.LastIndexOf("]") + 1)
Form2.TextBox1.Text = Me.TextBox1.Text
End If
sss = fr.ReadLine
End While
Else
TextBox1.Text = "Not Find! 请从网上下载歌词!"
Form2.TextBox1.Text = "Not Find! 请从网上下载歌词!"
End If
Label1.Text = "当前进度:" + Me.AxWindowsMediaPlayer1.Ctlcontrols.currentPositionString
End Sub
Private Sub HScrollBar1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar1.Scroll
Me.AxWindowsMediaPlayer1.Ctlcontrols.currentPosition = Me.HScrollBar1.Value / 1000 * Me.AxWindowsMediaPlayer1.currentMedia.duration
End Sub
Private Sub Button7_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
Me.AxWindowsMediaPlayer1.Ctlcontrols.fastForward()
End Sub
Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
Me.AxWindowsMediaPlayer1.Ctlcontrols.fastReverse()
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
i = 0
j = False
l = False
Label2.Text = "歌曲名: "
Label3.Text = "歌曲演唱者: "
Label4.Text = "歌曲描述: "
Label5.Text = "歌曲类型: "
Label6.Text = "歌曲大小: "
Button8.Enabled = False
End Sub
Private Sub ListBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.DoubleClick
Me.AxWindowsMediaPlayer1.URL = ListBox1.Items(ListBox1.SelectedIndex)
Me.AxWindowsMediaPlayer1.Ctlcontrols.play()
Label2.Text = "歌曲名: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Title")
Label3.Text = "歌曲演唱者: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Author")
Label4.Text = "歌曲描述: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Description")
Label5.Text = "歌曲类型: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("FileType")
Label6.Text = "歌曲大小: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("FileSize")
Timer1.Start()
End Sub
Private Sub playsound()
Timer1.Stop()
TrackBar1.Value = Me.AxWindowsMediaPlayer1.settings.volume
If j = False Then
Me.AxWindowsMediaPlayer1.URL = ListBox1.Items(ListBox1.SelectedIndex)
ElseIf j = True Then
k = (ListBox1.SelectedIndex + 1) Mod soundname.Length
Me.AxWindowsMediaPlayer1.URL = ListBox1.Items(k)
j = False
End If
ListBox1.SelectedIndex = k
Me.AxWindowsMediaPlayer1.Ctlcontrols.play()
Label2.Text = "歌曲名: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Title")
Label3.Text = "歌曲演唱者: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Author")
Label4.Text = "歌曲描述: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Description")
Label5.Text = "歌曲类型: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("FileType")
Label6.Text = "歌曲大小: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("FileSize")
Timer1.Start()
End Sub
Private Sub selectsound()
Dim open As New OpenFileDialog
Dim i As Integer
With open
.Filter = "所有mp3文件(*.mp3)|*.mp3|所有wma文件(*.wma)|*.wma"
.Multiselect = True
.Title = "请选择歌曲"
End With
If (open.ShowDialog = Windows.Forms.DialogResult.OK) Then
soundname = open.FileNames
For i = 0 To soundname.GetUpperBound(0)
ListBox1.Items.Add(soundname(i))
Next
ListBox1.SelectedIndex = 0
End If
End Sub
Private Sub AxWindowsMediaPlayer1_PlayStateChange(ByVal sender As System.Object, ByVal e As AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) Handles AxWindowsMediaPlayer1.PlayStateChange
If AxWindowsMediaPlayer1.playState = WMPLib.WMPPlayState.wmppsMediaEnded Then
j = True
Timer2.Start()
End If
End Sub
Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
playsound()
Timer2.Stop()
End Sub
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
Timer1.Stop()
If ListBox1.SelectedIndex = 0 Then
Me.AxWindowsMediaPlayer1.URL = ListBox1.Items(soundname.Length - 1)
ListBox1.SelectedIndex = (soundname.Length - 1)
Else
Me.AxWindowsMediaPlayer1.URL = ListBox1.Items((ListBox1.SelectedIndex Mod soundname.Length) - 1)
ListBox1.SelectedIndex = (ListBox1.SelectedIndex Mod soundname.Length) - 1
End If
Me.AxWindowsMediaPlayer1.Ctlcontrols.play()
Label2.Text = "歌曲名: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Title")
Label3.Text = "歌曲演唱者: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Author")
Label4.Text = "歌曲描述: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("Description")
Label5.Text = "歌曲类型: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("FileType")
Label6.Text = "歌曲大小: " + Me.AxWindowsMediaPlayer1.currentMedia.getItemInfo("FileSize")
Timer1.Start()
End Sub
Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
Form2.Show()
End Sub
End Class