您可以在动态创建的表单上实现IDisposable

时间:2014-07-04 11:30:55

标签: vb.net module idisposable

我正在尝试一个消息框,当显示时,主应用程序正在使用视觉样式(但为此我不会浪费时间重新发明轮子)。随着它的发展,这已经变成了一个非常有趣的小练习,在此过程中我学到了很多东西。

首先,我在VB中这样做,所以我将所有代码放在它自己的dll中,然后又放在一个Module中,以便在最终项目中引用这个dll的最终用户(在这种情况下我) )可以调用MyDll.MessageBox.show()。

我第一次称之为一切都完全符合预期,第二次奇怪的事情开始发生。经过多次实验后,我只能得出结论,在我的消息框第一次关闭后,它才被正确处理掉。

现在我无法在包含创建消息框的代码的模块上实现IDisposable,因为VB不允许它。我试图明确处理对象,因为它关闭,但显然不起作用。我错过了一些东西,但说实话,我对这个问题有点不了解。

我在这里阅读了各种帖子(尽管几乎所有帖子都与c#以及你可以积极实施IDisposable的领域有关),所以我仍然不是更聪明的。

我是否开始关注正确的区域(IDisposable),在这种情况下,我应该如何继续进行,因为这是从一个模块发出的,或者我在完全错误的区域中查找?

由于

代码:

这是show方法:

Public Function Show(ByVal text As String) As DialogResult
    If String.IsNullOrEmpty(text) Then
        Throw New ArgumentNullException("text", "You need to supply text for the message itself.")
    Else
        MessageText = text
    End If

    MessageCaption = String.Empty
    SetMessageButtons(VtlMessageBoxButtons.OK)
    IconSelected = False

    Return CreateVtlMessageBox()
End Function

这导致了CreateVtlMessageBox

Private Function CreateVtlMessageBox() As DialogResult
    'check to see that we have a theme to use
    If String.IsNullOrEmpty(CurrentC1ThemeInUse) Then
        Throw New ArgumentException("No theme has been set for the message box to use.  Please ensure that you have set a value for the property 'CurrentC1ThemeInUse'.")
        Exit Function
    End If

    'we have a theme so we'll continue
    _maximumWidth = CType((SystemInformation.WorkingArea.Width * 0.6), Integer)
    _maximumHeight = CType((SystemInformation.WorkingArea.Height * 0.9), Integer)
    frm = New Form With {.Text = MessageCaption,
                               .MaximizeBox = False,
                               .MinimizeBox = False,
                               .ShowIcon = False,
                               .ShowInTaskbar = False,
                               .FormBorderStyle = FormBorderStyle.FixedDialog,
                               .StartPosition = FormStartPosition.CenterParent}

    AddHandler frm.Load, AddressOf FormLoad
    AddHandler frm.FormClosing, AddressOf FormClosing
    AddHandler frm.FormClosed, AddressOf FormClosed

    Dim result As DialogResult
    Using frm
        result = frm.ShowDialog
    End Using
    Return result
End Function

我通过实验添加了formClosing和Closed方法,我认为它们是多余的,我将删除它们。

Private Sub FormClosing(sender As Object, e As FormClosingEventArgs)
    If sl isNot nothing Then
        sl.Dispose
    End If
End Sub
Private Sub FormClosed(sender As Object,e As FormClosedEventArgs)
    frm.Dispose
End Sub

为了澄清,sl是我最初认为是问题的标签控件。 另一方面,FormLoad可以完成驴工作,我认为问题的根源可能就在那里以及它所依赖的方法。

Private Sub FormLoad(sender As Object, e As EventArgs)


    frm.Size = New Size(_maximumWidth, _maximumHeight)
    _maximumLayoutWidth = frm.ClientSize.Width - LeftPadding - RightPadding
    _maximumLayoutHeight = frm.ClientSize.Height - TopPadding - BottomPadding

    If IconSelected Then
        CreateAndPositionIconOnForm()
    End If
    SetTheText()
    PositionAndSizeTheSuperLabel()
    SetTheOptimumSizeForTheForm()
    LayoutTheForm()
    If frm Is Nothing Then
        Return
    Else
        If IconSelected Then
            frm.Controls.Add(IconPanel)
        End If
        frm.Controls.Add(sl)
    End If




    Dim lThemeName As String = CurrentC1ThemeInUse
    If Not String.IsNullOrEmpty(lThemeName) Then
        Dim lThemeLocator As New C1ThemeLocator(locationType:=C1ThemeLocator.LocationType.ThemesFolder, themeName:=lThemeName)
        Dim lTheme As C1Theme = New C1ThemeLocator(lThemeLocator).GetTheme()

        C1ThemeController.ApplyThemeToControlTree(frm, lTheme)
    End If

    If NoCancelButton Then
        'disable the close Button
        Disable(frm)
    End If


End Sub

当我第二次调用消息框时,添加下面的SetTheTex方法通过显式处理它解决了sl的问题。

Private Sub SetTheText
     If sl Is Nothing Then
        sl = New C1SuperLabel With {.Text = MessageText}
    Else
        sl.Dispose
         sl = New C1SuperLabel With {.Text = MessageText}
    End If
End Sub

现在第二次调用消息框时,它不会抛出一个未处理的异常,因为它在我处理sl之前就会发生,但它确实复制了所有的buutons,并且每次调用它时都会继续添加它们试。

与此相关的两位代码如下所示。

Private Sub SetTheOptimumSizeForTheForm()
    Dim ncWidth As Integer = frm.Width - frm.ClientSize.Width
    Dim ncHeight As Integer = frm.Height - frm.ClientSize.Height

    Dim messageRowWidth As Integer
    If IconSelected Then
        messageRowWidth = sl.Width + IconToMessagePadding + IconPanel.Width
    Else
        messageRowWidth = sl.Width + RightPadding
    End If




    _buttonsRowWidth = GetWidthOfAllAvailableButtons()
    Dim captionWidth As Integer = GetCaptionSize().Width + CloseButtonWidth



    Dim maxItemWidth As Integer = Math.Max(messageRowWidth, _buttonsRowWidth)
    Dim requiredWidth As Integer = LeftPadding + maxItemWidth + RightPadding + ncWidth
    'Since Caption width is not client width, we do the check here
    If requiredWidth < captionWidth Then
        requiredWidth = captionWidth

    End If

    Dim requiredHeight As Integer
    If IconSelected Then
        requiredHeight = TopPadding + Math.Max(sl.Height, IconPanel.Height) + ItemPadding + ItemPadding + GetButtonSize().Height + BottomPadding + ncHeight
    Else
        requiredHeight = TopPadding + sl.Height + ItemPadding + ItemPadding + GetButtonSize().Height + BottomPadding + ncHeight
    End If


    If requiredHeight > _maximumHeight Then
        sl.Height -= requiredHeight - _maximumHeight
    End If
    Dim height As Integer = Math.Min(requiredHeight, _maximumHeight)
    Dim width As Integer = Math.Min(requiredWidth, _maximumWidth)

    frm.Size = New Size(width, height)


End Sub






Private Sub LayoutTheForm()

    If IconSelected Then
        IconPanel.Location = New Point(LeftPadding, TopPadding)
        sl.Location = New Point(LeftPadding + IconPanel.Width + IconToMessagePadding * (If(IconPanel.Width = 0, 0, 1)), TopPadding)
    Else
        sl.Location = New Point(LeftPadding + IconToMessagePadding, TopPadding)
    End If



    Dim buttonSize As Size = GetButtonSize()

    'buttons need to be positioned from the right of the message box
    Dim allButtonsWidth As Integer = _buttonsRowWidth + ButtonPadding
    Dim firstButtonX As Integer = CType(frm.ClientSize.Width - allButtonsWidth, Integer)
    Dim firstButtonY As Integer = frm.ClientSize.Height - BottomPadding - buttonSize.Height


    Dim nextButtonLocation As Point = New Point(firstButtonX, firstButtonY)
    Dim foundDefaultButton As Boolean = False
    Dim i As Integer


    For Each button As String In MessageButtons
        Dim buttonCtrl As C1Button = AddMessageBoxButton(button, buttonSize, nextButtonLocation)
        nextButtonLocation.X += buttonSize.Width + ButtonPadding
        i = buttonCtrl.Location.Y
        buttonCtrl.Anchor = AnchorStyles.Bottom And AnchorStyles.Right
        frm.Controls.Add(buttonCtrl)
    Next

End Sub

我希望这有助于遵循我的逻辑或缺乏逻辑!

1 个答案:

答案 0 :(得分:1)

我强烈建议你从模块中删除所有这些代码。这并非真正使用模块。相反,创建一个表单的子类。

Class MyMessageBox
    Inherits Form

    Public Sub New(ByVal messageCaption As String)

        'we have a theme so we'll continue
        _maximumWidth = CType((SystemInformation.WorkingArea.Width * 0.6), Integer)
        _maximumHeight = CType((SystemInformation.WorkingArea.Height * 0.9), Integer)

        Text = messageCaption,
        MaximizeBox = False,
        MinimizeBox = False,
        ShowIcon = False,
        ShowInTaskbar = False,
        FormBorderStyle = FormBorderStyle.FixedDialog,
        StartPosition = FormStartPosition.CenterParent}

    End Sub

    Public Shared Function Show(ByVal text As String) As DialogResult
        If String.IsNullOrEmpty(text) Then
            Throw New ArgumentNullException("text", "You need to supply text for the message itself.")
        Else
            MessageText = text
        End If

        MessageCaption = String.Empty
        SetMessageButtons(VtlMessageBoxButtons.OK)
        IconSelected = False

        'check to see that we have a theme to use
        If String.IsNullOrEmpty(CurrentC1ThemeInUse) Then
            Throw New ArgumentException("No theme has been set for the message box to use.  Please ensure that you have set a value for the property 'CurrentC1ThemeInUse'.")
            Exit Function
        End If

        Dim frm = New MyMessageBox(MessageCaption)

        Dim result As DialogResult
        Using frm
            result = frm.ShowDialog
        End Using
        Return result
    End Function

    Private Sub FormLoad(sender As Object, e As EventArgs) Handles Me.Load
    End Sub

End Class

这个想法是共享函数创建一个继承表单的实例,其中包含要添加到其中的所有特殊功能。这样,该表单可以处理IDispose。您的所有活动也将成为该表单的一部分,而不是在模块中。每个表单还将拥有自己的变量实例,这将减少冲突。