TB2Merge, Version 0.5 (alt)

Hinweis: dies ist nicht die neueste Version!

Zurück zur Übersicht

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 ;)
Flocke's Garage
Valid HTML 4.01 Transitional Valid CSS!
(C) 2005-2018 Volker Siebert.
Creative Commons-LizenzvertragDer gesamte Inhalt dieser Webseite steht unter einer Creative Commons-Lizenz (sofern nicht anders angegeben).