• 编程实战——电影管理器之XML存储电影信息数据


    但凡管理器之类的软件,存储数据是必不可少的。存储数据的话,有几种选择。一是用数据库,把数据存储到数据库里;一是用文本文件,把数据存储到文本文件里;一种是利用XML文件,把数据对象转换为XML后,存储到XML文件(实际上也是文本文件)。

    把数据对象和XML文件对应起来,有一个术语,称之为XML序列化。参看之前写的文章“利用XML序列化实现程序配置文件”,“简述Xml.Serialization如何序列化对象到XML文件

    在本软件的设计中,设计了两种基本的数据对象

    一是电影对象(类clsFilm),存储一部电影的信息,如:中文名(DesChineseName)、英文名(DesEnglishName)、时长(DesDuration)等

    二是电影合集对象(类clsFilmCollection),存储多部电影合集的信息,如:中文名(DesChineseName)、文件个数(DesCount)、文件总大小(DesTotalSize)等。

    在设计上,电影合集对象(类clsFilmCollection)包含子集合(ChildFilmItem),子集合(ChildFilmItem)中的元素可以是电影对象(类clsFilm)也可以是电影集合对象(类clsFilmCollection)。

    例如:我现在有一个名为“欧美”的电影集合对象,子集合包含了名为“遗落战境”的电影对象和名为“变形金刚”的电影集合对象。而“变形金刚”的电影集合对象又包含了名为“变形金刚壹”、“变形金刚贰”、“变形金刚叁”的电影对象。

    把这两种不同的类(类clsFilm和类clsFilmCollection)统一到集合(ChildFilmItem)中,采用的办法是让它们都实现I_Film接口(或者是定义一个抽象基类,两个类都去继承这个抽象基类)。如下面代码所示

     
    Public Interface I_Film
        Property Title As String
        ReadOnly Property FilmImage As Image
        Property Des1 As String
        Property Des2 As String
        Property Des3 As String
        Property Des4 As String
        Function Hint() As List(Of I_Film)
        Function [GetType]() As Type
    End Interface

    Public Class clsFilm
        Implements I_Film

        Private _Des(3) As String
        Private _Title As String
        Private _ImageFile As String
        Private _Image As Image

        Private _FileName As String

        Public Sub New()
            _Image = Nothing
        End Sub

        Public Property FileName As String
            Set(value As String)
                _FileName = value
            End Set
            Get
                Return _FileName
            End Get
        End Property

        Public Property DesEnglishName As String Implements I_Film.Des1
            Get
                Return _Des(0)
            End Get
            Set(value As String)
                _Des(0) = value
            End Set
        End Property

        Public Property DesAudioLanguage As String Implements I_Film.Des2
            Get
                Return _Des(1)
            End Get
            Set(value As String)
                _Des(1) = value
            End Set
        End Property

        Public Property DesResolution As String Implements I_Film.Des3
            Get
                Return _Des(2)
            End Get
            Set(value As String)
                _Des(2) = value
            End Set
        End Property

        Public Property DesDuration As String Implements I_Film.Des4
            Get
                Return _Des(3)
            End Get
            Set(value As String)
                _Des(3) = value
            End Set
        End Property

        Public Property ImageFile As String
            Get
                Return _ImageFile
            End Get
            Set(value As String)
                _ImageFile = value
            End Set
        End Property

        Public ReadOnly Property FilmImage As System.Drawing.Image Implements I_Film.FilmImage
            Get
                If _Image Is Nothing Then
                    _Image = Image.FromFile(_ImageFile).GetThumbnailImage(100, 140, Nothing, System.IntPtr.Zero)
                End If
                Return _Image
            End Get
        End Property

        Public Property DesChineseName As String Implements I_Film.Title
            Get
                Return _Title
            End Get
            Set(value As String)
                _Title = value
            End Set
        End Property

        Public Function Hint() As List(Of I_Film) Implements I_Film.Hint
            Return Nothing
        End Function

        Public Function GetType1() As System.Type Implements I_Film.GetType
            Return Me.GetType
        End Function
    End Class

    Public Class clsFilmCollection
        Implements I_Film

        Private _Title As String
        Private _Des(3) As String

        Private _ImageFile As String
        Private _Image As Image

        Public ChildFilmItem As List(Of I_Film)

        Public Sub New()
            ChildFilmItem = New List(Of I_Film)
        End Sub

        Public Property DesEnglishName As String Implements I_Film.Des1
            Get
                Return _Des(0)
            End Get
            Set(value As String)
                _Des(0) = value
            End Set
        End Property

        Public Property DesLanguage As String Implements I_Film.Des2
            Get
                Return _Des(1)
            End Get
            Set(value As String)
                _Des(1) = value
            End Set
        End Property

        Public Property DesCount As String Implements I_Film.Des3
            Get
                Return _Des(2)
            End Get
            Set(value As String)
                _Des(2) = value
            End Set
        End Property

        Public Property DesTotalSize As String Implements I_Film.Des4
            Get
                Return _Des(3)
            End Get
            Set(value As String)
                _Des(3) = value
            End Set
        End Property

        Public Property ImageFile As String
            Get
                Return _ImageFile
            End Get
            Set(value As String)
                _ImageFile = value
            End Set
        End Property

        Public ReadOnly Property FilmImage As System.Drawing.Image Implements I_Film.FilmImage
            Get
                If _Image Is Nothing Then
                    _Image = Image.FromFile(_ImageFile).GetThumbnailImage(100, 140, Nothing, System.IntPtr.Zero)
                End If
                Return _Image
            End Get
        End Property

        Public Function Hint() As List(Of I_Film) Implements I_Film.Hint
            Return ChildFilmItem
        End Function

        Public Property DesChineseName As String Implements I_Film.Title
            Get
                Return _Title
            End Get
            Set(value As String)
                _Title = value
            End Set
        End Property

        Public Function GetType1() As System.Type Implements I_Film.GetType
            Return Me.GetType
        End Function
    End Class

    把这两个类(clsFilm和clsFilmCollection)实现相同的接口(I_Film),一是可以统一到一个集合中,另一个是在渲染到主画面的时候,只要针对接口I_Film编写代码即可。比方说,接口I_Film的Des4属性,在渲染的时候,只要把这个属性渲染到第四行即可。而相应的,类clsFilm对应的属性是DesDuration属性(时长),类clsFilmCollection对应的属性是DesTotalSize(总文件大小)。

    还需要一个管理类,来管理它们,于是初步写了下面的类

     
    Public Class clsFilmManager
        Private _Films As List(Of I_Film)

        Public Sub New()
            _Films = New List(Of I_Film)
        End Sub
    End Class

    接着用XmlSerializer类尝试把上面这个类序列化到XML文件。但是报错,没有序列化成功。在网上查了相关的资料后,有人说XmlSerializer类不支持序列化接口的集合,在把接口改成抽象类之后,就可以了。OK!!把接口改成抽象类试了试,还是不行(代码就不贴了)。

    仔细想想,接口I_Film,有两个类clsFilm和clsFilmCollection实现它。在序列化的时候,XmlSerializer类可能无法明确的知道该接口对应是哪个类而导致序列化失败。

    那就自己写一个XML的转换的类(clsFilmXml),实现数据对象和XML文件转换的功能。

    先定义两个内部变量,_FileName和FilmCollections。FilmCollections是个clsFilmCollection集合。在我的设计里,程序启动的时候包含“欧美”、“动画”、“国内”、“港台”、“日韩”、“纪录”这六个电影合集。每个合集下再各自包含电影或电影合集

      
        Private _FileName As String
        Public FilmCollections As List(Of clsFilmCollection)

        Public Sub New()
            FilmCollections = New List(Of clsFilmCollection)
        End Sub

    接下来是Load方法,把XML文件转换为电影数据对象。调用两个私有方法:_XML2Film方法,把XML文件中的FilmInfo标签转换为clsFilm对象;_XML2FilmCollection方法,把XML文件中的FilmCollection标签转换为clsFilmCollection对象。在_XML2FilmCollection方法中,还对子标签进行判断,如果是FilmInfo标签,则调用_XML2Film方法获得clsFilm对象;如果是FilmCollection标签,则再调用_XML2FilmCollection方法获得clsFilmCollection对象。

      
        Public Sub Load(XmlFile As String)
            _FileName = XmlFile

            Dim Document As New Xml.XmlDocument
            Document.Load(_FileName)

            Dim Films As Xml.XmlElement

            For Each Films In Document.DocumentElement.ChildNodes
                If Films.Name = "FilmCollection" Then FilmCollections.Add(_XML2FilmCollection(Films))
            Next
        End Sub 

        Private Function _XML2Film(Element As Xml.XmlElement) As clsFilm
            Dim Film As New clsFilm

            Dim ChildElement As Xml.XmlElement

            For Each ChildElement In Element.ChildNodes
                Select Case ChildElement.Name
                    Case "FileName"
                        Film.FileName = ChildElement.InnerText
                    Case "ImageFile"
                        Film.ImageFile = ChildElement.InnerText
                    Case "DesChineseName"
                        Film.DesChineseName = ChildElement.InnerText
                    Case "DesEnglishName"
                        Film.DesEnglishName = ChildElement.InnerText
                    Case "DesDuration"
                        Film.DesDuration = ChildElement.InnerText
                    Case "DesResolution"
                        Film.DesResolution = ChildElement.InnerText
                    Case "DesAudioLanguage"
                        Film.DesAudioLanguage = ChildElement.InnerText
                End Select 
            Next

            Return Film
        End Function

        Private Function _XML2FilmCollection(Element As Xml.XmlElement) As clsFilmCollection
            Dim Films As New clsFilmCollection

            Dim ChildElement As Xml.XmlElement

            For Each ChildElement In Element.ChildNodes
                Select Case ChildElement.Name
                    Case "ImageFile"
                        Films.ImageFile = ChildElement.InnerText
                    Case "DesChineseName"
                        Films.DesChineseName = ChildElement.InnerText
                    Case "DesEnglishName"
                        Films.DesEnglishName = ChildElement.InnerText
                    Case "DesLanguage"
                        Films.DesLanguage = ChildElement.InnerText
                    Case "DesCount"
                        Films.DesCount = ChildElement.InnerText
                    Case "DesTotalSize"
                        Films.DesTotalSize = ChildElement.InnerText
                    Case "FilmInfo"
                        Films.ChildFilmItem.Add(_XML2Film(ChildElement))
                    Case "FilmCollection"
                        Films.ChildFilmItem.Add(_XML2FilmCollection(ChildElement))
                End Select
            Next
            Return Films
        End Function

    接下来是Save方法,把电影数据对象转换为XML文件。和Load方法类似,也是调用了两个私有方法:_Film2XML方法,把clsFilm对象转换为FilmInfo标签;_FilmCollection2XML方法,把clsFilmCollection对象转换为FilmCollection标签。在_FilmCollection2XML方法中,对clsFilmCollection对象的ChildFilmItem集合中的元素进行判断(利用FilmItem.GetType Is GetType(clsFilm)语句进行判断),若是clsFilm对象,调用_Film2XML方法获得FilmInfo标签;若不是,再调用_FilmCollection2XML方法获得FilmCollection标签。

      
        Public Sub Save(Optional XmlFile As String = "")
            If XmlFile = "" Then XmlFile = _FileName

            Dim Document As New Xml.XmlDocument

            Dim Root As Xml.XmlElement = Document.CreateElement("FilmRoot")

            Dim Films As clsFilmCollection

            For Each Films In FilmCollections
                Root.AppendChild(_FilmCollection2XML(Films, Document))
            Next

            Document.AppendChild(Root)
            Document.Save(XmlFile)
        End Sub

        Private Function _Film2XML(Film As clsFilm, XML As Xml.XmlDocument) As Xml.XmlElement
            Dim FilmElement As Xml.XmlElement = XML.CreateElement("FilmInfo")

            FilmElement.InnerXml = String.Format("<FileName>{0}</FileName><ImageFile>{1}</ImageFile><DesChineseName>{2}</DesChineseName><DesEnglishName>{3}</DesEnglishName><DesDuration>{4}</DesDuration><DesResolution>{5}</DesResolution><DesAudioLanguage>{6}</DesAudioLanguage>", Film.FileName, Film.ImageFile, Film.DesChineseName, Film.DesEnglishName, Film.DesDuration, Film.DesResolution, Film.DesAudioLanguage)
            Return FilmElement
        End Function

        Private Function _FilmCollection2XML(Films As clsFilmCollection, Document As Xml.XmlDocument) As Xml.XmlElement
            Dim FilmCollectionElement As Xml.XmlElement = Document.CreateElement("FilmCollection")

            Dim S As String = ""
            With Films
                If .ImageFile <> "" Then S &= String.Format("<ImageFile>{0}</ImageFile>", .ImageFile)
                If .DesChineseName <> "" Then S &= String.Format("<DesChineseName>{0}</DesChineseName>", .DesChineseName)
                If .DesEnglishName <> "" Then S &= String.Format("<DesEnglishName>{0}</DesEnglishName>", .DesEnglishName)
                If .DesLanguage <> "" Then S &= String.Format("<DesLanguage>{0}</DesLanguage>", .DesLanguage)
                If .DesCount <> "" Then S &= String.Format("<DesCount>{0}</DesCount>", .DesCount)
                If .DesTotalSize <> "" Then S &= String.Format("<DesTotalSize>{0}</DesTotalSize>", .DesTotalSize)
            End With

            FilmCollectionElement.InnerXml = S

            Dim FilmItem As I_Film
            For Each FilmItem In Films.ChildFilmItem
                If FilmItem.GetType Is GetType(clsFilm) Then
                    FilmCollectionElement.AppendChild(_Film2XML(FilmItem, Document))
                Else
                    FilmCollectionElement.AppendChild(_FilmCollection2XML(FilmItem, Document))
                End If
            Next
            Return FilmCollectionElement
        End Function

    为了后面的准备,我们有时需要获得所有的电影的中文名。于是,写了下面的两个方法。GetAllDesChineseName方法获得所有的电影的中文名,私有方法_GetAllDesChineseName获得指定clsFilmCollection对象下的所有的电影的中文名。还是利用FilmItem.GetType Is GetType(clsFilm)来判断是否是clsFilm对象,由于FilmItem是接口I_Film对象,那么如果FilmItem是clsFilm对象,则调用接口I_Film中的Des1属性(对应clsFilm对象的DesChineseName属性)来获得电影的中文名。

      
        Public Function GetAllDesChineseName() As List(Of String)
            Dim Films As clsFilmCollection
            Dim Names As New List(Of String)

            For Each Films In FilmCollections
                Names.AddRange(_GetAllDesChineseName(Films))
            Next
            Return Names
        End Function

        Private Function _GetAllDesChineseName(Films As clsFilmCollection) As List(Of String)
            Dim FilmItem As I_Film
            Dim Names As New List(Of String)

            For Each FilmItem In Films.ChildFilmItem
                If FilmItem.GetType Is GetType(clsFilm) Then
                    Names.Add(FilmItem.Des1)
                Else
                    Names.AddRange(_GetAllDesChineseName(FilmItem))
                End If
            Next

            Return Names
        End Function

    最后是把电影添加到集合的方法。

    有两个方法:

    AddFilm方法,把clsFilm对象添加到由Films指定的集合中。例如AddFilm(Film , "欧美"),把Film添加到名为“欧美”的电影集合中

    AddFilmByBrother方法,把clsFilm对象和BrotherFilm指定的电影组成一个集合

    例如:原本已经有“变形金刚壹”这部电影,现在又有“变形金刚贰”这部电影,我当然希望这两部电影能在一个电影集合中,即“变形金刚”集合。

    那么我可以调用AddFilmByBrother(Film , "变形金刚壹")来实现该功能。

    首先要找到“变形金刚壹”电影的clsFilm对象,以及该对象所处的clsFilmCollection对象。通过私有方法_FindBrother来实现。

    再判断该对象所处的clsFilmCollection对象是否是顶级集合(如“欧美”集合,通过判断clsFilmCollection对象的ImageFile属性)

    如果是顶级集合,则新建一个clsFilmCollection对象,把这两部影片都添加到这个新建的clsFilmCollection对象(例如:把“变形金刚壹”和“变形金刚贰”都添加到新建的clsFilmCollection对象)。把BrotherFilm指定的电影从顶级集合中删掉。把新建的clsFilmCollection对象添加到顶级集合。

    如果不是顶级集合(之前可能“变形金刚壹”和“变形金刚前传”组成了集合“变形金刚”),则把新电影添加到这个集合即可(把“变形金刚贰”添加到“变形金刚”集合)

    最后_GetTotalSize方法是获得指定集合中所有的文件的大小,以GB为单位。

      
        Public Sub AddFilm(Film As clsFilm, Films As String)
            Dim FilmItem As clsFilmCollection

            For Each FilmItem In FilmCollections
                If FilmItem.DesChineseName = Films Then
                    FilmItem.ChildFilmItem.Add(Film)
                    Exit Sub
                End If
            Next
        End Sub

        Public Sub AddFilmByBrother(Film As clsFilm, BrotherFilm As String)

            Dim Films As clsFilmCollection, Brother As clsFilm = Nothing

            For Each Films In FilmCollections
                _FindBrother(BrotherFilm, Films, Brother)
                If Not (Brother Is Nothing) Then
                    If Films.ImageFile = "" Then
                        Films.ChildFilmItem.Remove(Brother)
                        Dim NewFilms As New clsFilmCollection
                        NewFilms.DesChineseName = Brother.DesChineseName
                        NewFilms.DesEnglishName = Brother.DesEnglishName
                        NewFilms.DesLanguage = Brother.DesAudioLanguage
                        NewFilms.DesCount = 2
                        NewFilms.ImageFile = Brother.ImageFile
                        NewFilms.ChildFilmItem.Add(Brother)
                        NewFilms.ChildFilmItem.Add(Film)
                        NewFilms.DesTotalSize = _GetTotalSize(NewFilms)

                        Films.ChildFilmItem.Add(NewFilms)
                    Else
                        Films.ChildFilmItem.Add(Film)
                        Films.DesCount = CInt(Films.DesCount) + 1
                        Films.DesTotalSize = _GetTotalSize(Films)
                    End If
                    Exit Sub
                End If
            Next

        End Sub

        Private Sub _FindBrother(BrotherFilm As String, ByRef Films As clsFilmCollection, ByRef Brother As clsFilm)
            Dim FilmItem As I_Film

            For Each FilmItem In Films.ChildFilmItem
                If FilmItem.GetType Is GetType(clsFilm) Then
                    If FilmItem.Title = BrotherFilm Then
                        Brother = FilmItem
                        Exit Sub
                    End If
                Else
                    _FindBrother(BrotherFilm, FilmItem, Brother)
                    If Not (Brother Is Nothing) Then
                        Films = FilmItem
                        Exit Sub
                    End If
                End If
            Next
            Brother = Nothing
        End Sub

        Private Function _GetTotalSize(Films As clsFilmCollection) As String
            Dim SizeCount As Long = 0

            Dim FilmItem As clsFilm

            For Each FilmItem In Films.ChildFilmItem
                SizeCount += My.Computer.FileSystem.GetFileInfo(FilmItem.FileName).Length
            Next

            SizeCount = SizeCount * 10 / 1024 / 1024 / 1024

            Return CSng(SizeCount) / 10 & "GB" 

        End Function

    最后是该类的完整代码(VB2010)

     
    Public Class clsFilmXml
        Private _FileName As String
        Public FilmCollections As List(Of clsFilmCollection)

        Public Sub New()
            FilmCollections = New List(Of clsFilmCollection)
        End Sub

        Public Sub Load(XmlFile As String)
            _FileName = XmlFile

            Dim Document As New Xml.XmlDocument
            Document.Load(_FileName)

            Dim Films As Xml.XmlElement

            For Each Films In Document.DocumentElement.ChildNodes
                If Films.Name = "FilmCollection" Then FilmCollections.Add(_XML2FilmCollection(Films))
            Next
        End Sub

        Public Sub Save(Optional XmlFile As String = "")
            If XmlFile = "" Then XmlFile = _FileName

            Dim Document As New Xml.XmlDocument

            Dim Root As Xml.XmlElement = Document.CreateElement("FilmRoot")

            Dim Films As clsFilmCollection

            For Each Films In FilmCollections
                Root.AppendChild(_FilmCollection2XML(Films, Document))
            Next

            Document.AppendChild(Root)
            Document.Save(XmlFile)
        End Sub

        Private Function _Film2XML(Film As clsFilm, XML As Xml.XmlDocument) As Xml.XmlElement
            Dim FilmElement As Xml.XmlElement = XML.CreateElement("FilmInfo")

            FilmElement.InnerXml = String.Format("<FileName>{0}</FileName><ImageFile>{1}</ImageFile><DesChineseName>{2}</DesChineseName><DesEnglishName>{3}</DesEnglishName><DesDuration>{4}</DesDuration><DesResolution>{5}</DesResolution><DesAudioLanguage>{6}</DesAudioLanguage>", Film.FileName, Film.ImageFile, Film.DesChineseName, Film.DesEnglishName, Film.DesDuration, Film.DesResolution, Film.DesAudioLanguage)
            Return FilmElement
        End Function

        Private Function _FilmCollection2XML(Films As clsFilmCollection, Document As Xml.XmlDocument) As Xml.XmlElement
            Dim FilmCollectionElement As Xml.XmlElement = Document.CreateElement("FilmCollection")

            Dim S As String = ""
            With Films
                If .ImageFile <> "" Then S &= String.Format("<ImageFile>{0}</ImageFile>", .ImageFile)
                If .DesChineseName <> "" Then S &= String.Format("<DesChineseName>{0}</DesChineseName>", .DesChineseName)
                If .DesEnglishName <> "" Then S &= String.Format("<DesEnglishName>{0}</DesEnglishName>", .DesEnglishName)
                If .DesLanguage <> "" Then S &= String.Format("<DesLanguage>{0}</DesLanguage>", .DesLanguage)
                If .DesCount <> "" Then S &= String.Format("<DesCount>{0}</DesCount>", .DesCount)
                If .DesTotalSize <> "" Then S &= String.Format("<DesTotalSize>{0}</DesTotalSize>", .DesTotalSize)
            End With

            FilmCollectionElement.InnerXml = S

            Dim FilmItem As I_Film
            For Each FilmItem In Films.ChildFilmItem
                If FilmItem.GetType Is GetType(clsFilm) Then
                    FilmCollectionElement.AppendChild(_Film2XML(FilmItem, Document))
                Else
                    FilmCollectionElement.AppendChild(_FilmCollection2XML(FilmItem, Document))
                End If
            Next
            Return FilmCollectionElement
        End Function

        Private Function _XML2Film(Element As Xml.XmlElement) As clsFilm
            Dim Film As New clsFilm

            Dim ChildElement As Xml.XmlElement

            For Each ChildElement In Element.ChildNodes
                Select Case ChildElement.Name
                    Case "FileName"
                        Film.FileName = ChildElement.InnerText
                    Case "ImageFile"
                        Film.ImageFile = ChildElement.InnerText
                    Case "DesChineseName"
                        Film.DesChineseName = ChildElement.InnerText
                    Case "DesEnglishName"
                        Film.DesEnglishName = ChildElement.InnerText
                    Case "DesDuration"
                        Film.DesDuration = ChildElement.InnerText
                    Case "DesResolution"
                        Film.DesResolution = ChildElement.InnerText
                    Case "DesAudioLanguage"
                        Film.DesAudioLanguage = ChildElement.InnerText
                End Select

            Next

            Return Film
        End Function

        Private Function _XML2FilmCollection(Element As Xml.XmlElement) As clsFilmCollection
            Dim Films As New clsFilmCollection

            Dim ChildElement As Xml.XmlElement

            For Each ChildElement In Element.ChildNodes
                Select Case ChildElement.Name
                    Case "ImageFile"
                        Films.ImageFile = ChildElement.InnerText
                    Case "DesChineseName"
                        Films.DesChineseName = ChildElement.InnerText
                    Case "DesEnglishName"
                        Films.DesEnglishName = ChildElement.InnerText
                    Case "DesLanguage"
                        Films.DesLanguage = ChildElement.InnerText
                    Case "DesCount"
                        Films.DesCount = ChildElement.InnerText
                    Case "DesTotalSize"
                        Films.DesTotalSize = ChildElement.InnerText
                    Case "FilmInfo"
                        Films.ChildFilmItem.Add(_XML2Film(ChildElement))
                    Case "FilmCollection"
                        Films.ChildFilmItem.Add(_XML2FilmCollection(ChildElement))
                End Select
            Next
            Return Films
        End Function

        Public Function GetAllDesChineseName() As List(Of String)
            Dim Films As clsFilmCollection
            Dim Names As New List(Of String)

            For Each Films In FilmCollections
                Names.AddRange(_GetAllDesChineseName(Films))
            Next
            Return Names
        End Function

        Private Function _GetAllDesChineseName(Films As clsFilmCollection) As List(Of String)
            Dim FilmItem As I_Film
            Dim Names As New List(Of String)

            For Each FilmItem In Films.ChildFilmItem
                If FilmItem.GetType Is GetType(clsFilm) Then
                    Names.Add(FilmItem.Des1)
                Else
                    Names.AddRange(_GetAllDesChineseName(FilmItem))
                End If
            Next

            Return Names
        End Function

        Public Sub AddFilm(Film As clsFilm, Films As String)
            Dim FilmItem As clsFilmCollection

            For Each FilmItem In FilmCollections
                If FilmItem.DesChineseName = Films Then
                    FilmItem.ChildFilmItem.Add(Film)
                    Exit Sub
                End If
            Next
        End Sub

        Public Sub AddFilmByBrother(Film As clsFilm, BrotherFilm As String)

            Dim Films As clsFilmCollection, Brother As clsFilm = Nothing

            For Each Films In FilmCollections
                _FindBrother(BrotherFilm, Films, Brother)
                If Not (Brother Is Nothing) Then
                    If Films.ImageFile = "" Then
                        Films.ChildFilmItem.Remove(Brother)
                        Dim NewFilms As New clsFilmCollection
                        NewFilms.DesChineseName = Brother.DesChineseName
                        NewFilms.DesEnglishName = Brother.DesEnglishName
                        NewFilms.DesLanguage = Brother.DesAudioLanguage
                        NewFilms.DesCount = 2
                        NewFilms.ImageFile = Brother.ImageFile
                        NewFilms.ChildFilmItem.Add(Brother)
                        NewFilms.ChildFilmItem.Add(Film)
                        NewFilms.DesTotalSize = _GetTotalSize(NewFilms)

                        Films.ChildFilmItem.Add(NewFilms)
                    Else
                        Films.ChildFilmItem.Add(Film)
                        Films.DesCount = CInt(Films.DesCount) + 1
                        Films.DesTotalSize = _GetTotalSize(Films)
                    End If
                    Exit Sub
                End If
            Next

        End Sub

        Private Sub _FindBrother(BrotherFilm As String, ByRef Films As clsFilmCollection, ByRef Brother As clsFilm)
            Dim FilmItem As I_Film

            For Each FilmItem In Films.ChildFilmItem
                If FilmItem.GetType Is GetType(clsFilm) Then
                    If FilmItem.Title = BrotherFilm Then
                        Brother = FilmItem
                        Exit Sub
                    End If
                Else
                    _FindBrother(BrotherFilm, FilmItem, Brother)
                    If Not (Brother Is Nothing) Then
                        Films = FilmItem
                        Exit Sub
                    End If
                End If
            Next
            Brother = Nothing
        End Sub

        Private Function _GetTotalSize(Films As clsFilmCollection) As String
            Dim SizeCount As Long = 0

            Dim FilmItem As clsFilm

            For Each FilmItem In Films.ChildFilmItem
                SizeCount += My.Computer.FileSystem.GetFileInfo(FilmItem.FileName).Length
            Next

            SizeCount = SizeCount * 10 / 1024 / 1024 / 1024

            Return CSng(SizeCount) / 10 & "GB"


        End Function

    End Class

    贴代码于此,也是希望和大家交流,如果有什么建议的话,望不吝赐教。

    题外话

    在研究Direct2D时,从官网上下载了Windows API Code Pack 1.1后

    解压到文件夹,在我的开发文档里引用了Microsoft.WindowsAPICodePack.DirectX.dll

    在执行初始化语句时

    _d2DFactory = Direct2D1.D2DFactory.CreateFactory()

    就报了如下的错误

    image

    有谁能解决这个问题么?并能提供Direct2D的详细的开发资料么。

    现在还同时在研究SharpDX,但也苦于缺少相关的资料和教程,有谁能提供么?

  • 相关阅读:
    优化输出质数
    springboot嵌入式Servlet容器自动配置原理
    springboot中配置servlet三大组件
    springboot中springmvc的自定义配置
    springboot实现自定义国际化
    springboot错误处理机制及自定义错误处理
    SpringBoot对静态资源的映射规则
    docker中启动mysql容器
    Java函数式编程(一)
    java并发编程之美——高级篇(三)
  • 原文地址:https://www.cnblogs.com/grenet/p/3247545.html
Copyright © 2020-2023  润新知