Laden...

MDI - Fenster im unteren Bereich eines anderen Fenster platzieren

Erstellt von Echo]6[ vor 15 Jahren Letzter Beitrag vor 15 Jahren 5.483 Views
E
Echo]6[ Themenstarter:in
111 Beiträge seit 2006
vor 15 Jahren
MDI - Fenster im unteren Bereich eines anderen Fenster platzieren

Hallo,

ich versuche gerade eine MDI-Anwendung zu schreiben und mein derzeitiges Layout ist folgendermaßen:

Ich habe oben und links an der Seite jeweils ein Toolstrip. In der Mitte ist also nun der Bereich in dem die Fenster geöffnet werden sollen. Mein Vorhaben ist nun (an dem ich momentan etwas verzweifle) folgendes:

  1. Ein MDIChild maxiermiert öffnen, indem sich im oberen Bereich Eingabefelder befinden und im unteren halt alles frei ist. (klappt!)

  2. Das erste MDIChild bleibt geöffnet und es soll im unteren Bereich ein neues Fenster geöffnet werden. (klappt nicht)

  3. Nach Klick auf einen Button, soll das untere Fenster geschlossen werden und ein anderes im unteren Bereich geöffnet werden. (klappt nicht)

Ich habe es schon mit einem SplitContainer versucht, aber das Fenster welches im unteren Bereich angezeigt werden soll, passt sich nicht dem ganzen unteren Bereich an!

Habt ihr vielleicht ne Idee, wie man soetwas lösen könnte?

MfG
Echo

P.S. Sry, wg. dem Titel! (mir fiel nichts anderes ein)

915 Beiträge seit 2006
vor 15 Jahren

Hrm, das ganze ist nicht so einfach und leider gibt es viele Lösungsmöglichkeiten:
Schau mal im Forum was du unter Windows Widget so findest, ansonsten kannst dir auch mal gerne die UtilitiesLib von mir ansehen – dort habe ich es zwar etwas komplizierter gemacht aber im Prinzip lässt sich das Vereinfachen:
Erstell eine neue Klasse und leite von Form ab, erstelle einen neue Propertie vom Typ System.Windows.Forms.DockStyle mit setter und getter. Erstelle dann ein Propertie vom Typ Control für das ParentMDIControl.

Überschreibe die WndProc(ref Message m), fange die Windowsnachricht Nachrichten WindowsMessages.WM_NCHITTEST ab. Gebe anhand der Positionierung des DockStyle die entsprechenden HitTest Werte zurück. Ergo, DockStyle.Bottom -> NCHITTEST für Klick auf den linken, links unten, rechts, rechts unten, rechts oben, links oben und unteren Rand = HITTEST.HTCLIENT während bei klick auf oberen Rand = HITTEST. HTTOP. Somit unterbindest du das verschieben des Fensters.
Fange dann die Windowsnachricht WM_CREATE ab, klinke dabei über SetParent anhand des ParentMDIControl.Handel das this.Handle ein.
Soo wenn nun den Designer öffnest und das ChildForm einbindest wird es zur Laufzeit in den Designer geladen. Der Vorteil, du kannst auf deinem MainForm direkt das ChildForm bearbeiten und irgendwelche Controls draufziehen.

Kannst dir auch mal das Widget Projekt in der UtilitiesLib von mir ansehen, dann erkennst evtl. den Weg den man verwenden kann. Ich nutze dabei nur ein Panel das ich etwas modifiziere so das es wieder ein Windows Form wird. Den schlussendlich sind alle Controls wieder als Form herstellbar, kannst also auch aus einer TreeList wieder ein Form machen.

Wenn der Weg zu komplex sein sollte, gibt es auch eine reine .NET Lösung (ist eher dann ein gebastel) oder Fremdanbieter Controls (die aber kosten).

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

M
205 Beiträge seit 2008
vor 15 Jahren

Hallo,

machs mit einem SplitContainer damit gehts total einfach. Du legst dir ein MDIForm an, in diesem machst du einen SplitContainer rein (Orientation = Horizontal, Dock = Fill) im Code öffnest du dann deine Formulare .


            Form f = new Form();
            f.MdiParent  = this;
            f.Parent = this.splitContainer1.Panel1;
            f.Dock = DockStyle.Fill;
            f.Show();

            Form f2 = new Form();
            f2.MdiParent = this;
            f2.Parent = this.splitContainer1.Panel2;
            f2.Dock = DockStyle.Fill;
            f2.Show();

falls es wiedu schriebst nocht genau passt kannst du eigenschaften am layout für die ränder festlegen, kontrolliere die panels ob bei der Eigenschaft "padding was drinnen steht, wenn ja auf 0 setzen. Wenn du es ohnehin nicht verschiebbar machen willst kannsz ja noch im SplitContainer die Eigenschaften IsSplitterFixed = true und SplitterWidth auf eins setzen. Das schaur dann nicht so schlecht aus.

mfg Markus

E
Echo]6[ Themenstarter:in
111 Beiträge seit 2006
vor 15 Jahren

Danke erstmal für eure Antworten!

@Andreas.May

Du hast Recht, es ist (zumindest für mich) noch ein wenig zu komplex! Welche Fremdanbieter Controls meinst du denn, mit denen man das vielleicht leichter realisieren kann?

@markus.bodlos

Das hat soweit geklappt, aber wie kann ich denn beim Klick auf einen Button das untere Fenster schließen und ein anderes dort öffnen? Ich habe ja nachher links ein Menü, indem ich mehrere Punkte habe, über die ich ja ein Fenster im unteren Bereich öffne. Wie bekomme ich nun den Namen des unteren Fensters raus, damit ich weiß welches ich schließen muss, bevor ich ein neues öffne?

MfG
Echo

M
205 Beiträge seit 2008
vor 15 Jahren

Stichwort: Globale Variable, da das aber grundlagen sind befasse dich bitte mit diesen Quellen :rtfm: 🛈 📗

mfg Markus

U
400 Beiträge seit 2008
vor 15 Jahren

Füge deinem MDI-Child doch einfach ein Fenster als Control hinzu.


Form myform = new Form();
myform.TopLevel = false;
MyMDIChild.Controls.add(myform);
myform.show();

Wenn du das so machst , kannst du das Fenster über die Controls-Eigneschaft deines MDIChild schliessen. Darfst aber hinterher nicht vergessen , das Fenster wieder mit Controls.Remove(myform); zu entfernen, sonst könnte es etwas an der Performance saugen , wenn du mehrmals ein Fenster öffnest.

M
205 Beiträge seit 2008
vor 15 Jahren

Hallo Pria,

was soll das bringen? ihm geht es ja primär um das layout und bei einem mdi formular ein child explizit zu den controls hinzufüen ist ja unnötig. Man setzt die Eigenschaft "MdiParent".

Code im MDI Formular:


Form myform = new Form();
myform.MdiParent = this;
myform.Show();

mfg Markus

915 Beiträge seit 2006
vor 15 Jahren

@markus.bodlos

Pria Weg geht auch, das Problem dabei ist, dass das ChildForm (MDIForm) innerhalb der MainForm (ParentForm) verschoben werden kann vom Benutzer. Die Möglichkeit geht auch, wenn man dem Benutzer die Möglichkeit nimmt das ChildForm zu bewegen.

Das was der Threadersteller eigentlich möchte ist so ne Sache, eigentlich ist das ein Widget Thema, kein MDI. Ein MDI ist ein Container der es expleziet dem Benutzer erlaubt innerhalb des Containers schalten und walten zu können wie es ihm beliebt.

Man kann beide Vorschläge, also deinen und Pria's mixen. Oberhalb des MDIContainers kann man über WinAPI SetParent (evtl. muss man noch ein bisschen mehr tun) das fest platzierte ChildForm anbringen und dann wie gehabt bei den variablen MDIChilds diese im Container mit aufnehmen.

Das Problem an der Geschichte ist mehr das es zu viele Möglichkeiten gibt das ganze zu lösen. Die Frage ist daher eher was man genau möchte. Im Prinzip kann man das ganze auch mit UserControls lösen. Wie gesagt, am besten wäre es Echo]6[ malt nen Bild, hängt es an und sagt, genauso und nicht anders muss es aussehen.

Allerdings denke ich das dien Vorschlag wirklich ausreicht, wenn es einfach sein darf 🙂

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

U
400 Beiträge seit 2008
vor 15 Jahren

@markus.bodlos

wenn ich das nicht falsch interpretier habe , möchte Echo]6[ doch in einem MDI-Child ein Form unterbringen? Dann kann er es doch besser als Control eibinden.

M
205 Beiträge seit 2008
vor 15 Jahren

Oha, dann hab ich das falsch verstanden, dachte ihm eht es um ein docking von fenstern in einem MDI Parent window. Sorry

mfg Markus

915 Beiträge seit 2006
vor 15 Jahren
Widget

Schaut, ich denke er will sowas:

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

915 Beiträge seit 2006
vor 15 Jahren

Wie gesagt, das Ding hab ich in knapp ner Minute erstellt - es ist simpel die Frage ist nur was man möchte. Sollen die Border der MDIControl aktiv sein, darf der Benutzer das MDIControlerform verschieben usw.

Das beste wäre wie gesagt, Echo]6[ malt nen Bild wie es genau auszusehen hat und was der Benutzer darf und was nicht, wie das verschieben.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

E
Echo]6[ Themenstarter:in
111 Beiträge seit 2006
vor 15 Jahren

Hallo!

Hier mal ein Bild vom Layout der Anwendung.

Das obere Fenster soll Eingabefelder beinhalten und beim Klick auf eine Gruppe geöffnet werden. Dieses Fenster soll die ganze Zeit angezeigt werden, sprich bis man halt links im Menü eine andere Gruppe ausgewählt hat.

Hat man nun eine Gruppe ausgewählt und klickt dann auf ein Item, so soll dann das dazugehörige Fenster im unteren Bereich angezeigt werden. Klickt man auf das nächste Item, so soll das untere Fenster geschlossen und ein neues geöffnet werden.

Die Fenster sollen nicht verschiebbar sein, also halt "FormBorderStyle" = None!

Ich hoffe, ich könnt euch jetzt eher vorstellen, was ich so vorhab!

Gruß
Echo

M
205 Beiträge seit 2008
vor 15 Jahren

Ja, das ist genau das was ich in meinem ersten Post gepostet habe!
Zum design, würde vorschöagen du erstellt erstmal dein mdi formular in diesem platzierst dann eben deinen toolstrip (dock:top) und ein tablelayoutpanel (dock:fill) mit 2 spalten und 2 reihen. die erste spalte nutzt du um deine Gruppen und items anzuzeigen, in der 2ten Splate erstellt du einen Splitcontainer (würde auch mit Panels gehen, splitcnt ist aber comfortabler) mit rowspan = 2 und die formulare erstellst du im container wie in meinem ersten post beschrieben, im Anhang ein Bild wie es dann ausschauen könnte.

mfg Markus

915 Beiträge seit 2006
vor 15 Jahren

@ markus.bodlos
Das alles lässt sich schön mit UserControls statt dann Forms abbilden 🙂

Aber hatte ohend as Bild von Echo]6[ auch Probleme zu verstehen inwiefern dann ein MDIContainer da mit einspielt.

@Echo]6[

Für die umsetzung mit UserControls zum Abbild von markus.bodlos, folgende vorgehensweise:

Ich schreibe es mal mit SplitContainer statt TableLayout, da man eigentlich dem Benutezr die Möglichkeit geben sollte die Breite der Ansichten selbst zu bestimmen.

Erstelle einfach eine MainForm, diese MainForm ist "kein MDIContainer", daher IsMdiContainer = false. Als zweites hast du einen SplitContainer der Senkrecht ist und DockStyle = Fill.
In diesen SplitContainer hast du links die Menüs rechts ist dein Content Bereich.

In den Contentbereich machst du wieder einen SplitContainer rein, diese trennt waagerecht. Oben hast du das fixe UserControl unten das dynamische Usercontrol.

So, warum UserControls, deine UserControls sind deine "ChildForms", sprich für jedes Childform was du davor hattest hast du nun ein eigenes UserControl. Damit die UserControls im unteren Bereich dynamsich reingeladen werdne können schreibst du ein Interface das du in alle UserControls implementierst.

Das Interface könnte folgende Methoden:

  • enum ControlType
    {
    NONE= 0,
    ControlA,
    ControlB,
    .....
    }

  • Show(Control parent);

  • Hide()

  • ControlType

Warum show und Hide, ganz einfach, getätigte Einstellungen sollen nicht verloren gehen. Daher initalisierst du deine UserControls und behällst sie in einer Liste von deiner MainForm. Wenn nun ein menüpunkt links gedrückt wird, löst du auf deiner MainForm ein CklickEvent aus, im ClickEvent selber erhällst du wieder als sender das entsprechende Menü, wenn Menü X daher gedrückt lade den Type = ControlTypeA usw.

Das ganze geht sehr schnell zu programmieren, ca. 10-20 min.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(