TB2Merge, Version 0.5 (alt)
Hinweis: dies ist nicht die neueste Version!
Datei: INFO.de.txt
TB2Merge.pas Hilfs-Unit für Toolbar2000 und davon abgeleitete Komponenten wie TBX oder SpTBX, um zwei Toolbars (Menubars) miteinander zu vermischen. Version 0.5 - die aktuelle Version gibt's immer unter http://flocke.vssd.de/prog/code/pascal/tb2merge/ Copyright (C) 2005 Volker Siebert <flocke@vssd.de> Alle Rechte vorbehalten. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------- Delphi-Versionen: 5, 6, 7 und 2005. Der Grund für das Schreiben der Unit war die Portierung einer alten Anwendung mit *vielen* MDI Formularen nach TBX, wobei ein TTBXToolBar als Hauptmenu eingesetzt werden sollte. Das Wichtigste zuerst: ToolbarMerger arbeitet auf sortiert angeordneten Blöcken von Elementen, die den selben "GroupIndex" Wert besitzen. Das funktioniert ganz ähnlich wie die VCL die Menüs von MDI Kind- und Haupt- fenstern miteinander verbindet. Das bedeutet aber auch, dass z.B. bei Elementen mit den Indizes ( 2, 1, 9, 8 ) das Ganze nicht richtig funktio- nieren wird - die Indizes müssen in aufsteigender Reihenfolge sortiert sein. Kleiner Werte, die hinter größeren stehen, werden automatisch mit diesen zusammengefasst, also sind die o.g. Indizes gleichbedeutend mit ( 2, 2, 9, 9 ). Die einzige Ausnahme von dieser Regel sind Trennlinien, da man denen keinen GroupIndex zuweisen kann. Standardmäßig werden diese mit den ihnen folgenden Elementen zusammengefasst, dieses Verhalten kann man aber über die Option "moSeparatorAfterItems" steuern. Hier ein einfaches Beispiel: Ursprüngliche Hauptmenüleiste: +-------+------------+-------+-------+ | Datei | Bearbeiten | Extra | Hilfe | +-------+------------+-------+-------+ | | | | | | +-------+-- GroupIndex = 9 +----------+-------------------- GroupIndex = 0 MDI Kind Menüleiste: +--------+----------+ | Suchen | Dokument | +--------+----------+ | | +---------+-------------- GroupIndex = 1 Verbundene Menüleiste: +-------+------------+--------+----------+-------+-------+ | Datei | Bearbeiten | Suchen | Dokument | Extra | Hilfe | +-------+------------+--------+----------+-------+-------+ Der Hauptvorteil liegt hier darin, dass die hinzugefügten Einträge zusammen mit den Ereignismethoden und Aktionen, weiterhin zum alten Fenster gehören und die Ereignisse auch in diesem Kontext ausgelöst werden. ToolbarMerger geht aber noch weiter, er kann nämlich auch rekursiv in Untermenüs gehen und dort einzelne Menüeinträge ersetzen, wie z.B. die Einträge "&Speichern" und "&Drucken" dennoch alle anderen Einträge aus dem Dateimenü unverändert belassen. Es gibt ein paar Optionen, die man beim Aufruf von ToolbarMerger.Merge angeben kann und die das Verhalten beeinflussen. Man stelle sich die folgende Situation vor: Originalmenü Eingefügtes Menü ( Ziel ) ( Quelle ) +-----------+ +----------------------+ 1 | Undo | 2 | Repeat | 1 | Redo | +----------------------+ ---+ Q b Z b +--- +-----------+ 5 | Cut [D] | | u l i l | 5 | Cut [A] | 5 | Paste special... [E] | ---+ e o e o | 5 | Copy [B] | +----------------------+ l c l c +--- 5 | Paste [C] | 8 | Insert object... | l k - k +-----------+ +----------------------+ - 9 | Find | 9 | Replace | +-----------+ * moKeepTarget, moRecursive > Da es keine jeweils passenden Einträge für die Indizes 1, 2, 8 und 9 gibt, werden diese Blöcke beim Mischen immer erhalten bleiben. Der Unterschied ergibt sich erst beim Index 5 weil er auf beiden Seiten vorkommt. Wenn man weder moKeepTarget noch moRecursive angibt, dann wird der komplette Zielblock durch den kompletten Quellblock ersetzt. Dies imitiert das Verhalten der VCL beim Mischen zweier Menüs. > Hier bekommt man ( 1 | 2 | D E | 8 | 9 ) Mit "moKeepTarget" versucht die Routine, für jeden Eintrag im Zielmenü einen passenden Eintrag im neuen Menü zu finden (wie ein passender Eintrag identifiziert wird steht weiter unten). Wenn einer gefunden wird, dann wird der Zieleintrag dadurch ersetzt. Ansonsten bleibt der Zielein- trag erhalten. Am Ende werden einfach die noch nicht benutzen Einträge aus dem neuen Menü angehängt. > Hier bekommt man ( 1 | 2 | D B C E | 8 | 9 ) "moRecursive" arbeitet ähnlich, d.h. es wird ein passender Eintrag für jedes Element im Zielmenü gesucht. Unterschiedlich wird das Vorgehen erst, wenn zwei passende Einträge mit Untermenüs gefunden werden. Dann wird der Zieleintrag beibehalten (mit allen Eigenschaften) und statt dessen werden die Untermenüs rekursiv miteinander verbunden. * moMatchByCaption, moMatchByTag (nur relevant in Verbindung mit moKeepTarget oder moRecursive) Ohne weitere Angabe identifiziert das System passende Einträge an ihrem Namen, d.h. tbMainMenuBar.miFileSave und tbChildMenuBar.miFileSave passen weil sie denselben Namen haben. Mit "moMatchByCaption" oder "moMatchByTag" werden passende Einträge über die Beschriftung bzw. über die Tag-Nummer identifiziert. * moSeparatorAfterItems Diese Option bewirkt, dass Trennlinien zusammen mit den Elementen behan- delt werden, die *vor* ihnen liegen. Standardmäßig werden Trennlinien zusammen mit den darauf folgenden behandelt. In der Praxis benutzt man einfach das globale Symbol "ToolbarMerger" (es ist eine Funktion, sollte aber wie eine globale Varible behandelt werden), um zwei Toolbars miteinander zu verbinden. Für fsMDIChild Formulare sollte man den folgenden Code benutzen und die Meldung WM_MDIACTIVATE abfangen: interface Teil: +------------------------------------------------------------------------- | type | TfrmChild = class(TForm) | ... | protected | procedure WMMDIActivate(var Message: TWMMDIActivate); | message WM_MDIACTIVATE; | ... | end; +------------------------------------------------------------------------- implementation Teil: +------------------------------------------------------------------------- | procedure TfrmChild.WMMDIActivate(var Message: TWMMDIActivate); | begin | inherited; | | if Message.ActiveWnd = Handle then | ToolbarMerger.Merge(frmMain.tbMainMenu, tbChildMenu, []) | else | ToolbarMerger.UnmergeAll(tbChildMenu); | end; +------------------------------------------------------------------------- Man kann für alle Formulare aber auch wie im folgenden Code die Ereignisse FormActivate, FormDeactivate und FormDestroy verwenden: events: +------------------------------------------------------------------------- | procedure TfrmChild.FormActivate(Sender: TObject); | begin | ToolbarMerger.Merge(frmMain.tbMainMenu, tbChildMenu, []); | end; | | procedure TfrmChild.FormDeactivate(Sender: TObject); | begin | // Das ist normalerweise *NICHT* nötig | ToolbarMerger.UnmergeAll(tbChildMenu); | end; | | procedure TfrmChild.FormDestroy(Sender: TObject); | begin | ToolbarMerger.UnmergeAll(tbChildMenu); | end; +------------------------------------------------------------------------- Es lohnt sich auch einen Blick in die Beispielanwendung, ein paar Zeilen Code sagen normalerweise mehr als 1.000 Worte ;) |