| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716 |
- unit TB2Toolbar;
- {
- Toolbar2000
- Copyright (C) 1998-2005 by Jordan Russell
- All rights reserved.
- The contents of this file are subject to the "Toolbar2000 License"; you may
- not use or distribute this file except in compliance with the
- "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
- TB2k-LICENSE.txt or at:
- http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
- Alternatively, the contents of this file may be used under the terms of the
- GNU General Public License (the "GPL"), in which case the provisions of the
- GPL are applicable instead of those in the "Toolbar2000 License". A copy of
- the GPL may be found in GPL-LICENSE.txt or at:
- http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt
- If you wish to allow use of your version of this file only under the terms of
- the GPL and not to allow others to use your version of this file under the
- "Toolbar2000 License", indicate your decision by deleting the provisions
- above and replace them with the notice and other provisions required by the
- GPL. If you do not delete the provisions above, a recipient may use your
- version of this file under either the "Toolbar2000 License" or the GPL.
- $jrsoftware: tb2k/Source/TB2Toolbar.pas,v 1.108 2005/07/30 18:17:20 jr Exp $
- }
- interface
- {$I TB2Ver.inc}
- uses
- Types,
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ImgList,
- Menus, ActnList,
- TB2Item, TB2Dock;
- type
- TTBCustomToolbar = class;
- TTBChevronItem = class;
- TTBChevronItemClass = class of TTBChevronItem;
- TTBToolbarViewClass = class of TTBToolbarView;
- TTBToolbarView = class(TTBView)
- private
- FToolbar: TTBCustomToolbar;
- protected
- procedure AutoSize(AWidth, AHeight: Integer); override;
- procedure DoUpdatePositions(var ASize: TPoint); override;
- function GetChevronItem: TTBCustomItem; override;
- function GetMDIButtonsItem: TTBCustomItem; override;
- function GetMDISystemMenuItem: TTBCustomItem; override;
- public
- constructor Create(AOwner: TComponent); override;
- function GetFont: TFont; override;
- procedure InvalidatePositions; override;
- procedure EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions); override;
- end;
- TTBChevronPriorityForNewItems = (tbcpHighest, tbcpLowest);
- { MP }
- TToolbarGetBaseSizeEvent = procedure(Toolbar: TTBCustomToolbar; var ASize: TPoint) of object;
- TTBCustomToolbar = class(TTBCustomDockableWindow, ITBItems)
- private
- FBaseSize: TPoint;
- FChevronItem: TTBChevronItem;
- FChevronMoveItems: Boolean;
- FChevronPriorityForNewItems: TTBChevronPriorityForNewItems;
- FDisableAlignArrange: Integer;
- FFloatingWidth: Integer;
- FIgnoreMouseLeave: Boolean;
- FItem: TTBRootItem;
- FLastWrappedLines: Integer;
- FMenuBar: Boolean;
- FOnShortCut: TShortCutEvent;
- FProcessShortCuts: Boolean;
- FMainWindowHookInstalled: Boolean;
- FShrinkMode: TTBShrinkMode;
- FSizeData: Pointer;
- FSystemFont: Boolean;
- FUpdateActions: Boolean;
- { MP }
- FOnGetBaseSize: TToolbarGetBaseSizeEvent;
- FOnEndModal: TNotifyEvent;
- procedure CancelHover;
- function CalcChevronOffset(const ADock: TTBDock;
- const AOrientation: TTBViewOrientation): Integer;
- function CalcWrapOffset(const ADock: TTBDock): Integer;
- function CreateWrapper(Index: Integer; Ctl: TControl): TTBControlItem;
- function FindWrapper(Ctl: TControl): TTBControlItem;
- function GetChevronHint: String;
- function GetImages: TCustomImageList;
- function GetItems: TTBCustomItem;
- function GetLinkSubitems: TTBCustomItem;
- function GetOptions: TTBItemOptions;
- procedure InstallMainWindowHook;
- function IsChevronHintStored: Boolean;
- class function MainWindowHook(var Message: TMessage): Boolean;
- procedure SetChevronHint(const Value: String);
- procedure SetChevronMoveItems(Value: Boolean);
- procedure SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems);
- procedure SetFloatingWidth(Value: Integer);
- procedure SetImages(Value: TCustomImageList);
- procedure SetLinkSubitems(Value: TTBCustomItem);
- procedure SetMainWindowHook;
- procedure SetMenuBar(Value: Boolean);
- procedure SetOptions(Value: TTBItemOptions);
- procedure SetProcessShortCuts(Value: Boolean);
- procedure SetShrinkMode(Value: TTBShrinkMode);
- procedure SetSystemFont(Value: Boolean);
- procedure UninstallMainWindowHook;
- procedure UpdateViewProperties;
- procedure CMColorChanged(var Message: TMessage); message CM_COLORCHANGED;
- procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE;
- procedure CMControlListChange(var Message: TCMControlListChange); message CM_CONTROLLISTCHANGE;
- procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
- procedure CMDialogChar(var Message: TCMDialogChar); message CM_DIALOGCHAR;
- procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
- procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
- procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
- procedure CMShowHintChanged(var Message: TMessage); message CM_SHOWHINTCHANGED;
- procedure CMWinIniChange(var Message: TWMSettingChange); message CM_WININICHANGE;
- procedure WMCancelMode(var Message: TWMCancelMode); message WM_CANCELMODE;
- procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT;
- procedure WMMouseLeave(var Message: TMessage); message WM_MOUSELEAVE;
- procedure WMNCMouseMove(var Message: TWMNCMouseMove); message WM_NCMOUSEMOVE;
- procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR;
- procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
- protected
- FMDIButtonsItem: TTBCustomItem;
- FMDISystemMenuItem: TTBCustomItem;
- FView: TTBToolbarView;
- procedure AlignControls(AControl: TControl; var Rect: TRect); override;
- procedure BuildPotentialSizesList(SizesList: TList); dynamic;
- procedure ControlExistsAtPos(const P: TPoint; var ControlExists: Boolean);
- override;
- function DoArrange(CanMoveControls: Boolean; PreviousDockType: TTBDockType;
- NewFloating: Boolean; NewDock: TTBDock): TPoint; override;
- procedure DoContextPopup(MousePos: TPoint; var Handled: Boolean); override;
- procedure GetBaseSize(var ASize: TPoint); override;
- procedure GetMinBarSize(var MinimumSize: TPoint);
- procedure GetMinShrinkSize(var AMinimumSize: Integer); override;
- function GetShrinkMode: TTBShrinkMode; override;
- function GetChevronItemClass: TTBChevronItemClass; dynamic;
- function GetItemClass: TTBRootItemClass; dynamic;
- function GetViewClass: TTBToolbarViewClass; dynamic;
- procedure Loaded; override;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
- procedure Paint; override;
- procedure ResizeBegin(ASizeHandle: TTBSizeHandle); override;
- procedure ResizeTrack(var Rect: TRect; const OrigRect: TRect); override;
- procedure ResizeTrackAccept; override;
- procedure ResizeEnd; override;
- procedure SetChildOrder(Child: TComponent; Order: Integer); override;
- procedure ChangeScale(M, D: Integer); override;
- property SystemFont: Boolean read FSystemFont write SetSystemFont default True;
- property OnShortCut: TShortCutEvent read FOnShortCut write FOnShortCut;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure BeginUpdate;
- procedure EndUpdate;
- procedure CreateWrappersForAllControls;
- procedure GetTabOrderList(List: TList); override;
- procedure InitiateAction; override;
- function IsShortCut(var Message: TWMKey): Boolean;
- function KeyboardOpen(Key: Char; RequirePrimaryAccel: Boolean): Boolean;
- procedure ReadPositionData(var S: string); override;
- function WritePositionData: string; override;
- procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
- property ChevronHint: String read GetChevronHint write SetChevronHint stored IsChevronHintStored;
- property ChevronMoveItems: Boolean read FChevronMoveItems write SetChevronMoveItems default True;
- property ChevronPriorityForNewItems: TTBChevronPriorityForNewItems read FChevronPriorityForNewItems
- write SetChevronPriorityForNewItems default tbcpHighest;
- property FloatingWidth: Integer read FFloatingWidth write SetFloatingWidth default 0;
- property Images: TCustomImageList read GetImages write SetImages;
- property Items: TTBRootItem read FItem;
- property LinkSubitems: TTBCustomItem read GetLinkSubitems write SetLinkSubitems;
- property Options: TTBItemOptions read GetOptions write SetOptions default [];
- property MenuBar: Boolean read FMenuBar write SetMenuBar default False;
- property ProcessShortCuts: Boolean read FProcessShortCuts write SetProcessShortCuts default False;
- property ShrinkMode: TTBShrinkMode read FShrinkMode write SetShrinkMode default tbsmChevron;
- property UpdateActions: Boolean read FUpdateActions write FUpdateActions default True;
- property View: TTBToolbarView read FView;
- { MP }
- property OnGetBaseSize: TToolbarGetBaseSizeEvent read FOnGetBaseSize write FOnGetBaseSize;
- property OnEndModal: TNotifyEvent read FOnEndModal write FOnEndModal;
- published
- property Hint stored False; { Hint is set dynamically; don't save it }
- end;
- TTBToolbar = class(TTBCustomToolbar)
- published
- property ActivateParent;
- property Align;
- property Anchors;
- property AutoResize;
- property BorderStyle;
- property Caption;
- property ChevronHint;
- property ChevronMoveItems;
- property ChevronPriorityForNewItems;
- property CloseButton;
- property CloseButtonWhenDocked;
- property Color;
- property CurrentDock;
- property DefaultDock;
- property DockableTo;
- property DockMode;
- property DockPos;
- property DockRow;
- property DragHandleStyle;
- property FloatingMode;
- property FloatingWidth;
- property Font;
- property FullSize;
- property HideWhenInactive;
- property Images;
- property Items;
- property LastDock;
- property LinkSubitems;
- property MenuBar;
- property Options;
- property ParentFont;
- property ParentShowHint;
- property PopupMenu;
- property ProcessShortCuts;
- property Resizable;
- property ShowCaption;
- property ShowHint;
- property ShrinkMode;
- property SmoothDrag;
- property Stretch;
- property SystemFont;
- property TabOrder;
- property UpdateActions;
- property UseLastDock;
- property Visible;
- property OnClose;
- property OnCloseQuery;
- {$IFDEF JR_D5}
- property OnContextPopup;
- {$ENDIF}
- property OnDragDrop;
- property OnDragOver;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property OnMove;
- property OnRecreated;
- property OnRecreating;
- property OnDockChanged;
- property OnDockChanging;
- property OnDockChangingHidden;
- property OnResize;
- property OnShortCut;
- property OnVisibleChanged;
- { MP }
- property OnGetBaseSize;
- property OnEndModal;
- end;
- { TTBChevronItem & TTBChevronItemViewer }
- TTBChevronItem = class(TTBCustomItem)
- private
- FToolbar: TTBCustomToolbar;
- function GetDefaultHint: String;
- public
- constructor Create(AOwner: TComponent); override;
- function GetChevronParentView: TTBView; override;
- function GetItemViewerClass(AView: TTBView): TTBItemViewerClass; override;
- end;
- TTBChevronItemViewer = class(TTBItemViewer)
- protected
- procedure Paint(const Canvas: TCanvas; const ClientAreaRect: TRect;
- IsSelected, IsPushed, UseDisabledShadow: Boolean); override;
- function CaptionShown: Boolean; override;
- end;
- const
- tbChevronSize = 12;
- implementation
- uses
- TB2Consts, TB2Common, TB2Hook, PasTools;
- const
- { Constants for TTBCustomToolbar-specific registry values. Do not localize! }
- rvFloatRightX = 'FloatRightX';
- DockTypeToOrientation: array[TTBDockType] of TTBViewOrientation =
- (tbvoHorizontal, tbvoFloating, tbvoHorizontal, tbvoVertical);
- type
- { Used internally by the TCustomToolbar97.Resize* procedures }
- PToolbar97SizeData = ^TToolbar97SizeData;
- TToolbar97SizeData = record
- SizeHandle: TTBSizeHandle;
- NewSizes: TList; { List of valid new sizes. Items are casted into TSmallPoints }
- OrigLeft, OrigTop, OrigWidth, OrigHeight, NCXDiff: Integer;
- CurRightX: Integer;
- DisableSensCheck, OpSide: Boolean;
- SizeSens: Integer;
- end;
- procedure HookProc(Code: THookProcCode; Wnd: HWND; WParam: WPARAM;
- LParam: LPARAM);
- var
- Msg: PMsg;
- MainForm: TForm;
- begin
- { Work around an annoying Windows or VCL bug. If you close all MDI child
- windows, the MDI client window gets the focus, and when it has the focus,
- pressing Alt+[char] doesn't send a WM_SYSCOMMAND message to the form for
- some reason. It seems silly to have to use a hook for this, but I don't
- see a better workaround.
- Also, route Alt+- to the main form so that when an MDI child form is
- maximized, Alt+- brings up the TB2k MDI system menu instead of the
- system's. }
- if (Code = hpGetMessage) and (WParam = PM_REMOVE) then begin
- Msg := PMsg(LParam);
- if (Msg.message = WM_SYSCHAR) and (Msg.hwnd <> 0) then begin
- { Note: On Windows NT/2000/XP, even though we install the hook using
- SetWindowsHookExW, Msg.wParam may either be an ANSI character or a
- Unicode character, due to an apparent bug on these platforms. It is
- an ANSI character when the message passes through a separate
- SetWindowsHookExA-installed WH_GETMESSAGE hook first, and that hook
- calls us via CallNextHookEx. Windows apparently "forgets" to convert
- the character from ANSI back to Unicode in this case.
- We can't convert the character code because there seems to be no way
- to detect whether it is ANSI or Unicode. So we can't really do much
- with Msg.wParam, apart from comparing it against character codes that
- are the same between ANSI and Unicode, such as '-'. }
- MainForm := Application.MainForm;
- if Assigned(MainForm) and MainForm.HandleAllocated and (GetCapture = 0) and
- ((Msg.hwnd = MainForm.ClientHandle) or
- ((Msg.wParam = Ord('-')) and (MainForm.ClientHandle <> 0) and
- IsChild(MainForm.ClientHandle, Msg.hwnd))) then begin
- { Redirect the message to the main form.
- Note: Unfortunately, due to a bug in Windows NT 4.0 (and not
- 2000/XP/9x/Me), modifications to the message don't take effect if
- another WH_GETMESSAGE hook has been installed above this one.
- (The bug is that CallNextHookEx copies lParam^ to a local buffer, but
- does not propogate the changes made by the hook back to lParam^ when
- it returns.) I don't know of any clean workaround, other than to
- ensure other WH_GETMESSAGE hooks are installed *before*
- Toolbar2000's. }
- Msg.hwnd := MainForm.Handle;
- end;
- end;
- end;
- end;
- constructor TTBChevronItem.Create(AOwner: TComponent);
- begin
- inherited;
- FToolbar := AOwner as TTBCustomToolbar;
- ItemStyle := ItemStyle + [tbisSubMenu, tbisNoAutoOpen];
- Hint := GetDefaultHint;
- Caption := EscapeAmpersands(GetShortHint(Hint));
- end;
- function TTBChevronItem.GetChevronParentView: TTBView;
- begin
- Result := FToolbar.FView;
- end;
- function TTBChevronItem.GetDefaultHint: String;
- begin
- Result := STBChevronItemMoreButtonsHint;
- end;
- function TTBChevronItem.GetItemViewerClass(AView: TTBView): TTBItemViewerClass;
- begin
- Result := TTBChevronItemViewer;
- end;
- procedure TTBChevronItemViewer.Paint(const Canvas: TCanvas;
- const ClientAreaRect: TRect; IsSelected, IsPushed, UseDisabledShadow: Boolean);
- const
- Pattern: array[Boolean, 0..15] of Byte = (
- ($CC, 0, $66, 0, $33, 0, $66, 0, $CC, 0, 0, 0, 0, 0, 0, 0),
- ($88, 0, $D8, 0, $70, 0, $20, 0, $88, 0, $D8, 0, $70, 0, $20, 0));
- var
- DC: HDC;
- R2: TRect;
- TempBmp: TBitmap;
- procedure DrawPattern(const Color, Offset: Integer);
- begin
- SelectObject(DC, GetSysColorBrush(Color));
- BitBlt(DC, R2.Left, R2.Top + Offset, R2.Right - R2.Left,
- R2.Bottom - R2.Top, TempBmp.Canvas.Handle, 0, 0, $00E20746 {ROP_DSPDxax});
- end;
- begin
- DC := Canvas.Handle;
- R2 := ClientAreaRect;
- if Item.Enabled then begin
- if IsPushed then
- DrawEdge(DC, R2, BDR_SUNKENOUTER, BF_RECT)
- else if IsSelected and not(csDesigning in Item.ComponentState) then
- DrawEdge(DC, R2, BDR_RAISEDINNER, BF_RECT);
- end;
- if View.Orientation <> tbvoVertical then begin
- R2.Top := 4;
- R2.Bottom := R2.Top + 5;
- Inc(R2.Left, 2);
- R2.Right := R2.Left + 8;
- end
- else begin
- R2.Left := R2.Right - 9;
- R2.Right := R2.Left + 5;
- Inc(R2.Top, 2);
- R2.Bottom := R2.Top + 8;
- end;
- if IsPushed then
- OffsetRect(R2, 1, 1);
- TempBmp := TBitmap.Create;
- try
- TempBmp.Handle := CreateBitmap(8, 8, 1, 1,
- @Pattern[View.Orientation = tbvoVertical]);
- SetTextColor(DC, clBlack);
- SetBkColor(DC, clWhite);
- if Item.Enabled then
- DrawPattern(COLOR_BTNTEXT, 0)
- else begin
- DrawPattern(COLOR_BTNHIGHLIGHT, 1);
- DrawPattern(COLOR_BTNSHADOW, 0);
- end;
- finally
- TempBmp.Free;
- end;
- end;
- function TTBChevronItemViewer.CaptionShown: Boolean;
- begin
- Result := False;
- end;
- { TTBToolbarView }
- constructor TTBToolbarView.Create(AOwner: TComponent);
- begin
- FToolbar := AOwner as TTBCustomToolbar;
- inherited;
- end;
- procedure TTBToolbarView.AutoSize(AWidth, AHeight: Integer);
- begin
- FToolbar.FBaseSize := BaseSize;
- if FToolbar.IsAutoResized then
- FToolbar.ChangeSize(AWidth, AHeight);
- end;
- procedure TTBToolbarView.DoUpdatePositions(var ASize: TPoint);
- begin
- { Reset CurrentSize because it probably won't be valid after positions
- are recalculated [2001-06-24] }
- FToolbar.CurrentSize := 0;
- FToolbar.GetMinBarSize(ASize);
- { On FullSize toolbars, increase ASize.X/Y to WrapOffset so that
- right-aligned items always appear at the right edge even when the toolbar
- isn't wrapping }
- if FToolbar.FullSize then begin
- if (Orientation = tbvoHorizontal) and (ASize.X < WrapOffset) then
- ASize.X := WrapOffset
- else if (Orientation = tbvoVertical) and (ASize.Y < WrapOffset) then
- ASize.Y := WrapOffset;
- end;
- { Increment FDisableAlignArrange so that we don't recursively arrange when
- CalculatePositions moves controls }
- Inc(FToolbar.FDisableAlignArrange);
- try
- inherited;
- finally
- Dec(FToolbar.FDisableAlignArrange);
- end;
- end;
- procedure TTBToolbarView.InvalidatePositions;
- begin
- { Reset CurrentSize because it probably won't be valid after positions
- are recalculated [2001-06-04] }
- FToolbar.CurrentSize := 0;
- inherited;
- end;
- function TTBToolbarView.GetFont: TFont;
- begin
- if not FToolbar.SystemFont then
- Result := FToolbar.Font
- else
- Result := inherited GetFont;
- end;
- function TTBToolbarView.GetChevronItem: TTBCustomItem;
- begin
- Result := FToolbar.FChevronItem;
- end;
- function TTBToolbarView.GetMDIButtonsItem: TTBCustomItem;
- begin
- Result := FToolbar.FMDIButtonsItem;
- end;
- function TTBToolbarView.GetMDISystemMenuItem: TTBCustomItem;
- begin
- Result := FToolbar.FMDISystemMenuItem;
- end;
- procedure TTBToolbarView.EnterToolbarLoop(Options: TTBEnterToolbarLoopOptions);
- begin
- inherited;
- if Assigned(FToolbar.OnEndModal) then
- FToolbar.OnEndModal(FToolbar);
- end;
- { TTBCustomToolbar }
- type
- {}TTBCustomItemAccess = class(TTBCustomItem);
- TTBItemViewerAccess = class(TTBItemViewer);
- constructor TTBCustomToolbar.Create(AOwner: TComponent);
- begin
- inherited;
- ControlStyle := ControlStyle + [csAcceptsControls, csActionClient] -
- [csCaptureMouse];
- DockableWindowStyles := DockableWindowStyles - [tbdsResizeEightCorner,
- tbdsResizeClipCursor];
- FItem := GetItemClass.Create(Self);
- FItem.ParentComponent := Self;
- FChevronItem := GetChevronItemClass.Create(Self);
- FChevronItem.LinkSubitems := FItem;
- FChevronMoveItems := True;
- FView := GetViewClass.CreateView(Self, nil, FItem, Self, True, False,
- not(csDesigning in ComponentState));
- FView.BackgroundColor := clBtnFace;
- FUpdateActions := True;
- FShrinkMode := tbsmChevron;
- FSystemFont := True;
- Color := clBtnFace;
- SetBounds(Left, Top, 23, 22);{}
- { MP }
- FOnGetBaseSize := nil;
- FOnEndModal := nil;
- end;
- destructor TTBCustomToolbar.Destroy;
- begin
- { Call Destroying to ensure csDestroying is in ComponentState now. Only
- needed for Delphi 4 and earlier since Delphi 5 calls Destroying in
- TComponent.BeforeDestruction }
- Destroying;
- UninstallHookProc(Self, HookProc);
- UninstallMainWindowHook;
- FreeAndNil(FView);
- FreeAndNil(FChevronItem);
- FreeAndNil(FItem);
- inherited;
- end;
- function TTBCustomToolbar.GetItems: TTBCustomItem;
- begin
- Result := FItem;
- end;
- function TTBCustomToolbar.GetItemClass: TTBRootItemClass;
- begin
- Result := TTBRootItem;
- end;
- function TTBCustomToolbar.GetViewClass: TTBToolbarViewClass;
- begin
- Result := TTBToolbarView;
- end;
- function TTBCustomToolbar.GetChevronItemClass: TTBChevronItemClass;
- begin
- Result := TTBChevronItem;
- end;
- procedure TTBCustomToolbar.CreateWrappersForAllControls;
- { Create wrappers for any controls that don't already have them }
- var
- L: TList;
- I, J, C: Integer;
- begin
- if ControlCount = 0 then
- Exit;
- L := TList.Create;
- try
- L.Capacity := ControlCount;
- for I := 0 to ControlCount-1 do
- L.Add(Controls[I]);
- C := FItem.Count-1;
- for I := 0 to C do
- if FItem[I] is TTBControlItem then begin
- J := L.IndexOf(TTBControlItem(FItem[I]).Control);
- if J <> -1 then
- L[J] := nil;
- end;
- for I := 0 to L.Count-1 do
- if Assigned(L[I]) then
- CreateWrapper(FItem.Count, L[I]);
- finally
- L.Free;
- end;
- end;
- procedure TTBCustomToolbar.Loaded;
- begin
- CreateWrappersForAllControls;
- inherited;
- end;
- procedure TTBCustomToolbar.GetChildren(Proc: TGetChildProc; Root: TComponent);
- begin
- TTBCustomItemAccess(FItem).GetChildren(Proc, Root);
- inherited;
- end;
- procedure TTBCustomToolbar.SetChildOrder(Child: TComponent; Order: Integer);
- begin
- if Child is TTBCustomItem then
- TTBCustomItemAccess(FItem).SetChildOrder(Child, Order);
- end;
- procedure TTBCustomToolbar.AlignControls(AControl: TControl; var Rect: TRect);
- { VCL calls this whenever any child controls in the toolbar are moved, sized,
- inserted, etc., and also when the toolbar is resized. }
- begin
- if FDisableAlignArrange = 0 then
- Arrange;
- end;
- procedure TTBCustomToolbar.InitiateAction;
- begin
- inherited;
- {}{ also add this to popupmenu(?) }
- { Update visible top-level items }
- if FUpdateActions then
- FView.InitiateActions;
- end;
- procedure TTBCustomToolbar.CMColorChanged(var Message: TMessage);
- begin
- { Synchronize FView.BackgroundColor with the new color }
- if Assigned(FView) then
- FView.BackgroundColor := Color;
- inherited;
- end;
- function TTBCustomToolbar.CreateWrapper(Index: Integer;
- Ctl: TControl): TTBControlItem;
- var
- I: Integer;
- S: String;
- begin
- Result := TTBControlItem.CreateControlItem(Owner, Ctl);
- if (csDesigning in ComponentState) and Assigned(Owner) then begin
- { Needs a name for compatibility with form inheritance }
- I := 1;
- while True do begin
- S := Format('TBControlItem%d', [I]);
- if Owner.FindComponent(S) = nil then
- Break;
- Inc(I);
- end;
- Result.Name := S;
- end;
- FItem.Insert(Index, Result);
- end;
- function TTBCustomToolbar.FindWrapper(Ctl: TControl): TTBControlItem;
- var
- I: Integer;
- Item: TTBCustomItem;
- begin
- Result := nil;
- for I := 0 to FItem.Count-1 do begin
- Item := FItem[I];
- if (Item is TTBControlItem) and
- (TTBControlItem(Item).Control = Ctl) then begin
- Result := TTBControlItem(Item);
- Break;
- end;
- end;
- end;
- procedure TTBCustomToolbar.CMControlChange(var Message: TCMControlChange);
- { A CM_CONTROLCHANGE handler must be used instead of a CM_CONTROLLISTCHANGE
- handler because when a CM_CONTROLLISTCHANGE message is sent it is relayed to
- *all* parents. CM_CONTROLCHANGE messages are only sent to the immediate
- parent. }
- begin
- inherited;
- { Don't automatically create TTBControlItem wrappers if the component
- is loading or being updated to reflect changes in an ancestor form,
- because wrappers will be streamed in }
- if Message.Inserting and not(csLoading in ComponentState) and
- not(csUpdating in ComponentState) and
- (FindWrapper(Message.Control) = nil) then
- CreateWrapper(FItem.Count, Message.Control);
- end;
- procedure TTBCustomToolbar.CMControlListChange(var Message: TCMControlListChange);
- { Don't handle deletions inside CM_CONTROLCHANGE because CM_CONTROLCHANGE is
- sent *before* a control begins removing itself from its parent. (It used
- to handle both insertions and deletions inside CM_CONTROLCHANGE but this
- caused AV's.) }
- var
- Item: TTBControlItem;
- begin
- inherited;
- if not Message.Inserting and Assigned(FItem) then begin
- while True do begin
- Item := FindWrapper(Message.Control);
- if Item = nil then Break;
- { The control is being removed the control, not necessarily destroyed,
- so set DontFreeControl to True }
- Item.DontFreeControl := True;
- Item.Free;
- end;
- end;
- end;
- procedure TTBCustomToolbar.CMHintShow(var Message: TCMHintShow);
- { Since the items on a toolbar aren't "real" controls, it needs a CM_HINTSHOW
- handler for their hints to be displayed. }
- var
- V: TTBItemViewer;
- begin
- with Message.HintInfo^ do begin
- HintStr := '';
- V := FView.ViewerFromPoint(CursorPos);
- if Assigned(V) then begin
- if not IsRectEmpty(V.BoundsRect) then begin
- CursorRect := V.BoundsRect;
- HintStr := V.GetHintText;
- end;
- end;
- end;
- end;
- procedure TTBCustomToolbar.CMShowHintChanged(var Message: TMessage);
- begin
- inherited;
- if ShowHint then
- FView.Style := FView.Style + [vsAlwaysShowHints]
- else
- FView.Style := FView.Style - [vsAlwaysShowHints];
- end;
- procedure TTBCustomToolbar.WMGetObject(var Message: TMessage);
- begin
- if not FView.HandleWMGetObject(Message) then
- inherited;
- end;
- procedure TTBCustomToolbar.WMSetCursor(var Message: TWMSetCursor);
- var
- P: TPoint;
- Cursor: HCURSOR;
- R: TRect;
- begin
- if not(csDesigning in ComponentState) and
- (Message.CursorWnd = WindowHandle) and
- (Smallint(Message.HitTest) = HTCLIENT) then begin
- GetCursorPos(P);
- FView.UpdateSelection(@P, True);
- if Assigned(FView.Selected) then begin
- Cursor := 0;
- R := FView.Selected.BoundsRect;
- P := ScreenToClient(P);
- Dec(P.X, R.Left);
- Dec(P.Y, R.Top);
- TTBItemViewerAccess(FView.Selected).GetCursor(P, Cursor);
- if Cursor <> 0 then begin
- SetCursor(Cursor);
- Message.Result := 1;
- Exit;
- end;
- end;
- end;
- inherited;
- end;
- procedure TTBCustomToolbar.WMSysCommand(var Message: TWMSysCommand);
- begin
- if FMenuBar and Enabled and Showing then
- with Message do
- if (CmdType and $FFF0 = SC_KEYMENU) and (Key <> VK_SPACE) and
- (GetCapture = 0) then begin
- if not KeyboardOpen(Char(Key), False) then begin
- if Key = Ord('-') then Exit;
- MessageBeep(0);
- end;
- Result := 1;
- end;
- end;
- procedure TTBCustomToolbar.Paint;
- var
- R: TRect;
- begin
- { Draw dotted border in design mode on undocked toolbars }
- if not Docked and (csDesigning in ComponentState) then
- with Canvas do begin
- R := ClientRect;
- Pen.Style := psDot;
- Pen.Color := clBtnShadow;
- Brush.Style := bsClear;
- Rectangle(R.Left, R.Top, R.Right, R.Bottom);
- Pen.Style := psSolid;
- end;
- FView.DrawSubitems(Canvas);
- end;
- procedure TTBCustomToolbar.CMDialogKey(var Message: TCMDialogKey);
- begin
- if (Message.CharCode = VK_MENU) and FMenuBar then
- FView.SetAccelsVisibility(True);
- inherited;
- end;
- procedure TTBCustomToolbar.CMDialogChar(var Message: TCMDialogChar);
- begin
- { On toolbars that aren't menu bars, handle CM_DIALOGCHAR instead of
- WM_SYSCOMMAND }
- if not FMenuBar and Enabled and Showing and (Message.CharCode <> 0) then
- if KeyboardOpen(Chr(Message.CharCode), True) then begin
- Message.Result := 1;
- Exit;
- end;
- inherited;
- end;
- procedure TTBCustomToolbar.CancelHover;
- begin
- if not MouseCapture then
- FView.UpdateSelection(nil, True);
- end;
- procedure TTBCustomToolbar.CMMouseLeave(var Message: TMessage);
- begin
- CancelHover;
- inherited;
- end;
- procedure TTBCustomToolbar.DoContextPopup(MousePos: TPoint;
- var Handled: Boolean);
- begin
- CancelHover;
- inherited;
- end;
- procedure TTBCustomToolbar.MouseMove(Shift: TShiftState; X, Y: Integer);
- var
- P: TPoint;
- Item: TTBCustomItem;
- begin
- if not(csDesigning in ComponentState) then begin
- P := ClientToScreen(Point(X, Y));
- FView.UpdateSelection(@P, True);
- if Assigned(FView.Selected) then begin
- Item := FView.Selected.Item;
- if not(tboLongHintInMenuOnly in Item.EffectiveOptions) then
- Hint := Item.Hint
- else
- Hint := '';
- with TTBItemViewerAccess(FView.Find(Item)) do
- begin
- MouseMove(X - BoundsRect.Left, Y - BoundsRect.Top);
- end;
- end
- else
- Hint := '';
- end;
- { Call TrackMouseEvent to be sure that we are notified when the mouse leaves
- the window. We won't get a CM_MOUSELEAVE message if the mouse moves
- directly from the toolbar to another application's window }
- CallTrackMouseEvent(Handle, TME_LEAVE);
- inherited;
- end;
- procedure TTBCustomToolbar.WMCancelMode(var Message: TWMCancelMode);
- begin
- inherited;
- { We can receive a WM_CANCELMODE message during a modal loop if a dialog
- pops up. Respond by hiding menus to make it look like the modal loop
- has returned, even though it really hasn't yet.
- Note: Similar code in TTBModalHandler.WndProc. }
- if vsModal in FView.State then
- FView.CancelMode;
- end;
- procedure TTBCustomToolbar.WMMouseLeave(var Message: TMessage);
- begin
- { A WM_MOUSELEAVE handler is necessary because the control won't get a
- CM_MOUSELEAVE message if the user presses Alt+Space. Also, CM_MOUSELEAVE
- messages are also not sent if the application is in a
- Application.ProcessMessages loop. }
- if not FIgnoreMouseLeave then
- CancelHover;
- inherited;
- end;
- procedure TTBCustomToolbar.WMNCMouseMove(var Message: TWMNCMouseMove);
- begin
- Hint := '';
- CancelHover;
- inherited;
- end;
- function TTBCustomToolbar.KeyboardOpen(Key: Char;
- RequirePrimaryAccel: Boolean): Boolean;
- var
- I: TTBItemViewer;
- IsOnlyItemWithAccel: Boolean;
- begin
- I := nil;
- FView.SetAccelsVisibility(True);
- try
- Result := False;
- if Key = #0 then begin
- I := FView.FirstSelectable;
- if I = nil then Exit;
- FView.Selected := I;
- FView.EnterToolbarLoop([]);
- end
- else begin
- I := FView.NextSelectableWithAccel(nil, Key, RequirePrimaryAccel,
- IsOnlyItemWithAccel);
- if (I = nil) or not I.Item.Enabled then
- Exit;
- if IsOnlyItemWithAccel then begin
- FView.Selected := I;
- FView.EnterToolbarLoop([tbetExecuteSelected]);
- end
- else if FMenuBar then begin
- FView.Selected := I;
- FView.EnterToolbarLoop([]);
- end
- else
- Exit;
- end;
- Result := True;
- finally
- if Assigned(I) then
- FView.SetAccelsVisibility(False);
- end;
- end;
- procedure TTBCustomToolbar.MouseDown(Button: TMouseButton; Shift: TShiftState;
- X, Y: Integer);
- var
- OldParent: TWinControl;
- P: TPoint;
- Item: TTBCustomItem;
- begin
- OldParent := Parent;
- inherited;
- if Parent <> OldParent then
- { if the inherited handler (TTBDockableWindow.MouseDown) changed the Parent
- (due to the toolbar moving between docks), nothing else should be done }
- Exit;
- if not(csDesigning in ComponentState) and (Button = mbLeft) then begin
- P := ClientToScreen(Point(X, Y));
- FView.UpdateSelection(@P, True);
- if Assigned(FView.Selected) then begin
- Item := FView.Selected.Item;
- if not(tbisClicksTransparent in TTBCustomItemAccess(Item).ItemStyle) then begin
- FIgnoreMouseLeave := True;
- try
- FView.EnterToolbarLoop([tbetMouseDown]);
- finally
- FIgnoreMouseLeave := False;
- end;
- end;
- end;
- end;
- end;
- procedure TTBCustomToolbar.CMFontChanged(var Message: TMessage);
- begin
- inherited;
- if not FSystemFont then
- Arrange;
- end;
- function TTBCustomToolbar.GetChevronHint: String;
- begin
- Result := FChevronItem.Hint;
- end;
- procedure TTBCustomToolbar.SetChevronHint(const Value: String);
- begin
- FChevronItem.Hint := Value;
- FChevronItem.Caption := EscapeAmpersands(GetShortHint(Value));
- end;
- procedure TTBCustomToolbar.SetChevronMoveItems(Value: Boolean);
- begin
- if FChevronMoveItems <> Value then begin
- FChevronMoveItems := Value;
- FView.UsePriorityList := Value and not(csDesigning in ComponentState);
- end;
- end;
- procedure TTBCustomToolbar.SetChevronPriorityForNewItems(Value: TTBChevronPriorityForNewItems);
- begin
- FChevronPriorityForNewItems := Value;
- FView.NewViewersGetHighestPriority := (Value = tbcpHighest);
- end;
- function TTBCustomToolbar.IsChevronHintStored: Boolean;
- begin
- Result := (FChevronItem.Hint <> FChevronItem.GetDefaultHint);
- end;
- function TTBCustomToolbar.GetImages: TCustomImageList;
- begin
- Result := FItem.SubMenuImages;
- end;
- procedure TTBCustomToolbar.SetImages(Value: TCustomImageList);
- begin
- FItem.SubMenuImages := Value;
- end;
- function TTBCustomToolbar.GetLinkSubitems: TTBCustomItem;
- begin
- Result := FItem.LinkSubitems;
- end;
- procedure TTBCustomToolbar.SetLinkSubitems(Value: TTBCustomItem);
- begin
- FItem.LinkSubitems := Value;
- end;
- procedure TTBCustomToolbar.SetMenuBar(Value: Boolean);
- begin
- if FMenuBar <> Value then begin
- FMenuBar := Value;
- if Value then begin
- ControlStyle := ControlStyle + [csMenuEvents];
- FView.Style := FView.Style + [vsMenuBar, vsUseHiddenAccels];
- end
- else begin
- ControlStyle := ControlStyle - [csMenuEvents];
- FView.Style := FView.Style - [vsMenuBar, vsUseHiddenAccels];
- end;
- if not(csLoading in ComponentState) then begin
- FullSize := Value;
- if Value then
- ShrinkMode := tbsmWrap
- else
- ShrinkMode := tbsmChevron;
- CloseButton := not Value;
- ProcessShortCuts := Value;
- end;
- if Value and not(csDesigning in ComponentState) then
- InstallHookProc(Self, HookProc, [hpGetMessage])
- else
- UninstallHookProc(Self, HookProc);
- SetMainWindowHook;
- end;
- end;
- function TTBCustomToolbar.GetOptions: TTBItemOptions;
- begin
- Result := FItem.Options;
- end;
- procedure TTBCustomToolbar.SetOptions(Value: TTBItemOptions);
- begin
- FItem.Options := Value;
- end;
- procedure TTBCustomToolbar.SetProcessShortCuts(Value: Boolean);
- begin
- if FProcessShortCuts <> Value then begin
- FProcessShortCuts := Value;
- SetMainWindowHook;
- end;
- end;
- procedure TTBCustomToolbar.SetSystemFont(Value: Boolean);
- begin
- if FSystemFont <> Value then begin
- FSystemFont := Value;
- Arrange;
- end;
- end;
- procedure TTBCustomToolbar.SetShrinkMode(Value: TTBShrinkMode);
- begin
- if FShrinkMode <> Value then begin
- FShrinkMode := Value;
- if Docked then
- CurrentDock.ArrangeToolbars
- else if not Floating then
- Arrange;
- end;
- end;
- procedure TTBCustomToolbar.SetFloatingWidth(Value: Integer);
- begin
- if FFloatingWidth <> Value then begin
- FFloatingWidth := Value;
- if Floating then begin
- UpdateViewProperties;
- Arrange;
- end;
- end;
- end;
- function TTBCustomToolbar.CalcWrapOffset(const ADock: TTBDock): Integer;
- begin
- if ADock = nil then
- Result := FFloatingWidth
- else begin
- if FShrinkMode = tbsmWrap then begin
- if not(ADock.Position in [dpLeft, dpRight]) then
- Result := ADock.Width - ADock.NonClientWidth - NonClientWidth
- else
- Result := ADock.Height - ADock.NonClientHeight - NonClientHeight;
- end
- else
- Result := 0;
- end;
- end;
- function TTBCustomToolbar.CalcChevronOffset(const ADock: TTBDock;
- const AOrientation: TTBViewOrientation): Integer;
- begin
- if (FShrinkMode = tbsmChevron) and Docked and (ADock = CurrentDock) then begin
- Result := CurrentSize;
- { Subtract non-client size }
- if AOrientation <> tbvoVertical then
- Dec(Result, NonClientWidth)
- else
- Dec(Result, NonClientHeight);
- if Result < 0 then
- Result := 0; { in case CurrentSize wasn't properly initialized yet }
- end
- else
- Result := 0;
- end;
- procedure TTBCustomToolbar.UpdateViewProperties;
- var
- DT: TTBDockType;
- begin
- DT := TBGetDockTypeOf(CurrentDock, Floating);
- FView.Orientation := DockTypeToOrientation[DT];
- FView.ChevronSize := tbChevronSize;
- if Assigned(CurrentDock) or Floating then begin
- FView.ChevronOffset := CalcChevronOffset(CurrentDock, FView.Orientation);
- FView.WrapOffset := CalcWrapOffset(CurrentDock);
- end
- else begin
- FView.ChevronOffset := 0;
- FView.WrapOffset := 0;
- { Only enable chevron/wrapping when the width of the toolbar is fixed }
- if not AutoResize or ((akLeft in Anchors) and (akRight in Anchors)) then begin
- if FShrinkMode = tbsmChevron then
- FView.ChevronOffset := Width - NonClientWidth
- else if FShrinkMode = tbsmWrap then
- FView.WrapOffset := Width - NonClientWidth;
- end;
- end;
- end;
- {}{DOCKING STUFF}
- procedure TTBCustomToolbar.ReadPositionData(var S: string);
- begin
- inherited;
- if Floating then
- FloatingWidth := StrToIntDef(CutToChar(S, ':', true), 0);
- end;
- function TTBCustomToolbar.WritePositionData: string;
- begin
- Result := inherited;
- if Floating then
- Result := Result + ':' + IntToStr(FFloatingWidth);
- end;
- procedure TTBCustomToolbar.GetMinBarSize(var MinimumSize: TPoint);
- var
- WH: Integer;
- begin
- MinimumSize.X := 0;
- MinimumSize.Y := 0;
- if Docked then begin
- WH := CurrentDock.GetMinRowSize(EffectiveDockRow, Self);
- if not(CurrentDock.Position in [dpLeft, dpRight]) then
- MinimumSize.Y := WH
- else
- MinimumSize.X := WH;
- end;
- end;
- procedure TTBCustomToolbar.GetBaseSize(var ASize: TPoint);
- begin
- FView.ValidatePositions;
- ASize := FBaseSize;
- { MP }
- if Assigned(FOnGetBaseSize) then FOnGetBaseSize(Self, ASize);
- end;
- function TTBCustomToolbar.DoArrange(CanMoveControls: Boolean;
- PreviousDockType: TTBDockType; NewFloating: Boolean; NewDock: TTBDock): TPoint;
- var
- DT: TTBDockType;
- O: TTBViewOrientation;
- TempBaseSize: TPoint;
- begin
- //outputdebugstring (pchar(format('%s.DoArrange(%d)', [Name, Ord(CanMoveControls)])));
- if CanMoveControls then begin
- UpdateViewProperties;
- Result := FView.UpdatePositions;
- end
- else begin
- DT := TBGetDockTypeOf(NewDock, NewFloating);
- O := DockTypeToOrientation[DT];
- Result.X := 0;
- Result.Y := 0;
- FView.CalculatePositions(False, O, CalcWrapOffset(NewDock),
- CalcChevronOffset(NewDock, O), tbChevronSize, TempBaseSize, Result,
- FLastWrappedLines);
- end;
- end;
- procedure TTBCustomToolbar.ControlExistsAtPos(const P: TPoint;
- var ControlExists: Boolean);
- var
- P2: TPoint;
- begin
- inherited;
- if not ControlExists and not(csDesigning in ComponentState) then begin
- P2 := ClientToScreen(P);
- FView.UpdateSelection(@P2, True);
- if Assigned(FView.Selected) and
- not(tbisClicksTransparent in TTBCustomItemAccess(FView.Selected.Item).ItemStyle) then
- ControlExists := True;
- end;
- end;
- procedure TTBCustomToolbar.BuildPotentialSizesList(SizesList: TList);
- var
- Margins: TRect;
- MinX, SaveWrapX: Integer;
- X, PrevWrappedLines: Integer;
- S: TPoint;
- S2: TSmallPoint;
- begin
- View.GetMargins(tbvoFloating, Margins);
- MinX := Margins.Left + Margins.Right;
- SaveWrapX := FFloatingWidth;
- try
- { Add the widest size to the list }
- FFloatingWidth := 0;
- S := DoArrange(False, dtNotDocked, True, nil);
- SizesList.Add(Pointer(PointToSmallPoint(S)));
- { Calculate and add rest of sizes to the list }
- PrevWrappedLines := 1;
- X := S.X-1;
- while X >= MinX do begin
- FFloatingWidth := X;
- S := DoArrange(False, dtNotDocked, True, nil);
- if S.X > X then { if it refuses to go any smaller }
- Break
- else
- if X = S.X then begin
- S2 := PointToSmallPoint(S);
- if FLastWrappedLines <> PrevWrappedLines then
- SizesList.Add(Pointer(S2))
- else
- SizesList[SizesList.Count-1] := Pointer(S2);
- PrevWrappedLines := FLastWrappedLines;
- Dec(X);
- end
- else
- X := S.X;
- end;
- finally
- FFloatingWidth := SaveWrapX;
- 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 TTBCustomToolbar.ResizeBegin(ASizeHandle: TTBSizeHandle);
- const
- MaxSizeSens = 12;
- var
- I, NewSize: Integer;
- S, N: TSmallPoint;
- P: TPoint;
- begin
- inherited;
- FSizeData := AllocMem(SizeOf(TToolbar97SizeData));
- with PToolbar97SizeData(FSizeData)^ do begin
- SizeHandle := ASizeHandle;
- OrigLeft := Parent.Left;
- OrigTop := Parent.Top;
- OrigWidth := Parent.Width;
- OrigHeight := Parent.Height;
- NCXDiff := ClientToScreen(Point(0, 0)).X - OrigLeft;
- CurRightX := FFloatingWidth;
- 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 TTBCustomToolbar.ResizeTrack(var Rect: TRect; const OrigRect: TRect);
- var
- Pos: TPoint;
- NewOpSide: Boolean;
- Reverse: Boolean;
- I: Integer;
- P: TSmallPoint;
- begin
- inherited;
- with PToolbar97SizeData(FSizeData)^ do begin
- GetCursorPos(Pos);
- Dec(Pos.X, OrigLeft); Dec(Pos.Y, OrigTop);
- if SizeHandle = twshLeft then
- Pos.X := OrigWidth-Pos.X
- else
- if SizeHandle = twshTop then
- Pos.Y := OrigHeight-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 < OrigWidth
- else
- NewOpSide := Pos.Y < OrigHeight;
- if (not DisableSensCheck) or (OpSide <> NewOpSide) then begin
- DisableSensCheck := False;
- OpSide := NewOpSide;
- if SizeHandle in [twshLeft, twshRight] then begin
- if (Pos.X >= OrigWidth-SizeSens) and (Pos.X < OrigWidth+SizeSens) then
- Pos.X := OrigWidth;
- end
- else begin
- if (Pos.Y >= OrigHeight-SizeSens) and (Pos.Y < OrigHeight+SizeSens) then
- Pos.Y := OrigHeight;
- end;
- end;
- Rect := OrigRect;
- if SizeHandle in [twshLeft, twshRight] then
- Reverse := Pos.X > OrigWidth
- else
- Reverse := Pos.Y > OrigHeight;
- 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 TTBCustomToolbar.ResizeTrackAccept;
- begin
- inherited;
- FloatingWidth := PToolbar97SizeData(FSizeData)^.CurRightX;
- end;
- procedure TTBCustomToolbar.ResizeEnd;
- begin
- inherited;
- if Assigned(FSizeData) then begin
- PToolbar97SizeData(FSizeData)^.NewSizes.Free;
- FreeMem(FSizeData);
- FSizeData := nil;
- end;
- end;
- function TTBCustomToolbar.GetShrinkMode: TTBShrinkMode;
- begin
- Result := FShrinkMode;
- end;
- procedure TTBCustomToolbar.GetMinShrinkSize(var AMinimumSize: Integer);
- var
- I: TTBItemViewer;
- begin
- I := FView.HighestPriorityViewer;
- if Assigned(I) then begin
- if not(CurrentDock.Position in [dpLeft, dpRight]) then
- AMinimumSize := I.BoundsRect.Right - I.BoundsRect.Left
- else
- AMinimumSize := I.BoundsRect.Bottom - I.BoundsRect.Top;
- end;
- if not(CurrentDock.Position in [dpLeft, dpRight]) then
- Inc(AMinimumSize, NonClientWidth)
- else
- Inc(AMinimumSize, NonClientHeight);
- Inc(AMinimumSize, tbChevronSize);
- end;
- procedure TTBCustomToolbar.BeginUpdate;
- begin
- FView.BeginUpdate;
- end;
- procedure TTBCustomToolbar.EndUpdate;
- begin
- FView.EndUpdate;
- end;
- procedure TTBCustomToolbar.GetTabOrderList(List: TList);
- var
- CtlList: TList;
- I, J: Integer;
- CtlI, CtlJ: TWinControl;
- begin
- inherited;
- { Remove off-edge items and their children from List }
- CtlList := TList.Create;
- try
- FView.GetOffEdgeControlList(CtlList);
- for I := 0 to CtlList.Count-1 do begin
- CtlI := CtlList[I];
- J := 0;
- while J < List.Count do begin
- CtlJ := List[J];
- if (CtlJ = CtlI) or CtlI.ContainsControl(CtlJ) then
- List.Delete(J)
- else
- Inc(J);
- end;
- end;
- finally
- CtlList.Free;
- end;
- end;
- procedure TTBCustomToolbar.CMWinIniChange(var Message: TWMSettingChange);
- begin
- inherited;
- if Message.Flag = SPI_SETNONCLIENTMETRICS then begin
- TBInitToolbarSystemFont;
- Arrange;
- end;
- end;
- function TTBCustomToolbar.IsShortCut(var Message: TWMKey): Boolean;
- begin
- Result := False;
- if Assigned(FOnShortCut) then
- FOnShortCut(Message, Result);
- Result := Result or FItem.IsShortCut(Message);
- end;
- var
- HookCount: Integer;
- HookList: TList;
- class function TTBCustomToolbar.MainWindowHook(var Message: TMessage): Boolean;
- function GetActiveForm: TCustomForm;
- var
- Wnd: HWND;
- Ctl: TWinControl;
- begin
- { Note: We don't use Screen.ActiveCustomForm because when an EXE calls a
- DLL that shows a modal form, Screen.ActiveCustomForm doesn't change in
- the EXE; it remains set to the last form that was active in the EXE.
- Use FindControl(GetActiveWindow) instead to avoid this problem; it will
- return nil when a form in another module is active. }
- Result := nil;
- Wnd := GetActiveWindow;
- if Wnd <> 0 then begin
- Ctl := FindControl(Wnd);
- if Assigned(Ctl) and (Ctl is TCustomForm) then
- Result := TCustomForm(Ctl);
- end;
- end;
- function HandleShortCutOnForm(const Form: TCustomForm): Boolean;
- var
- I: Integer;
- Toolbar: TTBCustomToolbar;
- begin
- Result := False;
- if Form = nil then
- Exit;
- for I := 0 to HookList.Count-1 do begin
- Toolbar := HookList[I];
- if Toolbar.ProcessShortCuts and
- (TBGetToolWindowParentForm(Toolbar) = Form) and
- IsWindowEnabled(Form.Handle) and
- Toolbar.IsShortCut(TWMKey(Message)) then begin
- Message.Result := 1;
- Result := True;
- Exit;
- end;
- end;
- end;
- function TraverseControls(Container: TWinControl): Boolean;
- var
- I: Integer;
- Control: TControl;
- begin
- Result := False;
- if Container.Showing then
- for I := 0 to Container.ControlCount - 1 do begin
- Control := Container.Controls[I];
- if Control.Visible and Control.Enabled then begin
- if (csMenuEvents in Control.ControlStyle) and
- ((Control is TTBDock) or (Control is TTBCustomToolbar)) and
- (Control.Perform(WM_SYSCOMMAND, TMessage(Message).WParam,
- TMessage(Message).LParam) <> 0) or (Control is TWinControl) and
- TraverseControls(TWinControl(Control)) then begin
- Result := True;
- Exit;
- end;
- end;
- end;
- end;
- var
- ActiveForm: TCustomForm;
- ActiveMDIChild: TForm;
- begin
- Result := False;
- if (Message.Msg = CM_APPKEYDOWN) and Assigned(HookList) then begin
- { Process shortcuts on toolbars. Search forms in this order:
- 1. If the active form is an MDI parent form, the active MDI child form
- if it has the focus.
- 2. The active form.
- 3. The main form. }
- ActiveForm := GetActiveForm;
- if Assigned(ActiveForm) and (ActiveForm is TForm) and
- (TForm(ActiveForm).FormStyle = fsMDIForm) then begin
- ActiveMDIChild := TForm(ActiveForm).ActiveMDIChild;
- { Don't search the child form if a control on the MDI parent form is
- currently focused (i.e. Screen.ActiveCustomForm <> ActiveMDIChild) }
- if Assigned(ActiveMDIChild) and
- (Screen.ActiveCustomForm = ActiveMDIChild) and
- HandleShortCutOnForm(ActiveMDIChild) then begin
- Result := True;
- Exit;
- end;
- end;
- if HandleShortCutOnForm(ActiveForm) then
- Result := True
- else begin
- if (Application.MainForm <> ActiveForm) and
- HandleShortCutOnForm(Application.MainForm) then
- Result := True;
- end;
- end
- else if Message.Msg = CM_APPSYSCOMMAND then begin
- { Handle "Alt or Alt+[key] pressed on secondary form" case. If there's a
- menu bar on the active form we want the keypress to go to it instead of
- to the main form (the VCL's default handling). }
- ActiveForm := GetActiveForm;
- if Assigned(ActiveForm) and IsWindowEnabled(ActiveForm.Handle) and
- IsWindowVisible(ActiveForm.Handle) and TraverseControls(ActiveForm) then begin
- Message.Result := 1;
- Result := True;
- end;
- end;
- end;
- procedure TTBCustomToolbar.SetMainWindowHook;
- begin
- if (ProcessShortCuts or MenuBar) and not(csDesigning in ComponentState) then
- InstallMainWindowHook
- else
- UninstallMainWindowHook;
- end;
- procedure TTBCustomToolbar.InstallMainWindowHook;
- begin
- if FMainWindowHookInstalled then
- Exit;
- if HookCount = 0 then
- Application.HookMainWindow(MainWindowHook);
- Inc(HookCount);
- AddToList(HookList, Self);
- FMainWindowHookInstalled := True;
- end;
- procedure TTBCustomToolbar.UninstallMainWindowHook;
- begin
- if not FMainWindowHookInstalled then
- Exit;
- FMainWindowHookInstalled := False;
- RemoveFromList(HookList, Self);
- Dec(HookCount);
- if HookCount = 0 then
- Application.UnhookMainWindow(MainWindowHook);
- end;
- procedure TTBCustomToolbar.ChangeScale(M, D: Integer);
- begin
- inherited;
- Items.ChangeScale(M, D);
- View.RecreateAllViewers;
- end;
- end.
|