Title: Customize Toolbars at runtime
Question: Professional applications like Word or Excel let the user design the toolbars and let create new toolbars at runtime. This ist usually done with a little customize dialog and drag & drop functions.
Answer:
Professional applications like Word or Excel let the user design the toolbars and let create new toolbars at runtime. This ist usually done with a little customize dialog and drag & drop functions. This sample shows you, how to get this functionality simple into your program.
First of all, you must make some decissions to your program design. All functions, that can be put on a toolbar must defined in an Actionlist, because we need a list of functions that can be asigned to the toolbuttons. To minimize this work an Actionlist is the right thing, because wie can walk through the functions, have an automatic integration of the images for the toolbuttons via the imagelist, centralized shortcuts and have unique names for the functions to save and restore it.
The next thing is, that you should save and restore the customized toolbars to an inifile or the registry. This is done by the TFiletoolbar component included with this sample. Note, that you must assign the Actionlist to TFiletoolbars to get the save/restore work.
The customize dialog is built with formstyle fsStayOnTop, so the window is on top of our application. The form is displayed with the Show methode, because we must interact in the mainform for doing Drag & Drop.
For further details look at the TFiletoolbar documentation and to the source of the demo project. In the source you find detailed comments to anything that ist neccesary for get it working in your application.
Download the whole sample project including TFiletoolbar component for saving and restoring Toolbars.
http://www.helli.de/DelphiCorner/dc_tips/dc_tip4/dc_tip4.html
TToolbar97 component pack by Jordan Russel, Version 1.75 or higher available from http://www.jordanr.dhs.org/ (Freeware for non commercial use) is needed.
Example of Drag&Drop functions from Sample project:
//---------------------------------------------------------------
// Drag & Drop of Toolbar Buttons
// These functions are plugged to the OnDragOver, OnDragDrop and
// OnDragEnd property of any toolbar and any button on it.
// By user defined buttons and toolbars this is done automatic,
// by predefined toolbars you must plug in the functions in
// Objectinspector
//---------------------------------------------------------------
procedure TForm1.ToolbarDragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
// This function must be plugged to the OnDragOver property of
// any toolbars and toolbuttons
//
// Check if Dropping is allowed
begin
if Source is TListView then
// Docking allowed only from CustomizeDialog Command Listview
Accept:= (Source as TListView).Name = CustomizeDialog.Commands.Name;
end;
procedure TForm1.ToolbarDragDrop(Sender, Source: TObject; X, Y: Integer);
// This function must be plugged to the OnDragDrop property of
// any toolbars and toolbuttons
//
// Handler for TToolbutton97 objects for dropping from CustomizeDialog
var t: TListView;
act: TAction;
ti: TListItem;
tb, tb2: TToolbarButton97;
ftb: TFileToolbar;
oi: Integer;
begin
if Source is TListView then begin // Is it from the Listview?
t:= Source as TListView;
if Assigned (t) then begin
// Get the selected item, it holds the desired action
ti:= t.Selected;
if Assigned (ti) then begin
// The action is stored in the data property of the item
act:= ti.Data;
if Assigned (act) then begin
// create a toolbutton on the fly
tb:= TToolbarButton97.Create (self);
if Assigned (tb) then begin
tb.Images:= ImageList1; // Assign the Imagelist
tb.DisplayMode:= dmGlyphOnly; // display only the image
// mode is turned to dmManual when leaving the
// CustomizeDialog but to handle Drag&Drop, it must be
// dmAutomatic by now
tb.DragMode:= dmAutomatic;
tb.Action:= act; // the desired Action
// Assign the handlers
tb.OnDragDrop:= ToolbarDragDrop;
tb.OnDragOver:= ToolbarDragOver;
tb.OnEndDrag:= ToolbarEndDrag;
// Hints like parent
tb.ParentShowHint:= True;
// Look for the place to add the button on the toolbar
ftb:= nil;
oi:= x div tb.Width;
// Convert Position from pixel to number of buttons
if Sender is TFileToolbar then begin
// dropped direct to the toolbar?
ftb:= Sender as TFileToolbar;
end else if Sender is TToolbarButton97 then begin
// placed on an other button?
tb2:= Sender as TToolbarButton97;
if Assigned (tb2) then begin
// Get parent and Orderindex of the button
ftb:= tb2.Parent as TFileToolbar;
oi:= ftb.OrderIndex[tb2];
end;
end;
if Assigned (ftb) then begin // We have a parent...
// generate a unique name for the button
tb.Name:= 'tbB' + CustomizeDialog.DateStamp;
// Insert the button on the toolbar
ftb.InsertControl (tb);
ftb.OrderIndex[tb]:= oi; // and set the Orderindex
end;
end;
end;
end;
end;
end;
end;
procedure TForm1.ToolbarEndDrag(Sender, Target: TObject; X, Y: Integer);
// This function must be plugged to the OnEndDrag property of any
// toolbutton. The toolbars must not have this, because you cant
// throw them out of the program...
//
// Handler for TToolbarbutton97 objects to throw 'em out
// of the Toolbar
var tb: TToolbarButton97;
ftb: TFileToolbar;
begin
if not Assigned (Target) then begin
// No target so throw the button away
tb:= Sender as TToolbarButton97;
if Assigned (tb) then begin
ftb:= tb.Parent as TFileToolbar;
// Delete the button
if Assigned (ftb) then ftb.RemoveControl (tb);
end;
end;
end;