#vb.net #module #idisposable
#vb.net #модуль #idisposable
Вопрос:
Я экспериментирую с messagebox, который при отображении использует визуальный стиль, используемый основным приложением (но для этого я бы не стал тратить свое время на повторное изобретение колеса). Как выяснилось, это превратилось в довольно интересное небольшое упражнение, и в процессе я многому научился на этом пути.
Прежде всего, я делаю это в VB, поэтому я поместил весь свой код в его собственную библиотеку dll и, в свою очередь, в модуль, чтобы в конечных проектах, которые ссылаются на эту библиотеку 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
For clarification sl is a label control which I had originally thought to be the issue.
FormLoad on the other hand does the donkey work and I think the root of the problem may well be there and the methods it in turn calls.
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. похоже, что на самом деле это диалоговое окно, используемое в MessageBox. Что это такое и как оно используется (ваш код) и что означают «странные вещи», помогло бы узнать, в чем проблема (ы). IDisposable не звучит так, как будто это применимо.
2. Вопрос: Вы абсолютно правы, что это диалоговое окно. Я изначально не добавлял код, поскольку его довольно много, но я добавлю столько, сколько, как я думаю, даст вам представление о том, что происходит.
3. вероятно, это проблема в том, как это вызывается / используется. начните с того, как она вызывается
4. Наконец-то я нашел проблему, в которую верю. Суперметка (sl) явно удалялась, но при явном выполнении этого во второй раз это сработало. Я также должен был избавиться от массива, используемого для хранения кнопок окна сообщений, хотя и это я пропустил.
Ответ №1:
Я бы настоятельно рекомендовал вам удалить весь этот код из модуля. На самом деле это не использование модуля. Вместо этого создайте подкласс form.
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. Все ваши события также будут частью этой формы, а не находиться в модуле. Каждая форма также будет иметь свой собственный экземпляр своей переменной, что уменьшит конфликт.
Комментарии:
1. Большое вам спасибо за ваш ответ и код для иллюстрации. Если ничего другого, это, наконец, не привело к снижению цен на то, как следует относиться к подклассу, для которого это определенный плюс.