CenterParent funktioniert nicht bei .ShowDialog() aus BackgroundWorker

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    CenterParent funktioniert nicht bei .ShowDialog() aus BackgroundWorker

    Hallo

    wie kann ich erreichen, dass die Form2, die aus der Form1 mittels BackgroundWorker aufgerufen wird, zentriert über der Form1 liegt?
    Normalerweise reicht es ja, bei Form2 die StartPosition auf CenterParent einzustellen. Ist dies eingestellt, funktioniert es mit dem Button2 ohne Probleme.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Friend WithEvents bwShowDialog As New System.ComponentModel.BackgroundWorker
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. bwShowDialog.RunWorkerAsync()
    5. End Sub
    6. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    7. Using dlg As New Form2
    8. dlg.ShowDialog()
    9. End Using
    10. End Sub
    11. Private Sub bwShowDialog_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwShowDialog.DoWork
    12. Threading.Thread.Sleep(1000) ' puffer, um den sekundären Monitor auszuwählen. Dient der Prüfung, ob die Form2 dann auch bei mehreren Monitoren immer über der Form1 liegt
    13. Using dlg As New Form2
    14. dlg.ShowDialog()
    15. End Using
    16. End Sub
    17. Private Sub bwShowDialog_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bwShowDialog.RunWorkerCompleted
    18. Return
    19. End Sub
    20. End Class

    DanCooper schrieb:

    Normalerweise
    startet ein Dialog im selben Thread wie das Parent.
    Da der BGW ein anderer Thread ist, musst Du den Dialog von Hand zentrieren:

    VB.NET-Quellcode

    1. Private Sub bwShowDialog_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bwShowDialog.DoWork
    2. Using dlg As New Form2
    3. dlg.ParentBounds = Me.Bounds
    4. dlg.ShowDialog()
    5. End Using
    6. End Sub

    VB.NET-Quellcode

    1. Public Sub New()
    2. InitializeComponent()
    3. Me.StartPosition = FormStartPosition.Manual
    4. End Sub
    5. Public WriteOnly Property ParentBounds() As Rectangle
    6. Set(value As Rectangle)
    7. Me.Left = value.Left + (value.Width - Me.Width) \ 2
    8. Me.Top = value.Top + (value.Height - Me.Height) \ 2
    9. End Set
    10. End Property
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    .... oder aber Du teilst .Showdialog mit, wo er denn zentrieren soll:

    VB.NET-Quellcode

    1. Public Class Form1
    2. .
    3. .
    4. .
    5. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    6. Using dlg As New Form2
    7. dlg.ShowDialog(Me)
    8. End Using
    9. End Sub
    10. .
    11. .
    12. ,
    13. End Class
    Besten Dank euch zwei! Ich nutze nun beide Varianten.

    Bei Aufrufen aus bwShowDialog.DoWork verwende ich die (etwas erweiterte) Variante von @RodFromGermany, da ich hier einiges Übergeben muss, ausserdem müsste ich bei .ShowDialog(Me) erst noch ein Invoke machen:

    VB.NET-Quellcode

    1. Private manualStartPos As Boolean = False
    2. Public WriteOnly Property ParentBounds() As Rectangle
    3. Set(value As Rectangle)
    4. Me.Left = value.Left + (value.Width - Me.Width) \ 2
    5. Me.Top = value.Top + (value.Height - Me.Height) \ 2
    6. Me.manualStartPos = True
    7. End Set
    8. End Property
    9. Public Overloads Function ShowDialog(ByRef DBMovie As Structures.DBMovie, ByVal Type As Enums.ImageType_Movie, ByRef ImageList As List(Of MediaContainers.Image), ByRef efList As List(Of String), ByRef etList As List(Of String), Optional ByVal _isEdit As Boolean = False) As DialogResult
    10. Me.tMovie = DBMovie
    11. Me.tIsMovie = True
    12. Me._ImageList = ImageList
    13. Me._efList = efList
    14. Me._etList = etList
    15. Me.DLType = Type
    16. Me.isEdit = _isEdit
    17. Select Case DLType
    18. Case Enums.ImageType_Movie.Banner
    19. aDes = Master.eSize.poster_names(0).description
    20. Case Enums.ImageType_Movie.ClearArt
    21. aDes = Master.eSize.poster_names(0).description
    22. Case Enums.ImageType_Movie.ClearLogo
    23. aDes = Master.eSize.poster_names(0).description
    24. Case Enums.ImageType_Movie.DiscArt
    25. aDes = Master.eSize.poster_names(0).description
    26. Case Enums.ImageType_Movie.Fanart
    27. aDes = Master.eSize.backdrop_names(0).description
    28. Case Enums.ImageType_Movie.Landscape
    29. aDes = Master.eSize.poster_names(0).description
    30. Case Enums.ImageType_Movie.Poster
    31. aDes = Master.eSize.poster_names(0).description
    32. End Select
    33. Me.SetUp()
    34. If manualStartPos Then Me.StartPosition = FormStartPosition.Manual
    35. Return MyBase.ShowDialog()
    36. End Function



    Beim Aufrufen einer anderen Form aus bwShowDialog.RunWorkerCompleted nutze ich dann die Lösung von @us4711, da diese Form ohne Parameter angezeigt wird und auch kein Invoke nötig ist.

    :thumbsup:

    DanCooper schrieb:

    VB.NET-Quellcode

    1. Public Overloads Function ShowDialog(...)
    ist suboptimal, genau dafür wurden die Properties erfunden. :D
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!