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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }
  4. {       BusinessSkinForm                                            }
  5. {       Version 2.90                                                }
  6. {                                                                   }
  7. {       Copyright (c) 2000-2004 Almediadev                          }
  8. {       ALL RIGHTS RESERVED                                         }
  9. {                                                                   }
  10. {       Home:  http://www.almdev.com                                }
  11. {       Support: support@almdev.com                                 }
  12. {                                                                   }
  13. {*******************************************************************}
  14.                      
  15. unit bsSkinGrids;
  16. {$P+,S-,W-,R-}
  17. {$WARNINGS OFF}
  18. {$HINTS OFF}
  19. interface
  20. uses Messages, Windows, SysUtils, Classes, Graphics, Menus, Controls, Forms,
  21.      StdCtrls, Mask, bsSkinData, bsSkinCtrls, bsSkinMenus;
  22. const
  23.   MaxCustomExtents = MaxListSize;
  24.   MaxShortInt = High(ShortInt);
  25. type
  26.   bsEInvalidGridOperation = class(Exception);
  27.   { Internal grid types }
  28.   TbsGetExtentsFunc = function(Index: Longint): Integer of object;
  29.   TbsGridAxisDrawInfo = record
  30.     EffectiveLineWidth: Integer;
  31.     FixedBoundary: Integer;
  32.     GridBoundary: Integer;
  33.     GridExtent: Integer;
  34.     LastFullVisibleCell: Longint;
  35.     FullVisBoundary: Integer;
  36.     FixedCellCount: Integer;
  37.     FirstGridCell: Integer;
  38.     GridCellCount: Integer;
  39.     GetExtent: TbsGetExtentsFunc;
  40.   end;
  41.   TbsGridDrawInfo = record
  42.     Horz, Vert: TbsGridAxisDrawInfo;
  43.   end;
  44.   TbsGridState = (gsNormal, gsSelecting, gsRowSizing, gsColSizing,
  45.     gsRowMoving, gsColMoving);
  46.   TbsGridMovement = gsRowMoving..gsColMoving;
  47.   { TInplaceEdit }
  48.   { The inplace editor is not intended to be used outside the grid }
  49.   TbsSkinCustomGrid = class;
  50.   
  51.   TbsSkinInplaceEdit = class(TCustomMaskEdit)
  52.   private
  53.     FGrid: TbsSkinCustomGrid;
  54.     FClickTime: Longint;
  55.     FSysPopupMenu: TbsSkinPopupMenu;
  56.     procedure DoUndo(Sender: TObject);
  57.     procedure DoCut(Sender: TObject);
  58.     procedure DoCopy(Sender: TObject);
  59.     procedure DoPaste(Sender: TObject);
  60.     procedure DoDelete(Sender: TObject);
  61.     procedure DoSelectAll(Sender: TObject);
  62.     procedure CreateSysPopupMenu;
  63.     procedure WMAFTERDISPATCH(var Message: TMessage); message WM_AFTERDISPATCH;
  64.     procedure WMCONTEXTMENU(var Message: TWMCONTEXTMENU); message WM_CONTEXTMENU;
  65.     procedure InternalMove(const Loc: TRect; Redraw: Boolean);
  66.     procedure SetGrid(Value: TbsSkinCustomGrid);
  67.     procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  68.     procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
  69.     procedure WMPaste(var Message); message WM_PASTE;
  70.     procedure WMCut(var Message); message WM_CUT;
  71.     procedure WMClear(var Message); message WM_CLEAR;
  72.   protected
  73.     procedure CreateParams(var Params: TCreateParams); override;
  74.     procedure DblClick; override;
  75.     function EditCanModify: Boolean; override;
  76.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  77.     procedure KeyPress(var Key: Char); override;
  78.     procedure KeyUp(var Key: Word; Shift: TShiftState); override;
  79.     procedure BoundsChanged; virtual;
  80.     procedure UpdateContents; virtual;
  81.     procedure WndProc(var Message: TMessage); override;
  82.     property  Grid: TbsSkinCustomGrid read FGrid;
  83.   public
  84.     constructor Create(AOwner: TComponent); override;
  85.     destructor Destroy; override;
  86.     procedure Deselect;
  87.     procedure Hide;
  88.     procedure Invalidate;
  89.     procedure Move(const Loc: TRect);
  90.     function PosEqual(const Rect: TRect): Boolean;
  91.     procedure SetFocus;
  92.     procedure UpdateLoc(const Loc: TRect);
  93.     function Visible: Boolean;
  94.   end;
  95.   { TbsSkinCustomGrid }
  96.   TGridOption = (goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine,
  97.     goRangeSelect, goDrawFocusSelected, goRowSizing, goColSizing, goRowMoving,
  98.     goColMoving, goEditing, goTabs, goRowSelect,
  99.     goAlwaysShowEditor, goThumbTracking);
  100.   TGridOptions = set of TGridOption;
  101.   TGridDrawState = set of (gdSelected, gdFocused, gdFixed);
  102.   TGridScrollDirection = set of (sdLeft, sdRight, sdUp, sdDown);
  103.   TGridCoord = record
  104.     X: Longint;
  105.     Y: Longint;
  106.   end;
  107.   TGridRect = record
  108.     case Integer of
  109.       0: (Left, Top, Right, Bottom: Longint);
  110.       1: (TopLeft, BottomRight: TGridCoord);
  111.   end;
  112.   TSelectCellEvent = procedure (Sender: TObject; ACol, ARow: Longint;
  113.     var CanSelect: Boolean) of object;
  114.   TDrawCellEvent = procedure (Sender: TObject; ACol, ARow: Longint;
  115.     Rect: TRect; State: TGridDrawState) of object;
  116.   TbsSkinCustomGrid = class(TbsSkinControl)
  117.   private
  118.     FUseSkinFont: Boolean;
  119.     FUseSkinCellHeight: Boolean;
  120.     FGridLineColor: TColor;
  121.     FHScrollBar: TbsSkinScrollBar;
  122.     FVScrollBar: TbsSkinScrollBar;
  123.     FAnchor: TGridCoord;
  124.     FBorderStyle: TBorderStyle;
  125.     FCanEditModify: Boolean;
  126.     FColCount: Longint;
  127.     FColWidths: Pointer;
  128.     FTabStops: Pointer;
  129.     FCurrent: TGridCoord;
  130.     FDefaultColWidth: Integer;
  131.     FDefaultRowHeight: Integer;
  132.     FDefaultCellHeight: Integer;
  133.     FFixedCols: Integer;
  134.     FFixedRows: Integer;
  135.     FFixedColor: TColor;
  136.     FGridLineWidth: Integer;
  137.     FOptions: TGridOptions;
  138.     FRowCount: Longint;
  139.     FRowHeights: Pointer;
  140.     FTopLeft: TGridCoord;
  141.     FSizingIndex: Longint;
  142.     FSizingPos, FSizingOfs: Integer;
  143.     FMoveIndex, FMovePos: Longint;
  144.     FHitTest: TPoint;
  145.     FInplaceEdit: TbsSkinInplaceEdit;
  146.     FInplaceCol, FInplaceRow: Longint;
  147.     FColOffset: Integer;
  148.     FDefaultDrawing: Boolean;
  149.     FEditorMode: Boolean;
  150.     procedure SetGridLineColor(Value: TColor);
  151.     procedure SetDefaultCellHeight(Value: Integer);
  152.     procedure OnVScrollBarChange(Sender: TObject);
  153.     procedure OnVScrollBarPageUp(Sender: TObject);
  154.     procedure OnVScrollBarPageDown(Sender: TObject);
  155.     procedure OnHScrollBarChange(Sender: TObject);
  156.     procedure OnVScrollBarUpButtonClick(Sender: TObject);
  157.     procedure OnVScrollBarDownButtonClick(Sender: TObject);
  158.     procedure OnHScrollBarUpButtonClick(Sender: TObject);
  159.     procedure OnHScrollBarDownButtonClick(Sender: TObject);
  160.     procedure OnHScrollBarPageUp(Sender: TObject);
  161.     procedure OnHScrollBarPageDown(Sender: TObject);
  162.     function CalcCoordFromPoint(X, Y: Integer;
  163.       const DrawInfo: TbsGridDrawInfo): TGridCoord;
  164.     procedure CalcDrawInfoXY(var DrawInfo: TbsGridDrawInfo;
  165.       UseWidth, UseHeight: Integer);
  166.     function CalcMaxTopLeft(const Coord: TGridCoord;
  167.       const DrawInfo: TbsGridDrawInfo): TGridCoord;
  168.     procedure CancelMode;
  169.     procedure ChangeGridOrientation(RightToLeftOrientation: Boolean);
  170.     procedure ChangeSize(NewColCount, NewRowCount: Longint);
  171.     procedure ClampInView(const Coord: TGridCoord);
  172.     procedure DrawSizingLine(const DrawInfo: TbsGridDrawInfo);
  173.     procedure DrawMove;
  174.     procedure FocusCell(ACol, ARow: Longint; MoveAnchor: Boolean);
  175.     procedure GridRectToScreenRect(GridRect: TGridRect;
  176.       var ScreenRect: TRect; IncludeLine: Boolean);
  177.     procedure HideEdit;
  178.     procedure Initialize;
  179.     procedure InvalidateGrid;
  180.     procedure InvalidateRect(ARect: TGridRect);
  181.     procedure ModifyScrollBar(ScrollBar, ScrollCode, Pos: Cardinal;
  182.       UseRightToLeft: Boolean);
  183.     procedure MoveAdjust(var CellPos: Longint; FromIndex, ToIndex: Longint);
  184.     procedure MoveAnchor(const NewAnchor: TGridCoord);
  185.     procedure MoveAndScroll(Mouse, CellHit: Integer; var DrawInfo: TbsGridDrawInfo;
  186.       var Axis: TbsGridAxisDrawInfo; Scrollbar: Integer; const MousePt: TPoint);
  187. //    procedure MoveCurrent(ACol, ARow: Longint; MoveAnchor, Show: Boolean);
  188.     procedure MoveTopLeft(ALeft, ATop: Longint);
  189.     procedure ResizeCol(Index: Longint; OldSize, NewSize: Integer);
  190.     procedure ResizeRow(Index: Longint; OldSize, NewSize: Integer);
  191.     procedure SelectionMoved(const OldSel: TGridRect);
  192.     procedure ScrollDataInfo(DX, DY: Integer; var DrawInfo: TbsGridDrawInfo);
  193.     procedure TopLeftMoved(const OldTopLeft: TGridCoord);
  194.     function GetColWidths(Index: Longint): Integer;
  195.     function GetRowHeights(Index: Longint): Integer;
  196.     function GetSelection: TGridRect;
  197.     function GetTabStops(Index: Longint): Boolean;
  198.     function GetVisibleRowCount: Integer;
  199.     function GetVisibleColCount: Integer;
  200.     function IsActiveControl: Boolean;
  201.     procedure ReadColWidths(Reader: TReader);
  202.     procedure ReadRowHeights(Reader: TReader);
  203.     procedure SetBorderStyle(Value: TBorderStyle);
  204.     procedure SetCol(Value: Longint);
  205.     procedure SetColWidths(Index: Longint; Value: Integer);
  206.     procedure SetDefaultColWidth(Value: Integer);
  207.     procedure SetDefaultRowHeight(Value: Integer);
  208.     procedure SetEditorMode(Value: Boolean);
  209.     procedure SetFixedColor(Value: TColor);
  210.     procedure SetFixedCols(Value: Integer);
  211.     procedure SetFixedRows(Value: Integer);
  212.     procedure SetGridLineWidth(Value: Integer);
  213.     procedure SetLeftCol(Value: Longint);
  214.     procedure SetOptions(Value: TGridOptions);
  215.     procedure SetRow(Value: Longint);
  216.     procedure SetRowHeights(Index: Longint; Value: Integer);
  217.     procedure SetSelection(Value: TGridRect);
  218.     procedure SetTabStops(Index: Longint; Value: Boolean);
  219.     procedure SetTopRow(Value: Longint);
  220.     procedure UpdateText;
  221.     procedure UpdateEdit; 
  222.     procedure WriteColWidths(Writer: TWriter);
  223.     procedure WriteRowHeights(Writer: TWriter);
  224.     procedure CMCancelMode(var Msg: TMessage); message CM_CANCELMODE;
  225.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  226.     procedure CMDesignHitTest(var Msg: TCMDesignHitTest); message CM_DESIGNHITTEST;
  227.     procedure CMWanTbsecialKey(var Msg: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
  228.     procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  229.     procedure WMChar(var Msg: TWMChar); message WM_CHAR;
  230.     procedure WMCancelMode(var Msg: TWMCancelMode); message WM_CANCELMODE;
  231.     procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
  232.     procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
  233.     procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
  234.     procedure WMKillFocus(var Msg: TWMKillFocus); message WM_KILLFOCUS;
  235.     procedure WMLButtonDown(var Message: TMessage); message WM_LBUTTONDOWN;
  236.     procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
  237.     procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
  238.     procedure WMSetFocus(var Msg: TWMSetFocus); message WM_SETFOCUS;
  239.     procedure WMSize(var Msg: TWMSize); message WM_SIZE;
  240.     procedure WMTimer(var Msg: TWMTimer); message WM_TIMER;
  241.     procedure WMPAINT(var Msg: TWMPAINT); message WM_PAINT;
  242.     procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
  243.   protected
  244.     FInCheckScrollBars: Boolean;
  245.     FGridState: TbsGridState;
  246.     FSaveCellExtents: Boolean;
  247.     DesignOptionsBoost: TGridOptions;
  248.     VirtualView: Boolean;
  249.     //
  250.     procedure SetColCount(Value: Longint); virtual;
  251.     procedure MoveCurrent(ACol, ARow: Longint; MoveAnchor, Show: Boolean); virtual;
  252.     procedure SetRowCount(Value: Longint); virtual;
  253.     //
  254.     procedure SetHScrollBar(Value: TbsSkinScrollBar); virtual;
  255.     procedure SetVScrollBar(Value: TbsSkinScrollBar); virtual;
  256.     procedure UpdateScrollPos(UpDateVert: Boolean); virtual;
  257.     procedure UpdateScrollRange(UpDateVert: Boolean); virtual;
  258.     procedure GetSkinData; override;
  259.     procedure CalcDrawInfo(var DrawInfo: TbsGridDrawInfo);
  260.     procedure CalcFixedInfo(var DrawInfo: TbsGridDrawInfo);
  261.     procedure CalcSizingState(X, Y: Integer; var State: TbsGridState;
  262.       var Index: Longint; var SizingPos, SizingOfs: Integer;
  263.       var FixedInfo: TbsGridDrawInfo); virtual;
  264.     function CreateEditor: TbsSkinInplaceEdit; virtual;
  265.     procedure CreateParams(var Params: TCreateParams); override;
  266.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  267.     procedure KeyPress(var Key: Char); override;
  268.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  269.       X, Y: Integer); override;
  270.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  271.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  272.       X, Y: Integer); override;
  273.     procedure AdjustSize(Index, Amount: Longint; Rows: Boolean); reintroduce; dynamic;
  274.     function BoxRect(ALeft, ATop, ARight, ABottom: Longint): TRect;
  275.     procedure DoExit; override;
  276.     function CellRect(ACol, ARow: Longint): TRect;
  277.     function CanEditAcceptKey(Key: Char): Boolean; dynamic;
  278.     function CanGridAcceptKey(Key: Word; Shift: TShiftState): Boolean; dynamic;
  279.     function CanEditModify: Boolean; dynamic;
  280.     function CanEditShow: Boolean; virtual;
  281.     function DoMouseWheelDown(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  282.     function DoMouseWheelUp(Shift: TShiftState; MousePos: TPoint): Boolean; override;
  283.     function GetEditText(ACol, ARow: Longint): string; dynamic;
  284.     procedure SetEditText(ACol, ARow: Longint; const Value: string); dynamic;
  285.     function GetEditMask(ACol, ARow: Longint): string; dynamic;
  286.     function GetEditLimit: Integer; dynamic;
  287.     function GetGridWidth: Integer;
  288.     function GetGridHeight: Integer;
  289.     procedure HideEditor;
  290.     procedure ShowEditor;
  291.     procedure ShowEditorChar(Ch: Char);
  292.     procedure InvalidateEditor;
  293.     procedure MoveColumn(FromIndex, ToIndex: Longint);
  294.     procedure ColumnMoved(FromIndex, ToIndex: Longint); dynamic;
  295.     procedure MoveRow(FromIndex, ToIndex: Longint);
  296.     procedure RowMoved(FromIndex, ToIndex: Longint); dynamic;
  297.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect;
  298.       AState: TGridDrawState); virtual; abstract;
  299.     procedure DefineProperties(Filer: TFiler); override;
  300.     procedure MoveColRow(ACol, ARow: Longint; MoveAnchor, Show: Boolean);
  301.     function SelectCell(ACol, ARow: Longint): Boolean; virtual;
  302.     procedure SizeChanged(OldColCount, OldRowCount: Longint); dynamic;
  303.     function Sizing(X, Y: Integer): Boolean;
  304.     procedure ScrollData(DX, DY: Integer);
  305.     procedure InvalidateCell(ACol, ARow: Longint);
  306.     procedure InvalidateCol(ACol: Longint);
  307.     procedure InvalidateRow(ARow: Longint);
  308.     procedure TopLeftChanged; dynamic;
  309.     procedure TimedScroll(Direction: TGridScrollDirection); dynamic;
  310.     procedure Paint; override;
  311.     procedure ColWidthsChanged; dynamic;
  312.     procedure RowHeightsChanged; dynamic;
  313.     procedure DeleteColumn(ACol: Longint); virtual;
  314.     procedure DeleteRow(ARow: Longint); virtual;
  315.     procedure UpdateDesigner;
  316.     function BeginColumnDrag(var Origin, Destination: Integer;
  317.       const MousePt: TPoint): Boolean; dynamic;
  318.     function BeginRowDrag(var Origin, Destination: Integer;
  319.       const MousePt: TPoint): Boolean; dynamic;
  320.     function CheckColumnDrag(var Origin, Destination: Integer;
  321.       const MousePt: TPoint): Boolean; dynamic;
  322.     function CheckRowDrag(var Origin, Destination: Integer;
  323.       const MousePt: TPoint): Boolean; dynamic;
  324.     function EndColumnDrag(var Origin, Destination: Integer;
  325.       const MousePt: TPoint): Boolean; dynamic;
  326.     function EndRowDrag(var Origin, Destination: Integer;
  327.       const MousePt: TPoint): Boolean; dynamic;
  328.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
  329.     property Col: Longint read FCurrent.X write SetCol;
  330.     property Color default clWindow;
  331.     property ColCount: Longint read FColCount write SetColCount default 5;
  332.     property ColWidths[Index: Longint]: Integer read GetColWidths write SetColWidths;
  333.     property DefaultColWidth: Integer read FDefaultColWidth write SetDefaultColWidth default 64;
  334.     property DefaultDrawing: Boolean read FDefaultDrawing write FDefaultDrawing default True;
  335.     property DefaultRowHeight: Integer read FDefaultRowHeight write SetDefaultRowHeight default 24;
  336.     property EditorMode: Boolean read FEditorMode write SetEditorMode;
  337.     property FixedColor: TColor read FFixedColor write SetFixedColor default clBtnFace;
  338.     property FixedCols: Integer read FFixedCols write SetFixedCols default 1;
  339.     property FixedRows: Integer read FFixedRows write SetFixedRows default 1;
  340.     property GridHeight: Integer read GetGridHeight;
  341.     property GridLineWidth: Integer read FGridLineWidth write SetGridLineWidth default 1;
  342.     property GridWidth: Integer read GetGridWidth;
  343.     property HitTest: TPoint read FHitTest;
  344.     property InplaceEditor: TbsSkinInplaceEdit read FInplaceEdit;
  345.     property LeftCol: Longint read FTopLeft.X write SetLeftCol;
  346.     property Options: TGridOptions read FOptions write SetOptions
  347.       default [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine,
  348.       goRangeSelect];
  349.     property ParentColor default False;
  350.     property Row: Longint read FCurrent.Y write SetRow;
  351.     property RowCount: Longint read FRowCount write SetRowCount default 5;
  352.     property RowHeights[Index: Longint]: Integer read GetRowHeights write SetRowHeights;
  353.     property Selection: TGridRect read GetSelection write SetSelection;
  354.     property TabStops[Index: Longint]: Boolean read GetTabStops write SetTabStops;
  355.     property TopRow: Longint read FTopLeft.Y write SetTopRow;
  356.     property VisibleColCount: Integer read GetVisibleColCount;
  357.     property VisibleRowCount: Integer read GetVisibleRowCount;
  358.     procedure Notification(AComponent: TComponent;
  359.       Operation: TOperation); override;
  360.     procedure CMVisibleChanged(var Message: TMessage); message CM_VISIBLECHANGED;
  361.   public
  362.     // skin properties
  363.     FixedCellRect, SelectCellRect, FocusCellRect: TRect;
  364.     FixedCellLeftOffset, FixedCellRightOffset: Integer;
  365.     FixedCellTextRect: TRect;
  366.     CellLeftOffset, CellRightOffset: Integer;
  367.     CellTextRect: TRect;
  368.     LinesColor, BGColor: TColor;
  369.     FontName: String;
  370.     FontStyle: TFontStyles;
  371.     FontHeight: Integer;
  372.     FontColor, SelectFontColor, FocusFontColor: TColor;
  373.     FixedFontName: String;
  374.     FixedFontStyle: TFontStyles;
  375.     FixedFontHeight: Integer;
  376.     FixedFontColor: TColor;
  377.     Picture: TBitMap;
  378.     procedure ChangeSkinData; override;
  379.     function GetNewTextRect(CellR: TRect; AState: TGridDrawState): TRect;
  380.     //
  381.     constructor Create(AOwner: TComponent); override;
  382.     destructor Destroy; override;
  383.     function MouseCoord(X, Y: Integer): TGridCoord;
  384.   published
  385.     property TabStop default True;
  386.     property UseSkinFont: Boolean read FUseSkinFont write FUseSkinFont;
  387.     property UseSkinCellHeight: Boolean read
  388.       FUseSkinCellHeight write FUseSkinCellHeight;
  389.     property HScrollBar: TbsSkinScrollBar read FHScrollBar
  390.                                           write SetHScrollBar;
  391.     property VScrollBar: TbsSkinScrollBar read FVScrollBar
  392.                                           write SetVScrollBar;
  393.     property GridLineColor: TColor read FGridLineColor write SetGridLineColor;
  394.     property DefaultCellHeight: Integer read FDefaultCellHeight
  395.                                         write SetDefaultCellHeight;
  396.   end;
  397.   { TbsSkinDrawGrid }
  398.   TGetEditEvent = procedure (Sender: TObject; ACol, ARow: Longint; var Value: string) of object;
  399.   TSetEditEvent = procedure (Sender: TObject; ACol, ARow: Longint; const Value: string) of object;
  400.   TMovedEvent = procedure (Sender: TObject; FromIndex, ToIndex: Longint) of object;
  401.   TbsSkinDrawGrid = class(TbsSkinCustomGrid)
  402.   private
  403.     FOnColumnMoved: TMovedEvent;
  404.     FOnDrawCell: TDrawCellEvent;
  405.     FOnGetEditMask: TGetEditEvent;
  406.     FOnGetEditText: TGetEditEvent;
  407.     FOnRowMoved: TMovedEvent;
  408.     FOnSelectCell: TSelectCellEvent;
  409.     FOnSetEditText: TSetEditEvent;
  410.     FOnTopLeftChanged: TNotifyEvent;
  411.   protected
  412.     procedure ColumnMoved(FromIndex, ToIndex: Longint); override;
  413.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect;
  414.       AState: TGridDrawState); override;
  415.     function GetEditMask(ACol, ARow: Longint): string; override;
  416.     function GetEditText(ACol, ARow: Longint): string; override;
  417.     procedure RowMoved(FromIndex, ToIndex: Longint); override;
  418.     function SelectCell(ACol, ARow: Longint): Boolean; override;
  419.     procedure SetEditText(ACol, ARow: Longint; const Value: string); override;
  420.     procedure TopLeftChanged; override;
  421.   public
  422.     function CellRect(ACol, ARow: Longint): TRect;
  423.     procedure MouseToCell(X, Y: Integer; var ACol, ARow: Longint);
  424.     property Canvas;
  425.     property Col;
  426.     property ColWidths;
  427.     property EditorMode;
  428.     property GridHeight;
  429.     property GridWidth;
  430.     property LeftCol;
  431.     property Selection;
  432.     property Row;
  433.     property RowHeights;
  434.     property TabStops;
  435.     property TopRow;
  436.   published
  437.     property Align;
  438.     property Anchors;
  439.     property BiDiMode;
  440.     property BorderStyle;
  441.     property Color;
  442.     property ColCount;
  443.     property Constraints;
  444.     property DefaultColWidth;
  445.     property DefaultRowHeight;
  446.     property DefaultDrawing;
  447.     property DragCursor;
  448.     property DragKind;
  449.     property DragMode;
  450.     property Enabled;
  451.     property FixedColor;
  452.     property FixedCols;
  453.     property RowCount;
  454.     property FixedRows;
  455.     property Font;
  456.     property GridLineWidth;
  457.     property Options;
  458.     property ParentBiDiMode;
  459.     property ParentColor;
  460.     property ParentFont;
  461.     property ParentShowHint;
  462.     property PopupMenu;
  463.     property ShowHint;
  464.     property TabOrder;
  465.     property TabStop;
  466.     property Visible;
  467.     property VisibleColCount;
  468.     property VisibleRowCount;
  469.     property OnClick;
  470.     property OnColumnMoved: TMovedEvent read FOnColumnMoved write FOnColumnMoved;
  471.     property OnDblClick;
  472.     property OnDragDrop;
  473.     property OnDragOver;
  474.     property OnDrawCell: TDrawCellEvent read FOnDrawCell write FOnDrawCell;
  475.     property OnEndDock;
  476.     property OnEndDrag;
  477.     property OnEnter;
  478.     property OnExit;
  479.     property OnGetEditMask: TGetEditEvent read FOnGetEditMask write FOnGetEditMask;
  480.     property OnGetEditText: TGetEditEvent read FOnGetEditText write FOnGetEditText;
  481.     property OnKeyDown;
  482.     property OnKeyPress;
  483.     property OnKeyUp;
  484.     property OnMouseDown;
  485.     property OnMouseMove;
  486.     property OnMouseUp;
  487.     property OnMouseWheelDown;
  488.     property OnMouseWheelUp;
  489.     property OnRowMoved: TMovedEvent read FOnRowMoved write FOnRowMoved;
  490.     property OnSelectCell: TSelectCellEvent read FOnSelectCell write FOnSelectCell;
  491.     property OnSetEditText: TSetEditEvent read FOnSetEditText write FOnSetEditText;
  492.     property OnStartDock;
  493.     property OnStartDrag;
  494.     property OnTopLeftChanged: TNotifyEvent read FOnTopLeftChanged write FOnTopLeftChanged;
  495.   end;
  496.   { TbsSkinStringGrid }
  497.   TbsSkinStringGrid = class;
  498.   TbsSkinStringGridStrings = class(TStrings)
  499.   private
  500.     FGrid: TbsSkinStringGrid;
  501.     FIndex: Integer;
  502.     procedure CalcXY(Index: Integer; var X, Y: Integer);
  503.   protected
  504.     function Get(Index: Integer): string; override;
  505.     function GetCount: Integer; override;
  506.     function GetObject(Index: Integer): TObject; override;
  507.     procedure Put(Index: Integer; const S: string); override;
  508.     procedure PutObject(Index: Integer; AObject: TObject); override;
  509.     procedure SetUpdateState(Updating: Boolean); override;
  510.   public
  511.     constructor Create(AGrid: TbsSkinStringGrid; AIndex: Longint);
  512.     function Add(const S: string): Integer; override;
  513.     procedure Assign(Source: TPersistent); override;
  514.     procedure Clear; override;
  515.     procedure Delete(Index: Integer); override;
  516.     procedure Insert(Index: Integer; const S: string); override;
  517.   end;
  518.   TbsSkinStringGrid = class(TbsSkinDrawGrid)
  519.   private
  520.     FData: Pointer;
  521.     FRows: Pointer;
  522.     FCols: Pointer;
  523.     FUpdating: Boolean;
  524.     FNeedsUpdating: Boolean;
  525.     FEditUpdate: Integer;
  526.     procedure DisableEditUpdate;
  527.     procedure EnableEditUpdate;
  528.     procedure Initialize;
  529.     procedure Update(ACol, ARow: Integer); reintroduce;
  530.     procedure SetUpdateState(Updating: Boolean);
  531.     function GetCells(ACol, ARow: Integer): string;
  532.     function GetCols(Index: Integer): TStrings;
  533.     function GetObjects(ACol, ARow: Integer): TObject;
  534.     function GetRows(Index: Integer): TStrings;
  535.     procedure SetCells(ACol, ARow: Integer; const Value: string);
  536.     procedure SetCols(Index: Integer; Value: TStrings);
  537.     procedure SetObjects(ACol, ARow: Integer; Value: TObject);
  538.     procedure SetRows(Index: Integer; Value: TStrings);
  539.     function EnsureColRow(Index: Integer; IsCol: Boolean): TbsSkinStringGridStrings;
  540.     function EnsureDataRow(ARow: Integer): Pointer;
  541.   protected
  542.     procedure ColumnMoved(FromIndex, ToIndex: Longint); override;
  543.     procedure DrawCell(ACol, ARow: Longint; ARect: TRect;
  544.       AState: TGridDrawState); override;
  545.     function GetEditText(ACol, ARow: Longint): string; override;
  546.     procedure SetEditText(ACol, ARow: Longint; const Value: string); override;
  547.     procedure RowMoved(FromIndex, ToIndex: Longint); override;
  548.   public
  549.     constructor Create(AOwner: TComponent); override;
  550.     destructor Destroy; override;
  551.     property Cells[ACol, ARow: Integer]: string read GetCells write SetCells;
  552.     property Cols[Index: Integer]: TStrings read GetCols write SetCols;
  553.     property Objects[ACol, ARow: Integer]: TObject read GetObjects write SetObjects;
  554.     property Rows[Index: Integer]: TStrings read GetRows write SetRows;
  555.   end;
  556. implementation
  557. uses Math, Consts, bsUtils, Clipbrd, bsConst;
  558. type
  559.   PIntArray = ^TIntArray;
  560.   TIntArray = array[0..MaxCustomExtents] of Integer;
  561. procedure InvalidOp(const id: string);
  562. begin
  563.   raise bsEInvalidGridOperation.Create(id);
  564. end;
  565. function GridRect(Coord1, Coord2: TGridCoord): TGridRect;
  566. begin
  567.   with Result do
  568.   begin
  569.     Left := Coord2.X;
  570.     if Coord1.X < Coord2.X then Left := Coord1.X;
  571.     Right := Coord1.X;
  572.     if Coord1.X < Coord2.X then Right := Coord2.X;
  573.     Top := Coord2.Y;
  574.     if Coord1.Y < Coord2.Y then Top := Coord1.Y;
  575.     Bottom := Coord1.Y;
  576.     if Coord1.Y < Coord2.Y then Bottom := Coord2.Y;
  577.   end;
  578. end;
  579. function PointInGridRect(Col, Row: Longint; const Rect: TGridRect): Boolean;
  580. begin
  581.   Result := (Col >= Rect.Left) and (Col <= Rect.Right) and (Row >= Rect.Top)
  582.     and (Row <= Rect.Bottom);
  583. end;
  584. type
  585.   TXorRects = array[0..3] of TRect;
  586. procedure XorRects(const R1, R2: TRect; var XorRects: TXorRects);
  587. var
  588.   Intersect, Union: TRect;
  589.   function PtInRect(X, Y: Integer; const Rect: TRect): Boolean;
  590.   begin
  591.     with Rect do Result := (X >= Left) and (X <= Right) and (Y >= Top) and
  592.       (Y <= Bottom);
  593.   end;
  594.   function Includes(const P1: TPoint; var P2: TPoint): Boolean;
  595.   begin
  596.     with P1 do
  597.     begin
  598.       Result := PtInRect(X, Y, R1) or PtInRect(X, Y, R2);
  599.       if Result then P2 := P1;
  600.     end;
  601.   end;
  602.   function Build(var R: TRect; const P1, P2, P3: TPoint): Boolean;
  603.   begin
  604.     Build := True;
  605.     with R do
  606.       if Includes(P1, TopLeft) then
  607.       begin
  608.         if not Includes(P3, BottomRight) then BottomRight := P2;
  609.       end
  610.       else if Includes(P2, TopLeft) then BottomRight := P3
  611.       else Build := False;
  612.   end;
  613. begin
  614.   FillChar(XorRects, SizeOf(XorRects), 0);
  615.   if not Bool(IntersectRect(Intersect, R1, R2)) then
  616.   begin
  617.     { Don't intersect so its simple }
  618.     XorRects[0] := R1;
  619.     XorRects[1] := R2;
  620.   end
  621.   else
  622.   begin
  623.     UnionRect(Union, R1, R2);
  624.     if Build(XorRects[0],
  625.       Point(Union.Left, Union.Top),
  626.       Point(Union.Left, Intersect.Top),
  627.       Point(Union.Left, Intersect.Bottom)) then
  628.       XorRects[0].Right := Intersect.Left;
  629.     if Build(XorRects[1],
  630.       Point(Intersect.Left, Union.Top),
  631.       Point(Intersect.Right, Union.Top),
  632.       Point(Union.Right, Union.Top)) then
  633.       XorRects[1].Bottom := Intersect.Top;
  634.     if Build(XorRects[2],
  635.       Point(Union.Right, Intersect.Top),
  636.       Point(Union.Right, Intersect.Bottom),
  637.       Point(Union.Right, Union.Bottom)) then
  638.       XorRects[2].Left := Intersect.Right;
  639.     if Build(XorRects[3],
  640.       Point(Union.Left, Union.Bottom),
  641.       Point(Intersect.Left, Union.Bottom),
  642.       Point(Intersect.Right, Union.Bottom)) then
  643.       XorRects[3].Top := Intersect.Bottom;
  644.   end;
  645. end;
  646. procedure ModifyExtents(var Extents: Pointer; Index, Amount: Longint;
  647.   Default: Integer);
  648. var
  649.   LongSize, OldSize: LongInt;
  650.   NewSize: Integer;
  651.   I: Integer;
  652. begin
  653.   if Amount <> 0 then
  654.   begin
  655.     if not Assigned(Extents) then OldSize := 0
  656.     else OldSize := PIntArray(Extents)^[0];
  657.     if (Index < 0) or (OldSize < Index) then InvalidOp(SIndexOutOfRange);
  658.     LongSize := OldSize + Amount;
  659.     if LongSize < 0 then InvalidOp(STooManyDeleted)
  660.     else if LongSize >= MaxListSize - 1 then InvalidOp(SGridTooLarge);
  661.     NewSize := Cardinal(LongSize);
  662.     if NewSize > 0 then Inc(NewSize);
  663.     ReallocMem(Extents, NewSize * SizeOf(Integer));
  664.     if Assigned(Extents) then
  665.     begin
  666.       I := Index + 1;
  667.       while I < NewSize do
  668.       begin
  669.         PIntArray(Extents)^[I] := Default;
  670.         Inc(I);
  671.       end;
  672.       PIntArray(Extents)^[0] := NewSize-1;
  673.     end;
  674.   end;
  675. end;
  676. procedure UpdateExtents(var Extents: Pointer; NewSize: Longint;
  677.   Default: Integer);
  678. var
  679.   OldSize: Integer;
  680. begin
  681.   OldSize := 0;
  682.   if Assigned(Extents) then OldSize := PIntArray(Extents)^[0];
  683.   ModifyExtents(Extents, OldSize, NewSize - OldSize, Default);
  684. end;
  685. procedure MoveExtent(var Extents: Pointer; FromIndex, ToIndex: Longint);
  686. var
  687.   Extent: Integer;
  688. begin
  689.   if Assigned(Extents) then
  690.   begin
  691.     Extent := PIntArray(Extents)^[FromIndex];
  692.     if FromIndex < ToIndex then
  693.       Move(PIntArray(Extents)^[FromIndex + 1], PIntArray(Extents)^[FromIndex],
  694.         (ToIndex - FromIndex) * SizeOf(Integer))
  695.     else if FromIndex > ToIndex then
  696.       Move(PIntArray(Extents)^[ToIndex], PIntArray(Extents)^[ToIndex + 1],
  697.         (FromIndex - ToIndex) * SizeOf(Integer));
  698.     PIntArray(Extents)^[ToIndex] := Extent;
  699.   end;
  700. end;
  701. function CompareExtents(E1, E2: Pointer): Boolean;
  702. var
  703.   I: Integer;
  704. begin
  705.   Result := False;
  706.   if E1 <> nil then
  707.   begin
  708.     if E2 <> nil then
  709.     begin
  710.       for I := 0 to PIntArray(E1)^[0] do
  711.         if PIntArray(E1)^[I] <> PIntArray(E2)^[I] then Exit;
  712.       Result := True;
  713.     end
  714.   end
  715.   else Result := E2 = nil;
  716. end;
  717. function LongMulDiv(Mult1, Mult2, Div1: Longint): Longint; stdcall;
  718.   external 'kernel32.dll' name 'MulDiv';
  719. type
  720.   TSelection = record
  721.     StartPos, EndPos: Integer;
  722.   end;
  723. constructor TbsSkinInplaceEdit.Create(AOwner: TComponent);
  724. begin
  725.   inherited Create(AOwner);
  726.   ParentCtl3D := False;
  727.   Ctl3D := False;
  728.   TabStop := False;
  729.   BorderStyle := bsNone;
  730.   FSysPopupMenu := nil;
  731. end;
  732. destructor TbsSkinInplaceEdit.Destroy;
  733. begin
  734.   if FSysPopupMenu <> nil then FSysPopupMenu.Free;
  735.   inherited;
  736. end;
  737. procedure TbsSkinInplaceEdit.WMCONTEXTMENU;
  738. var
  739.   X, Y: Integer;
  740.   P: TPoint;
  741. begin
  742.   if PopupMenu <> nil
  743.   then
  744.     inherited
  745.   else
  746.     begin
  747.       CreateSysPopupMenu;
  748.       X := Message.XPos;
  749.       Y := Message.YPos;
  750.       if (X < 0) or (Y < 0)
  751.       then
  752.         begin
  753.           X := Width div 2;
  754.           Y := Height div 2;
  755.           P := Point(0, 0);
  756.           P := ClientToScreen(P);
  757.           X := X + P.X;
  758.           Y := Y + P.Y;
  759.         end;
  760.       if FSysPopupMenu <> nil
  761.       then
  762.         FSysPopupMenu.Popup2(Self, X, Y)
  763.     end;
  764. end;
  765. procedure TbsSkinInplaceEdit.WMAFTERDISPATCH;
  766. begin
  767.   if FSysPopupMenu <> nil
  768.   then
  769.     begin
  770.       FSysPopupMenu.Free;
  771.       FSysPopupMenu := nil;
  772.     end;
  773. end;
  774. procedure TbsSkinInplaceEdit.DoUndo;
  775. begin
  776.   Undo;
  777. end;
  778. procedure TbsSkinInplaceEdit.DoCut;
  779. begin
  780.   CutToClipboard;
  781. end;
  782. procedure TbsSkinInplaceEdit.DoCopy;
  783. begin
  784.   CopyToClipboard;
  785. end;
  786. procedure TbsSkinInplaceEdit.DoPaste;
  787. begin
  788.   PasteFromClipboard;
  789. end;
  790. procedure TbsSkinInplaceEdit.DoDelete;
  791. begin
  792.   ClearSelection;
  793. end;
  794. procedure TbsSkinInplaceEdit.DoSelectAll;
  795. begin
  796.   SelectAll;
  797. end;
  798. procedure TbsSkinInplaceEdit.CreateSysPopupMenu;
  799. function IsSelected: Boolean;
  800. var
  801.   i, j: Integer;
  802. begin
  803.   GetSel(i, j);
  804.   Result := (i < j);
  805. end;
  806. function IsFullSelected: Boolean;
  807. var
  808.   i, j: Integer;
  809. begin
  810.   GetSel(i, j);
  811.   Result := (i = 0) and (j = Length(Text));
  812. end;
  813. var
  814.   Item: TMenuItem;
  815. begin
  816.   if FSysPopupMenu <> nil then FSysPopupMenu.Free;
  817.   FSysPopupMenu := TbsSkinPopupMenu.Create(Self);
  818.   FSysPopupMenu.ComponentForm := TForm(GetParentForm(Self));
  819.   Item := TMenuItem.Create(FSysPopupMenu);
  820.   with Item do
  821.   begin
  822.     if (FGrid.SkinData <> nil) and (FGrid.SkinData.ResourceStrData <> nil)
  823.     then
  824.       Caption := FGrid.SkinData.ResourceStrData.GetResStr('EDIT_UNDO')
  825.     else
  826.       Caption := BS_Edit_Undo;
  827.     OnClick := DoUndo;
  828.     Enabled := Self.CanUndo;
  829.   end;
  830.   FSysPopupMenu.Items.Add(Item);
  831.   Item := TMenuItem.Create(FSysPopupMenu);
  832.   Item.Caption := '-';
  833.   FSysPopupMenu.Items.Add(Item);
  834.   Item := TMenuItem.Create(FSysPopupMenu);
  835.   with Item do
  836.   begin
  837.     if (FGrid.SkinData <> nil) and (FGrid.SkinData.ResourceStrData <> nil)
  838.     then
  839.       Caption := FGrid.SkinData.ResourceStrData.GetResStr('EDIT_CUT')
  840.     else
  841.       Caption := BS_Edit_Cut;
  842.     Enabled := IsSelected and not Self.ReadOnly;
  843.     OnClick := DoCut;
  844.   end;
  845.   FSysPopupMenu.Items.Add(Item);
  846.   Item := TMenuItem.Create(FSysPopupMenu);
  847.   with Item do
  848.   begin
  849.     if (FGrid.SkinData <> nil) and (FGrid.SkinData.ResourceStrData <> nil)
  850.     then
  851.       Caption := FGrid.SkinData.ResourceStrData.GetResStr('EDIT_COPY')
  852.     else
  853.       Caption := BS_Edit_Copy;
  854.     Enabled := IsSelected;
  855.     OnClick := DoCopy;
  856.   end;
  857.   FSysPopupMenu.Items.Add(Item);
  858.   Item := TMenuItem.Create(FSysPopupMenu);
  859.   with Item do
  860.   begin
  861.     if (FGrid.SkinData <> nil) and (FGrid.SkinData.ResourceStrData <> nil)
  862.     then
  863.       Caption := FGrid.SkinData.ResourceStrData.GetResStr('EDIT_PASTE')
  864.     else
  865.       Caption := BS_Edit_Paste;
  866.     Enabled := (ClipBoard.AsText <> '') and not ReadOnly;
  867.     OnClick := DoPaste;
  868.   end;
  869.   FSysPopupMenu.Items.Add(Item);
  870.   Item := TMenuItem.Create(FSysPopupMenu);
  871.   with Item do
  872.   begin
  873.     if (FGrid.SkinData <> nil) and (FGrid.SkinData.ResourceStrData <> nil)
  874.     then
  875.       Caption := FGrid.SkinData.ResourceStrData.GetResStr('EDIT_DELETE')
  876.     else
  877.       Caption := BS_Edit_Delete;
  878.     Enabled := IsSelected and not Self.ReadOnly;
  879.     OnClick := DoDelete;
  880.   end;
  881.   FSysPopupMenu.Items.Add(Item);
  882.   Item := TMenuItem.Create(FSysPopupMenu);
  883.   Item.Caption := '-';
  884.   FSysPopupMenu.Items.Add(Item);
  885.   Item := TMenuItem.Create(FSysPopupMenu);
  886.   with Item do
  887.   begin
  888.      if (FGrid.SkinData <> nil) and (FGrid.SkinData.ResourceStrData <> nil)
  889.     then
  890.       Caption := FGrid.SkinData.ResourceStrData.GetResStr('EDIT_SELECTALL')
  891.     else
  892.       Caption := BS_Edit_SelectAll;
  893.     Enabled := not IsFullSelected;
  894.     OnClick := DoSelectAll;
  895.   end;
  896.   FSysPopupMenu.Items.Add(Item);
  897. end;
  898. procedure TbsSkinInplaceEdit.CreateParams(var Params: TCreateParams);
  899. begin
  900.   inherited CreateParams(Params);
  901.   Params.Style := Params.Style or ES_MULTILINE;
  902. end;
  903. procedure TbsSkinInplaceEdit.SetGrid(Value: TbsSkinCustomGrid);
  904. begin
  905.   FGrid := Value;
  906. end;
  907. procedure TbsSkinInplaceEdit.CMShowingChanged(var Message: TMessage);
  908. begin
  909. end;
  910. procedure TbsSkinInplaceEdit.WMGetDlgCode(var Message: TWMGetDlgCode);
  911. begin
  912.   inherited;
  913.   if goTabs in Grid.Options then
  914.     Message.Result := Message.Result or DLGC_WANTTAB;
  915. end;
  916. procedure TbsSkinInplaceEdit.WMPaste(var Message);
  917. begin
  918.   if not EditCanModify then Exit;
  919.   inherited
  920. end;
  921. procedure TbsSkinInplaceEdit.WMClear(var Message);
  922. begin
  923.   if not EditCanModify then Exit;
  924.   inherited;
  925. end;
  926. procedure TbsSkinInplaceEdit.WMCut(var Message);
  927. begin
  928.   if not EditCanModify then Exit;
  929.   inherited;
  930. end;
  931. procedure TbsSkinInplaceEdit.DblClick;
  932. begin
  933.   Grid.DblClick;
  934. end;
  935. function TbsSkinInplaceEdit.EditCanModify: Boolean;
  936. begin
  937.   Result := Grid.CanEditModify;
  938. end;
  939. procedure TbsSkinInplaceEdit.KeyDown(var Key: Word; Shift: TShiftState);
  940.   procedure SendToParent;
  941.   begin
  942.     Grid.KeyDown(Key, Shift);
  943.     Key := 0;
  944.   end;
  945.   procedure ParentEvent;
  946.   var
  947.     GridKeyDown: TKeyEvent;
  948.   begin
  949.     GridKeyDown := Grid.OnKeyDown;
  950.     if Assigned(GridKeyDown) then GridKeyDown(Grid, Key, Shift);
  951.   end;
  952.   function ForwardMovement: Boolean;
  953.   begin
  954.     Result := goAlwaysShowEditor in Grid.Options;
  955.   end;
  956.   function Ctrl: Boolean;
  957.   begin
  958.     Result := ssCtrl in Shift;
  959.   end;
  960.   function Selection: TSelection;
  961.   begin
  962.     SendMessage(Handle, EM_GETSEL, Longint(@Result.StartPos), Longint(@Result.EndPos));
  963.   end;
  964.   function RightSide: Boolean;
  965.   begin
  966.     with Selection do
  967.       Result := ((StartPos = 0) or (EndPos = StartPos)) and
  968.         (EndPos = GetTextLen);
  969.    end;
  970.   function LeftSide: Boolean;
  971.   begin
  972.     with Selection do
  973.       Result := (StartPos = 0) and ((EndPos = 0) or (EndPos = GetTextLen));
  974.   end;
  975. begin
  976.   case Key of
  977.     VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, VK_ESCAPE: SendToParent;
  978.     VK_INSERT:
  979.       if Shift = [] then SendToParent
  980.       else if (Shift = [ssShift]) and not Grid.CanEditModify then Key := 0;
  981.     VK_LEFT: if ForwardMovement and (Ctrl or LeftSide) then SendToParent;
  982.     VK_RIGHT: if ForwardMovement and (Ctrl or RightSide) then SendToParent;
  983.     VK_HOME: if ForwardMovement and (Ctrl or LeftSide) then SendToParent;
  984.     VK_END: if ForwardMovement and (Ctrl or RightSide) then SendToParent;
  985.     VK_F2:
  986.       begin
  987.         ParentEvent;
  988.         if Key = VK_F2 then
  989.         begin
  990.           Deselect;
  991.           Exit;
  992.         end;
  993.       end;
  994.     VK_TAB: if not (ssAlt in Shift) then SendToParent;
  995.   end;
  996.   if (Key = VK_DELETE) and not Grid.CanEditModify then Key := 0;
  997.   if Key <> 0 then
  998.   begin
  999.     ParentEvent;
  1000.     inherited KeyDown(Key, Shift);
  1001.   end;
  1002. end;
  1003. procedure TbsSkinInplaceEdit.KeyPress(var Key: Char);
  1004. var
  1005.   Selection: TSelection;
  1006. begin
  1007.   Grid.KeyPress(Key);
  1008.   if (Key in [#32..#255]) and not Grid.CanEditAcceptKey(Key) then
  1009.   begin
  1010.     Key := #0;
  1011.     MessageBeep(0);
  1012.   end;
  1013.   case Key of
  1014.     #9, #27: Key := #0;
  1015.     #13:
  1016.       begin
  1017.         SendMessage(Handle, EM_GETSEL, Longint(@Selection.StartPos), Longint(@Selection.EndPos));
  1018.         if (Selection.StartPos = 0) and (Selection.EndPos = GetTextLen) then
  1019.           Deselect else
  1020.           SelectAll;
  1021.         Key := #0;
  1022.       end;
  1023.     ^H, ^V, ^X, #32..#255:
  1024.       if not Grid.CanEditModify then Key := #0;
  1025.   end;
  1026.   if Key <> #0 then inherited KeyPress(Key);
  1027. end;
  1028. procedure TbsSkinInplaceEdit.KeyUp(var Key: Word; Shift: TShiftState);
  1029. begin
  1030.   Grid.KeyUp(Key, Shift);
  1031. end;
  1032. procedure TbsSkinInplaceEdit.WndProc(var Message: TMessage);
  1033. var
  1034.   FOld: Boolean;
  1035. begin
  1036.   FOld := True;
  1037.   case Message.Msg of
  1038.     WM_SETFOCUS:
  1039.       begin
  1040.         if (GetParentForm(Self) = nil) or GetParentForm(Self).SetFocusedControl(Grid) then Dispatch(Message);
  1041.         Exit;
  1042.       end;
  1043.     WM_LBUTTONDOWN:
  1044.       begin
  1045.         if ((GetMessageTime - FClickTime) < GetDoubleClickTime) then
  1046.           Message.Msg := WM_LBUTTONDBLCLK;
  1047.         FClickTime := 0;
  1048.       end;
  1049.   end;
  1050.   if FOld then inherited WndProc(Message);
  1051. end;
  1052. procedure TbsSkinInplaceEdit.Deselect;
  1053. begin
  1054.   SendMessage(Handle, EM_SETSEL, $7FFFFFFF, Longint($FFFFFFFF));
  1055. end;
  1056. procedure TbsSkinInplaceEdit.Invalidate;
  1057. var
  1058.   Cur: TRect;
  1059. begin
  1060.   ValidateRect(Handle, nil);
  1061.   InvalidateRect(Handle, nil, True);
  1062.   Windows.GetClientRect(Handle, Cur);
  1063.   MapWindowPoints(Handle, Grid.Handle, Cur, 2);
  1064.   ValidateRect(Grid.Handle, @Cur);
  1065.   InvalidateRect(Grid.Handle, @Cur, False);
  1066. end;
  1067. procedure TbsSkinInplaceEdit.Hide;
  1068. begin
  1069.   if HandleAllocated and IsWindowVisible(Handle) then
  1070.   begin
  1071.     Invalidate;
  1072.     SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_HIDEWINDOW or SWP_NOZORDER or
  1073.       SWP_NOREDRAW);
  1074.     if Focused then Windows.SetFocus(Grid.Handle);
  1075.   end;
  1076. end;
  1077. function TbsSkinInplaceEdit.PosEqual(const Rect: TRect): Boolean;
  1078. var
  1079.   Cur: TRect;
  1080. begin
  1081.   GetWindowRect(Handle, Cur);
  1082.   MapWindowPoints(HWND_DESKTOP, Grid.Handle, Cur, 2);
  1083.   Result := EqualRect(Rect, Cur);
  1084. end;
  1085. procedure TbsSkinInplaceEdit.InternalMove(const Loc: TRect; Redraw: Boolean);
  1086. begin
  1087.   if IsRectEmpty(Loc) then Hide
  1088.   else
  1089.   begin
  1090.     CreateHandle;
  1091.     Redraw := Redraw or not IsWindowVisible(Handle);
  1092.     Invalidate;
  1093.     with Loc do
  1094.       SetWindowPos(Handle, HWND_TOP, Left, Top, Right - Left, Bottom - Top,
  1095.         SWP_SHOWWINDOW or SWP_NOREDRAW);
  1096.     BoundsChanged;
  1097.     if Redraw then Invalidate;
  1098.     if Grid.Focused then
  1099.       Windows.SetFocus(Handle);
  1100.   end;
  1101. end;
  1102. procedure TbsSkinInplaceEdit.BoundsChanged;
  1103. var
  1104.   R: TRect;
  1105. begin
  1106.   R := Rect(2, 2, Width - 2, Height);
  1107.   SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@R));
  1108.   SendMessage(Handle, EM_SCROLLCARET, 0, 0);
  1109. end;
  1110. procedure TbsSkinInplaceEdit.UpdateLoc(const Loc: TRect);
  1111. begin
  1112.   InternalMove(Loc, False);
  1113. end;
  1114. function TbsSkinInplaceEdit.Visible: Boolean;
  1115. begin
  1116.   Result := IsWindowVisible(Handle);
  1117. end;
  1118. procedure TbsSkinInplaceEdit.Move(const Loc: TRect);
  1119. begin
  1120.   InternalMove(Loc, True);
  1121. end;
  1122. procedure TbsSkinInplaceEdit.SetFocus;
  1123. begin
  1124.   if IsWindowVisible(Handle) then
  1125.     Windows.SetFocus(Handle);
  1126. end;
  1127. procedure TbsSkinInplaceEdit.UpdateContents;
  1128. begin
  1129.   Text := '';
  1130.   EditMask := Grid.GetEditMask(Grid.Col, Grid.Row);
  1131.   Text := Grid.GetEditText(Grid.Col, Grid.Row);
  1132.   MaxLength := Grid.GetEditLimit;
  1133. end;
  1134. { TbsSkinCustomGrid }
  1135. constructor TbsSkinCustomGrid.Create(AOwner: TComponent);
  1136. const
  1137.   GridStyle = [csCaptureMouse, csOpaque, csDoubleClicks];
  1138. begin
  1139.   inherited Create(AOwner);
  1140.   FHScrollBar := nil;
  1141.   FVScrollBar := nil;
  1142.   FUseSkinCellHeight := True;
  1143.   FUseSkinFont := True;
  1144.   Ctl3D := False;
  1145.   if NewStyleControls then
  1146.     ControlStyle := GridStyle else
  1147.     ControlStyle := GridStyle + [csFramed];
  1148.   FCanEditModify := True;
  1149.   FColCount := 5;
  1150.   FRowCount := 5;
  1151.   FFixedCols := 1;
  1152.   FFixedRows := 1;
  1153.   FGridLineWidth := 1;
  1154.   FOptions := [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine,
  1155.     goRangeSelect];
  1156.   DesignOptionsBoost := [goColSizing, goRowSizing];
  1157.   FFixedColor := clBtnFace;
  1158.   FBorderStyle := bsSingle;
  1159.   FDefaultColWidth := 64;
  1160.   FDefaultRowHeight := 20;
  1161.   FDefaultCellHeight := 20;
  1162.   FDefaultDrawing := True;
  1163.   FSaveCellExtents := True;
  1164.   FEditorMode := False;
  1165.   Picture := nil;
  1166.   Color := clWindow;
  1167.   ParentColor := False;
  1168.   TabStop := True;
  1169.   SetBounds(Left, Top, FColCount * FDefaultColWidth,
  1170.     FRowCount * FDefaultRowHeight);
  1171.   Initialize;
  1172.   FSkinDataName := 'grid';
  1173.   FGridLineColor := clWindowText;
  1174.   FInCheckScrollBars := False;
  1175. end;
  1176. destructor TbsSkinCustomGrid.Destroy;
  1177. begin
  1178.   FInplaceEdit.Free;
  1179.   inherited Destroy;
  1180.   FreeMem(FColWidths);
  1181.   FreeMem(FRowHeights);
  1182.   FreeMem(FTabStops);
  1183. end;
  1184. procedure TbsSkinCustomGrid.CMVisibleChanged;
  1185. begin
  1186.   inherited;
  1187.   if FVScrollBar <> nil then FVScrollBar.Visible := Self.Visible;
  1188.   if FHScrollBar <> nil then FHScrollBar.Visible := Self.Visible; 
  1189. end;
  1190. procedure TbsSkinCustomGrid.SetDefaultCellHeight(Value: Integer);
  1191. begin
  1192.   FDefaultCellHeight := Value;
  1193.   if FIndex = -1 then DefaultRowHeight := FDefaultCellHeight;
  1194. end;
  1195. procedure TbsSkinCustomGrid.SetGridLineColor;
  1196. begin
  1197.   FGridLineColor := Value;
  1198.   if FIndex = -1 then RePaint; 
  1199. end;
  1200. procedure TbsSkinCustomGrid.Notification;
  1201. begin
  1202.   inherited Notification(AComponent, Operation);
  1203.   if (Operation = opRemove) and (AComponent = FHScrollBar)
  1204.   then FHScrollBar := nil;
  1205.   if (Operation = opRemove) and (AComponent = FVScrollBar)
  1206.   then FVScrollBar := nil;
  1207. end;
  1208. procedure TbsSkinCustomGrid.SetHScrollBar;
  1209. begin
  1210.   FHScrollBar := Value;
  1211.   if FHScrollBar <> nil
  1212.   then
  1213.     begin
  1214.       FHScrollBar.Enabled := True;
  1215.       FHScrollBar.Visible := False;
  1216.       FHScrollBar.OnLastChange := OnHScrollBarChange;
  1217.       FHScrollBar.OnUpButtonClick := OnHScrollBarUpButtonClick;
  1218.       FHScrollBar.OnDownButtonClick := OnHScrollBarDownButtonClick;
  1219.       FHScrollBar.OnPageUp := OnHScrollBarPageUp;
  1220.       FHScrollBar.OnPageDown := OnHScrollBarPageDown;
  1221.       UpdateScrollRange(True);
  1222.     end;
  1223. end;
  1224. procedure TbsSkinCustomGrid.SetVScrollBar;
  1225. begin
  1226.   FVScrollBar := Value;
  1227.   if FVScrollBar <> nil
  1228.   then
  1229.     begin
  1230.       FVScrollBar.Enabled := True;
  1231.       FVScrollBar.Visible := False;
  1232.       FVScrollBar.OnLastChange := OnVScrollBarChange;
  1233.       FVScrollBar.OnUpButtonClick := OnVScrollBarUpButtonClick;
  1234.       FVScrollBar.OnDownButtonClick := OnVScrollBarDownButtonClick;
  1235.       FVScrollBar.OnPageUp := OnVScrollBarPageUp;
  1236.       FVScrollBar.OnPageDown := OnVScrollBarPageDown;
  1237.       UpdateScrollRange(True);
  1238.     end;  
  1239. end;
  1240. procedure TbsSkinCustomGrid.OnVScrollBarUpButtonClick(Sender: TObject);
  1241. begin
  1242.   SendMessage(Handle, WM_VSCROLL,
  1243.     MakeWParam(SB_LINEDOWN, VScrollBar.Position), 0);
  1244. end;
  1245. procedure TbsSkinCustomGrid.OnVScrollBarDownButtonClick(Sender: TObject);
  1246. begin
  1247.   SendMessage(Handle, WM_VSCROLL,
  1248.     MakeWParam(SB_LINEUP, VScrollBar.Position), 0);
  1249. end;
  1250. procedure TbsSkinCustomGrid.OnHScrollBarUpButtonClick(Sender: TObject);
  1251. begin
  1252.   FHScrollBar.Position := FHScrollBar.Position + FHScrollBar.SmallChange;
  1253.   SendMessage(Handle, WM_HSCROLL,
  1254.     MakeWParam(SB_THUMBPOSITION, FHScrollBar.Position), 0);
  1255. end;
  1256. procedure TbsSkinCustomGrid.OnHScrollBarDownButtonClick(Sender: TObject);
  1257. begin
  1258.   FHScrollBar.Position := FHScrollBar.Position - FHScrollBar.SmallChange;
  1259.   SendMessage(Handle, WM_HSCROLL,
  1260.     MakeWParam(SB_THUMBPOSITION, FHScrollBar.Position), 0);
  1261. end;
  1262. procedure TbsSkinCustomGrid.OnVScrollBarPageUp(Sender: TObject);
  1263. begin
  1264.   SendMessage(Handle, WM_VSCROLL,
  1265.   MakeWParam(SB_PAGEUP, 0), 0);
  1266. end;
  1267. procedure TbsSkinCustomGrid.OnVScrollBarPageDown(Sender: TObject);
  1268. begin
  1269.   SendMessage(Handle, WM_VSCROLL,
  1270.   MakeWParam(SB_PAGEDOWN, 0), 0);
  1271. end;
  1272. procedure TbsSkinCustomGrid.OnHScrollBarPageUp(Sender: TObject);
  1273. begin
  1274.   SendMessage(Handle, WM_HSCROLL,
  1275.   MakeWParam(SB_PAGEUP, 0), 0);
  1276. end;
  1277. procedure TbsSkinCustomGrid.OnHScrollBarPageDown(Sender: TObject);
  1278. begin
  1279.   SendMessage(Handle, WM_HSCROLL,
  1280.   MakeWParam(SB_PAGEDOWN, 0), 0);
  1281. end;
  1282. procedure TbsSkinCustomGrid.OnVScrollBarChange(Sender: TObject);
  1283. begin
  1284.   SendMessage(Handle, WM_VSCROLL,
  1285.   MakeWParam(SB_THUMBPOSITION, FVScrollBar.Position), 0);
  1286. end;
  1287. procedure TbsSkinCustomGrid.OnHScrollBarChange(Sender: TObject);
  1288. begin
  1289.   SendMessage(Handle, WM_HSCROLL,
  1290.   MakeWParam(SB_THUMBPOSITION, FHScrollBar.Position), 0);
  1291. end;
  1292. function TbsSkinCustomGrid.GetNewTextRect;
  1293. var
  1294.   SR1, SR2, R: TRect;
  1295.   OX, OY: Integer;
  1296. begin
  1297.   if FIndex < 0
  1298.   then
  1299.     begin
  1300.       Result := CellR;
  1301.       Exit;
  1302.     end
  1303.   else
  1304.     begin
  1305.       R := CellR;
  1306.       if gdFixed in AState
  1307.       then
  1308.         begin
  1309.           SR1 := FixedCellRect;
  1310.           SR2 := FixedCellTextRect;
  1311.         end
  1312.       else
  1313.         begin
  1314.           SR1 := SelectCellRect;
  1315.           SR2 := CellTextRect;
  1316.         end;
  1317.       if not IsNullRect(SR2)
  1318.       then
  1319.         begin
  1320.           if not UseSkinCellHeight
  1321.           then
  1322.             OY := RectHeight(R) - RectHeight(FixedCellRect)
  1323.           else
  1324.             OY := 0;  
  1325.           OX := RectWidth(CellR) - RectWidth(SR1);
  1326.           Inc(R.Left, SR2.Left);
  1327.           Inc(R.Top, SR2.Top);
  1328.           R.Right := R.Left + RectWidth(SR2) + OX;
  1329.           R.Bottom := R.Top + RectHeight(SR2) + OY;
  1330.         end;
  1331.       Result := R;
  1332.     end
  1333. end;
  1334. procedure TbsSkinCustomGrid.ChangeSkinData;
  1335. var
  1336.   i, Old: Integer;
  1337. begin
  1338.   GetSkinData;
  1339.   if FIndex > -1
  1340.   then
  1341.     begin
  1342.       Old := DefaultRowHeight;
  1343.       i := RectHeight(SelectCellRect);
  1344.       if (i <> Old) and FUseSkinCellHeight
  1345.       then
  1346.         DefaultRowHeight := i
  1347.       else
  1348.         Invalidate;
  1349.     end
  1350.   else
  1351.     begin
  1352.       DefaultRowHeight := FDefaultCellHeight;
  1353.       Invalidate;
  1354.     end;
  1355.   UpDateScrollRange(True);
  1356.   if FVScrollBar <> nil then FVScrollBar.Align := FVScrollBar.Align;
  1357.   if FHScrollBar <> nil then FHScrollBar.Align := FHScrollBar.Align;
  1358. end;
  1359. procedure TbsSkinCustomGrid.GetSkinData;
  1360. begin
  1361.   Picture := nil;
  1362.   FIndex := -1;
  1363.   inherited;
  1364.   if FIndex > -1
  1365.   then
  1366.     if TbsDataSkinControl(FSD.CtrlList.Items[FIndex]) is TbsDataSkinGridControl
  1367.     then
  1368.       with TbsDataSkinGridControl(FSD.CtrlList.Items[FIndex]) do
  1369.       begin
  1370.         //
  1371.         if (PictureIndex <> -1) and (PictureIndex < FSD.FActivePictures.Count)
  1372.         then
  1373.           Picture := TBitMap(FSD.FActivePictures.Items[PictureIndex])
  1374.         else
  1375.           Picture := nil;
  1376.         //
  1377.         Self.FixedCellRect := FixedCellRect;
  1378.         Self.SelectCellRect := SelectCellRect;
  1379.         Self.FocusCellRect := FocusCellRect;
  1380.         Self.FixedCellLeftOffset := FixedCellLeftOffset;
  1381.         Self.FixedCellRightOffset := FixedCellRightOffset;
  1382.         Self.FixedCellTextRect := FixedCellTextRect;
  1383.         Self.CellLeftOffset := CellLeftOffset;
  1384.         Self.CellRightOffset := CellRightOffset;
  1385.         Self.CellTextRect := CellTextRect;
  1386.         Self.LinesColor := LinesColor;
  1387.         Self.BGColor := BGColor;
  1388.         //
  1389.         Self.FontName := FontName;
  1390.         Self.FontStyle := FontStyle;
  1391.         Self.FontHeight := FontHeight;
  1392.         Self.FontColor := FontColor;
  1393.         Self.SelectFontColor := SelectFontColor;
  1394.         Self.FocusFontColor := FocusFontColor;
  1395.         Self.FixedFontName := FixedFontName;
  1396.         Self.FixedFontStyle := FixedFontStyle;
  1397.         Self.FixedFontHeight := FixedFontHeight;
  1398.         Self.FixedFontColor := FixedFontColor;
  1399.         if IsNullRect(Self.SelectCellRect)
  1400.         then
  1401.           Self.SelectCellRect := Self.FocusCellRect; 
  1402.         if IsNullRect(Self.FocusCellRect)
  1403.         then
  1404.           Self.FocusCellRect := Self.SelectCellRect;
  1405.         if IsNullRect(Self.FixedCellRect)
  1406.         then
  1407.           begin
  1408.             FIndex := -1;
  1409.             Picture := nil;
  1410.           end;
  1411.           
  1412.       end;
  1413. end;
  1414. procedure TbsSkinCustomGrid.AdjustSize(Index, Amount: Longint; Rows: Boolean);
  1415. var
  1416.   NewCur: TGridCoord;
  1417.   OldRows, OldCols: Longint;
  1418.   MovementX, MovementY: Longint;
  1419.   MoveRect: TGridRect;
  1420.   ScrollArea: TRect;
  1421.   AbsAmount: Longint;
  1422.   function DoSizeAdjust(var Count: Longint; var Extents: Pointer;
  1423.     DefaultExtent: Integer; var Current: Longint): Longint;
  1424.   var
  1425.     I: Integer;
  1426.     NewCount: Longint;
  1427.   begin
  1428.     NewCount := Count + Amount;
  1429.     if NewCount < Index then InvalidOp(STooManyDeleted);
  1430.     if (Amount < 0) and Assigned(Extents) then
  1431.     begin
  1432.       Result := 0;
  1433.       for I := Index to Index - Amount - 1 do
  1434.         Inc(Result, PIntArray(Extents)^[I]);
  1435.     end
  1436.     else
  1437.       Result := Amount * DefaultExtent;
  1438.     if Extents <> nil then
  1439.       ModifyExtents(Extents, Index, Amount, DefaultExtent);
  1440.     Count := NewCount;
  1441.     if Current >= Index then
  1442.       if (Amount < 0) and (Current < Index - Amount) then Current := Index
  1443.       else Inc(Current, Amount);
  1444.   end;
  1445. begin
  1446.   if Amount = 0 then Exit;
  1447.   NewCur := FCurrent;
  1448.   OldCols := ColCount;
  1449.   OldRows := RowCount;
  1450.   MoveRect.Left := FixedCols;
  1451.   MoveRect.Right := ColCount - 1;
  1452.   MoveRect.Top := FixedRows;
  1453.   MoveRect.Bottom := RowCount - 1;
  1454.   MovementX := 0;
  1455.   MovementY := 0;
  1456.   AbsAmount := Amount;
  1457.   if AbsAmount < 0 then AbsAmount := -AbsAmount;
  1458.   if Rows then
  1459.   begin
  1460.     MovementY := DoSizeAdjust(FRowCount, FRowHeights, DefaultRowHeight, NewCur.Y);
  1461.     MoveRect.Top := Index;
  1462.     if Index + AbsAmount <= TopRow then MoveRect.Bottom := TopRow - 1;
  1463.   end
  1464.   else
  1465.   begin
  1466.     MovementX := DoSizeAdjust(FColCount, FColWidths, DefaultColWidth, NewCur.X);
  1467.     MoveRect.Left := Index;
  1468.     if Index + AbsAmount <= LeftCol then MoveRect.Right := LeftCol - 1;
  1469.   end;
  1470.   GridRectToScreenRect(MoveRect, ScrollArea, True);
  1471.   if not IsRectEmpty(ScrollArea) then
  1472.   begin
  1473.     ScrollWindow(Handle, MovementX, MovementY, @ScrollArea, @ScrollArea);
  1474.     UpdateWindow(Handle);
  1475.   end;
  1476.   SizeChanged(OldCols, OldRows);
  1477.   if (NewCur.X <> FCurrent.X) or (NewCur.Y <> FCurrent.Y) then
  1478.     MoveCurrent(NewCur.X, NewCur.Y, True, True);
  1479. end;
  1480. function TbsSkinCustomGrid.BoxRect(ALeft, ATop, ARight, ABottom: Longint): TRect;
  1481. var
  1482.   GridRect: TGridRect;
  1483. begin
  1484.   GridRect.Left := ALeft;
  1485.   GridRect.Right := ARight;
  1486.   GridRect.Top := ATop;
  1487.   GridRect.Bottom := ABottom;
  1488.   GridRectToScreenRect(GridRect, Result, False);
  1489. end;
  1490. procedure TbsSkinCustomGrid.DoExit;
  1491. begin
  1492.   inherited DoExit;
  1493.   if not (goAlwaysShowEditor in Options) then HideEditor;
  1494. end;
  1495. function TbsSkinCustomGrid.CellRect(ACol, ARow: Longint): TRect;
  1496. begin
  1497.   Result := BoxRect(ACol, ARow, ACol, ARow);
  1498. end;
  1499. function TbsSkinCustomGrid.CanEditAcceptKey(Key: Char): Boolean;
  1500. begin
  1501.   Result := True;
  1502. end;
  1503. function TbsSkinCustomGrid.CanGridAcceptKey(Key: Word; Shift: TShiftState): Boolean;
  1504. begin
  1505.   Result := True;
  1506. end;
  1507. function TbsSkinCustomGrid.CanEditModify: Boolean;
  1508. begin
  1509.   Result := FCanEditModify;
  1510. end;
  1511. function TbsSkinCustomGrid.CanEditShow: Boolean;
  1512. begin
  1513.   Result := ([goRowSelect, goEditing] * Options = [goEditing]) and
  1514.     FEditorMode and not (csDesigning in ComponentState) and HandleAllocated and
  1515.     ((goAlwaysShowEditor in Options) or IsActiveControl);
  1516. end;
  1517. function TbsSkinCustomGrid.IsActiveControl: Boolean;
  1518. var
  1519.   H: Hwnd;
  1520.   ParentForm: TCustomForm;
  1521. begin
  1522.   Result := False;
  1523.   ParentForm := GetParentForm(Self);
  1524.   if Assigned(ParentForm) then
  1525.   begin
  1526.     if (ParentForm.ActiveControl = Self) then
  1527.       Result := True
  1528.   end
  1529.   else
  1530.   begin
  1531.     H := GetFocus;
  1532.     while IsWindow(H) and (Result = False) do
  1533.     begin
  1534.       if H = WindowHandle then
  1535.         Result := True
  1536.       else
  1537.         H := GetParent(H);
  1538.     end;
  1539.   end;
  1540. end;
  1541. function TbsSkinCustomGrid.GetEditMask(ACol, ARow: Longint): string;
  1542. begin
  1543.   Result := '';
  1544. end;
  1545. function TbsSkinCustomGrid.GetEditText(ACol, ARow: Longint): string;
  1546. begin
  1547.   Result := '';
  1548. end;
  1549. procedure TbsSkinCustomGrid.SetEditText(ACol, ARow: Longint; const Value: string);
  1550. begin
  1551. end;
  1552. function TbsSkinCustomGrid.GetEditLimit: Integer;
  1553. begin
  1554.   Result := 0;
  1555. end;
  1556. procedure TbsSkinCustomGrid.HideEditor;
  1557. begin
  1558.   FEditorMode := False;
  1559.   HideEdit;
  1560. end;
  1561. procedure TbsSkinCustomGrid.ShowEditor;
  1562. begin
  1563.   FEditorMode := True;
  1564.   UpdateEdit;
  1565. end;
  1566. procedure TbsSkinCustomGrid.ShowEditorChar(Ch: Char);
  1567. begin
  1568.   ShowEditor;
  1569.   if FInplaceEdit <> nil then
  1570.     PostMessage(FInplaceEdit.Handle, WM_CHAR, Word(Ch), 0);
  1571. end;
  1572. procedure TbsSkinCustomGrid.InvalidateEditor;
  1573. begin
  1574.   FInplaceCol := -1;
  1575.   FInplaceRow := -1;
  1576.   UpdateEdit;
  1577. end;
  1578. procedure TbsSkinCustomGrid.ReadColWidths(Reader: TReader);
  1579. var
  1580.   I: Integer;
  1581. begin
  1582.   with Reader do
  1583.   begin
  1584.     ReadListBegin;
  1585.     for I := 0 to ColCount - 1 do ColWidths[I] := ReadInteger;
  1586.     ReadListEnd;
  1587.   end;
  1588. end;
  1589. procedure TbsSkinCustomGrid.ReadRowHeights(Reader: TReader);
  1590. var
  1591.   I: Integer;
  1592. begin
  1593.   with Reader do
  1594.   begin
  1595.     ReadListBegin;
  1596.     for I := 0 to RowCount - 1 do RowHeights[I] := ReadInteger;
  1597.     ReadListEnd;
  1598.   end;
  1599. end;
  1600. procedure TbsSkinCustomGrid.WriteColWidths(Writer: TWriter);
  1601. var
  1602.   I: Integer;
  1603. begin
  1604.   with Writer do
  1605.   begin
  1606.     WriteListBegin;
  1607.     for I := 0 to ColCount - 1 do WriteInteger(ColWidths[I]);
  1608.     WriteListEnd;
  1609.   end;
  1610. end;
  1611. procedure TbsSkinCustomGrid.WriteRowHeights(Writer: TWriter);
  1612. var
  1613.   I: Integer;
  1614. begin
  1615.   with Writer do
  1616.   begin
  1617.     WriteListBegin;
  1618.     for I := 0 to RowCount - 1 do WriteInteger(RowHeights[I]);
  1619.     WriteListEnd;
  1620.   end;
  1621. end;
  1622. procedure TbsSkinCustomGrid.DefineProperties(Filer: TFiler);
  1623.   function DoColWidths: Boolean;
  1624.   begin
  1625.     if Filer.Ancestor <> nil then
  1626.       Result := not CompareExtents(TbsSkinCustomGrid(Filer.Ancestor).FColWidths, FColWidths)
  1627.     else
  1628.       Result := FColWidths <> nil;
  1629.   end;
  1630.   function DoRowHeights: Boolean;
  1631.   begin
  1632.     if Filer.Ancestor <> nil then
  1633.       Result := not CompareExtents(TbsSkinCustomGrid(Filer.Ancestor).FRowHeights, FRowHeights)
  1634.     else
  1635.       Result := FRowHeights <> nil;
  1636.   end;
  1637. begin
  1638.   inherited DefineProperties(Filer);
  1639.   if FSaveCellExtents then
  1640.     with Filer do
  1641.     begin
  1642.       DefineProperty('ColWidths', ReadColWidths, WriteColWidths, DoColWidths);
  1643.       DefineProperty('RowHeights', ReadRowHeights, WriteRowHeights, DoRowHeights);
  1644.     end;
  1645. end;
  1646. procedure TbsSkinCustomGrid.MoveColumn(FromIndex, ToIndex: Longint);
  1647. var
  1648.   Rect: TGridRect;
  1649. begin
  1650.   if FromIndex = ToIndex then Exit;
  1651.   if Assigned(FColWidths) then
  1652.   begin
  1653.     MoveExtent(FColWidths, FromIndex + 1, ToIndex + 1);
  1654.     MoveExtent(FTabStops, FromIndex + 1, ToIndex + 1);
  1655.   end;
  1656.   MoveAdjust(FCurrent.X, FromIndex, ToIndex);
  1657.   MoveAdjust(FAnchor.X, FromIndex, ToIndex);
  1658.   MoveAdjust(FInplaceCol, FromIndex, ToIndex);
  1659.   Rect.Top := 0;
  1660.   Rect.Bottom := VisibleRowCount;
  1661.   if FromIndex < ToIndex then
  1662.   begin
  1663.     Rect.Left := FromIndex;
  1664.     Rect.Right := ToIndex;
  1665.   end
  1666.   else
  1667.   begin
  1668.     Rect.Left := ToIndex;
  1669.     Rect.Right := FromIndex;
  1670.   end;
  1671.   InvalidateRect(Rect);
  1672.   ColumnMoved(FromIndex, ToIndex);
  1673.   if Assigned(FColWidths) then
  1674.     ColWidthsChanged;
  1675.   UpdateEdit;
  1676. end;
  1677. procedure TbsSkinCustomGrid.ColumnMoved(FromIndex, ToIndex: Longint);
  1678. begin
  1679. end;
  1680. procedure TbsSkinCustomGrid.MoveRow(FromIndex, ToIndex: Longint);
  1681. begin
  1682.   if Assigned(FRowHeights) then
  1683.     MoveExtent(FRowHeights, FromIndex + 1, ToIndex + 1);
  1684.   MoveAdjust(FCurrent.Y, FromIndex, ToIndex);
  1685.   MoveAdjust(FAnchor.Y, FromIndex, ToIndex);
  1686.   MoveAdjust(FInplaceRow, FromIndex, ToIndex);
  1687.   RowMoved(FromIndex, ToIndex);
  1688.   if Assigned(FRowHeights) then
  1689.     RowHeightsChanged;
  1690.   UpdateEdit;
  1691. end;
  1692. procedure TbsSkinCustomGrid.RowMoved(FromIndex, ToIndex: Longint);
  1693. begin
  1694. end;
  1695. function TbsSkinCustomGrid.MouseCoord(X, Y: Integer): TGridCoord;
  1696. var
  1697.   DrawInfo: TbsGridDrawInfo;
  1698. begin
  1699.   CalcDrawInfo(DrawInfo);
  1700.   Result := CalcCoordFromPoint(X, Y, DrawInfo);
  1701.   if Result.X < 0 then Result.Y := -1
  1702.   else if Result.Y < 0 then Result.X := -1;
  1703. end;
  1704. procedure TbsSkinCustomGrid.MoveColRow(ACol, ARow: Longint; MoveAnchor,
  1705.   Show: Boolean);
  1706. begin
  1707.   MoveCurrent(ACol, ARow, MoveAnchor, Show);
  1708. end;
  1709. function TbsSkinCustomGrid.SelectCell(ACol, ARow: Longint): Boolean;
  1710. begin
  1711.   Result := True;
  1712. end;
  1713. procedure TbsSkinCustomGrid.SizeChanged(OldColCount, OldRowCount: Longint);
  1714. begin
  1715. end;
  1716. function TbsSkinCustomGrid.Sizing(X, Y: Integer): Boolean;
  1717. var
  1718.   DrawInfo: TbsGridDrawInfo;
  1719.   State: TbsGridState;
  1720.   Index: Longint;
  1721.   Pos, Ofs: Integer;
  1722. begin
  1723.   State := FGridState;
  1724.   if State = gsNormal then
  1725.   begin
  1726.     CalcDrawInfo(DrawInfo);
  1727.     CalcSizingState(X, Y, State, Index, Pos, Ofs, DrawInfo);
  1728.   end;
  1729.   Result := State <> gsNormal;
  1730. end;
  1731. procedure TbsSkinCustomGrid.TopLeftChanged;
  1732. begin
  1733.   if FEditorMode and (FInplaceEdit <> nil) then FInplaceEdit.UpdateLoc(CellRect(Col, Row));
  1734. end;
  1735. procedure FillDWord(var Dest; Count, Value: Integer); register;
  1736. asm
  1737.   XCHG  EDX, ECX
  1738.   PUSH  EDI
  1739.   MOV   EDI, EAX
  1740.   MOV   EAX, EDX
  1741.   REP   STOSD
  1742.   POP   EDI
  1743. end;
  1744. function StackAlloc(Size: Integer): Pointer; register;
  1745. asm
  1746.   POP   ECX          { return address }
  1747.   MOV   EDX, ESP
  1748.   ADD   EAX, 3
  1749.   AND   EAX, not 3   // round up to keep ESP dword aligned
  1750.   CMP   EAX, 4092
  1751.   JLE   @@2
  1752. @@1:
  1753.   SUB   ESP, 4092
  1754.   PUSH  EAX          { make sure we touch guard page, to grow stack }
  1755.   SUB   EAX, 4096
  1756.   JNS   @@1
  1757.   ADD   EAX, 4096
  1758. @@2:
  1759.   SUB   ESP, EAX
  1760.   MOV   EAX, ESP     { function result = low memory address of block }
  1761.   PUSH  EDX          { save original SP, for cleanup }
  1762.   MOV   EDX, ESP
  1763.   SUB   EDX, 4
  1764.   PUSH  EDX          { save current SP, for sanity check  (sp = [sp]) }
  1765.   PUSH  ECX          { return to caller }
  1766. end;
  1767. procedure StackFree(P: Pointer); register;
  1768. asm
  1769.   POP   ECX                     { return address }
  1770.   MOV   EDX, DWORD PTR [ESP]
  1771.   SUB   EAX, 8
  1772.   CMP   EDX, ESP                { sanity check #1 (SP = [SP]) }
  1773.   JNE   @@1
  1774.   CMP   EDX, EAX                { sanity check #2 (P = this stack block) }
  1775.   JNE   @@1
  1776.   MOV   ESP, DWORD PTR [ESP+4]  { restore previous SP  }
  1777. @@1:
  1778.   PUSH  ECX                     { return to caller }
  1779. end;
  1780. procedure TbsSkinCustomGrid.Paint;
  1781. var
  1782.   LineColor: TColor;
  1783.   DrawInfo: TbsGridDrawInfo;
  1784.   Sel: TGridRect;
  1785.   UpdateRect: TRect;
  1786.   R, AFocRect, FocRect: TRect;
  1787.   PointsList: PIntArray;
  1788.   StrokeList: PIntArray;
  1789.   MaxStroke: Integer;
  1790.   FrameFlags1, FrameFlags2: DWORD;
  1791.   B: TBitMap;
  1792.   procedure DrawLines(DoHorz, DoVert: Boolean; Col, Row: Longint;
  1793.     const CellBounds: array of Integer; OnColor, OffColor: TColor);
  1794.   const
  1795.     FlatPenStyle = PS_Geometric or PS_Solid or PS_EndCap_Flat or PS_Join_Miter;
  1796.     procedure DrawAxisLines(const AxisInfo: TbsGridAxisDrawInfo;
  1797.       Cell, MajorIndex: Integer; UseOnColor: Boolean);
  1798.     var
  1799.       Line: Integer;
  1800.       LogBrush: TLOGBRUSH;
  1801.       Index: Integer;
  1802.       Points: PIntArray;
  1803.       StopMajor, StartMinor, StopMinor: Integer;
  1804.     begin
  1805.       with Canvas, AxisInfo do
  1806.       begin
  1807.         if EffectiveLineWidth <> 0 then
  1808.         begin
  1809.           Pen.Width := GridLineWidth;
  1810.           if UseOnColor then
  1811.             Pen.Color := OnColor
  1812.           else
  1813.             Pen.Color := OffColor;
  1814.           if Pen.Width > 1 then
  1815.           begin
  1816.             LogBrush.lbStyle := BS_Solid;
  1817.             LogBrush.lbColor := Pen.Color;
  1818.             LogBrush.lbHatch := 0;
  1819.             Pen.Handle := ExtCreatePen(FlatPenStyle, Pen.Width, LogBrush, 0, nil);
  1820.           end;
  1821.           Points := PointsList;
  1822.           Line := CellBounds[MajorIndex] + EffectiveLineWidth shr 1 +
  1823.             GetExtent(Cell);
  1824.           //!!! ??? Line needs to be incremented for RightToLeftAlignment ???
  1825.           if UseRightToLeftAlignment and (MajorIndex = 0) then Inc(Line);
  1826.           StartMinor := CellBounds[MajorIndex xor 1];
  1827.           StopMinor := CellBounds[2 + (MajorIndex xor 1)];
  1828.           StopMajor := CellBounds[2 + MajorIndex] + EffectiveLineWidth;
  1829.           Index := 0;
  1830.           repeat
  1831.             Points^[Index + MajorIndex] := Line;         { MoveTo }
  1832.             Points^[Index + (MajorIndex xor 1)] := StartMinor;
  1833.             Inc(Index, 2);
  1834.             Points^[Index + MajorIndex] := Line;         { LineTo }
  1835.             Points^[Index + (MajorIndex xor 1)] := StopMinor;
  1836.             Inc(Index, 2);
  1837.             Inc(Cell);
  1838.             Inc(Line, GetExtent(Cell) + EffectiveLineWidth);
  1839.           until Line > StopMajor;
  1840.            { 2 integers per point, 2 points per line -> Index div 4 }
  1841.           PolyPolyLine(Canvas.Handle, Points^, StrokeList^, Index shr 2);
  1842.         end;
  1843.       end;
  1844.     end;
  1845.   begin
  1846.     if (CellBounds[0] = CellBounds[2]) or (CellBounds[1] = CellBounds[3]) then Exit;
  1847.     if not DoHorz then
  1848.     begin
  1849.       DrawAxisLines(DrawInfo.Vert, Row, 1, DoHorz);
  1850.       DrawAxisLines(DrawInfo.Horz, Col, 0, DoVert);
  1851.     end
  1852.     else
  1853.     begin
  1854.       DrawAxisLines(DrawInfo.Horz, Col, 0, DoVert);
  1855.       DrawAxisLines(DrawInfo.Vert, Row, 1, DoHorz);
  1856.     end;
  1857.   end;
  1858.   procedure DrawSkinCell(B: TBitMap; AState: TGridDrawState; W, H: Integer);
  1859.   var
  1860.     Buffer: TBitMap;
  1861.   begin
  1862.     if not FUseSkinCellHeight
  1863.     then
  1864.       begin
  1865.         Buffer := TBitMap.Create;
  1866.         B.Width := W;
  1867.         B.Height := H;
  1868.       end;
  1869.     if (gdFixed in AState)
  1870.     then
  1871.       begin
  1872.         if FUseSkinCellHeight
  1873.         then
  1874.           CreateHSkinImage(FixedCellLeftOffset, FixedCellRightOffset,
  1875.            B, Picture, FixedCellRect, W, H)
  1876.         else
  1877.           CreateHSkinImage(FixedCellLeftOffset, FixedCellRightOffset,
  1878.            Buffer, Picture, FixedCellRect, W, H);
  1879.         if FUseSkinFont
  1880.         then
  1881.           with Canvas do
  1882.           begin
  1883.             Font.Name := FixedFontName;
  1884.             Font.Height := FixedFontHeight;
  1885.             Font.Color := FixedFontColor;
  1886.             Font.Style := FixedFontStyle;
  1887.           end
  1888.         else
  1889.           begin
  1890.             Canvas.Font.Assign(Self.Font);
  1891.             Canvas.Font.Color := FixedFontColor;
  1892.           end;
  1893.         if (SkinData <> nil) and (SkinData.ResourceStrData <> nil)
  1894.         then
  1895.           Canvas.Font.Charset := SkinData.ResourceStrData.CharSet
  1896.         else
  1897.           Canvas.Font.CharSet := Self.Font.CharSet;
  1898.       end
  1899.     else
  1900.     if (gdFocused in AState) or (goRowSelect in Options)
  1901.     then 
  1902.       begin
  1903.         if FUseSkinCellHeight
  1904.         then
  1905.           CreateHSkinImage(CellLeftOffset, CellRightOffset,
  1906.             B, Picture, FocusCellRect, W, H)
  1907.         else
  1908.           CreateHSkinImage(CellLeftOffset, CellRightOffset,
  1909.             Buffer, Picture, FocusCellRect, W, H);
  1910.         if FUseSkinFont
  1911.         then
  1912.           with Canvas do
  1913.           begin
  1914.             Font.Name := FontName;
  1915.             Font.Height := FontHeight;
  1916.             Font.Color := FocusFontColor;
  1917.             Font.Style := FontStyle;
  1918.           end
  1919.         else
  1920.           begin
  1921.             Canvas.Font.Assign(Self.Font);
  1922.             Canvas.Font.Color := FocusFontColor;
  1923.           end;
  1924.         if (SkinData <> nil) and (SkinData.ResourceStrData <> nil)
  1925.         then
  1926.           Canvas.Font.Charset := SkinData.ResourceStrData.CharSet
  1927.         else
  1928.           Canvas.Font.CharSet := Self.Font.CharSet;
  1929.       end
  1930.     else
  1931.     if (gdSelected in AState)
  1932.     then
  1933.       begin
  1934.         if FUseSkinCellHeight
  1935.         then
  1936.           CreateHSkinImage(CellLeftOffset, CellRightOffset,
  1937.             B, Picture, SelectCellRect, W, H)
  1938.         else
  1939.           CreateHSkinImage(CellLeftOffset, CellRightOffset,
  1940.             Buffer, Picture, SelectCellRect, W, H);
  1941.         if FUseSkinFont
  1942.         then
  1943.           with Canvas do
  1944.           begin
  1945.             Font.Name := FontName;
  1946.             Font.Height := FontHeight;
  1947.             Font.Color := SelectFontColor;
  1948.             Font.Style := FontStyle;
  1949.           end
  1950.         else
  1951.           begin
  1952.             Canvas.Font.Assign(Self.Font);
  1953.             Canvas.Font.Color := SelectFontColor;
  1954.           end;
  1955.         if (SkinData <> nil) and (SkinData.ResourceStrData <> nil)
  1956.         then
  1957.           Canvas.Font.Charset := SkinData.ResourceStrData.CharSet
  1958.         else
  1959.           Canvas.Font.CharSet := Self.Font.CharSet;
  1960.       end;
  1961.     if not FUseSkinCellHeight
  1962.     then
  1963.       begin
  1964.         B.Canvas.StretchDraw(Rect(0, 0, W, H), Buffer);
  1965.         Buffer.Free;
  1966.       end;
  1967.   end;
  1968.   procedure DrawCells(ACol, ARow: Longint; StartX, StartY, StopX, StopY: Integer;
  1969.     Color: TColor; IncludeDrawState: TGridDrawState);
  1970.   var
  1971.     CurCol, CurRow: Longint;
  1972.     AWhere, Where, TempRect: TRect;
  1973.     DrawState: TGridDrawState;
  1974.     Focused: Boolean;
  1975.   begin
  1976.     CurRow := ARow;
  1977.     Where.Top := StartY;
  1978.     while (Where.Top < StopY) and (CurRow < RowCount) do
  1979.     begin
  1980.       CurCol := ACol;
  1981.       Where.Left := StartX;
  1982.       Where.Bottom := Where.Top + RowHeights[CurRow];
  1983.       while (Where.Left < StopX) and (CurCol < ColCount) do
  1984.       begin
  1985.         Where.Right := Where.Left + ColWidths[CurCol];
  1986.         if (Where.Right > Where.Left) and RectVisible(Canvas.Handle, Where) then
  1987.         begin
  1988.           DrawState := IncludeDrawState;
  1989.           Focused := IsActiveControl;
  1990.           if Focused and (CurRow = Row) and (CurCol = Col)  then
  1991.             Include(DrawState, gdFocused);
  1992.           if PointInGridRect(CurCol, CurRow, Sel) then
  1993.             Include(DrawState, gdSelected);
  1994.           if not (gdFocused in DrawState) or not (goEditing in Options) or
  1995.             not FEditorMode or (csDesigning in ComponentState) then
  1996.           begin
  1997.             if DefaultDrawing or (csDesigning in ComponentState) then
  1998.               with Canvas do
  1999.               begin
  2000.                 if FIndex < 0
  2001.                 then
  2002.                   begin
  2003.                     Font := Self.Font;
  2004.                     if (gdSelected in DrawState) and
  2005.                        (not (gdFocused in DrawState) or
  2006.                        ([goDrawFocusSelected, goRowSelect] * Options <> []))
  2007.                     then
  2008.                       begin
  2009.                         Brush.Color := clHighlight;
  2010.                         Font.Color := clHighlightText;
  2011.                         FillRect(Where)
  2012.                       end
  2013.                     else
  2014.                       begin
  2015.                         Brush.Color := Color;
  2016.                         FillRect(Where);
  2017.                         if gdFixed in DrawState
  2018.                         then
  2019.                           begin
  2020.                             R := Where;
  2021.                             Frm3D(Canvas, R, clBtnHighLight, clBtnShadow);
  2022.                           end;
  2023.                       end;
  2024.                   end
  2025.                 else
  2026.                   if not (gdSelected in DrawState) and
  2027.                      not (gdFocused in DrawState) and
  2028.                      not (gdFixed in DrawState)
  2029.                   then
  2030.                     begin
  2031.                       if FUseSkinFont
  2032.                       then
  2033.                         begin
  2034.                           Font.Name := FontName;
  2035.                           Font.Height := FontHeight;
  2036.                           Font.Color := FontColor;
  2037.                           Font.Style := FontStyle;
  2038.                         end
  2039.                       else
  2040.                         begin
  2041.                           Font.Assign(Self.Font);
  2042.                           Font.Color := FontColor;
  2043.                         end;
  2044.                       if (SkinData <> nil) and (SkinData.ResourceStrData <> nil)
  2045.                       then
  2046.                         Font.Charset := SkinData.ResourceStrData.CharSet
  2047.                       else
  2048.                         Font.CharSet := Self.Font.CharSet;
  2049.                       Brush.Color := BGColor;
  2050.                       FillRect(Where);
  2051.                     end
  2052.                   else
  2053.                     begin
  2054.                       B := TBitMap.Create;
  2055.                       DrawSkinCell(B, DrawState,
  2056.                       RectWidth(Where), RectHeight(Where));
  2057.                       Draw(Where.Left, Where.Top, B);
  2058.                       B.Free;
  2059.                     end;
  2060.               end;
  2061.             DrawCell(CurCol, CurRow, Where, DrawState);
  2062.             if FIndex < 0
  2063.             then
  2064.             if DefaultDrawing and not (csDesigning in ComponentState) and
  2065.               (gdFocused in DrawState) and
  2066.               ([goEditing, goAlwaysShowEditor] * Options <> [goEditing, goAlwaysShowEditor])
  2067.               and not (goRowSelect in Options)
  2068.             then
  2069.             begin
  2070.               if not UseRightToLeftAlignment
  2071.               then
  2072.                 DrawFocusRect(Canvas.Handle, Where)
  2073.               else
  2074.                 begin
  2075.                   AWhere := Where;
  2076.                   AWhere.Left := Where.Right;
  2077.                   AWhere.Right := Where.Left;
  2078.                   DrawFocusRect(Canvas.Handle, AWhere)
  2079.                 end;
  2080.             end;
  2081.           end;
  2082.         end;
  2083.         Where.Left := Where.Right + DrawInfo.Horz.EffectiveLineWidth;
  2084.         Inc(CurCol);
  2085.       end;
  2086.       Where.Top := Where.Bottom + DrawInfo.Vert.EffectiveLineWidth;
  2087.       Inc(CurRow);
  2088.     end;
  2089.   end;
  2090. begin
  2091.   if (Width <= 0) or (Height <=0) then Exit;
  2092.   GetSkinData;
  2093.   
  2094.   if UseRightToLeftAlignment then ChangeGridOrientation(True);
  2095.   UpdateRect := Canvas.ClipRect;
  2096.   CalcDrawInfo(DrawInfo);
  2097.   with DrawInfo do
  2098.   begin
  2099.     if (Horz.EffectiveLineWidth > 0) or (Vert.EffectiveLineWidth > 0) then
  2100.     begin
  2101.       { Draw the grid line in the four areas (fixed, fixed), (variable, fixed),
  2102.         (fixed, variable) and (variable, variable) }
  2103.       if FIndex > -1
  2104.       then
  2105.         LineColor := LinesColor
  2106.       else
  2107.         LineColor := FGridLineColor;
  2108.       MaxStroke := Max(Horz.LastFullVisibleCell - LeftCol + FixedCols,
  2109.                         Vert.LastFullVisibleCell - TopRow + FixedRows) + 3;
  2110.       PointsList := StackAlloc(MaxStroke * sizeof(TPoint) * 2);
  2111.       StrokeList := StackAlloc(MaxStroke * sizeof(Integer));
  2112.       FillDWord(StrokeList^, MaxStroke, 2);
  2113.       if ColorToRGB(Color) = clSilver then LineColor := clGray;
  2114.       DrawLines(goFixedHorzLine in Options, goFixedVertLine in Options,
  2115.         0, 0, [0, 0, Horz.FixedBoundary, Vert.FixedBoundary], LineColor{clBlack}, FixedColor);
  2116.       DrawLines(goFixedHorzLine in Options, goFixedVertLine in Options,
  2117.         LeftCol, 0, [Horz.FixedBoundary, 0, Horz.GridBoundary,
  2118.         Vert.FixedBoundary], LineColor{clBlack}, FixedColor);
  2119.       DrawLines(goFixedHorzLine in Options, goFixedVertLine in Options,
  2120.         0, TopRow, [0, Vert.FixedBoundary, Horz.FixedBoundary,
  2121.         Vert.GridBoundary], LineColor{clBlack}, FixedColor);
  2122.       // skin
  2123.       DrawLines(goHorzLine in Options, goVertLine in Options, LeftCol,
  2124.         TopRow, [Horz.FixedBoundary, Vert.FixedBoundary, Horz.GridBoundary,
  2125.         Vert.GridBoundary], LineColor, Color);
  2126.       //
  2127.       StackFree(StrokeList);
  2128.       StackFree(PointsList);
  2129.     end;
  2130.     { Draw the cells in the four areas }
  2131.     Sel := Selection;
  2132.     FrameFlags1 := 0;
  2133.     FrameFlags2 := 0;
  2134.     if goFixedVertLine in Options then
  2135.     begin
  2136.       FrameFlags1 := BF_RIGHT;
  2137.       FrameFlags2 := BF_LEFT;
  2138.     end;
  2139.     if goFixedHorzLine in Options then
  2140.     begin
  2141.       FrameFlags1 := FrameFlags1 or BF_BOTTOM;
  2142.       FrameFlags2 := FrameFlags2 or BF_TOP;
  2143.     end;
  2144.     if not IsRightToLeft
  2145.     then
  2146.       DrawCells(0, 0, 0, 0, Horz.FixedBoundary, Vert.FixedBoundary, FixedColor,
  2147.        [gdFixed])
  2148.     else
  2149.       DrawCells(0, 0, 1, 0, Horz.FixedBoundary, Vert.FixedBoundary, FixedColor,
  2150.        [gdFixed]);
  2151.     DrawCells(LeftCol, 0, Horz.FixedBoundary - FColOffset, 0, Horz.GridBoundary,  //!! clip
  2152.       Vert.FixedBoundary, FixedColor, [gdFixed]);
  2153.     if not IsRightToLeft
  2154.     then
  2155.       DrawCells(0, TopRow, 0, Vert.FixedBoundary, Horz.FixedBoundary,
  2156.         Vert.GridBoundary, FixedColor, [gdFixed])
  2157.     else
  2158.       DrawCells(0, TopRow, 1, Vert.FixedBoundary, Horz.FixedBoundary,
  2159.         Vert.GridBoundary, FixedColor, [gdFixed]);
  2160.     DrawCells(LeftCol, TopRow, Horz.FixedBoundary - FColOffset,                   //!! clip
  2161.       Vert.FixedBoundary, Horz.GridBoundary, Vert.GridBoundary, Color, []);
  2162.     if not (csDesigning in ComponentState) and
  2163.       (goRowSelect in Options) and DefaultDrawing and Focused then
  2164.     begin
  2165.       GridRectToScreenRect(GetSelection, FocRect, False);
  2166.       if FIndex < 0
  2167.       then
  2168.         if not UseRightToLeftAlignment
  2169.         then
  2170.           Canvas.DrawFocusRect(FocRect)
  2171.         else
  2172.           begin
  2173.             AFocRect := FocRect;
  2174.             AFocRect.Left := FocRect.Right;
  2175.             AFocRect.Right := FocRect.Left;
  2176.             Canvas.DrawFocusRect(AFocRect)
  2177.           end;
  2178.     end;
  2179.     { Fill in area not occupied by cells }
  2180.      if Horz.GridBoundary < Horz.GridExtent then
  2181.         begin
  2182.           if FIndex > -1
  2183.           then
  2184.             Canvas.Brush.Color := BGColor
  2185.           else
  2186.             Canvas.Brush.Color := Color;
  2187.           if not IsRightToLeft
  2188.           then
  2189.             Canvas.FillRect(Rect(Horz.GridBoundary, 0, Horz.GridExtent + 1, Vert.GridBoundary))
  2190.           else
  2191.             Canvas.FillRect(Rect(Horz.GridBoundary, -20, Horz.GridExtent + 1, Vert.GridBoundary));
  2192.         end;
  2193.         if Vert.GridBoundary < Vert.GridExtent then
  2194.         begin
  2195.           if FIndex > -1
  2196.           then
  2197.             Canvas.Brush.Color := BGColor
  2198.           else
  2199.             Canvas.Brush.Color := Color;
  2200.            if not IsRightToLeft
  2201.           then
  2202.             Canvas.FillRect(Rect(0, Vert.GridBoundary, Horz.GridExtent, Vert.GridExtent))
  2203.           else
  2204.             Canvas.FillRect(Rect(-20, Vert.GridBoundary, Horz.GridExtent, Vert.GridExtent));
  2205.          end;
  2206.       end;
  2207.    if UseRightToLeftAlignment then ChangeGridOrientation(False);
  2208. end;
  2209. function TbsSkinCustomGrid.CalcCoordFromPoint(X, Y: Integer;
  2210.   const DrawInfo: TbsGridDrawInfo): TGridCoord;
  2211.   function DoCalc(const AxisInfo: TbsGridAxisDrawInfo; N: Integer): Integer;
  2212.   var
  2213.     I, Start, Stop: Longint;
  2214.     Line: Integer;
  2215.   begin
  2216.     with AxisInfo do
  2217.     begin
  2218.       if N < FixedBoundary then
  2219.       begin
  2220.         Start := 0;
  2221.         Stop :=  FixedCellCount - 1;
  2222.         Line := 0;
  2223.       end
  2224.       else
  2225.       begin
  2226.         Start := FirstGridCell;
  2227.         Stop := GridCellCount - 1;
  2228.         Line := FixedBoundary;
  2229.       end;
  2230.       Result := -1;
  2231.       for I := Start to Stop do
  2232.       begin
  2233.         Inc(Line, GetExtent(I) + EffectiveLineWidth);
  2234.         if N < Line then
  2235.         begin
  2236.           Result := I;
  2237.           Exit;
  2238.         end;
  2239.       end;
  2240.     end;
  2241.   end;
  2242.   function DoCalcRightToLeft(const AxisInfo: TbsGridAxisDrawInfo; N: Integer): Integer;
  2243.   var
  2244.     I, Start, Stop: Longint;
  2245.     Line: Integer;
  2246.   begin
  2247.     N := ClientWidth - N;
  2248.     with AxisInfo do
  2249.     begin
  2250.       if N < FixedBoundary then
  2251.       begin
  2252.         Start := 0;
  2253.         Stop :=  FixedCellCount - 1;
  2254.         Line := ClientWidth;
  2255.       end
  2256.       else
  2257.       begin
  2258.         Start := FirstGridCell;
  2259.         Stop := GridCellCount - 1;
  2260.         Line := FixedBoundary;
  2261.       end;
  2262.       Result := -1;
  2263.       for I := Start to Stop do
  2264.       begin
  2265.         Inc(Line, GetExtent(I) + EffectiveLineWidth);
  2266.         if N < Line then
  2267.         begin
  2268.           Result := I;
  2269.           Exit;
  2270.         end;
  2271.       end;
  2272.     end;
  2273.   end;
  2274. begin
  2275.   if not UseRightToLeftAlignment then
  2276.     Result.X := DoCalc(DrawInfo.Horz, X)
  2277.   else
  2278.     Result.X := DoCalcRightToLeft(DrawInfo.Horz, X);
  2279.   Result.Y := DoCalc(DrawInfo.Vert, Y);
  2280. end;
  2281. procedure TbsSkinCustomGrid.CalcDrawInfo(var DrawInfo: TbsGridDrawInfo);
  2282. begin
  2283.   CalcDrawInfoXY(DrawInfo, ClientWidth, ClientHeight);
  2284. end;
  2285. procedure TbsSkinCustomGrid.CalcDrawInfoXY(var DrawInfo: TbsGridDrawInfo;
  2286.   UseWidth, UseHeight: Integer);
  2287.   procedure CalcAxis(var AxisInfo: TbsGridAxisDrawInfo; UseExtent: Integer);
  2288.   var
  2289.     I: Integer;
  2290.   begin
  2291.     with AxisInfo do
  2292.     begin
  2293.       GridExtent := UseExtent;
  2294.       GridBoundary := FixedBoundary;
  2295.       FullVisBoundary := FixedBoundary;
  2296.       LastFullVisibleCell := FirstGridCell;
  2297.       for I := FirstGridCell to GridCellCount - 1 do
  2298.       begin
  2299.         Inc(GridBoundary, GetExtent(I) + EffectiveLineWidth);
  2300.         if GridBoundary > GridExtent + EffectiveLineWidth then
  2301.         begin
  2302.           GridBoundary := GridExtent;
  2303.           Break;
  2304.         end;
  2305.         LastFullVisibleCell := I;
  2306.         FullVisBoundary := GridBoundary;
  2307.       end;
  2308.     end;
  2309.   end;
  2310. begin
  2311.   CalcFixedInfo(DrawInfo);
  2312.   CalcAxis(DrawInfo.Horz, UseWidth);
  2313.   CalcAxis(DrawInfo.Vert, UseHeight);
  2314. end;
  2315. procedure TbsSkinCustomGrid.CalcFixedInfo(var DrawInfo: TbsGridDrawInfo);
  2316.   procedure CalcFixedAxis(var Axis: TbsGridAxisDrawInfo; LineOptions: TGridOptions;
  2317.     FixedCount, FirstCell, CellCount: Integer; GetExtentFunc: TbsGetExtentsFunc);
  2318.   var
  2319.     I: Integer;
  2320.   begin
  2321.     with Axis do
  2322.     begin
  2323.       if LineOptions * Options = [] then
  2324.         EffectiveLineWidth := 0
  2325.       else
  2326.         EffectiveLineWidth := GridLineWidth;
  2327.       FixedBoundary := 0;
  2328.       for I := 0 to FixedCount - 1 do
  2329.         Inc(FixedBoundary, GetExtentFunc(I) + EffectiveLineWidth);
  2330.       FixedCellCount := FixedCount;
  2331.       FirstGridCell := FirstCell;
  2332.       GridCellCount := CellCount;
  2333.       GetExtent := GetExtentFunc;
  2334.     end;
  2335.   end;
  2336. begin
  2337.   CalcFixedAxis(DrawInfo.Horz, [goFixedVertLine, goVertLine], FixedCols,
  2338.     LeftCol, ColCount, GetColWidths);
  2339.   CalcFixedAxis(DrawInfo.Vert, [goFixedHorzLine, goHorzLine], FixedRows,
  2340.     TopRow, RowCount, GetRowHeights);
  2341. end;
  2342. { Calculates the TopLeft that will put the given Coord in view }
  2343. function TbsSkinCustomGrid.CalcMaxTopLeft(const Coord: TGridCoord;
  2344.   const DrawInfo: TbsGridDrawInfo): TGridCoord;
  2345.   function CalcMaxCell(const Axis: TbsGridAxisDrawInfo; Start: Integer): Integer;
  2346.   var
  2347.     Line: Integer;
  2348.     I, Extent: Longint;
  2349.   begin
  2350.     Result := Start;
  2351.     with Axis do
  2352.     begin
  2353.       Line := GridExtent + EffectiveLineWidth;
  2354.       for I := Start downto FixedCellCount do
  2355.       begin
  2356.         Extent := GetExtent(I);
  2357.         Dec(Line, Extent);
  2358.         Dec(Line, EffectiveLineWidth);
  2359.         if Line < FixedBoundary then Break;
  2360.         if Extent > 0 then Result := I;
  2361.       end;
  2362.     end;
  2363.   end;
  2364. begin
  2365.   Result.X := CalcMaxCell(DrawInfo.Horz, Coord.X);
  2366.   Result.Y := CalcMaxCell(DrawInfo.Vert, Coord.Y);
  2367. end;
  2368. procedure TbsSkinCustomGrid.CalcSizingState(X, Y: Integer; var State: TbsGridState;
  2369.   var Index: Longint; var SizingPos, SizingOfs: Integer;
  2370.   var FixedInfo: TbsGridDrawInfo);
  2371.   procedure CalcAxisState(const AxisInfo: TbsGridAxisDrawInfo; Pos: Integer;
  2372.     NewState: TbsGridState);
  2373.   var
  2374.     I, Line, Back, Range: Integer;
  2375.   begin
  2376.     if UseRightToLeftAlignment then
  2377.       Pos := ClientWidth - Pos;
  2378.     with AxisInfo do
  2379.     begin
  2380.       Line := FixedBoundary;
  2381.       Range := EffectiveLineWidth;
  2382.       Back := 0;
  2383.       if Range < 7 then
  2384.       begin
  2385.         Range := 7;
  2386.         Back := (Range - EffectiveLineWidth) shr 1;
  2387.       end;
  2388.       for I := FirstGridCell to GridCellCount - 1 do
  2389.       begin
  2390.         Inc(Line, GetExtent(I));
  2391.         if Line > GridBoundary then Break;
  2392.         if (Pos >= Line - Back) and (Pos <= Line - Back + Range) then
  2393.         begin
  2394.           State := NewState;
  2395.           SizingPos := Line;
  2396.           SizingOfs := Line - Pos;
  2397.           Index := I;
  2398.           Exit;
  2399.         end;
  2400.         Inc(Line, EffectiveLineWidth);
  2401.       end;
  2402.       if (GridBoundary = GridExtent) and (Pos >= GridExtent - Back)
  2403.         and (Pos <= GridExtent) then
  2404.       begin
  2405.         State := NewState;
  2406.         SizingPos := GridExtent;
  2407.         SizingOfs := GridExtent - Pos;
  2408.         Index := LastFullVisibleCell + 1;
  2409.       end;
  2410.     end;
  2411.   end;
  2412.   function XOutsideHorzFixedBoundary: Boolean;
  2413.   begin
  2414.     with FixedInfo do
  2415.       if not UseRightToLeftAlignment then
  2416.         Result := X > Horz.FixedBoundary
  2417.       else
  2418.         Result := X < ClientWidth - Horz.FixedBoundary;
  2419.   end;
  2420.   function XOutsideOrEqualHorzFixedBoundary: Boolean;
  2421.   begin
  2422.     with FixedInfo do
  2423.       if not UseRightToLeftAlignment then
  2424.         Result := X >= Horz.FixedBoundary
  2425.       else
  2426.         Result := X <= ClientWidth - Horz.FixedBoundary;
  2427.   end;
  2428. var
  2429.   EffectiveOptions: TGridOptions;
  2430. begin
  2431.   State := gsNormal;
  2432.   Index := -1;
  2433.   EffectiveOptions := Options;
  2434.   if csDesigning in ComponentState then
  2435.     EffectiveOptions := EffectiveOptions + DesignOptionsBoost;
  2436.   if [goColSizing, goRowSizing] * EffectiveOptions <> [] then
  2437.     with FixedInfo do
  2438.     begin
  2439.       Vert.GridExtent := ClientHeight;
  2440.       Horz.GridExtent := ClientWidth;
  2441.       if (XOutsideHorzFixedBoundary) and (goColSizing in EffectiveOptions) then
  2442.       begin
  2443.         if Y >= Vert.FixedBoundary then Exit;
  2444.         CalcAxisState(Horz, X, gsColSizing);
  2445.       end
  2446.       else if (Y > Vert.FixedBoundary) and (goRowSizing in EffectiveOptions) then
  2447.       begin
  2448.         if XOutsideOrEqualHorzFixedBoundary then Exit;
  2449.         CalcAxisState(Vert, Y, gsRowSizing);
  2450.       end;
  2451.     end;
  2452. end;
  2453. procedure TbsSkinCustomGrid.ChangeGridOrientation(RightToLeftOrientation: Boolean);
  2454. var
  2455.   Org: TPoint;
  2456.   Ext: TPoint;
  2457. begin
  2458.   if RightToLeftOrientation then
  2459.   begin
  2460.     Org := Point(ClientWidth,0);
  2461.     Ext := Point(-1,1);
  2462.     SetMapMode(Canvas.Handle, mm_Anisotropic);
  2463.     SetWindowOrgEx(Canvas.Handle, Org.X, Org.Y, nil);
  2464.     SetViewportExtEx(Canvas.Handle, ClientWidth, ClientHeight, nil);
  2465.     SetWindowExtEx(Canvas.Handle, Ext.X*ClientWidth, Ext.Y*ClientHeight, nil);
  2466.   end
  2467.   else
  2468.   begin
  2469.     Org := Point(0,0);
  2470.     Ext := Point(1,1);
  2471.     SetMapMode(Canvas.Handle, mm_Anisotropic);
  2472.     SetWindowOrgEx(Canvas.Handle, Org.X, Org.Y, nil);
  2473.     SetViewportExtEx(Canvas.Handle, ClientWidth, ClientHeight, nil);
  2474.     SetWindowExtEx(Canvas.Handle, Ext.X*ClientWidth, Ext.Y*ClientHeight, nil);
  2475.   end;
  2476. end;
  2477. procedure TbsSkinCustomGrid.ChangeSize(NewColCount, NewRowCount: Longint);
  2478. var
  2479.   OldColCount, OldRowCount: Longint;
  2480.   OldDrawInfo: TbsGridDrawInfo;
  2481.   procedure MinRedraw(const OldInfo, NewInfo: TbsGridAxisDrawInfo; Axis: Integer);
  2482.   var
  2483.     R: TRect;
  2484.     First: Integer;
  2485.   begin
  2486.     First := Min(OldInfo.LastFullVisibleCell, NewInfo.LastFullVisibleCell);
  2487.     // Get the rectangle around the leftmost or topmost cell in the target range.
  2488.     R := CellRect(First and not Axis, First and Axis);
  2489.     R.Bottom := Height;
  2490.     R.Right := Width;
  2491.     Windows.InvalidateRect(Handle, @R, False);
  2492.   end;
  2493.   procedure DoChange;
  2494.   var
  2495.     Coord: TGridCoord;
  2496.     NewDrawInfo: TbsGridDrawInfo;
  2497.   begin
  2498.     if FColWidths <> nil then
  2499.     begin
  2500.       UpdateExtents(FColWidths, ColCount, DefaultColWidth);
  2501.       UpdateExtents(FTabStops, ColCount, Integer(True));
  2502.     end;
  2503.     if FRowHeights <> nil then
  2504.       UpdateExtents(FRowHeights, RowCount, DefaultRowHeight);
  2505.     Coord := FCurrent;
  2506.     if Row >= RowCount then Coord.Y := RowCount - 1;
  2507.     if Col >= ColCount then Coord.X := ColCount - 1;
  2508.     if (FCurrent.X <> Coord.X) or (FCurrent.Y <> Coord.Y) then
  2509.       MoveCurrent(Coord.X, Coord.Y, True, True);
  2510.     if (FAnchor.X <> Coord.X) or (FAnchor.Y <> Coord.Y) then
  2511.       MoveAnchor(Coord);
  2512.     if VirtualView or
  2513.       (LeftCol <> OldDrawInfo.Horz.FirstGridCell) or
  2514.       (TopRow <> OldDrawInfo.Vert.FirstGridCell) then
  2515.       InvalidateGrid
  2516.     else if HandleAllocated then
  2517.     begin
  2518.       CalcDrawInfo(NewDrawInfo);
  2519.       MinRedraw(OldDrawInfo.Horz, NewDrawInfo.Horz, 0);
  2520.       MinRedraw(OldDrawInfo.Vert, NewDrawInfo.Vert, -1);
  2521.     end;
  2522.     UpdateScrollRange(True);
  2523.     SizeChanged(OldColCount, OldRowCount);
  2524.   end;
  2525. begin
  2526.   if HandleAllocated then
  2527.     CalcDrawInfo(OldDrawInfo);
  2528.   OldColCount := FColCount;
  2529.   OldRowCount := FRowCount;
  2530.   FColCount := NewColCount;
  2531.   FRowCount := NewRowCount;
  2532.   if FixedCols > NewColCount then FFixedCols := NewColCount - 1;
  2533.   if FixedRows > NewRowCount then FFixedRows := NewRowCount - 1;
  2534.   try
  2535.     DoChange;
  2536.   except
  2537.     { Could not change size so try to clean up by setting the size back }
  2538.     FColCount := OldColCount;
  2539.     FRowCount := OldRowCount;
  2540.     DoChange;
  2541.     InvalidateGrid;
  2542.     raise;
  2543.   end;
  2544. end;
  2545. { Will move TopLeft so that Coord is in view }
  2546. procedure TbsSkinCustomGrid.ClampInView(const Coord: TGridCoord);
  2547. var
  2548.   DrawInfo: TbsGridDrawInfo;
  2549.   MaxTopLeft: TGridCoord;
  2550.   OldTopLeft: TGridCoord;
  2551. begin
  2552.   if not HandleAllocated then Exit;
  2553.   CalcDrawInfo(DrawInfo);
  2554.   with DrawInfo, Coord do
  2555.   begin
  2556.     if (X > Horz.LastFullVisibleCell) or
  2557.       (Y > Vert.LastFullVisibleCell) or (X < LeftCol) or (Y < TopRow) then
  2558.     begin
  2559.       OldTopLeft := FTopLeft;
  2560.       MaxTopLeft := CalcMaxTopLeft(Coord, DrawInfo);
  2561.       Update;
  2562.       if X < LeftCol then FTopLeft.X := X
  2563.       else if X > Horz.LastFullVisibleCell then FTopLeft.X := MaxTopLeft.X;
  2564.       if Y < TopRow then FTopLeft.Y := Y
  2565.       else if Y > Vert.LastFullVisibleCell then FTopLeft.Y := MaxTopLeft.Y;
  2566.       TopLeftMoved(OldTopLeft);
  2567.     end;
  2568.   end;
  2569. end;
  2570. procedure TbsSkinCustomGrid.DrawSizingLine(const DrawInfo: TbsGridDrawInfo);
  2571. var
  2572.   OldPen: TPen;
  2573. begin
  2574.   OldPen := TPen.Create;
  2575.   try
  2576.     with Canvas, DrawInfo do
  2577.     begin
  2578.       OldPen.Assign(Pen);
  2579.       Pen.Style := psDot;
  2580.       Pen.Mode := pmXor;
  2581.       Pen.Width := 1;
  2582.       try
  2583.         if FGridState = gsRowSizing then
  2584.         begin
  2585.           MoveTo(0, FSizingPos);
  2586.           LineTo(Horz.GridBoundary, FSizingPos);
  2587.         end
  2588.         else
  2589.         begin
  2590.           MoveTo(FSizingPos, 0);
  2591.           LineTo(FSizingPos, Vert.GridBoundary);
  2592.         end;
  2593.       finally
  2594.         Pen := OldPen;
  2595.       end;
  2596.     end;
  2597.   finally
  2598.     OldPen.Free;
  2599.   end;
  2600. end;
  2601. procedure TbsSkinCustomGrid.DrawMove;
  2602. var
  2603.   OldPen: TPen;
  2604.   Pos: Integer;
  2605.   R: TRect;
  2606. begin
  2607.   OldPen := TPen.Create;
  2608.   try
  2609.     with Canvas do
  2610.     begin
  2611.       OldPen.Assign(Pen);
  2612.       try
  2613.         Pen.Style := psDot;
  2614.         Pen.Mode := pmXor;
  2615.         Pen.Width := 5;
  2616.         if FGridState = gsRowMoving then
  2617.         begin
  2618.           R := CellRect(0, FMovePos);
  2619.           if FMovePos > FMoveIndex then
  2620.             Pos := R.Bottom else
  2621.             Pos := R.Top;
  2622.           MoveTo(0, Pos);
  2623.           LineTo(ClientWidth, Pos);
  2624.         end
  2625.         else
  2626.         begin
  2627.           R := CellRect(FMovePos, 0);
  2628.           if FMovePos > FMoveIndex then
  2629.             if not UseRightToLeftAlignment then
  2630.               Pos := R.Right
  2631.             else
  2632.               Pos := R.Left
  2633.           else
  2634.             if not UseRightToLeftAlignment then
  2635.               Pos := R.Left
  2636.             else
  2637.               Pos := R.Right;
  2638.           MoveTo(Pos, 0);
  2639.           LineTo(Pos, ClientHeight);
  2640.         end;
  2641.       finally
  2642.         Canvas.Pen := OldPen;
  2643.       end;
  2644.     end;
  2645.   finally