cxheader.pas

来自「胜天进销存源码,国产优秀的进销存」· PAS 代码 · 共 1,754 行 · 第 1/4 页

PAS
1,754
字号
{********************************************************************}
{                                                                    }
{       Developer Express Visual Component Library                   }
{       ExpressEditors                                               }
{                                                                    }
{       Copyright (c) 1998-2008 Developer Express Inc.               }
{       ALL RIGHTS RESERVED                                          }
{                                                                    }
{   The entire contents of this file is protected by U.S. and        }
{   International Copyright Laws. Unauthorized reproduction,         }
{   reverse-engineering, and distribution of all or any portion of   }
{   the code contained in this file is strictly prohibited and may   }
{   result in severe civil and criminal penalties and will be        }
{   prosecuted to the maximum extent possible under the law.         }
{                                                                    }
{   RESTRICTIONS                                                     }
{                                                                    }
{   THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES            }
{   (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE     }
{   SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS    }
{   LICENSED TO DISTRIBUTE THE EXPRESSEDITORS AND ALL                }
{   ACCOMPANYING VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{                                                                    }
{   THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED       }
{   FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE         }
{   COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE        }
{   AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT   }
{   AND PERMISSION FROM DEVELOPER EXPRESS INC.                       }
{                                                                    }
{   CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON        }
{   ADDITIONAL RESTRICTIONS.                                         }
{                                                                    }
{********************************************************************}

unit cxHeader;

{$I cxVer.inc}

interface

uses
  Windows, Classes, Controls, Graphics, ImgList, Messages, SysUtils, cxClasses,
  cxContainer, cxControls, cxGraphics, cxCustomData, cxLookAndFeelPainters, cxLookAndFeels,
  cxEdit, cxEditUtils, cxExtEditConsts, cxExtEditUtils, CommCtrl;

const
  CM_GETHEADERITEMINFO = WM_DX + 25;

type
  TcxHeaderSortOrder = TcxDataSortOrder;
  TcxCustomHeader = class;
  TcxHeader = class;
  TcxHeaderSection = class;
  TcxHeaderSections = class;
  TcxSectionTrackState = (tsTrackBegin, tsTrackMove, tsTrackEnd, tsTrackNone);
  TcxHeaderSectionRects = array of TRect;
  TcxHeaderSectionWidths = array of Integer;
  TcxHeaderState = (hsNone, hsSized, hsDragged, hsPressed);
  THeaderItemInfo = packed record
    ImageIndex: Integer;
    Rect: TRect;
    SectionAlignment: TAlignment;
    SortOrder: TcxHeaderSortOrder;
    State: TcxButtonState;
    Text: string;
  end;
  PHeaderItemInfo = ^THeaderItemInfo;

  TcxDrawSectionEvent = procedure(HeaderControl: TcxCustomHeader;
    Section: TcxHeaderSection; const ARect: TRect; Pressed: Boolean) of object;
  TcxSectionNotifyEvent = procedure(HeaderControl: TcxCustomHeader;
    Section: TcxHeaderSection) of object;
  TcxSectionTrackEvent = procedure(HeaderControl: TcxCustomHeader;
    Section: TcxHeaderSection; Width: Integer; State: TcxSectionTrackState) of object;
  TcxSectionDragEvent = procedure (Sender: TObject; FromSection, ToSection: TcxHeaderSection;
    var AllowDrag: Boolean) of object;
  TcxSectionChangingSortOrderEvent = procedure (Sender: TObject;
    const Section: TcxHeaderSection; const AOldSortOrder: TcxHeaderSortOrder;
    var ANewSortOrder: TcxHeaderSortOrder; var AllowChange: Boolean) of object;
  TcxSectionChangedSortOrderEvent = procedure (Sender: TObject;
    const Section: TcxHeaderSection; const ASortOrder: TcxHeaderSortOrder) of object;

  { CM_GETHEADERITEMINFO }

  TCMHeaderItemInfo = packed record
    Msg: Cardinal;
    Index: Integer;
    HeaderItemInfo: PHeaderItemInfo;
    Result: Longint;
  end;

  { TcxHeaderSection }

  TcxHeaderSection = class(TCollectionItem)
  private
    FAlignment: TAlignment;
    FAllowClick: Boolean;
    FAllowResize: Boolean;
    FAutoSize: Boolean;
    FBiDiMode: TBiDiMode;
    FDataIndex: Integer;
    FImageIndex: TImageIndex;
    FMaxWidth: TcxNaturalNumber;
    FMinWidth: TcxNaturalNumber;
    FParentBiDiMode: Boolean;
    FSortOrder: TcxHeaderSortOrder;
    FState: TcxButtonState;
    FText: string;
    FWidth: Integer;
    function GetLeft: Integer;
    function GetRight: Integer;
    function IsBiDiModeStored: Boolean;
    function IsDataIndexStored: Boolean;
    function GetHeaderControl: TcxCustomHeader;
    procedure SetAlignment(Value: TAlignment);
    procedure SetAutoSize(Value: Boolean);
    procedure SetBiDiMode(Value: TBiDiMode);
    procedure SetDataIndex(Value: Integer);
    procedure SetMaxWidth(Value: TcxNaturalNumber);
    procedure SetMinWidth(Value: TcxNaturalNumber);
    procedure SetParentBiDiMode(Value: Boolean);
    procedure SetState(Value: TcxButtonState);
    procedure SetText(const Value: string);
    procedure SetWidth(Value: Integer);
    procedure SetImageIndex(const Value: TImageIndex);
    procedure SetSortOrder(Value: TcxHeaderSortOrder);
  protected
    function GetDisplayName: string; override;
    property State: TcxButtonState read FState write SetState;
  public
    constructor Create(Collection: TCollection); override;
    procedure Assign(Source: TPersistent); override;
    procedure ParentBiDiModeChanged;
    function UseRightToLeftAlignment: Boolean;
    function UseRightToLeftReading: Boolean;
    property Left: Integer read GetLeft;
    property Right: Integer read GetRight;
    property HeaderControl: TcxCustomHeader read GetHeaderControl;
  published
    property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify;
    property AllowClick: Boolean read FAllowClick write FAllowClick default False;
    property AllowResize: Boolean read FAllowResize write FAllowResize default True;
    property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
    property BiDiMode: TBiDiMode read FBiDiMode write SetBiDiMode stored IsBiDiModeStored;
    property DataIndex: Integer read FDataIndex write SetDataIndex
      stored IsDataIndexStored;
    property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1;
    property MaxWidth: TcxNaturalNumber read FMaxWidth write SetMaxWidth default 1000;
    property MinWidth: TcxNaturalNumber read FMinWidth write SetMinWidth default 30;
    property ParentBiDiMode: Boolean read FParentBiDiMode write SetParentBiDiMode default True;
    property SortOrder: TcxHeaderSortOrder read FSortOrder write SetSortOrder default soNone;
    property Text: string read FText write SetText;
    property Width: Integer read FWidth write SetWidth default 50;
  end;

  { TcxHeaderSections }

  TcxHeaderSections = class(TCollection)
  private
    FHeaderControl: TcxCustomHeader;
    function GetItem(Index: Integer): TcxHeaderSection;
    procedure SetItem(Index: Integer; Value: TcxHeaderSection);
  protected
    function GetOwner: TPersistent; override;
    procedure Update(Item: TCollectionItem); override;
  public
    constructor Create(HeaderControl: TcxCustomHeader);
    procedure Assign(Source: TPersistent); override;
    function Add: TcxHeaderSection;
    function Insert(Index: Integer): TcxHeaderSection;
    property Items[Index: Integer]: TcxHeaderSection read GetItem write SetItem; default;
  end;

  { TcxCustomHeader }

  TcxCustomHeader = class(TcxControl, IcxMouseTrackingCaller)
  private
    FAllowSort: Boolean;
    FBrush: TBrush;
    FDragReorder: Boolean;
    FHotSectionIndex: Integer;
    FImages: TCustomImageList;
    FImagesChangeLink: TChangeLink;
    FLastDrawPosOnMove: Integer;
    FLineDC: HDC;
    FLineVisible: Boolean;
    FMouseOnSizer: Boolean;
    FPrevBrush: HBrush;
    FPrevMousePos: Integer;
    FResizeUpdate: Boolean;
    FScreenCursor: TCursor;
    FScreenCursorSaved: Boolean;
    FSectionDragged: Boolean;
    FSections: TcxHeaderSections;
    FSectionsFitCalculating: Boolean;
    FSectionStream: TMemoryStream;
    FSelectedSectionIndex: Integer;
    FSizedSectionIndex: Integer;
    FState: TcxHeaderState;
    FUnderMouseSectionIndex: Integer;
    FOnSectionClick: TcxSectionNotifyEvent;
    FOnSectionResize: TcxSectionNotifyEvent;
    FOnSectionEndResize: TcxSectionNotifyEvent;
    FOnSectionTrack: TcxSectionTrackEvent;
    FOnDrawSection: TcxDrawSectionEvent;
    FOnSectionEndDrag: TNotifyEvent;
    FOnSectionDrag: TcxSectionDragEvent;
    FOnSectionChangingSortOrder: TcxSectionChangingSortOrderEvent;
    FOnSectionChangedSortOrder: TcxSectionChangedSortOrderEvent;
    FOnSectionChange: TNotifyEvent;
    FOnSectionsChange: TNotifyEvent;    
    procedure ImageListChange(Sender: TObject);
    procedure RestoreScreenCursor;
    procedure SetScreenCursor(ACursor: TCursor);
    procedure SetSections(Value: TcxHeaderSections);
    procedure UpdateSection(Index: Integer);
    procedure UpdateSections;
    procedure SetImages(Value: TCustomImageList);
    procedure SetAllowSort(Value: Boolean);
    function GetSectionIndexAtPos(X, Y: Integer; AIncludeNonSectionPart: Boolean = False): Integer;

    function GetSelectedSection: TcxHeaderSection;
    function GetSizedSection: TcxHeaderSection;
    function GetUnderMouseSection: TcxHeaderSection;
    function IsSectionIndex(AIndex: Integer): Boolean;
    procedure IcxMouseTrackingCaller.MouseLeave = HeaderMouseLeave;
    procedure HeaderMouseLeave;
    procedure SetHotSectionIndex(Value: Integer);
    procedure SetMouseOnSizer(Value: Boolean);
    procedure SetSectionState(AIndex: Integer; AState: TcxButtonState);
    procedure SetSelectedSectionIndex(Value: Integer);
    procedure SetSizedSectionIndex(Value: Integer);
    procedure SetUnderMouseSectionIndex(Value: Integer);
    procedure UpdateDraggedSection;
    procedure UpdatePressedSection;
    procedure UpdateSizedSection;
    procedure UpdateUnderMouseSection;

    procedure CMBiDiModeChanged(var Message: TMessage); message CM_BIDIMODECHANGED;
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure WMCaptureChanged(var Message: TMessage); message WM_CAPTURECHANGED;
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
    procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;
    procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure WMWindowPosChanged(var Message: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED;
    procedure HDMGetItemCount(var Message: TMessage); message HDM_GETITEMCOUNT;
    procedure HDMGetItemInfo(var Message: TCMHeaderItemInfo); message CM_GETHEADERITEMINFO;

    procedure AllocateSplitLineDC;
    procedure ReleaseSplitLine;
    procedure DrawSplitLine(XPos: Integer);
    procedure InitResize(XPos: Integer);

    property HotSectionIndex: Integer read FHotSectionIndex write SetHotSectionIndex;
    property MouseOnSizer: Boolean read FMouseOnSizer write SetMouseOnSizer;
    property SelectedSection: TcxHeaderSection read GetSelectedSection;
    property SelectedSectionIndex: Integer read FSelectedSectionIndex write SetSelectedSectionIndex;
    property SizedSection: TcxHeaderSection read GetSizedSection;
    property SizedSectionIndex: Integer read FSizedSectionIndex write SetSizedSectionIndex;
    property UnderMouseSection: TcxHeaderSection read GetUnderMouseSection;
    property UnderMouseSectionIndex: Integer read FUnderMouseSectionIndex write SetUnderMouseSectionIndex;
  protected
    procedure ChangeSectionSortOrder(ASection: TcxHeaderSection;
      ANewSortOrder: TcxHeaderSortOrder; ADeleteOtherSorting: Boolean); dynamic;
    function DoSectionChangingSortOrder(ASection: TcxHeaderSection;
      ANewSortOrder: TcxHeaderSortOrder): Boolean;
    procedure DoSectionChangedSortOrder(ASection: TcxHeaderSection);
    function DoSectionDrag(FromSection, ToSection: TcxHeaderSection): Boolean; virtual;
    procedure DoSectionEndDrag; virtual;
    function GetSectionRect(Index: Integer): TRect;
    function GetSectionRectBySectionWidths(AHeaderWidth: Integer;
      const ASectionWidths: TcxHeaderSectionWidths; AIndex: Integer): TRect; virtual;
    function CreateSection: TcxHeaderSection; virtual;
    procedure CreateParams(var Params: TCreateParams); override;
    procedure CreateWnd; override;
    procedure DestroyWnd; override;
    procedure LookAndFeelChanged(Sender: TcxLookAndFeel;
      AChangedValues: TcxLookAndFeelValues); override;
    procedure Notification(AComponent: TComponent;
      Operation: TOperation); override;
    procedure DrawSection(SectionIndex: Integer); dynamic;
    procedure DoSectionClickEvent(Section: TcxHeaderSection); dynamic;
    procedure DoSectionChange;
    procedure DoSectionsChange;
    procedure DoSectionDragEvent(FromSection, ToSection: TcxHeaderSection; var AllowDrag: Boolean); dynamic;
    procedure DoSectionEndDragEvent; dynamic;
    procedure DoSectionResizeEvent(Section: TcxHeaderSection); dynamic;
    procedure DoSectionEndResizeEvent(Section: TcxHeaderSection); dynamic;
    procedure DoSectionTrackEvent(Section: TcxHeaderSection; Width: Integer;
      State: TcxSectionTrackState); dynamic;
    procedure DisableSort; virtual;
    procedure FitToClientWidth;
    function GetSectionContentBounds(ASectionBounds: TRect;
      AState: TcxButtonState): TRect;
    function IsInnerControl: Boolean; virtual;
    procedure Paint; override;
    property OnSectionsChange: TNotifyEvent read FOnSectionsChange
      write FOnSectionsChange;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure CalcSectionWidths(AHeaderWidth: Integer;
      out AWidths: TcxHeaderSectionWidths); virtual;
    procedure FlipChildren(AllLevels: Boolean); override;
    function GetAutoHeight: Integer;
    property AllowSort: Boolean read FAllowSort write SetAllowSort default True;
    property DragReorder: Boolean read FDragReorder write FDragReorder default False;
    property Images: TCustomImageList read FImages write SetImages;
    property LookAndFeel;
    property ResizeUpdate: Boolean read FResizeUpdate write FResizeUpdate default True;
    property Sections: TcxHeaderSections read FSections write SetSections;
    property OnDrawSection: TcxDrawSectionEvent read FOnDrawSection
      write FOnDrawSection;
    property OnSectionChange: TNotifyEvent read FOnSectionChange
      write FOnSectionChange;
    property OnSectionChangedSortOrder: TcxSectionChangedSortOrderEvent
      read FOnSectionChangedSortOrder write FOnSectionChangedSortOrder;
    property OnSectionChangingSortOrder: TcxSectionChangingSortOrderEvent
      read FOnSectionChangingSortOrder write FOnSectionChangingSortOrder;
    property OnSectionClick: TcxSectionNotifyEvent read FOnSectionClick
      write FOnSectionClick;
    property OnSectionDrag: TcxSectionDragEvent read FOnSectionDrag
      write FOnSectionDrag;
    property OnSectionEndDrag: TNotifyEvent read FOnSectionEndDrag
      write FOnSectionEndDrag;
    property OnSectionEndResize: TcxSectionNotifyEvent read FOnSectionEndResize
      write FOnSectionEndResize;
    property OnSectionResize: TcxSectionNotifyEvent read FOnSectionResize
      write FOnSectionResize;
    property OnSectionTrack: TcxSectionTrackEvent read FOnSectionTrack
      write FOnSectionTrack;
  end;

  { TcxHeader }
  
  TcxHeader = class(TcxCustomHeader)
  published
    property Align;
    property AllowSort;
    property Anchors;
    property BiDiMode;
    property Color;
    property Constraints;
    property DragCursor;
    property DragKind;
    property DragMode;
    property DragReorder;
    property Enabled;
    property Font;
    property Images;
    property LookAndFeel;
    property ParentBiDiMode;
    property ParentColor;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ResizeUpdate;
    property Sections;
    property ShowHint;
    property Visible;
    property OnContextPopup;
    property OnDragDrop;
    property OnDragOver;
    property OnDrawSection;
    property OnEndDock;
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnSectionChange;
    property OnSectionChangedSortOrder;
    property OnSectionChangingSortOrder;
    property OnSectionClick;
    property OnSectionDrag;
    property OnSectionEndDrag;
    property OnSectionEndResize;
    property OnSectionResize;
    property OnSectionTrack;
    property OnStartDock;
    property OnStartDrag;
  end;

procedure DrawHeaderSection(AHeaderHandle: HWND; AIndex: Integer;
  ACanvas: TcxCanvas; ALookAndFeel: TcxLookAndFeel; AImages: TCustomImageList = nil);
function SendGetStructMessage(Handle: HWND; Msg: UINT; WParam: WPARAM; var LParam): LRESULT;

implementation

uses
  Forms, Math, dxThemeConsts, dxThemeManager, dxUxTheme;

const
  ImageTextOffset = 2;
  SortingMarkOffset = 4;
  SortingMarkWidth = 7;
  cxHeaderSectionTextLeftRightIndent = 4;
  cxHeaderSectionTextTopBottomIndent = 2;

procedure DrawHeaderSection(AHeaderHandle: HWND; AIndex: Integer;
  ACanvas: TcxCanvas; ALookAndFeel: TcxLookAndFeel; AImages: TCustomImageList);

  procedure DrawSortingMark(const ARect: TRect; ASortOrder: TcxHeaderSortOrder);
  var
    ASavedPenColor: TColor;
    ASortingMarkRect: TRect;
  begin
    if ASortOrder <> soNone then
    begin
      ASavedPenColor := ACanvas.Pen.Color;
      ASortingMarkRect := ARect;
      Dec(ASortingMarkRect.Right, SortingMarkOffset);
      ASortingMarkRect.Left := ASortingMarkRect.Right - SortingMarkWidth;
      ALookAndFeel.Painter.DrawSortingMark(ACanvas, ASortingMarkRect,
        ASortOrder = soAscending);
      ACanvas.Pen.Color := ASavedPenColor;
    end;
  end;

  function GetTextRect(const ANormalContentRect: TRect; ASortOrder: TcxHeaderSortOrder): TRect;
  begin
    Result := ANormalContentRect;
    Inc(Result.Left, cxHeaderSectionTextLeftRightIndent);
    Dec(Result.Right, cxHeaderSectionTextLeftRightIndent);
    if ASortOrder <> soNone then
      Dec(Result.Right, SortingMarkOffset + SortingMarkWidth);
  end;

  function GetImageRect(var ATextRect: TRect; var AHeaderItemInfo: THeaderItemInfo): TRect;
  var
    ATextWidth: Integer;
  begin
    Result := ATextRect;
    ATextWidth := ACanvas.TextWidth(AHeaderItemInfo.Text);
    case AHeaderItemInfo.SectionAlignment of
      taLeftJustify:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?