Zweite Form immer im Vordergrund (vor der ersten) und sichtbar falls geöffnet (nicht topmost)?

  • VB.NET

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Zweite Form immer im Vordergrund (vor der ersten) und sichtbar falls geöffnet (nicht topmost)?

    Hallo,

    stehe vor einem Grundlagenproblem. Ich möchte, dass eine zweite Form - sobald geöffnet - immer im Vordergrund ist, wenn die erste Form vom Benutzer angeklickt wird (in der Taskbar oder direkt). Jedoch soll die Form nicht vor anderen Fenstern außerhalb des Programms sein, was topmost ausschließt.

    Ein paar Versuche habe ich leider ohne Erfolg ausprobiert:

    Im Event GotFocus von Form1:
    Form2.Focus()

    Allerdings wird das GotFocus Event gar nicht aufgerufen, wenn ich von einem anderen Fenster zu meiner Form1 wechsel?


    Beim erstellen von Form2 - anstelle von Form2.Show, Form2.ShowDialog.
    Problem: Das Fenster verlangt keinerlei Eingabe, es entstehen weitere Probleme wenn die Form so aufgerufen wird.

    Im Form2.LostFocus
    Form2.Focus
    -> Entspricht quasi topmost und die Form ist wiederum immer im Vordergrund.


    Hat mir jemand die richtige Idee, ich steh grad voll aufm Schlauch ;)

    Grüße
    Du kannst mit

    VB.NET-Quellcode

    1. Me.BringToFront()

    arbeiten, aber wenn Du auf das 1. Fenster klickst, ist das 2. Fenster kurz dahinter.
    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!
    Wie wäre es, wenn Form1 ein MDI-Container und Form2 ein MDI-Child ist?
    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!
    Ich denke, du mußt bei Form2.Show nur ein OwnerForm als Parameter angeben.

    in Form1:

    VB.NET-Quellcode

    1. Form2.Show(Me)


    Dann werden immer beide Forms aktiviert, aber man kann zwischen den Forms wechseln.

    Wenn darüberhinaus Form2 das einzig zugreifbare Form sein soll, musstes mit .ShowDialog(Me) anzeigen
    Dann werden immer beide Forms aktiviert, aber man kann zwischen den Forms wechseln.


    Das ist so schon der Fall. Das Problem / Der Wunsch besteht wirklich nur darin, dass wenn ich die erste Form aktiviere (also z.B. in der Taskleiste auf das Symbol klicke), automatisch die zweite Form darüber erscheint.

    Form2 ist aber ein reines Infofenster, es gibt keine Eingabe seitens des Benutzer (falls Du dich noch an meinen Thread von letzter Woche erinnerst, es handelt sich immer noch um den WaitingScreen ;)). Wie oben beschrieben gibt es beim Aufruf von ShowDialog Komplikationen. Das Fenster wird dadurch nicht mehr aktualisiert und schließt auch nicht mehr, da der Rest vom Code nicht ausgeführt wird.
    Ich verstehe nicht recht, warum du das postest. Dann ist eben oben genanntes Form2.Show(Me) das Mittel der Wahl.

    Die Positionierung von Form2 ist damit natürlich noch nicht definiert, denn Forms sind konzeptionell erstmal so vorgesehen, dass es dem User obliegt, sie da hinzuschieben, wo er sie haben will.
    Ich glaub ich hatte dich missverstanden.

    Ich habe nun .Show(Me) getestet, allerdings wird das Fenster in einem seperaten Thread (Backgroundworker) erstellt, aktualisiert und wieder geschlossen.

    .Show(Me) anstelle von Show führt zum Fehler:

    "Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement Form1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde."
    Ich kann das Fenster aber nicht im Backgroundworker aktualisieren wenn es im Mainthread erstellt wurde.

    Mal kurz der ungefähren Aufbau:


    VB.NET-Quellcode

    1. Dim winWaitingScreen As Object ' Global
    2. [...]
    3. Private Sub bgw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
    4. winWaitingScreen.Show()
    5. FunktionDieDatenRausziehtUndFensterAktualisiert()
    6. If Not winWaitingScreen Is Nothing Then
    7. winWaitingScreen.Dispose()
    8. winWaitingScreen = Nothing
    9. End If
    10. Private Sub btnResult_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResult.Click
    11. winWaitingScreen = New WaitingScreen
    12. bgw.RunWorkerAsync()
    13. End Sub

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ray“ ()

    Doch, mit Control.Invoke kannst du Aufrufe an den MainThread delegieren.

    Ich halte eh nicht viel vom BGW, ich hab ein AsyncWorker gebastelt, um derlei Dinge ordentlich typisiert zu erledigen.

    Edit: Ein Event alleine löst das Problem nicht, das muß auch in den Mainthread delegiert werden, entweder das Schicken des Events, oder die Verarbeitung desselben.

    RodFromGermany schrieb:

    Schick ein Event

    Bitte schreib's so, dass ich wenigstens danach googlen kann - nicht umsonst hab ich (in diesem Fall) im Grundlagen Forum geschrieben.

    ErfinderDesRades schrieb:

    Doch, mit Control.Invoke kannst du Aufrufe an den MainThread delegieren.


    Damit werd ich mich jetzt mal beschäftigen, vielen Dank!

    Ich halte eh nicht viel vom BGW, ich hab ein AsyncWorker gebastelt, um derlei Dinge ordentlich typisiert zu erledigen.

    Edit: Ein Event alleine löst das Problem nicht, das muß auch in den Mainthread delegiert werden, entweder das Schicken des Events, oder die Verarbeitung desselben.


    Das werd ich mir danach mal angucken ;).
    Google: "vb.net events"
    vb-paradise "event" :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!

    RodFromGermany schrieb:

    Google: "vb.net events"
    vb-paradise "event" :D


    Naja ich werd ma gucken :D

    ErfinderDesRades schrieb:

    Doch, mit Control.Invoke kannst du Aufrufe an den MainThread delegieren.


    Soooo, ich hab jetzt mal schnell geguckt, allerdings ist Threading generell vollkommen neu für mich, deswegen bin ich mir sehr unsicher ob mein Code korrekt ist, oder mal wieder aus Zufall funktioniert.

    Wie hier beschrieben wurde, habe ich eine Funktion UpdateControl und ein Delegate UpdateTextHandler erstellt.

    Wenn die Labels meines WaitingScreens aktualisiert werden sollen:

    VB.NET-Quellcode

    1. Me.Invoke(New UpdateTextHandler(AddressOf UpdateControl), winWaitingScreen.Label1, "BlablaLabel1Update")


    Danach der Refresh (vorallem hier frag ich mich ob das so passt):

    VB.NET-Quellcode

    1. Me.Invoke(New MethodInvoker(AddressOf winWaitingScreen.Refresh))


    Ist das VB regelkonform?

    Es funktioniert jetzt aufjeden Fall und mein ursprüngliches Problem hat sich damit auch gelöst - über .Show(Me) bleibt winWaitingScreen immer im Vordergrund, also vielen, vielen Dank dafür schonmal.
    Ja, das sieht gut aus.
    Das hättest Du aber schneller ausprobiert, denke ich.
    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!

    RodFromGermany schrieb:

    Das hättest Du aber schneller ausprobiert, denke ich.


    Guten Morgen!

    Selbstverständlich habe ich alles bereits ausprobiert und es klappt auch wunderbar ;). (deswegen auch:
    Es funktioniert jetzt aufjeden Fall und mein ursprüngliches Problem hat sich damit auch gelöst
    )

    Meine Nachfrage galt nur der Korrektheit der Umsetzung, da in letzter Zeit doch recht häufig das Resultat zwar in Ordnung war, mein Code dahinter allerdings verbesserungswürdig :D.

    In diesem Sinne...
    Das geht mir ähnlich.
    Ich steige gerade von 2008 auf 2010 um, da gibt es schon einige Features, die den Code eleganter aussehen lassen.
    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!

    ray schrieb:

    bin ich mir sehr unsicher ob mein Code korrekt ist, oder mal wieder aus Zufall funktioniert.

    also der Waitingscreen scheint jetzt ja im MainThread zu laufen, dann haut das schon hin.

    2 Verbesserungen:
    1) Control.Invoke zwingt den NebenThread zu warten, bis der MainThread das Invoking durchgeführt hat. Damit bremst man also zur Abwechslung nicht das Gui aus, sondern den Workerthread.
    Control.BeginInvoke funzt genauso wie Control.Invoke, blos kann der Workerthread gleich weiterworken.
    2) wenn alles mit rechten Dingen zugeht, braucht der WaitingScreen nicht extra refresht zu werden. Ein Label, welches einen anderen Text zugewiesen bekommt, löst selbst den NeuzeichnungsVorgang aus, da sollte man nicht mit einem erzwungenen Refresh eingreifen.