home *** CD-ROM | disk | FTP | other *** search
- unit TB97Tlbr;
-
- {
- Toolbar97
- Copyright (C) 1998-2001 by Jordan Russell
- For conditions of distribution and use, see LICENSE.TXT.
-
- TCustomToolbar97, TToolbar97, TToolbarSep97
-
- $Id: TB97Tlbr.pas,v 1.3 2001/02/26 17:52:42 jr Exp $
- }
-
- interface
-
- {$I TB97Ver.inc}
-
- uses
- Windows, Messages, Classes, Controls, Graphics,
- TB97;
-
- type
- { TCustomToolbar97 }
-
- TToolbarParams = record
- InitializeOrderByPosition, DesignOrderByPosition: Boolean;
- end;
-
- TCustomToolbar97 = class(TCustomToolWindow97)
- private
- FToolbarParams: TToolbarParams;
- FFloatingRightX: Integer;
- FOrderListDirty: Boolean;
- SizeData: Pointer;
-
- { Lists }
- SlaveInfo, { List of slave controls. Items are pointers to TSlaveInfo's }
- GroupInfo, { List of the control "groups". List items are pointers to TGroupInfo's }
- LineSeps, { List of the Y locations of line separators. Items are casted in TLineSep's }
- OrderList: TList; { List of the child controls, arranged using the current "OrderIndex" values }
-
- { Property access methods }
- function GetOrderedControls (Index: Integer): TControl;
- function GetOrderIndex (Control: TControl): Integer;
- procedure SetFloatingWidth (Value: Integer);
- procedure SetOrderIndex (Control: TControl; Value: Integer);
-
- { Internal }
- procedure CleanOrderList;
- procedure SetControlVisible (const Control: TControl;
- const LeftOrRight: Boolean);
- function ShouldControlBeVisible (const Control: TControl;
- const LeftOrRight: Boolean): Boolean;
- procedure FreeGroupInfo (const List: TList);
- procedure BuildGroupInfo (const List: TList; const TranslateSlave: Boolean;
- const OldDockType, NewDockType: TDockType);
-
- { Messages }
- procedure CMControlListChange (var Message: TCMControlListChange); message CM_CONTROLLISTCHANGE;
- procedure WMWindowPosChanging (var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
- protected
- property ToolbarParams: TToolbarParams read FToolbarParams;
-
- procedure Paint; override;
-
- procedure BuildPotentialSizesList (SizesList: TList); dynamic;
- function ChildControlTransparent (Ctl: TControl): Boolean; override;
- procedure GetParams (var Params: TToolWindowParams); override;
- procedure GetToolbarParams (var Params: TToolbarParams); dynamic;
- procedure ResizeBegin (ASizeHandle: TToolWindowSizeHandle); override;
- procedure ResizeTrack (var Rect: TRect; const OrigRect: TRect); override;
- procedure ResizeEnd (Accept: Boolean); override;
-
- procedure GetBarSize (var ASize: Integer; const DockType: TDockType); override;
- procedure GetMinimumSize (var AClientWidth, AClientHeight: Integer); override;
- procedure InitializeOrdering; override;
- function OrderControls (CanMoveControls: Boolean; PreviousDockType: TDockType;
- DockingTo: TDock97): TPoint; override;
- public
- property OrderedControls[Index: Integer]: TControl read GetOrderedControls;
- property OrderIndex[Control: TControl]: Integer read GetOrderIndex write SetOrderIndex;
- property FloatingWidth: Integer read FFloatingRightX write SetFloatingWidth;
-
- constructor Create (AOwner: TComponent); override;
- destructor Destroy; override;
- procedure ReadPositionData (const ReadIntProc: TPositionReadIntProc;
- const ReadStringProc: TPositionReadStringProc; const ExtraData: Pointer); override;
- procedure WritePositionData (const WriteIntProc: TPositionWriteIntProc;
- const WriteStringProc: TPositionWriteStringProc; const ExtraData: Pointer); override;
-
- procedure SetSlaveControl (const ATopBottom, ALeftRight: TControl);
- end;
-
- { TToolbar97 }
-
- TToolbar97 = class(TCustomToolbar97)
- published
- property ActivateParent;
- property BorderStyle;
- property Caption;
- property Color;
- property CloseButton;
- property CloseButtonWhenDocked;
- property DefaultDock;
- property DockableTo;
- property DockedTo;
- property DockMode;
- property DockPos;
- property DockRow;
- property DragHandleStyle;
- property FloatingMode;
- property Font;
- property FullSize;
- property HideWhenInactive;
- property LastDock;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ShowCaption;
- property ShowHint;
- property TabOrder;
- property UseLastDock;
- property Version;
- property Visible;
-
- property OnClose;
- property OnCloseQuery;
- property OnDragDrop;
- property OnDragOver;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnMove;
- property OnRecreated;
- property OnRecreating;
- property OnDockChanged;
- property OnDockChanging;
- property OnDockChangingEx;
- property OnDockChangingHidden;
- property OnResize;
- property OnVisibleChanged;
- end;
-
- { TToolbarSep97 }
-
- TToolbarSepSize = 1..MaxInt;
-
- TToolbarSep97 = class(TGraphicControl)
- private
- FBlank: Boolean;
- FSizeHorz, FSizeVert: TToolbarSepSize;
- procedure SetBlank (Value: Boolean);
- procedure SetSizeHorz (Value: TToolbarSepSize);
- procedure SetSizeVert (Value: TToolbarSepSize);
- protected
- procedure MouseDown (Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure Paint; override;
- procedure SetParent (AParent: TWinControl); override;
- public
- constructor Create (AOwner: TComponent); override;
- published
- { These two properties don't need to be stored since it automatically gets
- resized based on the setting of SizeHorz and SizeVert }
- property Width stored False;
- property Height stored False;
- property Blank: Boolean read FBlank write SetBlank default False;
- property SizeHorz: TToolbarSepSize read FSizeHorz write SetSizeHorz default 6;
- property SizeVert: TToolbarSepSize read FSizeVert write SetSizeVert default 6;
- property Visible;
- end;
-
-
- {$IFOPT J+}
- {$DEFINE _TB97_OPT_J}
- {$J-} { don't let the following typed constants be modified }
- {$ENDIF}
- const
- tb97DefaultBarWidthHeight = 8;
-
- tb97TopMarginFloating = 2;
- tb97TopMarginDocked = 0;
- tb97TopMargin: array[Boolean] of Integer = (tb97TopMarginFloating, tb97TopMarginDocked);
- tb97BottomMarginFloating = 1;
- tb97BottomMarginDocked = 0;
- tb97BottomMargin: array[Boolean] of Integer = (tb97BottomMarginFloating, tb97BottomMarginDocked);
- tb97LeftMarginFloating = 4;
- tb97LeftMarginDocked = 0;
- tb97LeftMargin: array[Boolean] of Integer = (tb97LeftMarginFloating, tb97LeftMarginDocked);
- tb97RightMarginFloating = 4;
- tb97RightMarginDocked = 0;
- tb97RightMargin: array[Boolean] of Integer = (tb97RightMarginFloating, tb97RightMarginDocked);
- tb97LineSpacing = 6;
- {$IFDEF _TB97_OPT_J}
- {$J+}
- {$UNDEF _TB97_OPT_J}
- {$ENDIF}
-
- implementation
-
- uses
- SysUtils, TB97Cmn, TB97Cnst;
-
- const
- { Constants for registry values. Do not localize! }
- { TCustomToolbar97 specific }
- rvFloatRightX = 'FloatRightX';
-
- type
- { Used internally by the TCustomToolbar97.Resize* procedures }
- PToolbar97SizeData = ^TToolbar97SizeData;
- TToolbar97SizeData = record
- SizeHandle: TToolWindowSizeHandle;
- NewSizes: TList; { List of valid new sizes. Items are casted into TSmallPoints }
- CurRightX: Integer;
- DisableSensCheck, OpSide: Boolean;
- SizeSens: Integer;
- end;
-
- { Used in TCustomToolbar97.GroupInfo lists }
- PGroupInfo = ^TGroupInfo;
- TGroupInfo = record
- GroupWidth, { Width in pixels of the group, if all controls were
- lined up left-to-right }
- GroupHeight: Integer; { Heights in pixels of the group, if all controls were
- lined up top-to-bottom }
- Members: TList;
- end;
-
- { Used in TCustomToolbar97.SlaveInfo lists }
- PSlaveInfo = ^TSlaveInfo;
- TSlaveInfo = record
- LeftRight,
- TopBottom: TControl;
- end;
-
- { Used in TCustomToolbar97.LineSeps lists }
- TLineSep = packed record
- Y: SmallInt;
- Blank: Boolean;
- Unused: Boolean;
- end;
-
- { Use by CompareControls }
- PCompareExtra = ^TCompareExtra;
- TCompareExtra = record
- Toolbar: TCustomToolbar97;
- ComparePositions: Boolean;
- CurDockType: TDockType;
- end;
-
-
- { TCustomToolbar97 }
-
- constructor TCustomToolbar97.Create (AOwner: TComponent);
- begin
- inherited;
- GetToolbarParams (FToolbarParams);
- GroupInfo := TList.Create;
- SlaveInfo := TList.Create;
- LineSeps := TList.Create;
- OrderList := TList.Create;
- end;
-
- destructor TCustomToolbar97.Destroy;
- var
- I: Integer;
- begin
- OrderList.Free;
- LineSeps.Free;
- if Assigned(SlaveInfo) then begin
- for I := SlaveInfo.Count-1 downto 0 do
- FreeMem (SlaveInfo.Items[I]);
- SlaveInfo.Free;
- end;
- FreeGroupInfo (GroupInfo);
- GroupInfo.Free;
- inherited;
- end;
-
- procedure TCustomToolbar97.ReadPositionData (const ReadIntProc: TPositionReadIntProc;
- const ReadStringProc: TPositionReadStringProc; const ExtraData: Pointer);
- begin
- inherited;
- FFloatingRightX := ReadIntProc(Name, rvFloatRightX, 0, ExtraData);
- end;
-
- procedure TCustomToolbar97.WritePositionData (const WriteIntProc: TPositionWriteIntProc;
- const WriteStringProc: TPositionWriteStringProc; const ExtraData: Pointer);
- begin
- inherited;
- WriteIntProc (Name, rvFloatRightX, FFloatingRightX, ExtraData);
- end;
-
- procedure TCustomToolbar97.GetMinimumSize (var AClientWidth, AClientHeight: Integer);
- begin
- AClientWidth := 0;
- AClientHeight := 0;
- end;
-
- procedure TCustomToolbar97.CleanOrderList;
- { TCustomToolbar97 uses a CM_CONTROLLISTCHANGE handler to detect when new
- controls are added to the toolbar. The handler adds the new controls to
- OrderList, which can be manipulated by the application using the OrderIndex
- property.
- The only problem is, the VCL relays CM_CONTROLLISTCHANGE messages
- to all parents of a control, not just the immediate parent. In pre-1.76
- versions of Toolbar97, OrderList contained not only the immediate children
- of the toolbar, but their children too. So this caused the OrderIndex
- property to return unexpected results.
- What this method does is clear out all controls in OrderList that aren't
- immediate children of the toolbar. (A check of Parent can't be put into the
- CM_CONTROLLISTCHANGE handler because that message is sent before a new
- Parent is assigned.) }
- var
- I: Integer;
- begin
- if not FOrderListDirty then
- Exit;
- I := 0;
- while I < OrderList.Count do begin
- if TControl(OrderList.List[I]).Parent <> Self then
- OrderList.Delete (I)
- else
- Inc (I);
- end;
- FOrderListDirty := False;
- end;
-
- function CompareControls (const Item1, Item2, ExtraData: Pointer): Integer; far;
- begin
- with PCompareExtra(ExtraData)^ do
- if ComparePositions then begin
- if CurDockType <> dtLeftRight then
- Result := TControl(Item1).Left - TControl(Item2).Left
- else
- Result := TControl(Item1).Top - TControl(Item2).Top;
- end
- else
- with Toolbar.OrderList do
- Result := IndexOf(Item1) - IndexOf(Item2);
- end;
-
- procedure TCustomToolbar97.InitializeOrdering;
- var
- Extra: TCompareExtra;
- begin
- inherited;
- { Initialize order of items in OrderList }
- if ToolbarParams.InitializeOrderByPosition then begin
- with Extra do begin
- Toolbar := Self;
- ComparePositions := True;
- CurDockType := GetDockTypeOf(DockedTo);
- end;
- CleanOrderList;
- ListSortEx (OrderList, CompareControls, @Extra);
- end;
- end;
-
- procedure TCustomToolbar97.GetBarSize (var ASize: Integer; const DockType: TDockType);
- var
- I: Integer;
- begin
- ASize := tb97DefaultBarWidthHeight;
- for I := 0 to ControlCount-1 do
- if not(Controls[I] is TToolbarSep97) then
- with Controls[I] do begin
- if ShouldControlBeVisible(Controls[I], DockType = dtLeftRight) then begin
- if DockType = dtLeftRight then begin
- if Width > ASize then ASize := Width;
- end
- else begin
- if Height > ASize then ASize := Height;
- end;
- end;
- end;
- end;
-
- procedure TCustomToolbar97.GetParams (var Params: TToolWindowParams);
- begin
- inherited;
- with Params do begin
- CallAlignControls := False;
- ResizeEightCorner := False;
- ResizeClipCursor := False;
- end;
- end;
-
- procedure TCustomToolbar97.GetToolbarParams (var Params: TToolbarParams);
- begin
- with Params do begin
- InitializeOrderByPosition := True;
- DesignOrderByPosition := True;
- end;
- end;
-
- procedure TCustomToolbar97.Paint;
- var
- S: Integer;
- begin
- inherited;
- { Long separators when not docked }
- if not Docked then
- for S := 0 to LineSeps.Count-1 do begin
- with TLineSep(LineSeps[S]) do begin
- if Blank then Continue;
- Canvas.Pen.Color := clBtnShadow;
- Canvas.MoveTo (1, Y-4); Canvas.LineTo (ClientWidth-1, Y-4);
- Canvas.Pen.Color := clBtnHighlight;
- Canvas.MoveTo (1, Y-3); Canvas.LineTo (ClientWidth-1, Y-3);
- end;
- end;
- end;
-
- function ControlVisibleOrDesigning (AControl: TControl): Boolean;
- begin
- Result := AControl.Visible or (csDesigning in AControl.ComponentState);
- end;
-
- procedure TCustomToolbar97.SetControlVisible (const Control: TControl;
- const LeftOrRight: Boolean);
- { If Control is a master or slave control, it automatically adjusts the
- Visible properties of both the master and slave control based on the value
- of LeftOrRight }
- var
- I: Integer;
- begin
- for I := 0 to SlaveInfo.Count-1 do
- with PSlaveInfo(SlaveInfo[I])^ do
- if (TopBottom = Control) or (LeftRight = Control) then begin
- if Assigned(TopBottom) then TopBottom.Visible := not LeftOrRight;
- if Assigned(LeftRight) then LeftRight.Visible := LeftOrRight;
- Exit;
- end;
- end;
-
- function TCustomToolbar97.ShouldControlBeVisible (const Control: TControl;
- const LeftOrRight: Boolean): Boolean;
- { If Control is a master or slave control, it returns the appropriate visibility
- setting based on the value of LeftOrRight, otherwise it simply returns the
- current Visible setting }
- var
- I: Integer;
- begin
- for I := 0 to SlaveInfo.Count-1 do
- with PSlaveInfo(SlaveInfo[I])^ do
- if TopBottom = Control then begin
- Result := not LeftOrRight;
- Exit;
- end
- else
- if LeftRight = Control then begin
- Result := LeftOrRight;
- Exit;
- end;
- Result := ControlVisibleOrDesigning(Control);
- end;
-
- procedure TCustomToolbar97.FreeGroupInfo (const List: TList);
- var
- I: Integer;
- L: PGroupInfo;
- begin
- if List = nil then Exit;
- for I := List.Count-1 downto 0 do begin
- L := List.Items[I];
- if Assigned(L) then begin
- L^.Members.Free;
- FreeMem (L);
- end;
- List.Delete (I);
- end;
- end;
-
- procedure TCustomToolbar97.BuildGroupInfo (const List: TList;
- const TranslateSlave: Boolean; const OldDockType, NewDockType: TDockType);
- var
- I: Integer;
- GI: PGroupInfo;
- Children: TList; {items casted into TControls}
- C: TControl;
- NewGroup: Boolean;
- Extra: TCompareExtra;
- begin
- FreeGroupInfo (List);
- if ControlCount = 0 then Exit;
-
- Children := TList.Create;
- try
- for I := 0 to ControlCount-1 do
- if (not TranslateSlave and ControlVisibleOrDesigning(Controls[I])) or
- (TranslateSlave and ShouldControlBeVisible(Controls[I], NewDockType = dtLeftRight)) then
- Children.Add (Controls[I]);
-
- with Extra do begin
- Toolbar := Self;
- CurDockType := OldDockType;
- ComparePositions := (csDesigning in ComponentState) and
- ToolbarParams.DesignOrderByPosition;
- end;
- if Extra.ComparePositions then begin
- CleanOrderList;
- ListSortEx (OrderList, CompareControls, @Extra);
- end;
- ListSortEx (Children, CompareControls, @Extra);
-
- GI := nil;
- NewGroup := True;
- for I := 0 to Children.Count-1 do begin
- if NewGroup then begin
- NewGroup := False;
- GI := AllocMem(SizeOf(TGroupInfo));
- { Note: AllocMem initializes the newly allocated data to zero }
- GI^.Members := TList.Create;
- List.Add (GI);
- end;
- C := Children[I];
- GI^.Members.Add (C);
- if C is TToolbarSep97 then
- NewGroup := True
- else begin
- with C do begin
- Inc (GI^.GroupWidth, Width);
- Inc (GI^.GroupHeight, Height);
- end;
- end;
- end;
- finally
- Children.Free;
- end;
- end;
-
- function TCustomToolbar97.OrderControls (CanMoveControls: Boolean;
- PreviousDockType: TDockType; DockingTo: TDock97): TPoint;
- { This arranges the controls on the toolbar }
- var
- NewDockType: TDockType;
- NewDocked: Boolean;
- RightX, I: Integer;
- CurBarSize, DockRowSize: Integer;
- GInfo: TList;
- AllowWrap: Boolean;
- MinPosPixels, MinRowPixels, CurPosPixel, CurLinePixel, G: Integer;
- GoToNewLine: Boolean;
- GI: PGroupInfo;
- Member: TControl;
- MemberIsSep: Boolean;
- GroupPosSize, MemberPosSize: Integer;
- PreviousSep: TToolbarSep97; PrevMinPosPixels: Integer;
- NewLineSep: TLineSep;
- label 1;
- begin
- NewDockType := GetDockTypeOf(DockingTo);
- NewDocked := Assigned(DockingTo);
-
- RightX := FFloatingRightX;
- if (NewDockType <> dtNotDocked) or (RightX = 0) then
- RightX := High(RightX)
- else begin
- { Make sure RightX isn't less than the smallest sized control + margins,
- in case one of the *LoadToolbarPositions functions happened to read
- a value too small. }
- for I := 0 to ControlCount-1 do
- if not(Controls[I] is TToolbarSep97) then
- with Controls[I] do
- if Width + (tb97LeftMarginFloating+tb97RightMarginFloating) > RightX then
- RightX := Width + (tb97LeftMarginFloating+tb97RightMarginFloating);
- end;
-
- if CanMoveControls and (SlaveInfo.Count <> 0) then
- for I := 0 to ControlCount-1 do
- if not(Controls[I] is TToolbarSep97) then
- SetControlVisible (Controls[I], NewDockType = dtLeftRight);
-
- GetBarSize (CurBarSize, NewDockType);
- if (DockingTo <> nil) and (DockingTo = DockedTo) then
- GetDockRowSize (DockRowSize)
- else
- DockRowSize := CurBarSize;
-
- if CanMoveControls then
- GInfo := GroupInfo
- else
- GInfo := TList.Create;
- try
- BuildGroupInfo (GInfo, not CanMoveControls, PreviousDockType, NewDockType);
-
- if CanMoveControls then
- LineSeps.Clear;
-
- CurLinePixel := tb97TopMargin[NewDocked];
- MinPosPixels := tb97LeftMargin[NewDocked];
- if GInfo.Count <> 0 then begin
- AllowWrap := not NewDocked;
- CurPosPixel := MinPosPixels;
- GoToNewLine := False;
- PreviousSep := nil; PrevMinPosPixels := 0;
- for G := 0 to GInfo.Count-1 do begin
- GI := PGroupInfo(GInfo[G]);
-
- if NewDockType <> dtLeftRight then
- GroupPosSize := GI^.GroupWidth
- else
- GroupPosSize := GI^.GroupHeight;
- if AllowWrap and
- (GoToNewLine or (CurPosPixel+GroupPosSize+tb97RightMargin[NewDocked] > RightX)) then begin
- GoToNewLine := False;
- CurPosPixel := tb97LeftMargin[NewDocked];
- if (G <> 0) and (PGroupInfo(GInfo[G-1])^.Members.Count <> 0) then begin
- Inc (CurLinePixel, CurBarSize + tb97LineSpacing);
- if Assigned(PreviousSep) then begin
- MinPosPixels := PrevMinPosPixels;
- if CanMoveControls then begin
- PreviousSep.Width := 0;
-
- LongInt(NewLineSep) := 0;
- NewLineSep.Y := CurLinePixel;
- NewLineSep.Blank := PreviousSep.Blank;
- LineSeps.Add (Pointer(NewLineSep));
- end;
- end;
- end;
- end;
- if CurPosPixel > MinPosPixels then MinPosPixels := CurPosPixel;
- for I := 0 to GI^.Members.Count-1 do begin
- Member := TControl(GI^.Members[I]);
- MemberIsSep := Member is TToolbarSep97;
- with Member do begin
- if not MemberIsSep then begin
- if NewDockType <> dtLeftRight then
- MemberPosSize := Width
- else
- MemberPosSize := Height;
- end
- else begin
- if NewDockType <> dtLeftRight then
- MemberPosSize := TToolbarSep97(Member).SizeHorz
- else
- MemberPosSize := TToolbarSep97(Member).SizeVert;
- end;
- { If RightX is passed, proceed to next line }
- if AllowWrap and not MemberIsSep and
- (CurPosPixel+MemberPosSize+tb97RightMargin[NewDocked] > RightX) then begin
- CurPosPixel := tb97LeftMargin[NewDocked];
- Inc (CurLinePixel, CurBarSize);
- GoToNewLine := True;
- end;
- if NewDockType <> dtLeftRight then begin
- if not MemberIsSep then begin
- if CanMoveControls then
- SetBounds (CurPosPixel, CurLinePixel+((DockRowSize-Height) div 2), Width, Height);
- Inc (CurPosPixel, Width);
- end
- else begin
- if CanMoveControls then
- SetBounds (CurPosPixel, CurLinePixel, TToolbarSep97(Member).SizeHorz, DockRowSize);
- Inc (CurPosPixel, TToolbarSep97(Member).SizeHorz);
- end;
- end
- else begin
- if not MemberIsSep then begin
- if CanMoveControls then
- SetBounds (CurLinePixel+((DockRowSize-Width) div 2), CurPosPixel, Width, Height);
- Inc (CurPosPixel, Height);
- end
- else begin
- if CanMoveControls then
- SetBounds (CurLinePixel, CurPosPixel, DockRowSize, TToolbarSep97(Member).SizeVert);
- Inc (CurPosPixel, TToolbarSep97(Member).SizeVert);
- end;
- end;
- PrevMinPosPixels := MinPosPixels;
- if not MemberIsSep then
- PreviousSep := nil
- else
- PreviousSep := TToolbarSep97(Member);
- if CurPosPixel > MinPosPixels then MinPosPixels := CurPosPixel;
- end;
- end;
- end;
- end
- else
- Inc (MinPosPixels, tb97DefaultBarWidthHeight);
-
- if csDesigning in ComponentState then
- Invalidate;
- finally
- if not CanMoveControls then begin
- FreeGroupInfo (GInfo);
- GInfo.Free;
- end;
- end;
-
- Inc (MinPosPixels, tb97RightMargin[NewDocked]);
- MinRowPixels := CurLinePixel + CurBarSize + tb97BottomMargin[NewDocked];
- if NewDockType <> dtLeftRight then begin
- Result.X := MinPosPixels;
- Result.Y := MinRowPixels;
- end
- else begin
- Result.X := MinRowPixels;
- Result.Y := MinPosPixels;
- end;
- end;
-
- procedure TCustomToolbar97.CMControlListChange (var Message: TCMControlListChange);
- { The VCL sends this message is sent whenever a child control is inserted into
- or deleted from the toolbar }
- var
- I: Integer;
- begin
- inherited;
- with Message, OrderList do begin
- { Delete any previous occurances of Control in OrderList. There shouldn't
- be any if Inserting=True, but just to be safe, check anyway. }
- while True do begin
- I := IndexOf(Control);
- if I = -1 then Break;
- Delete (I);
- end;
- if Inserting then begin
- Add (Control);
- FOrderListDirty := True;
- end;
- end;
- end;
-
- function CompareNewSizes (const Item1, Item2, ExtraData: Pointer): Integer; far;
- begin
- { Sorts in descending order }
- if ExtraData = nil then
- Result := TSmallPoint(Item2).X - TSmallPoint(Item1).X
- else
- Result := TSmallPoint(Item2).Y - TSmallPoint(Item1).Y;
- end;
-
- procedure TCustomToolbar97.BuildPotentialSizesList (SizesList: TList);
- var
- MinX, SaveFloatingRightX: Integer;
- X, LastY: Integer;
- S: TPoint;
- S2: TSmallPoint;
- begin
- MinX := tb97LeftMarginFloating + tb97RightMarginFloating;
- SaveFloatingRightX := FFloatingRightX;
- try
- { Add the widest size to the list }
- FFloatingRightX := 0;
- S := OrderControls(False, dtNotDocked, nil);
- SizesList.Add (Pointer(PointToSmallPoint(S)));
- { Calculate and add rest of sizes to the list }
- LastY := S.Y;
- X := S.X-1;
- while X >= MinX do begin
- FFloatingRightX := X;
- S := OrderControls(False, dtNotDocked, nil);
- if S.X > X then { if it refuses to go any smaller }
- Break
- else
- if X = S.X then begin
- if (S.Y = LastY) and (SizesList.Count > 1) then
- SizesList.Delete (SizesList.Count-1);
- S2 := PointToSmallPoint(S);
- if SizesList.IndexOf(Pointer(S2)) = -1 then
- SizesList.Add (Pointer(S2));
- LastY := S.Y;
- Dec (X);
- end
- else
- X := S.X;
- end;
- finally
- FFloatingRightX := SaveFloatingRightX;
- end;
- end;
-
- procedure TCustomToolbar97.ResizeBegin (ASizeHandle: TToolWindowSizeHandle);
- const
- MaxSizeSens = 12;
- var
- I, NewSize: Integer;
- S, N: TSmallPoint;
- P: TPoint;
- begin
- inherited;
-
- SizeData := AllocMem(SizeOf(TToolbar97SizeData));
-
- with PToolbar97SizeData(SizeData)^ do begin
- SizeHandle := ASizeHandle;
- CurRightX := FFloatingRightX;
- DisableSensCheck := False;
- OpSide := False;
-
- NewSizes := TList.Create;
- BuildPotentialSizesList (NewSizes);
- for I := 0 to NewSizes.Count-1 do begin
- P := SmallPointToPoint(TSmallPoint(NewSizes.List[I]));
- AddFloatingNCAreaToSize (P);
- NewSizes.List[I] := Pointer(PointToSmallPoint(P));
- end;
- ListSortEx (NewSizes, CompareNewSizes,
- Pointer(Ord(ASizeHandle in [twshTop, twshBottom])));
-
- SizeSens := MaxSizeSens;
- { Adjust sensitivity if it's too high }
- for I := 0 to NewSizes.Count-1 do begin
- Pointer(S) := NewSizes[I];
- if (S.X = Width) and (S.Y = Height) then begin
- if I > 0 then begin
- Pointer(N) := NewSizes[I-1];
- if ASizeHandle in [twshLeft, twshRight] then
- NewSize := N.X - S.X - 1
- else
- NewSize := N.Y - S.Y - 1;
- if NewSize < SizeSens then SizeSens := NewSize;
- end;
- if I < NewSizes.Count-1 then begin
- Pointer(N) := NewSizes[I+1];
- if ASizeHandle in [twshLeft, twshRight] then
- NewSize := S.X - N.X - 1
- else
- NewSize := S.Y - N.Y - 1;
- if NewSize < SizeSens then SizeSens := NewSize;
- end;
- Break;
- end;
- end;
- if SizeSens < 0 then SizeSens := 0;
- end;
- end;
-
- procedure TCustomToolbar97.ResizeTrack (var Rect: TRect; const OrigRect: TRect);
- var
- Pos: TPoint;
- NCXDiff: Integer;
- NewOpSide: Boolean;
- Reverse: Boolean;
- I: Integer;
- P: TSmallPoint;
- begin
- inherited;
-
- with PToolbar97SizeData(SizeData)^ do begin
- GetCursorPos (Pos);
-
- NCXDiff := ClientToScreen(Point(0, 0)).X - Left;
- Dec (Pos.X, Left); Dec (Pos.Y, Top);
- if SizeHandle = twshLeft then
- Pos.X := Width-Pos.X
- else
- if SizeHandle = twshTop then
- Pos.Y := Height-Pos.Y;
-
- { Adjust Pos to make up for the "sizing sensitivity", as seen in Office 97 }
- if SizeHandle in [twshLeft, twshRight] then
- NewOpSide := Pos.X < Width
- else
- NewOpSide := Pos.Y < Height;
- if (not DisableSensCheck) or (OpSide <> NewOpSide) then begin
- DisableSensCheck := False;
- OpSide := NewOpSide;
- if SizeHandle in [twshLeft, twshRight] then begin
- if (Pos.X >= Width-SizeSens) and (Pos.X < Width+SizeSens) then
- Pos.X := Width;
- end
- else begin
- if (Pos.Y >= Height-SizeSens) and (Pos.Y < Height+SizeSens) then
- Pos.Y := Height;
- end;
- end;
-
- Rect := OrigRect;
-
- if SizeHandle in [twshLeft, twshRight] then
- Reverse := Pos.X > Width
- else
- Reverse := Pos.Y > Height;
- if not Reverse then
- I := NewSizes.Count-1
- else
- I := 0;
- while True do begin
- if (not Reverse and (I < 0)) or
- (Reverse and (I >= NewSizes.Count)) then
- Break;
- Pointer(P) := NewSizes[I];
- if SizeHandle in [twshLeft, twshRight] then begin
- if (not Reverse and ((I = NewSizes.Count-1) or (Pos.X >= P.X))) or
- (Reverse and ((I = 0) or (Pos.X < P.X))) then begin
- if I = 0 then
- CurRightX := 0
- else
- CurRightX := P.X - NCXDiff*2;
- if SizeHandle = twshRight then
- Rect.Right := Rect.Left + P.X
- else
- Rect.Left := Rect.Right - P.X;
- Rect.Bottom := Rect.Top + P.Y;
- DisableSensCheck := not EqualRect(Rect, OrigRect);
- end;
- end
- else begin
- if (not Reverse and ((I = NewSizes.Count-1) or (Pos.Y >= P.Y))) or
- (Reverse and ((I = 0) or (Pos.Y < P.Y))) then begin
- if I = NewSizes.Count-1 then
- CurRightX := 0
- else
- CurRightX := P.X - NCXDiff*2;
- if SizeHandle = twshBottom then
- Rect.Bottom := Rect.Top + P.Y
- else
- Rect.Top := Rect.Bottom - P.Y;
- Rect.Right := Rect.Left + P.X;
- DisableSensCheck := not EqualRect(Rect, OrigRect);
- end;
- end;
- if not Reverse then
- Dec (I)
- else
- Inc (I);
- end;
- end;
- end;
-
- procedure TCustomToolbar97.ResizeEnd (Accept: Boolean);
- begin
- inherited;
- if Assigned(SizeData) then begin
- with PToolbar97SizeData(SizeData)^ do begin
- if Accept then
- FFloatingRightX := CurRightX;
- NewSizes.Free;
- end;
- FreeMem (SizeData);
- end;
- end;
-
- function TCustomToolbar97.GetOrderedControls (Index: Integer): TControl;
- begin
- CleanOrderList;
- Result := OrderList[Index];
- end;
-
- function TCustomToolbar97.GetOrderIndex (Control: TControl): Integer;
- begin
- CleanOrderList;
- Result := OrderList.IndexOf(Control);
- if Result = -1 then
- raise EInvalidOperation.CreateFmt(STB97ToolbarControlNotChildOfToolbar,
- [Control.Name]);
- end;
-
- procedure TCustomToolbar97.SetOrderIndex (Control: TControl; Value: Integer);
- var
- OldIndex: Integer;
- begin
- CleanOrderList;
- with OrderList do begin
- OldIndex := IndexOf(Control);
- if OldIndex = -1 then
- raise EInvalidOperation.CreateFmt(STB97ToolbarControlNotChildOfToolbar,
- [Control.Name]);
- if Value < 0 then Value := 0;
- if Value >= Count then Value := Count-1;
- if Value <> OldIndex then begin
- Delete (OldIndex);
- Insert (Value, Control);
- ArrangeControls;
- end;
- end;
- end;
-
- procedure TCustomToolbar97.SetFloatingWidth (Value: Integer);
- begin
- if FFloatingRightX <> Value then begin
- FFloatingRightX := Value;
- ArrangeControls;
- end;
- end;
-
- procedure TCustomToolbar97.SetSlaveControl (const ATopBottom, ALeftRight: TControl);
- var
- NewVersion: PSlaveInfo;
- begin
- GetMem (NewVersion, SizeOf(TSlaveInfo));
- with NewVersion^ do begin
- TopBottom := ATopBottom;
- LeftRight := ALeftRight;
- end;
- SlaveInfo.Add (NewVersion);
- ArrangeControls;
- end;
-
- function TCustomToolbar97.ChildControlTransparent (Ctl: TControl): Boolean;
- begin
- Result := Ctl is TToolbarSep97;
- end;
-
- procedure TCustomToolbar97.WMWindowPosChanging (var Message: TWMWindowPosChanging);
- var
- R: TRect;
- begin
- inherited;
- { When floating, invalidate the toolbar when resized so that the vertical
- separators get redrawn.
- Note to self: The Invalidate call must be in the WM_WINDOWPOSCHANGING
- handler. If it's in WM_SIZE or WM_WINDOWPOSCHANGED there can be repainting
- problems in rare cases (refer to Toolbar97 1.65a's implementation). }
- if not Docked and HandleAllocated then
- with Message.WindowPos^ do
- if flags and SWP_DRAWFRAME <> 0 then
- Invalidate
- else
- if flags and SWP_NOSIZE = 0 then begin
- GetWindowRect (Handle, R);
- if (R.Right-R.Left <> cx) or (R.Bottom-R.Top <> cy) then
- Invalidate;
- end;
- end;
-
-
- { TToolbarSep97 }
-
- constructor TToolbarSep97.Create (AOwner: TComponent);
- begin
- inherited;
- FSizeHorz := 6;
- FSizeVert := 6;
- ControlStyle := ControlStyle - [csOpaque, csCaptureMouse];
- end;
-
- procedure TToolbarSep97.SetParent (AParent: TWinControl);
- begin
- if (AParent <> nil) and not(AParent is TCustomToolbar97) then
- raise EInvalidOperation.Create(STB97SepParentNotAllowed);
- inherited;
- end;
-
- procedure TToolbarSep97.SetBlank (Value: Boolean);
- begin
- if FBlank <> Value then begin
- FBlank := Value;
- Invalidate;
- end;
- end;
-
- procedure TToolbarSep97.SetSizeHorz (Value: TToolbarSepSize);
- begin
- if FSizeHorz <> Value then begin
- FSizeHorz := Value;
- if Parent is TCustomToolbar97 then
- TCustomToolbar97(Parent).ArrangeControls;
- end;
- end;
-
- procedure TToolbarSep97.SetSizeVert (Value: TToolbarSepSize);
- begin
- if FSizeVert <> Value then begin
- FSizeVert := Value;
- if Parent is TCustomToolbar97 then
- TCustomToolbar97(Parent).ArrangeControls;
- end;
- end;
-
- procedure TToolbarSep97.Paint;
- var
- R: TRect;
- Z: Integer;
- begin
- inherited;
- if not(Parent is TCustomToolbar97) then Exit;
-
- with Canvas do begin
- { Draw dotted border in design mode }
- if csDesigning in ComponentState then begin
- Pen.Style := psDot;
- Pen.Color := clBtnShadow;
- Brush.Style := bsClear;
- R := ClientRect;
- Rectangle (R.Left, R.Top, R.Right, R.Bottom);
- Pen.Style := psSolid;
- end;
-
- if not FBlank then
- if GetDockTypeOf(TCustomToolbar97(Parent).DockedTo) <> dtLeftRight then begin
- Z := Width div 2;
- Pen.Color := clBtnShadow;
- MoveTo (Z-1, 0); LineTo (Z-1, Height);
- Pen.Color := clBtnHighlight;
- MoveTo (Z, 0); LineTo (Z, Height);
- end
- else begin
- Z := Height div 2;
- Pen.Color := clBtnShadow;
- MoveTo (0, Z-1); LineTo (Width, Z-1);
- Pen.Color := clBtnHighlight;
- MoveTo (0, Z); LineTo (Width, Z);
- end;
- end;
- end;
-
- procedure TToolbarSep97.MouseDown (Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- var
- P: TPoint;
- begin
- inherited;
- if not(Parent is TCustomToolbar97) then Exit;
-
- { Relay the message to the parent toolbar }
- P := Parent.ScreenToClient(ClientToScreen(Point(X, Y)));
- TCustomToolbar97(Parent).MouseDown (Button, Shift, P.X, P.Y);
- end;
-
- end.
-