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

Delphi控件源码

开发平台:

Delphi

  1. unit fcTreeHeader;
  2. interface
  3. {$R-}
  4. {$include fcifdef.pas}
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   ComCtrls, db, extctrls;
  8. type
  9.   TfcTreeHeader = class;
  10.   TfcTreeHeaderControl = class;
  11.   TfcTreeHeaderOption = (thcoAllowColumnMove, thcoSortTreeOnClick, thcoRightBorder);
  12.   TfcTreeHeaderOptions = set of TfcTreeHeaderOption;
  13.   TfcTreeHeaderSection = class(TCollectionItem)
  14.   private
  15.     FFieldName: string;
  16.     FImageIndex: integer;
  17.     FImageAlignment : TAlignment;
  18.     FText: string;
  19.     FWidth: Integer;
  20.     FMinWidth: Integer;
  21.     FMaxWidth: Integer;
  22.     FAlignment: TAlignment;
  23.     FStyle: THeaderSectionStyle;
  24.     FAllowClick: Boolean;
  25.     function GetLeft: Integer;
  26.     function GetRight: Integer;
  27.     procedure SetAlignment(Value: TAlignment);
  28.     procedure SetMaxWidth(Value: Integer);
  29.     procedure SetMinWidth(Value: Integer);
  30.     procedure SetStyle(Value: THeaderSectionStyle);
  31.     procedure SetText(const Value: string);
  32.     procedure SetWidth(Value: Integer);
  33.     procedure SetImageIndex(Value: integer);
  34.     procedure SetImageAlignment(Value: TAlignment);
  35.   protected
  36.     function GetDisplayName: string; override;
  37.   public
  38.     constructor Create(Collection: TCollection); override;
  39.     procedure Assign(Source: TPersistent); override;
  40.     property Left: Integer read GetLeft;
  41.     property Right: Integer read GetRight;
  42.     function PtInSection(pt: TPoint): boolean;
  43.   published
  44.     property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
  45.     property AllowClick: Boolean read FAllowClick write FAllowClick default True;
  46.     property MaxWidth: Integer read FMaxWidth write SetMaxWidth default 10000;
  47.     property MinWidth: Integer read FMinWidth write SetMinWidth default 0;
  48.     property Style: THeaderSectionStyle read FStyle write SetStyle default hsText;
  49.     property Text: string read FText write SetText;
  50.     property Width: Integer read FWidth write SetWidth;
  51.     property FieldName: string read FFieldName write FFieldName;
  52.     property ImageIndex: integer read FImageIndex write SetImageIndex;
  53.     property ImageAlignment: TAlignment read FImageAlignment write SetImageAlignment default taLeftJustify;
  54.   end;
  55.   TfcTreeHeaderSections = class(TCollection)
  56.   private
  57.     function GetItem(Index: Integer): TfcTreeHeaderSection;
  58.     procedure SetItem(Index: Integer; Value: TfcTreeHeaderSection);
  59.   protected
  60.     function GetOwner: TPersistent; override;
  61.     procedure Update(Item: TCollectionItem); override;
  62.   public
  63.     HeaderControl: TfcTreeHeaderControl;
  64.     constructor Create(HeaderControl: TfcTreeHeaderControl);
  65.     function Add: TfcTreeHeaderSection;
  66.     property Items[Index: Integer]: TfcTreeHeaderSection read GetItem write SetItem; default;
  67.   end;
  68.   TfcHeaderDrawSectionEvent = procedure(HeaderControl: TfcTreeHeader;
  69.     Section: TfcTreeHeaderSection; const Rect: TRect; Pressed: Boolean) of object;
  70.   TfcHeaderSectionNotifyEvent = procedure(HeaderControl: TfcTreeHeader;
  71.     Section: TfcTreeHeaderSection) of object;
  72.   TfcHeaderSectionDefaultEvent = procedure(HeaderControl: TfcTreeHeader;
  73.     Section: TfcTreeHeaderSection; var doDefault: boolean) of object;
  74.   TfcHeaderSectionTrackEvent = procedure(HeaderControl: TfcTreeHeader;
  75.     Section: TfcTreeHeaderSection; Width: Integer;
  76.     State: TSectionTrackState) of object;
  77.   TfcSectionDragEvent = procedure (Sender: TObject; FromSection, ToSection: TfcTreeHeaderSection) of object;
  78.   TfcHeaderSectionMoveEvent = procedure(HeaderControl: TfcTreeHeader;
  79.     Section: TfcTreeHeaderSection; DragFrom, DragTo: integer;
  80.     var AllowMove: boolean) of object;
  81.   TfcTreeHeaderControl = class(TWinControl)
  82.   private
  83.     FSections: TfcTreeHeaderSections;
  84.     FSectionDragged: Boolean;
  85.     FCanvas: TCanvas;
  86.     FHotTrack: Boolean;
  87.     FImageList: TImageList;
  88.     FOptions: TfcTreeHeaderOptions;
  89.     FTree: TWinControl; //fcDBCustomTreeView;
  90.     FHeader: TfcTreeHeader;
  91.     function  DoSectionDrag(FromSection, ToSection: TfcTreeHeaderSection): Boolean;
  92.     procedure SetHotTrack(Value: Boolean);
  93.     procedure SetSections(Value: TfcTreeHeaderSections);
  94.     procedure UpdateItem(Message, Index: Integer);
  95.     procedure UpdateSection(Index: Integer);
  96.     procedure UpdateSections;
  97.     procedure SetOptions(val: TfcTreeHeaderOptions);
  98.     procedure SetImageList(val: TImageList);
  99.     procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
  100.     procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
  101.     procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
  102.     procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;
  103.     procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  104.     procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
  105.     procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
  106.   protected
  107.     procedure RearrangeTreeColumns; virtual;
  108.     procedure CreateParams(var Params: TCreateParams); override;
  109.     procedure CreateWnd; override;
  110.     procedure Notification(AComponent: TComponent;
  111.       Operation: TOperation); override;
  112.     procedure WndProc(var Message: TMessage); override;
  113.   public
  114.     DesignerForm: TCustomForm;
  115.     HotTrackSection: integer;
  116.     constructor Create(AOwner: TComponent); override;
  117.     destructor Destroy; override;
  118.     property Canvas: TCanvas read FCanvas;
  119.     property Tree: TWinControl read FTree write FTree;
  120.     property Header: TfcTreeHeader read FHeader write FHeader;
  121.     property HotTrack: Boolean read FHotTrack write SetHotTrack default False;
  122.     property Images: TImageList read FImageList write SetImageList;
  123.     property Options: TfcTreeHeaderOptions read FOptions write SetOptions
  124.        default [thcoAllowColumnMove, thcoSortTreeOnClick, thcoRightBorder];
  125.     property Sections: TfcTreeHeaderSections read FSections write SetSections;
  126.   end;
  127.   TfcTreeHeader = class(TCustomPanel)
  128.   private
  129.     FOnDrawSection: TfcHeaderDrawSectionEvent;
  130.     FOnResize: TNotifyEvent;
  131.     FOnSectionMove: TfcHeaderSectionMoveEvent;
  132.     FOnSectionClick: TfcHeaderSectionNotifyEvent;
  133.     FOnSectionResize: TfcHeaderSectionNotifyEvent;
  134.     FOnSectionTrack: TfcHeaderSectionTrackEvent;
  135.     FOnSectionDrag: TfcSectionDragEvent;
  136.     FDisableThemes: boolean;
  137.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  138.     procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
  139.     procedure SetSections(Value: TfcTreeHeaderSections);
  140.     function GetSections: TfcTreeHeaderSections;
  141.     function GetHotTrack: boolean;
  142.     procedure SetHotTrack(Value: Boolean);
  143.     function GetImageList: TImageList;
  144.     procedure SetImageList(Value: TImageList);
  145.     procedure SetOptions(val: TfcTreeHeaderOptions);
  146.     function GetOptions: TfcTreeHeaderOptions;
  147.     function GetCanvas: TCanvas;
  148.     function GetTree: TWinControl;
  149.     Function GetMouseDown: TMouseEvent;
  150.     procedure SetMouseDown(Value: TMouseEvent);
  151.     Function GetMouseUp: TMouseEvent;
  152.     procedure SetMouseUp(Value: TMouseEvent);
  153.     Function GetMouseMove: TMouseMoveEvent;
  154.     procedure SetMouseMove(Value: TMouseMoveEvent);
  155.   protected
  156.     procedure DrawSection(Section: TfcTreeHeaderSection; const Rect: TRect;
  157.        Pressed: Boolean); dynamic;
  158.     procedure SectionMove(Section: TfcTreeHeaderSection;
  159.               DragFrom, DragTo: integer; var AllowMove: boolean); dynamic;
  160.     procedure SectionClick(Section: TfcTreeHeaderSection); dynamic;
  161.     procedure SectionResize(Section: TfcTreeHeaderSection); dynamic;
  162.     procedure SectionTrack(Section: TfcTreeHeaderSection; Width: Integer;
  163.       State: TSectionTrackState); dynamic;
  164.     procedure SectionDrag(FromSection, ToSection: TfcTreeHeaderSection); dynamic;
  165.   public
  166.     HeaderControl: TfcTreeHeaderControl;
  167.     constructor Create(AOwner: TComponent); override;
  168.     destructor Destroy; override;
  169.     procedure CreateWnd; override;
  170.     property Canvas: TCanvas read GetCanvas;
  171.     property Tree: TWinControl read GetTree;
  172.   published
  173.     property DragCursor;
  174.     property DragMode;
  175.     property Enabled;
  176.     property Font;
  177.     property HotTrack: Boolean read GetHotTrack write SetHotTrack default False;
  178.     property Sections: TfcTreeHeaderSections read GetSections write SetSections;
  179.     property ShowHint;
  180.     property ParentFont;
  181.     property ParentShowHint;
  182.     property PopupMenu;
  183.     property Visible;
  184.     property Images: TImageList read GetImageList write SetImageList;
  185.     property OnSectionDrag: TfcSectionDragEvent read FOnSectionDrag
  186.       write FOnSectionDrag;
  187.     property OnDragDrop;
  188.     property OnDragOver;
  189.     property OnEndDrag;
  190.     property OnMouseDown: TMouseEvent read GetMouseDown write SetMouseDown;
  191.     property OnMouseMove: TMouseMoveEvent read GetMouseMove write SetMouseMove;
  192.     property OnMouseUp: TMouseEvent read GetMouseUp write SetMouseUp;
  193.     property OnDrawSection: TfcHeaderDrawSectionEvent read FOnDrawSection write FOnDrawSection;
  194.     property OnResize: TNotifyEvent read FOnResize write FOnResize;
  195.     property OnSectionMove: TfcHeaderSectionMoveEvent read FOnSectionMove write FOnSectionMove;
  196.     property OnSectionClick: TfcHeaderSectionNotifyEvent read FOnSectionClick write FOnSectionClick;
  197.     property OnSectionResize: TfcHeaderSectionNotifyEvent read FOnSectionResize write FOnSectionResize;
  198.     property OnSectionTrack: TfcHeaderSectionTrackEvent read FOnSectionTrack write FOnSectionTrack;
  199.     property OnStartDrag;
  200.     property Options: TfcTreeHeaderOptions read GetOptions write SetOptions
  201.        default [thcoAllowColumnMove, thcoSortTreeOnClick, thcoRightBorder];
  202.     property DisableThemes : boolean read FDisableThemes write FDisableThemes default False;
  203.   end;
  204. implementation
  205. uses commctrl, typinfo, fccommon,
  206.   {$ifdef fcDelphi7Up}
  207.   themes,
  208.   {$endif}
  209.   {$ifdef ThemeManager}
  210.   thememgr, themesrv, uxtheme,
  211.   {$endif}
  212.   fcdbtreeview;
  213.   
  214. type
  215.   TfcWriteTextOption = (wtoAmpersandToUnderline, wtoEllipsis, wtoWordWrap, wtoMergeCanvas);
  216.   TfcWriteTextOptions = Set of TfcWriteTextOption;
  217. {3/31/98 - Determine if this is a single line edit control based on passed in rectangle}
  218. Function wwIsSingleLineEdit(AHandle:Integer; Rect: TRect; Flags:Integer): boolean;
  219. var OrigEditHeight,SingleLineEditHeight:Integer;
  220.     S:String;
  221. begin
  222.   Flags := Flags or DT_CALCRECT;
  223.   OrigEditHeight := Rect.Bottom-Rect.Top;
  224.   S:=' ';
  225.   SingleLineEditHeight := DrawText(AHandle,PChar(S),strlen(PChar(S)),Rect,Flags)+
  226.     3 + GetSystemMetrics(SM_CYBORDER) * 2;
  227.   result := OrigEditHeight <= SingleLineEditHeight;
  228. end;
  229. Procedure WriteTextLines(ACanvas: TCanvas;
  230.     const ARect: TRect; DX, DY: Integer; S: PChar; Alignment: TAlignment;
  231.     WriteOptions: TfcWriteTextOptions);
  232. const
  233.   AlignFlags : array [TAlignment] of Integer =
  234.     ( DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS,
  235.       DT_RIGHT or DT_WORDBREAK or DT_EXPANDTABS,
  236.       DT_CENTER or DT_WORDBREAK or DT_EXPANDTABS);
  237. var
  238.   R: TRect;
  239.   Flags: integer;
  240.   ADrawCanvas: TCanvas;
  241. begin
  242.     ADrawCanvas:= ACanvas;
  243.     with ARect do { Use offscreen bitmap to eliminate flicker and }
  244.     begin                     { brush origin tics in painting / scrolling.    }
  245.       if Alignment=taRightJustify then
  246.          R := Rect(1, DY, Right - Left - 5, Bottom - Top - 1)
  247.       else if Alignment=taLeftJustify then
  248.          R := Rect(DX, DY, Right - Left, Bottom - Top - 1)
  249.       else
  250.          R := Rect(0, DY, Right - Left, Bottom - Top - 1);
  251.       R.Left:= R.Left + ARect.Left;
  252.       R.Right:= R.Right + ARect.Left;
  253. //      B := Rect(0, 0, Right - Left, Bottom - Top);
  254.     end;
  255.     with ADrawCanvas do
  256.     begin
  257.       Font := ACanvas.Font;
  258.       Font.Color := ACanvas.Font.Color;
  259.       Brush := ACanvas.Brush;
  260.       Brush.Style := bsSolid;
  261.       {$ifdef fcUseThemeManager}
  262.       if not ThemeServices.ThemesEnabled then
  263.       {$endif}
  264.          FillRect(ARect);
  265.       SetBkMode(Handle, TRANSPARENT);
  266.       Flags:= AlignFlags[Alignment];
  267.       if not (wtoAmpersandToUnderline in WriteOptions) then
  268.          Flags:= Flags or DT_NOPREFIX;
  269.       {3/31/98 - Check to see if this is a single line edit control to
  270.        determine if we should or should not have word breaks}
  271.       if wwIsSingleLineEdit(Handle,R,Flags) or (wtoEllipsis in WriteOptions) then
  272.          Flags := Flags and not DT_WORDBREAK;
  273.       if wtoEllipsis in WriteOptions then
  274.          Flags:= Flags or DT_END_ELLIPSIS;  { If text does not fit then put ellipsis at end }
  275.       DrawText(Handle, S, StrLen(S), R, Flags);
  276.     end;
  277. end;
  278. constructor TfcTreeHeaderSection.Create(Collection: TCollection);
  279. begin
  280.   inherited Create(Collection);
  281.   FWidth := 50;
  282.   FMaxWidth := 10000;
  283.   FAllowClick := True;
  284.   FImageIndex:= -1;
  285.   FImageAlignment:= taLeftJustify;
  286. end;
  287. procedure TfcTreeHeaderSection.Assign(Source: TPersistent);
  288. begin
  289.   if Source is TfcTreeHeaderSection then
  290.   begin
  291.     Text := TfcTreeHeaderSection(Source).Text;
  292.     Width := TfcTreeHeaderSection(Source).Width;
  293.     MinWidth := TfcTreeHeaderSection(Source).MinWidth;
  294.     MaxWidth := TfcTreeHeaderSection(Source).MaxWidth;
  295.     Alignment := TfcTreeHeaderSection(Source).Alignment;
  296.     Style := TfcTreeHeaderSection(Source).Style;
  297.     AllowClick := TfcTreeHeaderSection(Source).AllowClick;
  298.     FieldName:= TfcTreeHeaderSection(Source).FieldName;
  299.     Exit;
  300.   end;
  301.   inherited Assign(Source);
  302. end;
  303. function TfcTreeHeaderSection.GetDisplayName: string;
  304. var TempText: string;
  305. begin
  306.   if Text = '' then TempText:= inherited GetDisplayName
  307.   else TempText:= text;
  308.   Result := inttostr(Index) + ' - ' + TempText;
  309. end;
  310. function TfcTreeHeaderSection.GetLeft: Integer;
  311. var
  312.   I: Integer;
  313. begin
  314.   Result := 0;
  315.   for I := 0 to Index - 1 do
  316.     Inc(Result, TfcTreeHeaderSections(Collection)[I].Width);
  317. end;
  318. function TfcTreeHeaderSection.PtInSection(pt: TPoint): boolean;
  319. var
  320.   I: Integer;
  321.   StartX, EndX: integer;
  322. begin
  323.   StartX := 0;
  324.   for I := 0 to Index - 1 do
  325.     Inc(StartX, TfcTreeHeaderSections(Collection)[I].Width);
  326.   EndX:= StartX + TfcTreeHeaderSections(Collection)[Index].Width;
  327.   result:= (pt.x>StartX) and (pt.x<EndX);
  328. end;
  329. function TfcTreeHeaderSection.GetRight: Integer;
  330. begin
  331.   Result := Left + Width;
  332. end;
  333. procedure TfcTreeHeaderSection.SetAlignment(Value: TAlignment);
  334. begin
  335.   if FAlignment <> Value then
  336.   begin
  337.     FAlignment := Value;
  338.     Changed(False);
  339.   end;
  340. end;
  341. procedure TfcTreeHeaderSection.SetMaxWidth(Value: Integer);
  342. begin
  343.   if Value < FMinWidth then Value := FMinWidth;
  344.   if Value > 10000 then Value := 10000;
  345.   FMaxWidth := Value;
  346.   SetWidth(FWidth);
  347. end;
  348. procedure TfcTreeHeaderSection.SetMinWidth(Value: Integer);
  349. begin
  350.   if Value < 0 then Value := 0;
  351.   if Value > FMaxWidth then Value := FMaxWidth;
  352.   FMinWidth := Value;
  353.   SetWidth(FWidth);
  354. end;
  355. procedure TfcTreeHeaderSection.SetStyle(Value: THeaderSectionStyle);
  356. begin
  357.   if FStyle <> Value then
  358.   begin
  359.     FStyle := Value;
  360.     Changed(False);
  361.   end;
  362. end;
  363. procedure TfcTreeHeaderSection.SetText(const Value: string);
  364. begin
  365.   if FText <> Value then
  366.   begin
  367.     FText := Value;
  368.     Changed(False);
  369.   end;
  370. end;
  371. procedure TfcTreeHeaderSection.SetImageIndex(Value: integer);
  372. begin
  373.    if FImageIndex<>Value then
  374.    begin
  375.       FImageIndex:= Value;
  376.       Changed(False);
  377.    end
  378. end;
  379. procedure TfcTreeHeaderSection.SetImageAlignment(Value: TAlignment);
  380. begin
  381.    if FImageAlignment<>Value then
  382.    begin
  383.       FImageAlignment:= Value;
  384.       Changed(False);
  385.    end
  386. end;
  387. procedure TfcTreeHeaderSection.SetWidth(Value: Integer);
  388. begin
  389.   if Value < FMinWidth then Value := FMinWidth;
  390.   if Value > FMaxWidth then Value := FMaxWidth;
  391.   if FWidth <> Value then
  392.   begin
  393.     FWidth := Value;
  394.     Changed(Index < Collection.Count - 1);
  395.   end;
  396. end;
  397. constructor TfcTreeHeaderSections.Create(HeaderControl: TfcTreeHeaderControl);
  398. begin
  399.   inherited Create(TfcTreeHeaderSection);
  400.   self.HeaderControl := HeaderControl;
  401. end;
  402. function TfcTreeHeaderSections.Add: TfcTreeHeaderSection;
  403. begin
  404.   Result := TfcTreeHeaderSection(inherited Add);
  405. end;
  406. function TfcTreeHeaderSections.GetItem(Index: Integer): TfcTreeHeaderSection;
  407. begin
  408.   Result := TfcTreeHeaderSection(inherited GetItem(Index));
  409. end;
  410. function TfcTreeHeaderSections.GetOwner: TPersistent;
  411. begin
  412.   Result := HeaderControl;
  413. end;
  414. procedure TfcTreeHeaderSections.SetItem(Index: Integer; Value: TfcTreeHeaderSection);
  415. begin
  416.   inherited SetItem(Index, Value);
  417. end;
  418. procedure TfcTreeHeaderSections.Update(Item: TCollectionItem);
  419. begin
  420.   if Item <> nil then
  421.     HeaderControl.UpdateSection(Item.Index) else
  422.     HeaderControl.UpdateSections;
  423. end;
  424. procedure TfcTreeHeaderControl.Notification(AComponent: TComponent;
  425.   Operation: TOperation);
  426. begin
  427.   inherited Notification(AComponent, Operation);
  428.   if (Operation = opRemove) then
  429.   begin
  430.      if AComponent = Tree then Tree:= nil;
  431.      if AComponent = FImageList then FImageList:= nil;
  432.   end
  433. end;
  434. constructor TfcTreeHeaderControl.Create(AOwner: TComponent);
  435. begin
  436.   inherited Create(AOwner);
  437.   ControlStyle := [];
  438.   Align := alTop;
  439.   Align := alNone;
  440.   Height := 17;
  441.   FSections := TfcTreeHeaderSections.Create(Self);
  442.   FCanvas := TControlCanvas.Create;
  443.   TControlCanvas(FCanvas).Control := Self;
  444.   FOptions:= [thcoAllowColumnMove, thcoSortTreeOnClick, thcoRightBorder];
  445.   HotTrackSection:= -1;
  446. end;
  447. destructor TfcTreeHeaderControl.Destroy;
  448. begin
  449.   FCanvas.Free;
  450.   FSections.Free;
  451.   DesignerForm.Free;
  452.   inherited Destroy;
  453. end;
  454. procedure TfcTreeHeaderControl.CreateParams(var Params: TCreateParams);
  455. const HDS_DRAGDROP = $0040; {W2W}
  456. begin
  457.   InitCommonControl(ICC_LISTVIEW_CLASSES);
  458.   inherited CreateParams(Params);
  459.   CreateSubClass(Params, 'SysHeader32');
  460.   with Params do
  461.   begin
  462.     Style := Style or HDS_BUTTONS;
  463.     if FHotTrack then Style := Style or HDS_HOTTRACK;
  464.     WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
  465.   end;
  466.   if thcoAllowColumnMove in Options then
  467.      Params.Style := Params.Style or HDS_DRAGDROP; { W2W}
  468. end;
  469. procedure TfcTreeHeaderControl.CreateWnd;
  470. begin
  471.   inherited CreateWnd;
  472.   UpdateSections;
  473. end;
  474. procedure TfcTreeHeader.DrawSection(Section: TfcTreeHeaderSection;
  475.   const Rect: TRect; Pressed: Boolean);
  476. begin
  477.   if Assigned(FOnDrawSection) then
  478.     FOnDrawSection(self, Section, Rect, Pressed) else
  479.     HeaderControl.FCanvas.FillRect(Rect);
  480. end;
  481. procedure TfcTreeHeader.SectionMove(Section: TfcTreeHeaderSection;
  482.               DragFrom, DragTo: integer; var AllowMove: boolean);
  483. begin
  484.   if Assigned(FOnSectionMove) then
  485.      FOnSectionMove(Self, Section, DragFrom, DragTo, AllowMove);
  486. end;
  487. procedure TfcTreeHeader.SectionClick(Section: TfcTreeHeaderSection);
  488. begin
  489.   if Assigned(FOnSectionClick) then FOnSectionClick(Self, Section);
  490. end;
  491. procedure TfcTreeHeader.SectionResize(Section: TfcTreeHeaderSection);
  492. begin
  493.   if Assigned(FOnSectionResize) then FOnSectionResize(Self, Section);
  494.   if HeaderControl.Tree<>Nil then
  495.   begin
  496.      TfcDBCustomTreeView(HeaderControl.Tree).LayoutChanged;  // Horz Scrollbar needs to be adjusted
  497.   end;
  498. end;
  499. procedure TfcTreeHeader.SectionTrack(Section: TfcTreeHeaderSection;
  500.   Width: Integer; State: TSectionTrackState);
  501. begin
  502.   if Assigned(FOnSectionTrack) then FOnSectionTrack(Self, Section, Width, State);
  503. end;
  504. procedure TfcTreeHeaderControl.SetHotTrack(Value: Boolean);
  505. begin
  506.   if FHotTrack <> Value then
  507.   begin
  508.     FHotTrack := Value;
  509.     RecreateWnd;
  510.   end;
  511. end;
  512. procedure TfcTreeHeaderControl.SetSections(Value: TfcTreeHeaderSections);
  513. begin
  514.   FSections.Assign(Value);
  515. end;
  516. procedure TfcTreeHeaderControl.UpdateItem(Message, Index: Integer);
  517. var
  518.   Item: THDItem;
  519. begin
  520.   with Sections[Index] do
  521.   begin
  522.     FillChar(Item, SizeOf(Item), 0);
  523.     Item.mask := HDI_WIDTH or HDI_TEXT or HDI_FORMAT;
  524.     Item.cxy := Width;
  525.     Item.pszText := PChar(Text);
  526.     Item.cchTextMax := Length(Text);
  527.     case Alignment of
  528.       taLeftJustify: Item.fmt := HDF_LEFT;
  529.       taRightJustify: Item.fmt := HDF_RIGHT;
  530.     else
  531.       Item.fmt := HDF_CENTER;
  532.     end;
  533.     if True or (Style = hsOwnerDraw) then
  534.       Item.fmt := Item.fmt or HDF_OWNERDRAW else
  535.       Item.fmt := Item.fmt or HDF_STRING;
  536.     SendMessage(Handle, Message, Index, Integer(@Item));
  537.   end;
  538. end;
  539. procedure TfcTreeHeaderControl.UpdateSection(Index: Integer);
  540. begin
  541.   if HandleAllocated then UpdateItem(HDM_SETITEM, Index);
  542. end;
  543. procedure TfcTreeHeaderControl.UpdateSections;
  544. var
  545.   I: Integer;
  546. begin
  547.   if HandleAllocated then
  548.   begin
  549.     for I := 0 to SendMessage(Handle, HDM_GETITEMCOUNT, 0, 0) - 1 do
  550.       SendMessage(Handle, HDM_DELETEITEM, 0, 0);
  551.     for I := 0 to Sections.Count - 1 do UpdateItem(HDM_INSERTITEM, I);
  552.   end;
  553. end;
  554. procedure TfcTreeHeaderControl.CNDrawItem(var Message: TWMDrawItem);
  555. var
  556.   SaveIndex: Integer;
  557.   pressed: boolean;
  558.   offset: integer;
  559.   Section: TfcTreeHeaderSection;
  560.   tempRect: TRect;
  561.   TopPosition: integer;
  562.   RequiredSpace: integer;
  563.   TextRect, ImageRect: TRect;
  564.   ImageListWidth: Integer;
  565.   pt: TPoint;
  566.   {$ifdef fcUseThemeManager}
  567.   Details: TThemedElementDetails;
  568.   {$endif}
  569. begin
  570.   with Message.DrawItemStruct^ do
  571.   begin
  572.     SaveIndex := SaveDC(hDC);
  573.     FCanvas.Handle := hDC;
  574.     FCanvas.Font := Font;
  575.     FCanvas.Brush.Color := clBtnFace;
  576.     FCanvas.Brush.Style := bsSolid;
  577.     GetCursorPos(pt);
  578.     pt:=  ScreenToClient(pt);
  579.     pressed:= itemState and ODS_SELECTED <> 0;
  580.     if fcUseThemes(self) then //ThemeServices.ThemesEnabled then
  581.     begin
  582.        {$ifdef fcUseThemeManager}
  583.        if (HotTrackSection>=0) and PtInRect(rcItem, pt) then
  584.        begin
  585.          if pressed then
  586.             Details := ThemeServices.GetElementDetails(thHeaderItemPressed)
  587.          else
  588.             Details := ThemeServices.GetElementDetails(thHeaderItemHot)
  589.        end
  590.        else
  591.          Details := ThemeServices.GetElementDetails(thHeaderItemNormal);
  592.        ThemeServices.DrawElement(Canvas.Handle, Details, rcItem);
  593.        {$endif}
  594. //       exit;
  595.     end;
  596.     if HotTrack and (HotTrackSection>=0) then begin
  597.        if (HotTrackSection>=0) and PtInRect(rcItem, pt) then
  598.        begin
  599.           FCanvas.Font.Color:= clBlue;
  600.        end;
  601.     end;
  602.     if Assigned(Header.FOnDrawSection) then
  603.        try
  604.           Header.DrawSection(Sections[itemID], rcItem,
  605.              itemState and ODS_SELECTED <> 0);
  606.        finally
  607.        end;
  608.     begin
  609.        Section:= Sections[itemID];
  610.        if pressed then offset:= 1 else offset:= 0;
  611.        tempRect:= rcItem;
  612.        if Section.ImageIndex<0 then
  613.          ImageListWidth:= 0
  614.        else if Images=nil then ImageListWidth:=0
  615.        else ImageListWidth:= Images.Width+1;
  616.        RequiredSpace:= Canvas.TextWidth(Section.Text) + ImageListWidth;
  617.        TextRect:= tempRect;
  618.        ImageRect:= TempRect;
  619.        case Section.Alignment of
  620.           taLeftJustify:
  621.              if Section.ImageAlignment = taLeftJustify then
  622.              begin
  623.                 TextRect.Left:= TempRect.Left + offset + ImageListWidth + 4;
  624.                 TextRect.Right:= TextRect.Left + Canvas.TextWidth(Section.Text) + 2;
  625.                 ImageRect.Left:= TempRect.Left + 4 + offset;
  626.                 ImageRect.Right:= ImageRect.Left + ImageListWidth;
  627.              end
  628.              else begin
  629.                 TextRect.Left:= TempRect.Left+offset + 4;
  630.                 TextRect.Right:= TextRect.Left + Canvas.TextWidth(Section.Text) + 2;
  631.                 ImageRect.Left:= TextRect.Right + 2;
  632.                 ImageRect.Right:= ImageRect.Left + ImageListWidth;
  633.              end;
  634.           taRightJustify:
  635.              if Section.ImageAlignment = taLeftJustify then
  636.              begin
  637.                 TextRect.Right:= TextRect.Right - 4;
  638.                 TextRect.Left:= TextRect.Right+offset-2-Canvas.TextWidth(Section.Text);
  639.                 ImageRect.Right:= TextRect.Left - 2;
  640.                 ImageRect.Left:= ImageRect.Right - ImageListWidth;
  641.              end
  642.              else begin
  643.                 TextRect.Right:= TextRect.Right - ImageListWidth - 4;
  644.                 TextRect.Left:= TextRect.Right+offset-2-Canvas.TextWidth(Section.Text);
  645.                 ImageRect.Right:= ImageRect.Right;
  646.                 ImageRect.Left:= ImageRect.Right - ImageListWidth - 2 + offset;
  647.              end;
  648.           taCenter:
  649.              if Section.ImageAlignment = taLeftJustify then
  650.              begin
  651.                 ImageRect.Left:= TextRect.Left + offset + ((TempRect.Right-TempRect.Left) - RequiredSpace) div 2;
  652.                 ImageRect.Right:= ImageRect.Left + ImageListWidth;
  653.                 TextRect.Left:= ImageRect.Right + 1;
  654.                 TextRect.Right:= TextRect.Left + Canvas.TextWidth(Section.Text) + 2;
  655.              end
  656.              else begin
  657.                 TextRect.Left:= TextRect.Left + offset + ((TempRect.Right-TempRect.Left) - RequiredSpace) div 2;
  658.                 TextRect.Right:= TextRect.Left + Canvas.TextWidth(Section.Text) + 2;
  659.                 ImageRect.Left:= TextRect.Right + 2;
  660.                 ImageRect.Right:= ImageRect.Left + ImageListWidth;
  661.              end;
  662.        end;
  663.        if (Images<>Nil) and (Section.ImageIndex>=0) then
  664.        begin
  665.           TopPosition:= rcItem.Top + offset + (rcItem.Bottom - rcItem.Top - Images.Height) div 2;
  666.           Images.Draw(Canvas, ImageRect.Left, TopPosition, Section.ImageIndex);
  667.        end;
  668.        WriteTextLines(Canvas, TextRect, 0, 2+offset, PChar(Section.Text),
  669.                 taLeftJustify,
  670.                  [wtoAmpersandToUnderline, wtoEllipsis]);
  671. {      if ThemeServices.ThemesEnabled and False then
  672.        begin
  673.          Details := ThemeServices.GetElementDetails(ttbSeparatorNormal);
  674.          TempRect:= rcItem;
  675.          TempRect.Left:= TempRect.Left - 2;
  676.          ThemeServices.DrawElement(Canvas.Handle, Details, TempRect);
  677.        end;
  678. }
  679.     end;
  680.     FCanvas.Handle := 0;
  681.     RestoreDC(hDC, SaveIndex);
  682.   end;
  683.   Message.Result := 1;
  684. end;
  685. procedure TfcTreeHeaderControl.RearrangeTreeColumns;
  686. var s:string;
  687.     i:integer;
  688.     OldDisplayFieldCount: integer;
  689.     fldName: string;
  690. begin
  691.   s:='';
  692.   for i:=0 to Sections.count-1 do begin
  693.      fldName:= Sections[i].FieldName;
  694.      if fldName = '' then
  695.        fldName:= Sections[i].Text;
  696.      s:=s+'"'+Sections[i].FieldName+'"';
  697.      if I<> Sections.Count-1 then
  698.         s:=s+'#9';
  699.   end;
  700.   OldDisplayFieldCount:= TfcDBTreeView(Tree).displayfields.count;
  701.   TfcDBTreeView(Tree).DisplayFields.Clear;
  702.   for i:= 0 to OldDisplayFieldCount-1 do
  703.      TfcDBTreeView(Tree).displayfields.Add(s);
  704.   Tree.invalidate;
  705. end;
  706. procedure TfcTreeHeaderControl.CNNotify(var Message: TWMNotify);
  707. const HDN_BEGINDRAG = HDN_FIRST - 10;
  708.       HDN_BEGINTRACK = HDN_FIRST - 6;
  709.       HDN_ENDDRAG = HDN_FIRST - 11;
  710.       HDM_ORDERTOINDEX = HDM_FIRST + 15;
  711.       HDM_GETORDERARRAY = HDM_FIRST + 17;
  712.       HDI_ORDER = $0080;
  713. type
  714.   TfcHDItem = packed record
  715.     Mask: Cardinal;
  716.     cxy: Integer;
  717.     pszText: PAnsiChar;
  718.     hbm: HBITMAP;
  719.     cchTextMax: Integer;
  720.     fmt: Integer;
  721.     lParam: LPARAM;
  722.     iImage: integer;
  723.     iOrder: integer;
  724.   end;
  725.   PwwHDItem = ^TfcHDItem;
  726. var
  727.   Section: TfcTreeHeaderSection;
  728.   TrackState: TSectionTrackState;
  729. //  OrderArray: array[0..40] of integer;
  730.   dragFrom, dragto: integer;
  731.   AllowMove: boolean;
  732.   MsgPos: Longint;
  733.   hdhti: THDHitTestInfo;
  734.   hdi: THDItem;
  735. //  FFromIndex, FToIndex: integer;
  736. begin
  737.   with PHDNotify(Message.NMHdr)^ do
  738.     case Hdr.code of
  739.       HDN_BEGINDRAG: begin
  740.          end;
  741.       HDN_ENDDRAG: begin
  742.           if (PwwHDItem(PItem)^.mask and HDI_ORDER)<>0 then  {Checks if ComCtrl supports this}
  743.           begin
  744.              Message.Result := 0;
  745.              MsgPos := GetMessagePos;
  746.              hdhti.Point.X := MsgPos and $FFFF;
  747.              Windows.ScreenToClient(Handle, hdhti.Point);
  748.              hdhti.Point.Y := ClientHeight div 2;
  749.              SendMessage(Handle, HDM_HITTEST, 0, Integer(@hdhti));
  750.              hdi.Mask := HDI_ORDER;
  751.              DragTo:= 0;
  752.              if hdhti.Item < 0 then
  753.                if (HHT_TOLEFT and hdhti.Flags) <> 0 then
  754.                  DragTo := 0
  755.                else begin
  756.                  if ((HHT_TORIGHT and hdhti.Flags) <> 0)
  757.                  or ((HHT_NOWHERE and hdhti.Flags) <> 0) then
  758.                    DragTo := Sections.Count - 1
  759.                end
  760.              else begin
  761.                Header_GetItem(Handle, hdhti.Item, hdi);
  762.                DragTo := hdi.iOrder;
  763.              end;
  764.              if DragTo<0 then exit;
  765.              AllowMove:= True;
  766.              Header_GetItem(Handle, Item, hdi);
  767.              DragFrom := hdi.iOrder;
  768.              Header.SectionMove(Sections[Item], DragFrom, DragTo, AllowMove);
  769.              FSectionDragged:= AllowMove;
  770.              if AllowMove then
  771.              begin
  772. //                Header_GetItem(Handle, Item, hdi);
  773. //                DragFrom := hdi.iOrder;
  774.                 Sections[DragFrom].index:= DragTo;
  775. //                FSectionDragged :=
  776.                    DoSectionDrag(Sections[DragFrom], Sections[DragTo]);
  777.                 if Tree<>Nil then
  778.                 begin
  779.                    RearrangeTreeColumns;
  780.                    Tree.invalidate; { W2W - Invalidate TreeView when header is moved }
  781.                 end
  782.              end;
  783.           end;
  784.           Message.result:= 1; { Don't do default processing }
  785.        end;
  786.       HDN_ITEMCLICK:
  787.         Header.SectionClick(Sections[Item]);
  788.       HDN_ITEMCHANGED:
  789.         if PItem^.mask and HDI_WIDTH <> 0 then
  790.         begin
  791.           Section := Sections[Item];
  792.           if Section.FWidth <> PItem^.cxy then
  793.           begin
  794.             Section.FWidth := PItem^.cxy;
  795.             Header.SectionResize(Section);
  796.           end;
  797.         end;
  798.       HDN_BEGINTRACK, HDN_TRACK, HDN_ENDTRACK:
  799.         begin
  800.           Section := Sections[Item];
  801.           case Hdr.code of
  802.             HDN_BEGINTRACK: TrackState := tsTrackBegin;
  803.             HDN_ENDTRACK: TrackState := tsTrackEnd;
  804.           else
  805.             TrackState := tsTrackMove;
  806.           end;
  807.           with PItem^ do
  808.           begin
  809.             if cxy < Section.MinWidth then cxy := Section.MinWidth;
  810.             if cxy > Section.MaxWidth then cxy := Section.MaxWidth;
  811.             Header.SectionTrack(Sections[Item], cxy, TrackState);
  812.           end;
  813.         end;
  814.     end;
  815. end;
  816. procedure TfcTreeHeaderControl.WMLButtonDown(var Message: TWMLButtonDown);
  817. var
  818.   Index: Integer;
  819.   Info: THDHitTestInfo;
  820. begin
  821.   Info.Point.X := Message.Pos.X;
  822.   Info.Point.Y := Message.Pos.Y;
  823.   Index := SendMessage(Handle, HDM_HITTEST, 0, Integer(@Info));
  824.   if (Index < 0) or (Info.Flags and HHT_ONHEADER = 0) or
  825.     Sections[Index].AllowClick then inherited;
  826. end;
  827. procedure TfcTreeHeader.WMSize(var Message: TWMSize);
  828. begin
  829.   inherited;
  830.   if not (csLoading in ComponentState) then Resize;
  831.   HeaderControl.Width:= Width -HeaderControl.Left;
  832.   HeaderControl.Height:= Height;
  833. end;
  834. procedure TfcTreeHeaderControl.WMWindowPosChanged(var Message: TWMWindowPosChanged);
  835. begin
  836.   inherited;
  837.   Invalidate;
  838. end;
  839. { Support design time sizing of the header sections }
  840. procedure TfcTreeHeaderControl.WndProc(var Message: TMessage);
  841. var hti: THDHitTestInfo;
  842.     pt: TPoint;
  843.     i: integer;
  844. begin
  845.   if csDesigning in ComponentState then begin
  846.      case Message.Msg of
  847.        WM_LBUTTONDOWN: begin
  848.             hti.Point.x:= TWMMouse(Message).xpos;
  849.             hti.Point.y:= TWMMouse(Message).ypos;
  850.             SendMessage(Handle, HDM_HITTEST, 0, longint(@hti));
  851.             if (hti.flags and HHT_ONDIVIDER)<>0 then begin
  852.                GetParentForm(self).Designer.modified;
  853.                Dispatch(Message);
  854.                exit;
  855.             end
  856.          end;
  857.        WM_LBUTTONUP:
  858.          begin
  859.             Dispatch(Message);
  860.             exit;
  861.          end;
  862.        WM_MOUSEMOVE:
  863.          begin
  864.             Dispatch(Message);
  865.             exit;
  866.          end;
  867.      end;
  868.      inherited;
  869.   end
  870.   else begin
  871.      case Message.Msg of
  872.        WM_MOUSEMOVE:
  873.          begin
  874.            if HotTrack or fcUseThemes(self) then begin //ThemeServices.ThemesEnabled then begin
  875.               GetCursorPos(pt);
  876.               pt:=  ScreenToClient(pt);
  877.               begin
  878.                 for i:= 0 to Sections.count-1 do begin
  879.                    if Sections[i].PtInSection(pt) then
  880.                    begin
  881.                       if HotTrackSection<>i then
  882.                       begin
  883.                          HotTrackSection:= i;
  884.                          invalidate;
  885.                       end
  886.                    end
  887.                  end;
  888.               end;
  889.            end;
  890.        end
  891.      end;
  892.      inherited;
  893.   end;
  894. end;
  895. procedure TfcTreeHeaderControl.SetOptions(val: TfcTreeHeaderOptions);
  896. begin
  897.    if FOptions<>val then
  898.    begin
  899.       FOptions:= val;
  900.       RecreateWnd;
  901.    end;
  902. end;
  903. procedure TfcTreeHeaderControl.SetImageList(val: TImageList);
  904. begin
  905.    FImageList:= Val;
  906.    Invalidate;
  907. end;
  908. procedure TfcTreeHeaderControl.WMPaint(var Message: TWMPaint);
  909. begin
  910.    inherited;
  911.    if thcoRightBorder in Options then
  912.    begin
  913.       Canvas.MoveTo(ClientRect.Right-1, 0);
  914.       Canvas.LineTo(ClientRect.Right-1, ClientRect.Bottom);
  915.    end;
  916. end;
  917. function TfcTreeHeaderControl.DoSectionDrag(FromSection, ToSection: TfcTreeHeaderSection): Boolean;
  918. begin
  919.   Result := True;
  920.   Header.SectionDrag(FromSection, ToSection);
  921. end;
  922. procedure TfcTreeHeader.SectionDrag(FromSection, ToSection: TfcTreeHeaderSection);
  923. begin
  924.   if Assigned(FOnSectionDrag) then FOnSectionDrag(Self, FromSection, ToSection)
  925. end;
  926. constructor TfcTreeHeader.Create(AOwner: TComponent);
  927. begin
  928.    inherited Create(AOwner);
  929.    HeaderControl:= TfcTreeHeaderControl.create(self);
  930.    HeaderControl.Header:= self;
  931.    Align:= alTop;
  932.    HeaderControl.Left:= 0;
  933.    HeaderControl.Top:= 0;
  934.    HeaderControl.Width:= Width;
  935.    HeaderControl.Height:= Height;
  936. end;
  937. procedure TfcTreeHeader.CreateWnd;
  938. begin
  939.    inherited CreateWnd;
  940.    HeaderControl.parent:= self;
  941.    HeaderControl.align:= alNone;
  942. end;
  943. destructor TfcTreeHeader.Destroy;
  944. begin
  945.   HeaderControl.Free;
  946.   inherited Destroy;
  947. end;
  948. procedure TfcTreeHeader.SetSections(Value: TfcTreeHeaderSections);
  949. begin
  950.    HeaderControl.Sections.Assign(Value);
  951. end;
  952. function TfcTreeHeader.GetSections: TfcTreeHeaderSections;
  953. begin
  954.    result:= HeaderControl.Sections;
  955. end;
  956. function TfcTreeHeader.GetHotTrack: boolean;
  957. begin
  958.   result:= HeaderControl.HotTrack;
  959. end;
  960. procedure TfcTreeHeader.SetHotTrack(Value: Boolean);
  961. begin
  962.    HeaderControl.HotTrack:= value;
  963. end;
  964. function TfcTreeHeader.GetImageList: TImageList;
  965. begin
  966.    result:= HeaderControl.Images;
  967. end;
  968. procedure TfcTreeHeader.SetImageList(Value: TImageList);
  969. begin
  970.    HeaderControl.Images:= Value;
  971. end;
  972. procedure TfcTreeHeader.SetOptions(val: TfcTreeHeaderOptions);
  973. begin
  974.    HeaderControl.Options:= val;
  975. end;
  976. function TfcTreeHeader.GetOptions: TfcTreeHeaderOptions;
  977. begin
  978.    result:= HeaderControl.Options;
  979. end;
  980. function TfcTreeHeader.GetCanvas: TCanvas;
  981. begin
  982.   result:= HeaderControl.Canvas;
  983. end;
  984. function TfcTreeHeader.GetTree: TWinControl;
  985. begin
  986.    result:= HeaderControl.Tree;
  987. end;
  988. procedure TfcTreeHeaderControl.CMMouseEnter(var Message: TMessage);
  989. begin
  990.   inherited;
  991. end;
  992. procedure TfcTreeHeaderControl.CMMouseLeave(var Message: TMessage);
  993. var r:TRect;
  994.     pt:TPoint;
  995. begin
  996.   GetCursorPos(pt);
  997.   pt := ScreenToClient(pt);
  998.   r := ClientRect;
  999.   if (PtInRect(r,pt)) then exit;
  1000.   if HotTrack or fcUseThemes(self) then begin//ThemeServices.ThemesEnabled then begin
  1001.      HotTrackSection:=-1;
  1002.      invalidate;
  1003.   end;
  1004.   inherited;
  1005. end;
  1006. Function TfcTreeHeader.GetMouseDown: TMouseEvent;
  1007. begin
  1008.    result:= HeaderControl.OnMouseDown;
  1009. end;
  1010. procedure  TfcTreeHeader.SetMouseDown(Value: TMouseEvent);
  1011. begin
  1012.    HeaderControl.OnMouseDown:= Value;
  1013. end;
  1014. Function TfcTreeHeader.GetMouseUp: TMouseEvent;
  1015. begin
  1016.    result:= HeaderControl.OnMouseUp;
  1017. end;
  1018. procedure  TfcTreeHeader.SetMouseUp(Value: TMouseEvent);
  1019. begin
  1020.    HeaderControl.OnMouseUp:= Value;
  1021. end;
  1022. Function TfcTreeHeader.GetMouseMove :TMouseMoveEvent;
  1023. begin
  1024.    result:= HeaderControl.OnMouseMove;
  1025. end;
  1026. procedure  TfcTreeHeader.SetMouseMove(Value: TMouseMoveEvent);
  1027. begin
  1028.    HeaderControl.OnMouseMove:= Value;
  1029. end;
  1030. procedure TfcTreeHeader.WMEraseBkgnd(var Message: TWMEraseBkgnd);
  1031. //var
  1032. //  Details: TThemedElementDetails;
  1033. begin
  1034. {  if ThemeServices.ThemesEnabled then
  1035.   begin
  1036.     Details := ThemeServices.GetElementDetails(thHeaderRoot);
  1037.     ThemeServices.DrawElement(Message.DC, Details, ClientRect, nil);
  1038.     Message.Result := 1;
  1039.   end
  1040.   else}
  1041.     inherited;
  1042. end;
  1043. end.