RAD Studio 2007: Layout & Docking



  • Hallo,

    ich habe eine MDI Anwendung mit mehreren MDI Kindfenstern. Wenn der Benutzer zur Laufzeit eins der Kindfenster mit der Maus bewegt möchte ich das bewegte Fenster an das Hauptfenster andocken, abhängig von der Region, wo der Benutzer die Maus wieder los lässt.
    Es gibt wohl sowas wie TForm::UseDockManager und einige Callbacks, aber ich habe jetzt nach 3h Google-Suche und Herumprobieren keinen Schimmer, wie man das irgendwie umsetzen kann. Die Embarcadero Hile schweigt sich über dieses Thema komplett aus, auf deren Webseite findet man allerdings zusammenkopierte Codeschnipsel, bei denen auch nicht erklärt wird, wie man welche Einstellungen wo vornehmen muss. Funktioniert also auch nicht.
    Hat jemand sowas mal gemacht und kann mir da weiterhelfen?



  • Ich habe mal die Docking-Komponenten aus der JVCL benutzt, kann diese aber nur bedingt empfehlen. In der Theorie sind die prima: das Docking-Layout kann gespeichert und wiederhergestellt werden, es unterstützt automatisches Ausblenden von angedockten Fenstern, mehrere Darstellungsstile etc. In der Praxis ist es aber zu leicht, sich das Layout fast irreversibel durcheinanderzubringen.

    Meines Wissens erfordert das Docking nicht MDI-Child-Fenster, sondern ganz gewöhnliche Top-level-Fenster. Mit denen kann man "tabbed MDI" imitieren (können die JVCL-Komponenten auch), aber richtiges MDI ist damit, glaube ich, nicht vereinbar.

    Aufgrund meiner Erfahrungen mit meinem Docking-UI habe ich mittlerweile die Arbeitshypothese übernommen, daß ein Docking-Layout die meisten Benutzer, so sie nicht selbst Softwareentwickler sind, überfordert, und man lieber robustere Alternativen benutzt wie etwa aus- und einklappbare Panels (wie z.B. in Live Mail) oder vorkonfigurierte Layouts, zwischen denen der Benutzer auswählen kann.

    Falls du aber unbedingt Docking verwenden willst, schau mal hier. Eine Demo für das VCL-integrierte Docking liegt dem C++Builder bei (in C++Builder XE unter Demos\CPP\VCL\Docking), aber die ist mit aktivem DWM ziemlich unerträglich (aber sieh selbst).



  • Hallo audacia,

    danke für deine Antwort. Ich habe mich gestern noch einige Zeit mit dem Thema befasst und bin nicht wirklich weiter gekommen.
    Was ich umsetzen möchte ist Folgendes:

    Es gibt 9 Fenstertypen, von denen es maximal eine Instanz gibt. Aus diesen 6 Fenstertypen soll sich der Benutzer verschiedene Ansichten selbst zusammen stellen können und als Ansicht speichern. Jede Ansicht ordnet die bestehenden Fenster einfach nur neu an (bzw. blendet sie aus). Typischerweise besteht eine Ansicht aus 3 Fenstern (z.b. ein großes Fenster am linken Rand mit 75% Breite, rechts daneben zwei kleine Informationsfenster übereinander). Damit der der Benutzer nicht jedes Mal pixelgenau schieben muss wäre die Verwendung eines Docking Managers schon ganz nett.
    Im Moment gibt es in dem Zusammenhang allerdings andere, größere Baustellen, ich habe den Dock Manager erst ein mal zurück gestellt. Vermutlich werde ich da einen eigenen implementieren müssen, da sich der TDockTree nicht ganz so verhält, wie ich mir das vorgestellt habe. Im ersten Schritt würde es vermutlich ausreichen, das Align Attribut jedes Kindfensters zu setzen.



  • Hallo,

    Wir haben bei uns ähnliche Erfahrungen mit der Akzeptanz von Docking-Layouts wie audacia gemacht. Wir hielten das ursprünglich für eine gute Idee recht frei konfigurierbare Fensterlayouts mit ein paar Vorgaben zu gestalten. Den Layoutmanager haben wir auch selber geschrieben.
    Beim Nutzer kam das aber nicht wirklich an. Die meisten Anwender schienen damit überfordert zu sein.
    Wir sind bei den neueren Versionen wieder auf Einfenster-Applikationen zurückgekehrt mit ausklappbaren Dialogen wenn nötig.



  • Hallo,

    ich habe für meine Anwendung ein Docking-Framework implementiert, das auf demvon audacia genannten Beispiel basiert. Um das Layout zu speichern bzw. wieder zu laden verwende ich den VCL-DockManager. Um diesen zu Initialisieren verwende ich folgenden Code:

    this->UseDockManager = false;
    TCaptionedDockTree *DockTree = new TCaptionedDockTree(this);
    void* dm = NULL;
    if(Supports(DockTree, __uuidof(IDockManager), &dm)) {
       this->DockManager = static_cast<IDockManager*>(dm);
    }
    this->UseDockManager = true;
    

    Das Interface IDockManager stellt die Funktionen SaveToStream und LoadFromStream bereit.

    Beispiel:

    TMemoryStream* Stream = new TMemoryStream();
    Stream->LoadFromFile("MyLayoutFile.lyt");
    Stream->Position = 0;
    this->DockManager->LoadFromStream(Stream);
    

    Die Stream-Position bitte auf 0 setzen!



  • Kerem schrieb:

    ich habe für meine Anwendung ein Docking-Framework implementiert, das auf demvon audacia genannten Beispiel basiert.

    Vermutlich hast du die Probleme, die das Beispiel mit dem DWM hat, selbst behoben? Das Ziehen von Fenstern ist mit dem VCL-Code unglaublich träge, weil DefaultDockImage() mit PatBlt() auf den Desktop zeichnet, und PatBlt() auf dem Desktopfenster sehr teuer ist, da es mutmaßlich für jeden Pixel einen DWM-Sync erfordert. Aber vermutlich läßt sich das sehr einfach durch irgendetwas auf der Basis von AlphaBlend() ersetzen, mit dem der DWM besser klarkommt.



  • Genau. Ich weiß nicht genau ab welcher, aber neuere C++ Builder Version liefern ein überearbeitetes Docking-Beispiel. Zusammengefasst wird eine eigene TTragDockObjectEx Klasse und ein transparentes Formular benötigt. Sieht nacher aus wie in der IDE.



  • Ich bin inzwischen wieder von der Idee abgerückt. Nicht, weil ich sie nicht sinnvoll finde, sondern weil sich der Aufwand mit Hausmitteln einfach nicht lohnt.
    Trotzdem Danke für die Hinweise und Anregungen.


Anmelden zum Antworten