fcOutlookBar.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:32k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit fcOutlookBar;
  2. {
  3. //
  4. // Components : TfcOutlookBar
  5. //
  6. // Copyright (c) 1999 by Woll2Woll Software
  7. //
  8. // 5/12/99 - RSW - Repaint current selection if its a non-rectangular button
  9. // 11/1/2001 - PYW - Publish ShowDownAsUp property.
  10. // 11/14/2001 - Added name for form inheritance issues.
  11. }
  12. interface
  13. uses Messages, Windows, Graphics, Classes, Forms, Controls, SysUtils, fcCommon, fcButtonGroup,
  14.   ExtCtrls, fcCollection, Dialogs, fcClearPanel, ComCtrls, fcOutlookList, fcImgBtn, fcButton,
  15.   fcImager, fcChangeLink, fcShapeBtn;
  16. {$i fcIfDef.pas}
  17. type
  18.   TfcOutlookPage = class;
  19.   TfcCustomOutlookBar = class;
  20.   TfcAnimation = class(TPersistent)
  21.   private
  22.     FEnabled: Boolean;
  23.     FInterval: Integer;
  24.     FSteps: Integer;
  25.   public
  26.     constructor Create;
  27.   published
  28.     property Enabled: Boolean read FEnabled write FEnabled;
  29.     property Interval: Integer read FInterval write FInterval;
  30.     property Steps: Integer read FSteps write FSteps;
  31.   end;
  32.   TfcOutlookPage = class(TfcButtonGroupItem)
  33.   private
  34.     FPanel: TfcOutlookPanel;
  35.     FOutlookList: TfcOutlookList;
  36.   protected
  37.     function GetOutlookBar: TfcCustomOutlookBar; virtual;
  38.     procedure SetIndex(Value: Integer); override;
  39.     procedure Loaded; override;
  40.   public
  41.     constructor Create(Collection: TCollection); override;
  42.     destructor Destroy; override;
  43.     procedure CreateOutlookList; virtual;
  44.     procedure GotSelected; override;
  45.     property OutlookBar: TfcCustomOutlookBar read GetOutlookBar;
  46.     property OutlookList: TfcOutlookList read FOutlookList;
  47.     property Panel: TfcOutlookPanel read FPanel write FPanel;
  48.   end;
  49.   TfcOutlookPages = class(TfcButtonGroupItems)
  50.   protected
  51.     function GetOutlookBar: TfcCustomOutlookBar; virtual;
  52.     function GetItems(Index: Integer): TfcOutlookPage;
  53.     procedure AnimateSetBounds(Control: TWinControl; Rect: TRect); virtual;
  54.   public
  55.     constructor Create(AButtonGroup: TfcCustomButtonGroup; ACollectionItemClass: TfcButtonGroupItemClass); override;
  56.     procedure ArrangeControls; override;
  57.     function Add: TfcOutlookPage;
  58.     function AddItem: TfcCollectionItem; override;
  59.     property OutlookBar: TfcCustomOutlookBar read GetOutlookBar;
  60.     property Items[Index: Integer]: TfcOutlookPage read GetItems; default;
  61.   end;
  62.   TfcCustomOutlookBarOption = (cboAutoCreateOutlookList, cboTransparentPanels);
  63.   TfcCustomOutlookBarOptions = set of TfcCustomOutlookBarOption;
  64.   TfcPanelAlignment = (paDynamic, paTop, paBottom);
  65.   TfcCustomOutlookBar = class(TfcCustomButtonGroup)
  66.   private
  67.     // Property Storage Variables
  68.     FAnimation: TfcAnimation;
  69.     FAnimatingControls: Boolean;
  70.     FAnimationLock: Integer;
  71.     FButtonSize: Integer;
  72.     FImager: TfcCustomImager;
  73.     FOptions: TfcCustomOutlookBarOptions;
  74.     FPanelAlignment: TfcPanelAlignment;
  75.     FShowButtons: Boolean;
  76.     FChangeLink: TfcChangeLink;
  77.     // Property Access Methods
  78.     function GetActivePage: TfcCustomBitBtn;
  79.     function GetItems: TfcOutlookPages;
  80.     procedure SetActivePage(Value: TfcCustomBitBtn);
  81.     procedure SetAnimatingControls(Value: Boolean);
  82.     procedure SetButtonSize(Value: Integer);
  83.     procedure SetImager(Value: TfcCustomImager);
  84.     procedure SetItems(Value: TfcOutlookPages);
  85.     procedure SetOptions(Value: TfcCustomOutlookBarOptions); virtual;
  86.     procedure SetPanelAlignment(Value: TfcPanelAlignment); virtual;
  87.     procedure SetShowButtons(Value: Boolean);
  88.     procedure CMControlListChange(var Message: TCMControlListChange); message CM_CONTROLLISTCHANGE;
  89.     procedure CMControlChange(var Message: TCMControlChange); message CM_CONTROLCHANGE;
  90.     procedure WMEraseBkgnd(var Message: TWMEraseBkGnd); message WM_ERASEBKGND; { 3/12/99 RSW - Need to prevent flicker }
  91.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  92.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  93.   protected
  94.     function GetCollectionClass: TfcButtonGroupItemsClass; override;
  95.     procedure WndProc(var Message: TMessage); override;
  96.     // Overridden methods
  97.     function ResizeToControl(Control: TControl; DoResize: Boolean): TSize; override;
  98.     procedure ButtonPressed(Sender: TObject); override;
  99.     procedure CreateWnd; override;
  100.     procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  101.     procedure ImagerChange(Sender: TObject);
  102.     procedure Loaded; override;
  103.     procedure Notification(AComponent: TComponent; AOperation: TOperation); override;
  104.     procedure Paint; override;
  105.     // Overridden property access methods
  106.     procedure SetName(const NewName: TComponentName); override;
  107.     function IsNonRectangularButton(Control: TControl): boolean; virtual;
  108.   public
  109.     Patch: Variant;
  110. //    InPaste: boolean;
  111.     constructor Create(AOwner: TComponent); override;
  112.     destructor Destroy; override;
  113.     function InAnimation: Boolean; virtual; { Button presses so begin animation, include 1 step }
  114.     procedure EnableAnimation;
  115.     procedure DisableAnimation;
  116.     property ActivePage: TfcCustomBitBtn read GetActivePage write SetActivePage;
  117.     property Animation: TfcAnimation read FAnimation write FAnimation;
  118.     property AnimatingControls: Boolean read FAnimatingControls write SetAnimatingControls;
  119.     property ButtonSize: Integer read FButtonSize write SetButtonSize;
  120.     property Canvas;
  121.     property Color;
  122.     property Imager: TfcCustomImager read FImager write SetImager;
  123.     property OutlookItems: TfcOutlookPages read GetItems write SetItems stored False;
  124.     property Options: TfcCustomOutlookBarOptions read FOptions write SetOptions;
  125.     property PanelAlignment: TfcPanelAlignment read FPanelAlignment write SetPanelAlignment;
  126.     property ShowButtons: Boolean read FShowButtons write SetShowButtons;
  127.   end;
  128.   TfcOutlookBar = class(TfcCustomOutlookBar)
  129.   published
  130.     {$ifdef fcDelphi4Up}
  131.     property Anchors;
  132.     property Constraints;
  133.     {$endif}
  134.     property ActivePage;
  135.     property Align;
  136.     property Animation;
  137.     property AutoBold;
  138.     property BevelInner;
  139.     property BevelOuter;
  140.     property BorderStyle nodefault;
  141.     property ButtonSize;
  142.     property ButtonClassName;
  143.     property Color;
  144.     property Font;
  145.     property ParentFont;
  146.     property Imager;
  147.     property OutlookItems;
  148.     property Layout;
  149.     property Options;
  150.     property PanelAlignment;
  151.     property ShowButtons;
  152.     property ShowDownAsUp default False;
  153.     property TabOrder;
  154.     property TabStop default True;  //7/30/99 - Support TabStop = False
  155.     property Visible;
  156. //    property Transparent; { 3/13/99 - RSW - Not supported}
  157.     property OnChange;
  158.     property OnChanging;
  159.     property OnEnter;
  160.     property OnExit;
  161.     property OnResize;
  162.     property OnKeyDown;
  163.     property OnKeyUp;
  164.     property OnKeyPress;
  165.   end;
  166. implementation
  167. constructor TfcAnimation.Create;
  168. begin
  169.   inherited;
  170.   FEnabled := True;
  171.   FInterval := 1;
  172.   FSteps := 7;
  173. end;
  174. constructor TfcOutlookPage.Create(Collection: TCollection);
  175.   function UniqueObjectName(oOwner: TWinControl; sPrefix: String): string;
  176.   var
  177.     iIndex: integer;
  178.     sName: String;
  179.   begin
  180.     iIndex:= 1;
  181.     sName:= sPrefix+inttostr(iIndex);
  182.     while oOwner.FindComponent(sName) <> nil do begin
  183.        inc(iIndex);
  184.        sName:= sPrefix+inttostr(iIndex);
  185.     end;
  186.     result:= sName;
  187.   end;
  188. begin
  189.   inherited;
  190.   if not (csLoading in ButtonGroup.ComponentState) then
  191.   begin
  192.     ButtonGroup.ButtonItems.ArrangingControls := True;
  193.     FPanel := TfcOutlookPanel.Create(ButtonGroup);
  194. //    FPanel.Name := fcGenerateName(FPanel.Owner, ButtonGroup.Name + 'Panel');
  195.     //11/14/2001 - Added name for form inheritance issues.
  196.     FPanel.Name := UniqueObjectName(ButtonGroup,'OutlookPanel');
  197.     FPanel.Parent := ButtonGroup;
  198.     FPanel.Visible := False;
  199.     FPanel.SendToBack;
  200.     FPanel.Top := -FPanel.Height - 10;
  201.     FPanel.OutlookPage := self;
  202. //    FPanel.BevelOuter := bvNone;
  203.     if cboAutoCreateOutlookList in OutlookBar.Options then
  204.       CreateOutlookList;
  205.     ButtonGroup.ButtonItems.ArrangingControls := False;
  206.   end;
  207. end;
  208. destructor TfcOutlookPage.Destroy;
  209. begin
  210.   OutlookBar.FItems.DeletingControl := True;
  211.   FPanel.Free;
  212.   OutlookBar.FItems.DeletingControl := False;
  213.   inherited;
  214. end;
  215. procedure TfcOutlookPage.SetIndex(Value: Integer);
  216. begin
  217.   inherited;
  218.   if not (csLoading in ButtonGroup.ComponentState) then OutlookBar.SetChildOrder(Panel, Value);
  219. end;
  220. function TfcOutlookPage.GetOutlookBar: TfcCustomOutlookBar;
  221. begin
  222.   result := TfcCustomOutlookBar(ButtonGroup);
  223. end;
  224. procedure TfcOutlookPage.Loaded;
  225. begin
  226.   Panel.Owner.RemoveComponent(Panel);
  227.   ButtonGroup.InsertComponent(Panel);
  228.   Panel.OutlookPage := self;
  229.   if FOutlookList <> nil then FOutlookList.OutlookPage := self;
  230. end;
  231. procedure TfcOutlookPage.CreateOutlookList;
  232. var component:TWinControl;
  233. begin
  234.   if FOutlookList <> nil then Exit;
  235. //  FOutlookList := TfcOutlookList.Create(GetParentForm(OutlookBar));
  236.   component := OutlookBar.Parent;
  237.   while (Component <> Nil) do
  238.   begin
  239.     if (Component is TCustomFrame) or (Component is TCustomForm) then begin
  240.        FOutlookList := TfcOutlookList.Create(Component);
  241.        break;
  242.     end;
  243.     Component := Component.Parent;
  244.   end;
  245.   with FOutlookList do
  246.   begin
  247.     Parent := FPanel;
  248.     Align := alClient;
  249.     BorderStyle := bsNone;
  250.     if Component <> nil then
  251.        Name := fcGenerateName(Component, self.OutlookBar.Name + 'OutlookList');
  252. //    Name := fcGenerateName(GetParentForm(self.OutlookBar), self.OutlookBar.Name + 'OutlookList');
  253.     OutlookPage := self;
  254.   end;
  255. end;
  256. procedure TfcOutlookPage.GotSelected;
  257. begin
  258.   Selected := True;
  259.   TfcButtonGroupItems(Collection).ArrangeControls;
  260. end;
  261. constructor TfcOutlookPages.Create(AButtonGroup: TfcCustomButtonGroup; ACollectionItemClass: TfcButtonGroupItemClass);
  262. begin
  263.   inherited Create(AButtonGroup, TfcOutlookPage);
  264. end;
  265. function TfcOutlookPages.GetOutlookBar: TfcCustomOutlookBar;
  266. begin
  267.   result := TfcCustomOutlookBar(ButtonGroup);
  268. end;
  269. function TfcOutlookPages.GetItems(Index: Integer): TfcOutlookPage;
  270. begin
  271.   result := TfcOutlookPage(inherited Items[Index]);
  272. end;
  273. procedure TfcOutlookPages.AnimateSetBounds(Control: TWinControl; Rect: TRect);
  274. begin
  275.   if Control is TfcOutlookPanel then
  276.   begin
  277.     if Control is TfcOutlookPanel then TfcOutlookPanel(Control).FPreventUpdate := True;
  278.     Control.BoundsRect := Rect;
  279.     if Control is TfcOutlookPanel then TfcOutlookPanel(Control).FPreventUpdate := False;
  280.   end else begin
  281.     with Rect do SetWindowPos(Control.Handle, 0, Left, Top, Right - Left, Bottom - Top, SWP_NOZORDER or SWP_NOREDRAW);
  282.     InvalidateRect(Control.Handle, nil, False);
  283.   end;
  284. end;
  285. type TfcOutlookButton = class(TfcCustomBitBtn);
  286. procedure TfcOutlookPages.ArrangeControls;
  287. var i: Integer;
  288.     ControlTop: Integer;
  289.     List: TList;
  290.     Item: TfcGroupAnimateItem;
  291.     CurItem: TfcOutlookPage;
  292.     PanelHeight: Integer;
  293.     OldPanel: TfcOutlookPanel;
  294.     OldPanelIndex: integer;
  295.     ASteps, AInterval: Integer;
  296.     ButtonRect: TRect;
  297.     InvalidButton: TWinControl;
  298.   //4/15/99 - PYW - Check to see if any child of one of the Outlookpages has a control with the
  299.   //                align property not set to alNone.
  300.   function ChildHasAlignmentSet: boolean;
  301.   var alignset:boolean;
  302.       i,j:integer;
  303.   begin
  304.     alignset := False;
  305.     for i := 0 to Count - 1 do
  306.        with TfcOutlookPage(Items[i]), Panel do
  307.        begin
  308.          if OutlookList = nil then
  309.          begin
  310.             for j:=0 to ControlCount - 1 do
  311.             begin
  312.                if Controls[j].Align <> alNone then begin
  313.                   alignset := True;
  314.                   break;
  315.                end;
  316.             end;
  317.          end;
  318.        end;
  319.        result := alignset;
  320.   end;
  321. {  function IsNonRectangularButton(Control: TControl): boolean;
  322.   var button: TfcCustomImageBtn;
  323.   begin
  324.      result:= False;
  325.      if (Control is TfcCustomImageBtn) then
  326.      begin
  327.         button:= TfcCustomImageBtn(control);
  328.          if ((Control is TfcCustomShapeBtn) and
  329.             ((Control as TfcCustomShapeBtn).Shape <> bsRect)) then result:= True
  330.          else if (not (Control is TfcCustomShapeBtn) and
  331.             (button.TransparentColor <> clNullColor)) then result:= True
  332.      end
  333.   end;
  334. }
  335.   procedure CleanUp;
  336.   var i:integer;
  337.   begin
  338.     ArrangingControls := False;
  339.     OutlookBar.AnimatingControls := False;
  340.     List.Free;
  341.     for i := 0 to Count - 1 do
  342.       with TfcOutlookPage(Items[i]) do
  343.         if OutlookList <> nil then OutlookList.ScrollButtonsVisible := True;
  344.   end;
  345. begin
  346.   if ArrangingControls or AddingControls then Exit;
  347.   ArrangingControls := True;
  348. //  OutlookBar.AnimatingControls := True; { Don't use this flag, RSW }
  349.   if OutlookBar.Layout = loVertical then PanelHeight := ButtonGroup.ClientHeight
  350.   else PanelHeight := ButtonGroup.ClientWidth;
  351.   PanelHeight := PanelHeight - VisibleCount * OutlookBar.ButtonSize;
  352.   List := TList.Create;
  353.   ControlTop := 0;
  354.   if OutlookBar.PanelAlignment = paTop then inc(ControlTop, PanelHeight);
  355.   OldPanel := nil;
  356.   OldPanelIndex:= -1;
  357.   for i := 0 to Count - 1 do
  358.     with TfcOutlookPage(Items[i]), Panel do
  359.     begin
  360.       if OutlookList <> nil then OutlookList.ScrollButtonsVisible := False;
  361.       if Visible then begin
  362.         OldPanel := TfcOutlookPage(Items[i]).Panel;
  363.         OldPanelIndex:= i;
  364.       end
  365.       else begin
  366.         Visible := False;
  367.         Top := -Height;
  368.       end;
  369.     end;
  370.   if not OutlookBar.ShowButtons then
  371.   begin
  372.     if OldPanel <> nil then OldPanel.Visible := False;
  373.     if OutlookBar.Selected <> nil then with (OutlookBar.Selected as TfcOutlookPage).Panel do
  374.     begin
  375.       BoundsRect := OutlookBar.ClientRect;
  376.       Visible := True;
  377.     end;
  378.     CleanUp;
  379.     exit;
  380.   end;
  381.   for i := 0 to VisibleCount - 1 do with OutlookBar do
  382.   begin
  383.     CurItem := TfcOutlookPage(VisibleItems[i]);
  384.     Item := TfcGroupAnimateItem.Create;
  385.     Item.MainItem := TfcAnimateListItem.Create;
  386.     Item.MainItem.Control := CurItem.Button;
  387.     Item.MainItem.OrigRect := CurItem.Button.BoundsRect;
  388.     Item.SecondItem := nil;
  389.     if Layout = loVertical then
  390.       Item.MainItem.FinalRect := Rect(0, ControlTop, ClientWidth, ControlTop + ButtonSize)
  391.     else Item.MainItem.FinalRect := Rect(ControlTop, 0, ControlTop + ButtonSize, ClientHeight);
  392.     if CurItem.Selected or ((OldPanel <> nil) and (OldPanel = CurItem.Panel)) then
  393.     begin
  394.       with CurItem.Button.BoundsRect do
  395.         if CurItem.Selected then case PanelAlignment of
  396.           paDynamic: if Layout = loVertical then CurItem.Panel.BoundsRect := Rect(Left, Bottom, Right, Bottom)
  397.                  else CurItem.Panel.BoundsRect := Rect(Right, Top, Right, Bottom);
  398.           paTop: if Layout = loVertical then CurItem.Panel.BoundsRect := Rect(Left, 0, Right, 0)
  399.                  else CurItem.Panel.BoundsRect := Rect(0, Top, 0, Bottom);
  400.           paBottom: if Layout= loVertical then CurItem.Panel.BoundsRect := Rect(Left, ClientHeight - PanelHeight, Right, ClientHeight - PanelHeight)
  401.                  else CurItem.Panel.BoundsRect := Rect(ClientWidth - PanelHeight, Top, ClientWidth - PanelHeight, Bottom);
  402.         end;
  403.       CurItem.Panel.Visible := True;
  404.       Item.SecondItem := TfcAnimateListItem.Create;
  405.       Item.SecondItem.Control := CurItem.Panel;
  406.       Item.SecondItem.OrigRect := CurItem.Panel.BoundsRect;
  407.       if CurItem.Selected then
  408.       begin
  409.         with Item.MainItem.FinalRect do case OutlookBar.PanelAlignment of
  410.           paDynamic: begin
  411.             if Layout = loVertical then Item.SecondItem.FinalRect := Rect(Left, Bottom, Right, Bottom + PanelHeight)
  412.             else Item.SecondItem.FinalRect := Rect(Right, Top, Right + PanelHeight, Bottom);
  413.             inc(ControlTop, PanelHeight);
  414.           end;
  415.           paTop: if Layout = loVertical then Item.SecondItem.FinalRect := Rect(Left, 0, Right, PanelHeight)
  416.             else Item.SecondItem.FinalRect := Rect(0, Top, PanelHeight, Bottom);
  417.           paBottom: if Layout = loVertical then Item.SecondItem.FinalRect := Rect(Left, OutlookBar.ClientHeight - PanelHeight, Right, OutlookBar.ClientHeight)
  418.             else Item.SecondItem.FinalRect := Rect(OutlookBar.ClientWidth - PanelHeight, Top, OutlookBar.ClientWidth, Bottom);
  419.         end;
  420.       end else with Item.MainItem.FinalRect do begin
  421.         if Layout = loVertical then Item.SecondItem.FinalRect := Rect(Left, Bottom, Right, Bottom)
  422.         else Item.SecondItem.FinalRect := Rect(Right, Top, Right, Bottom);
  423.       end;
  424.     end;
  425.     inc(ControlTop, OutlookBar.ButtonSize);
  426.     List.Add(Item);
  427.   end;
  428.   ASteps := OutlookBar.Animation.Steps;
  429.   AInterval := OutlookBar.Animation.Interval;
  430.   //4/15/99 - PYW - Check to see if any child of one of the Outlookpages has a control with the
  431.   //                align property not set to alNone.
  432.   if not OutlookBar.InAnimation or (csDesigning in OutlookBar.ComponentState) or
  433.      not OutlookBar.Animation.Enabled or ChildHasAlignmentSet then
  434.   begin
  435.     OutlookBar.AnimatingControls := False;
  436.     ASteps := 1;
  437.     AInterval := 0;
  438.   end;
  439.   for i:= 0 to count-1 do
  440.      TfcOutlookButton(Items[i].Button).DisableButton:= True;
  441.   fcAnimateControls(OutlookBar, OutlookBar.Canvas, List, AInterval, ASteps, AnimateSetBounds);
  442.   if (OldPanel <> nil) and (OutlookBar.Selected <> nil) and ((OutlookBar.Selected as TfcOutlookPage).Panel <> OldPanel) then
  443.   begin
  444.     OldPanel.Visible := False;
  445.     OldPanel.Top := -OutlookBar.Height;
  446.   end;
  447.   for i := 0 to List.Count - 1 do
  448.     with TfcGroupAnimateItem(List[i]) do
  449.     begin
  450.       if SecondItem <> nil then
  451.       begin
  452. {         if SecondItem.Control.Visible then with SecondItem.Control do
  453.          begin
  454.            for j := 0 to ControlCount - 1 do
  455.              if IsNonRectangularButton(Controls[j]) then
  456.              begin
  457.                r := SecondItem.Control.Controls[j].BoundsRect;
  458.                InvalidateRect(SecondItem.Control.Handle, @r, False);
  459.              end;
  460.          end;}
  461.          SecondItem.Free;
  462.       end;
  463.       MainItem.Free;
  464.       Free;
  465.     end;
  466.   CleanUp;
  467.   for i:= 0 to count-1 do
  468.      TfcOutlookButton(Items[i].Button).DisableButton:= False;
  469. {  if (ASteps=1) and (Outlookbar.Selected<>nil) and
  470.      (OldPanelIndex<OutlookBar.Selected.Index) then
  471.   begin
  472.      InvalidButton:= OutlookBar.Selected.Button;
  473.      if (InvalidButton<>nil) and
  474.         OutlookBar.IsNonRectangularButton(InvalidButton) then
  475.      begin
  476.         ButtonRect:= InvalidButton.BoundsRect;
  477.         InvalidateRect(OutlookBar.Handle, @ButtonRect, True);
  478.      end
  479.   end;
  480. }
  481.   { 5/12/99 - RSW - Clear background for any background area of image shaped buttons,
  482.     and execute code even for steps=1 }
  483.   { Repaint current selection if its a non-rectangular button}
  484.   if (ASteps>=1) and (OldPanelIndex>=0) and (OutlookBar.Selected<>nil) then
  485.   begin
  486.      { This button needs to be repainted if its a shape button }
  487.      if OldPanelIndex<OutlookBar.Selected.index then
  488.      begin
  489.         { Repaint OldPanelIndex + 1 to Seleccted.Index }
  490.         for i:= OldPanelIndex+1 to OutlookBar.Selected.Index do
  491.         begin
  492.            InvalidButton:= TfcOutlookPage(Items[i]).Button;
  493.            if not OutlookBar.IsNonRectangularButton(InvalidButton) then continue;
  494.            ButtonRect:= InvalidButton.BoundsRect;
  495.            InvalidateRect(OutlookBar.Handle, @ButtonRect, True);
  496.         end
  497.      end
  498.      else begin
  499.         { Repaint SelectedIndex + 1 to OldPanelIndex }
  500.         for i:= OutlookBar.Selected.Index+1 to OldPanelIndex do
  501.         begin
  502.            InvalidButton:= TfcOutlookPage(Items[i]).Button;
  503.            if not OutlookBar.IsNonRectangularButton(InvalidButton) then continue;
  504.            ButtonRect:= InvalidButton.BoundsRect;
  505.            InvalidateRect(OutlookBar.Handle, @ButtonRect, True);
  506.         end
  507.      end
  508.   end
  509. end;
  510. function TfcOutlookPages.Add: TfcOutlookPage;
  511. begin
  512.   result := TfcOutlookPage(inherited Add);
  513.   if Count = 1 then result.GotSelected;
  514. end;
  515. function TfcOutlookPages.AddItem: TfcCollectionItem;
  516. begin
  517.   result := Add;
  518. end;
  519. constructor TfcCustomOutlookBar.Create(AOwner: TComponent);
  520. begin
  521.   inherited;
  522.   FOptions := [cboAutoCreateOutlookList];
  523.   FAnimation := TfcAnimation.Create;
  524.   FButtonSize := 20;
  525.   FShowButtons := True;
  526.   FChangeLink := TfcChangeLink.Create;
  527.   FChangeLink.OnChange := ImagerChange;
  528.   AutoBold := False;
  529.   BorderStyle := bsSingle;
  530.   ShowDownAsUp := False;
  531. end;
  532. destructor TfcCustomOutlookBar.Destroy;
  533. begin
  534.   FAnimation.Free;
  535.   FChangeLink.Free;
  536.   inherited;
  537. end;
  538. procedure TfcCustomOutlookBar.EnableAnimation;
  539. begin
  540.   inc(FAnimationLock);
  541. end;
  542. procedure TfcCustomOutlookBar.DisableAnimation;
  543. begin
  544.   dec(FAnimationLock);
  545. end;
  546. function TfcCustomOutlookBar.GetCollectionClass: TfcButtonGroupItemsClass;
  547. begin
  548.   result := TfcOutlookPages;
  549. end;
  550. function TfcCustomOutlookBar.ResizeToControl(Control: TControl; DoResize: Boolean): TSize;
  551. begin
  552.   result := fcSize(Width, Height);
  553. end;
  554. procedure TfcCustomOutlookBar.ButtonPressed;
  555. begin
  556.   EnableAnimation;
  557.   if FItems.ArrangingControls then
  558.   begin
  559.     if OldSelected <> nil then OldSelected.Button.Down := True;
  560.   end else inherited;
  561.   DisableAnimation;
  562. end;
  563. procedure TfcCustomOutlookBar.CreateWnd;
  564. begin
  565.   inherited;
  566. end;
  567. procedure TfcCustomOutlookBar.GetChildren(Proc: TGetChildProc; Root: TComponent);
  568. var i: Integer;
  569. begin
  570.   inherited;
  571.   for i := 0 to FItems.Count - 1 do
  572.     Proc(TfcOutlookPage(FItems[i]).Panel);
  573. end;
  574. procedure TfcCustomOutlookBar.ImagerChange(Sender: TObject);
  575. begin
  576.   invalidate;
  577. //  inherited;
  578. end;
  579. procedure TfcCustomOutlookBar.Loaded;
  580. var i, j, k: Integer;
  581. begin
  582.   for i := 0 to ControlCount - 1 do
  583.     if Controls[i] is TfcOutlookPanel then
  584.       for j := 0 to FItems.Count - 1 do
  585.         if TfcOutlookPage(FItems[j]).Panel = nil then
  586.           with TfcOutlookPage(FItems[j]) do
  587.         begin
  588.           Panel := Controls[i] as TfcOutlookPanel;
  589.           for k := 0 to Panel.ControlCount - 1 do
  590.             if Panel.Controls[k] is TfcOutlookList then
  591.             begin
  592.               FOutlookList := Panel.Controls[k] as TfcOutlookList;
  593.               Break;
  594.             end;
  595.           Break;
  596.         end;
  597.   inherited;
  598.   FItems.ArrangingControls := True;
  599.   for i := 0 to FItems.Count - 1 do OutlookItems[i].Panel.Visible := False;
  600.   FItems.ArrangingControls := False;
  601.   FItems.ArrangeControls;
  602. end;
  603. procedure TfcCustomOutlookBar.Notification(AComponent: TComponent; AOperation: TOperation);
  604. var i: Integer;
  605. begin
  606.   inherited;
  607.   if (AOperation = opRemove) and (AComponent = FImager) then
  608.   begin
  609.      FImager := nil;
  610.      if not (csDestroying in ComponentState) then Invalidate;
  611.   end
  612.   else if (AOperation = opRemove) and not (csDestroying in ComponentState) then
  613.     for i := 0 to FItems.Count - 1 do
  614.       if AComponent = OutlookItems[i].OutlookList then
  615.       begin
  616.         OutlookItems[i].FOutlookList := nil;
  617.         Break;
  618.       end;
  619. end;
  620. procedure TfcCustomOutlookBar.Paint;
  621. var i, j: Integer;
  622.     TmpRgn, ClipRgn: HRGN;
  623.     ir, r, r1: TRect;
  624.     curPanel: TfcOutlookPanel;
  625.     function HaveNonRectangularOutlookButton: boolean;
  626.     var i: integer;
  627.     begin
  628.        result:= False;
  629.        for i := 0 to OutlookItems.Count - 1 do
  630.        begin
  631.            if IsNonRectangularButton(OutlookItems[i].Button) then
  632.            begin
  633.               result:= True;
  634.               break;
  635.            end
  636.        end
  637.     end;
  638. begin
  639.   if (OutlookItems.Count = 0) and (Imager = nil) then
  640.   begin
  641.     inherited;
  642.     Exit;
  643.   end;
  644.   if (FImager <> nil) or
  645.      { 5/2/99 - RSW - Go into this path if contain non-rectangular outlook button
  646.        Can likely go into this path even in rectangular case, but this would
  647.        require more testing }
  648.       HaveNonRectangularOutlookButton then
  649.   begin
  650.     if not AnimatingControls then
  651.     begin
  652.       { Clip out outlookbuttons and visible panel's child controls from imager's area to paint }
  653.       ClipRgn := CreateRectRgn(0, 0, 0, 0);
  654.       for i := 0 to OutlookItems.Count - 1 do
  655.       begin
  656.         // 4/19/99 Changed to get button's region, instead of just its rectangle
  657.         with OutlookItems[i].Button do
  658.         begin
  659.           TmpRgn := TfcOutlookButton(OutlookItems[i].Button).CreateRegion(False, Down);
  660.           OffsetRgn(TmpRgn, Left, Top);
  661.         end;
  662.         CombineRgn(ClipRgn, ClipRgn, TmpRgn, RGN_OR);
  663.         DeleteObject(TmpRgn);
  664.         with OutlookItems[i], Panel do
  665.           if Visible then
  666.           begin
  667.              if FImager=nil then
  668.              begin
  669.                TmpRgn := CreateRectRgn(Panel.Left, Panel.Top, Panel.Left + Panel.Width, Panel.Top + Panel.Height);
  670.                CombineRgn(ClipRgn, ClipRgn, TmpRgn, RGN_OR); { Only paint button area }
  671.                DeleteObject(TmpRgn);
  672.              end;
  673.             fcGetChildRegions(Panel, False, ClipRgn, Point(Left, Top), RGN_OR);
  674.           end;
  675.       end;
  676.       TmpRgn := CreateRectRgn(0, 0, ClientWidth, ClientHeight);
  677.       CombineRgn(ClipRgn, TmpRgn, ClipRgn, RGN_DIFF);
  678.       DeleteObject(TmpRgn);
  679.       SelectClipRgn(Canvas.Handle, ClipRgn);
  680.       DeleteObject(ClipRgn);  //4/2/99 - Does not seem neccesary
  681.     end;
  682.     if (FImager <> nil) then
  683.     begin
  684.        if FImager.WorkBitmap.Empty then FImager.UpdateWorkBitmap;
  685.        if FImager.DrawStyle=dsTile then
  686.           FImager.WorkBitmap.TileDraw(Canvas, ClientRect)
  687.        else
  688.           Canvas.StretchDraw(ClientRect, FImager.WorkBitmap);
  689.     end
  690.     else begin
  691.        Canvas.Brush.Color:= Color;
  692.        Canvas.FillRect(ClientRect);
  693.     end;
  694.     SelectClipRgn(Canvas.Handle, 0);
  695.   end else if (csDesigning in ComponentState) then inherited;
  696.   if (csDesigning in ComponentState) or (csDestroying in ComponentState) or (FItems = nil) then Exit;
  697.   // Code in here to prevent the Child controls in the panel from going invisible
  698. //  exit;
  699.   for i := 0 to FItems.Count - 1 do
  700.     if TfcOutlookPage(FItems[i]).Panel.Visible then
  701.     begin
  702.       with TfcOutlookPage(FItems[i]).Panel do
  703.       begin
  704.         curPanel:= TfcOutlookPage(FItems[i]).Panel;
  705.         for j := 0 to ControlCount - 1 do if Controls[j] is TWinControl then
  706.         begin
  707.           r := Controls[j].BoundsRect;
  708.           offsetRect(r, left, top); { Adjust to outlookbar coordinates }
  709.           with self.Canvas.ClipRect do
  710.           begin
  711.             r1:= self.canvas.cliprect;
  712.             if IntersectRect(ir, r1, r) then {or
  713. //          if fcRectInRect(r, self.Canvas.ClipRect) then
  714. //            if PtInRect(r, TopLeft) or PtInRect(r, BottomRight) or
  715. //               PtInRect(r, Point(Right, Top)) or PtInRect(r, Point(Left, Bottom)) then}
  716.             begin
  717.               IntersectRect(r, self.Canvas.ClipRect, r);
  718.               offsetRect(r, -curPanel.left, -curPanel.top); { Adjust to outlookbar coordinates }
  719.               offsetRect(r, -Controls[j].BoundsRect.Left, -Controls[j].BoundsRect.top);
  720.               InvalidateRect((Controls[j] as TWinControl).Handle, @r, False);
  721.             end
  722.           end
  723.         end;
  724.       end;
  725.       Break;
  726.     end;
  727. end;
  728. function TfcCustomOutlookBar.InAnimation: Boolean;
  729. begin
  730.   result := not (FAnimationLock = 0);
  731. end;
  732. function TfcCustomOutlookBar.GetActivePage: TfcCustomBitBtn;
  733. begin
  734.   result := nil;
  735.   if Selected <> nil then result := Selected.Button;
  736. end;
  737. function TfcCustomOutlookBar.GetItems: TfcOutlookPages;
  738. begin
  739.   result := TfcOutlookPages(inherited ButtonItems);
  740. end;
  741. procedure TfcCustomOutlookBar.SetActivePage(Value: TfcCustomBitBtn);
  742. begin
  743.   Selected := FItems.FindButton(Value);
  744. end;
  745. procedure TfcCustomOutlookBar.SetAnimatingControls(Value: Boolean);
  746. var i: Integer;
  747. begin
  748.   FAnimatingControls := Value;
  749.   for i := 0 to OutlookItems.Count - 1 do
  750.     OutlookItems[i].Panel.Animating := Value;
  751. end;
  752. procedure TfcCustomOutlookBar.SetButtonSize(Value: Integer);
  753. begin
  754.   if FButtonSize <> Value then
  755.   begin
  756.     FButtonSize := Value;
  757.     FItems.ArrangeControls;
  758.   end;
  759. end;
  760. procedure TfcCustomOutlookBar.SetImager(Value: TfcCustomImager);
  761. begin
  762.   if FImager <> nil then FImager.UnRegisterChanges(FChangeLink);
  763.   if Value<>FImager then
  764.   begin
  765.      FImager := Value;
  766.      if Value <> nil then
  767.      begin
  768.        Value.FreeNotification(self);
  769.        Value.RegisterChanges(FChangeLink);
  770.        Value.Parent := self;
  771.        Value.Align := alNone;
  772. //       if Value.DrawStyle <> dsStretch then
  773.           Value.DrawStyle := dsTile;
  774.        Value.Left:= 0;
  775.        Value.Top:= 0;
  776.        Value.Width:= 25;
  777.        Value.Height:= 25;
  778.        Value.Transparent:= False; { 4/30/99 }
  779.        Value.Visible := False;
  780.      end;
  781.      Invalidate; { 4/20/99 RSW }
  782.   end
  783. end;
  784. procedure TfcCustomOutlookBar.SetItems(Value: TfcOutlookPages);
  785. begin
  786.   inherited ButtonItems := Value;
  787. end;
  788. procedure TfcCustomOutlookBar.SetName(const NewName: TComponentName);
  789. var i: Integer;
  790. begin
  791.   for i := 0 to FItems.Count - 1 do
  792.   begin
  793.     if Copy(OutlookItems[i].Panel.Name, 1, Length(Name)) = Name then
  794.       OutlookItems[i].Panel.Name := NewName + fcSubstring(OutlookItems[i].Panel.Name, Length(Name) + 1, 0);
  795.     if (cboAutoCreateOutlookList in Options) and
  796.        (OutlookItems[i].Panel.ControlCount > 0) and (OutlookItems[i].Panel.Controls[0] is TListView) and
  797.        (Copy(OutlookItems[i].Panel.Controls[0].Name, 1, Length(Name)) = Name) then
  798.       OutlookItems[i].Panel.Controls[0].Name := NewName + fcSubstring(OutlookItems[i].Panel.Controls[0].Name, Length(Name) + 1, 0);
  799.   end;
  800.   inherited;
  801. end;
  802. procedure TfcCustomOutlookBar.SetOptions(Value: TfcCustomOutlookBarOptions);
  803. var ChangedOptions: TfcCustomOutlookBarOptions;
  804. begin
  805.   if FOptions <> Value then
  806.   begin
  807.     ChangedOptions := (FOptions - Value) + (Value - FOptions);
  808.     FOptions := Value;
  809. {    if not (csLoading in ComponentState) and (cboTransparentPanels in ChangedOptions) then
  810.       for i := 0 to FItems.Count - 1 do OutlookItems[i].Panel.Transparent := cboTransparentPanels in FOptions;}
  811.   end;
  812. end;
  813. procedure TfcCustomOutlookBar.SetPanelAlignment(Value: TfcPanelAlignment);
  814. begin
  815.   if FPanelAlignment <> Value then
  816.   begin
  817.     FPanelAlignment := Value;
  818.     if not (csLoading in ComponentState) then FItems.ArrangeControls;
  819.   end;
  820. end;
  821. procedure TfcCustomOutlookBar.SetShowButtons(Value: Boolean);
  822. var i: Integer;
  823. begin
  824.   if FShowButtons <> Value then
  825.   begin
  826.     FShowButtons := Value;
  827.     if not (csLoading in ComponentState) then
  828.       for i := 0 to FItems.Count - 1 do with FItems[i].Button do
  829.     begin
  830.       Visible := Value;
  831.       if Value then BringToFront else SendToBack;
  832.     end;
  833.     if not (csLoading in ComponentState) then
  834.     begin
  835.       FItems.ArrangingControls := False;
  836.       FItems.ArrangeControls;
  837.     end;
  838.   end;
  839. end;
  840. procedure TfcCustomOutlookBar.CMControlListChange(var Message: TCMControlListChange);
  841. begin
  842.   inherited;
  843. end;
  844. procedure TfcCustomOutlookBar.CMControlChange(var Message: TCMControlChange);
  845. begin
  846.   inherited;
  847.   if Message.Control is TfcCustomImager then
  848.   begin
  849.     if Message.Inserting then
  850.     begin
  851.        if Imager<>FImager then { RSW }
  852.           Imager := Message.Control as TfcCustomImager;
  853.     end
  854.     else Imager := nil;
  855.   end;
  856. end;
  857. { 3/12/99 - RSW - Prevent flicker }
  858. procedure TfcCustomOutlookBar.WMEraseBkgnd(var Message: TWMEraseBkGnd);
  859. begin
  860.   Message.result := 1;
  861. end;
  862. procedure TfcCustomOutlookBar.WMPaint(var Message: TWMPaint);
  863. begin
  864.   inherited;
  865. end;
  866. procedure TfcCustomOutlookBar.CMFontChanged(var Message: TMessage);
  867. begin
  868.   inherited;
  869.   Invalidate;  { 4/27/99 }
  870.   Update;
  871. end;
  872. function TfcCustomOutlookBar.IsNonRectangularButton(Control: TControl): boolean;
  873. var button: TfcCustomImageBtn;
  874. begin
  875.    result:= False;
  876.    if (Control is TfcCustomImageBtn) then
  877.    begin
  878.       button:= TfcCustomImageBtn(control);
  879.       if ((Control is TfcCustomShapeBtn) and
  880.          ((Control as TfcCustomShapeBtn).Shape <> bsRect)) then result:= True
  881.       else if (not (Control is TfcCustomShapeBtn) and
  882.          (button.TransparentColor <> clNullColor)) then result:= True
  883.    end
  884. end;
  885. procedure TfcCustomOutlookBar.WndProc(var Message: TMessage);
  886. begin
  887.   inherited;
  888. end;
  889. initialization
  890.   RegisterClasses([TfcOutlookPanel]);
  891. end.