5 uses Windows
, Messages
, KOL
;
8 MaxCustomExtents
= Maxint
div 16;
9 MaxShortInt
= High(ShortInt
);
12 PIntArray
= ^TIntArray
;
13 TIntArray
= array[0..MaxCustomExtents
] of Integer;
15 PStrListArray
= ^TStrListArray
;
16 TStrListArray
= array of PStrList
;
18 // TMyEvent = procedure(Sender: PControl; Str: String; const Error: Boolean; var Retry: Boolean) of object;
20 TScrollStyle
= (ssNone
, ssHorizontal
, ssVertical
, ssBoth
);
22 TGetExtentsFunc
= function(Index
: Longint): Integer of object;
24 TGridAxisDrawInfo
= record
25 EffectiveLineWidth
: Integer;
26 FixedBoundary
: Integer;
27 GridBoundary
: Integer;
29 LastFullVisibleCell
: Longint;
30 FullVisBoundary
: Integer;
31 FixedCellCount
: Integer;
32 FirstGridCell
: Integer;
33 GridCellCount
: Integer;
34 GetExtent
: TGetExtentsFunc
;
37 TGridDrawInfo
= record
38 Horz
, Vert
: TGridAxisDrawInfo
;
41 TGridState
= (gsNormal
, gsSelecting
, gsRowSizing
, gsColSizing
,
42 gsRowMoving
, gsColMoving
);
43 TGridMovement
= gsRowMoving
..gsColMoving
;
45 TGridOption
= (goFixedVertLine
, goFixedHorzLine
, goVertLine
, goHorzLine
,
46 goRangeSelect
, goDrawFocusSelected
, goRowSizing
, goColSizing
, goRowMoving
,
47 goColMoving
, goEditing
, goTabs
, goRowSelect
,
48 goAlwaysShowEditor
, goThumbTracking
);
49 TGridOptions
= set of TGridOption
;
50 TGridDrawState
= set of (gdSelected
, gdFocused
, gdFixed
);
51 TGridScrollDirection
= set of (sdLeft
, sdRight
, sdUp
, sdDown
);
60 0: (Left
, Top
, Right
, Bottom
: Longint);
61 1: (TopLeft
, BottomRight
: TGridCoord
);
64 TEditStyle
= (esSimple
, esEllipsis
, esPickList
);
66 TSelectCellEvent
= procedure (Sender
: PControl
; ACol
, ARow
: Longint;
67 var CanSelect
: Boolean) of object;
68 TDrawCellEvent
= procedure (Sender
: PControl
; Cnv
: PCanvas
; ACol
, ARow
: Longint;
69 Rect
: TRect
; State
: TGridDrawState
) of object;
72 TStGrd
= object(TControl
)
74 function GetColWidths(Index
: Integer): Integer;
75 function GetGridHeight
: Integer;
76 function GetGridWidth
: Integer;
77 function GetRowHeights(Index
: Integer): Integer;
78 function GetSelection
: TGridRect
;
79 // function GetTabStops(Index: Integer): Boolean;
80 function GetVisibleColCount
: Integer;
81 function GetVisibleRowCount
: Integer;
82 procedure SetCol(const Value
: Longint);
83 procedure SetColCount(Value
: Longint);
84 procedure SetColWidths(Index
: Integer; const Value
: Integer);
85 procedure SetDefaultColWidth(const Value
: Integer);
86 procedure SetDefaultRowHeight(const Value
: Integer);
87 procedure SetFixedCols(const Value
: Integer);
88 procedure SetFixedRows(const Value
: Integer);
89 procedure SetLeftCol(const Value
: Longint);
90 procedure SetOptions(Value
: TGridOptions
);
91 procedure SetRow(const Value
: Longint);
92 procedure SetRowCount(Value
: Longint);
93 procedure SetRowHeights(Index
: Integer; const Value
: Integer);
94 procedure SetScrollBars(const Value
: TScrollStyle
);
95 procedure SetSelection(const Value
: TGridRect
);
96 // procedure SetTabStops(Index: Integer; const Value: Boolean);
97 procedure SetTopRow(const Value
: Longint);
98 function GetCol
: Longint;
99 function GetLeftCol
: Longint;
100 function GetRow
: Longint;
101 function GetTopRow
: Longint;
102 function GetColCount
: Longint;
103 function GetDefaultColWidth
: Integer;
104 function GetDefaultDrawing
: Boolean;
105 function GetHitTest
: TPoint
;
106 procedure SetDefaultDrawing(const Value
: Boolean);
107 function GetDefaultRowHeight
: Integer;
108 function GetFixedCols
: Integer;
109 function GetFixedRows
: Integer;
110 function GetOptions
: TGridOptions
;
111 function GetRowCount
: Longint;
112 function GetScrollBars
: TScrollStyle
;
114 function CalcCoordFromPoint(X
, Y
: Integer; const DrawInfo
: TGridDrawInfo
): TGridCoord
;
115 procedure CalcDrawInfoXY(var DrawInfo
: TGridDrawInfo
; UseWidth
, UseHeight
: Integer);
116 procedure GridRectToScreenRect(GridRect
: TGridRect
; var ScreenRect
: TRect
; IncludeLine
: Boolean);
117 function IsActiveControl
: Boolean;
118 procedure MoveCurrent(ACol
, ARow
: Longint; _MoveAnchor
, _Show
: Boolean);
119 procedure ClampInView(const Coord
: TGridCoord
);
120 function CalcMaxTopLeft(const Coord
: TGridCoord
; const DrawInfo
: TGridDrawInfo
): TGridCoord
;
121 procedure SelectionMoved(const OldSel
: TGridRect
);
122 procedure InvalidateRect(ARect
: TGridRect
);
123 procedure ChangeSize(NewColCount
, NewRowCount
: Longint);
124 procedure MoveAnchor(const NewAnchor
: TGridCoord
);
125 procedure MoveTopLeft(ALeft
, ATop
: Longint);
126 procedure DrawSizingLine(const DrawInfo
: TGridDrawInfo
);
128 procedure MoveAndScroll(Mouse
, CellHit
: Integer; var DrawInfo
: TGridDrawInfo
;
129 var Axis
: TGridAxisDrawInfo
; Scrollbar
: Integer; const MousePt
: TPoint
);
130 procedure ModifyScrollBar(ScrollBar
, ScrollCode
, Pos
: Cardinal; UseRightToLeft
: Boolean);
131 procedure ScrollDataInfo(DX
, DY
: Integer; var DrawInfo
: TGridDrawInfo
);
132 procedure UpdateScrollPos
;
133 procedure UpdateScrollRange
;
134 procedure MoveAdjust(var CellPos
: Longint; FromIndex
, ToIndex
: Longint);
135 procedure CancelMode
;
138 procedure WMSetCursor(_HitTest
: Word);
139 function GetOnDrawCell
: TDrawCellEvent
;
140 procedure SetOnDrawCell(const Value
: TDrawCellEvent
);
141 function GetCells(ACol
, ARow
: Integer): string;
142 procedure SetCells(ACol
, ARow
: Integer; const Value
: string);
144 // function GetMyEvent: TMyEvent;
145 // procedure SetMyEvent(const Value: TMyEvent);
147 // procedure OnNewLVData(Sender: PControl; Idx, SubItem: Integer; var Txt: String;
148 // var ImgIdx: Integer; var State: DWORD; var Store: Boolean);
150 procedure CalcDrawInfo(var DrawInfo
: TGridDrawInfo
);
151 procedure CalcFixedInfo(var DrawInfo
: TGridDrawInfo
);
152 procedure CalcSizingState(X
, Y
: Integer; var State
: TGridState
; var Index
: Longint; var SizingPos
, SizingOfs
: Integer; var FixedInfo
: TGridDrawInfo
);// virtual;
153 procedure DrawCell(Cnv
: PCanvas
; ACol
, ARow
: Longint; ARect
: TRect
; AState
: TGridDrawState
);// virtual;
154 procedure FocusCell(ACol
, ARow
: Longint; _MoveAnchor
: Boolean);
155 procedure InvalidateCell(ACol
, ARow
: Longint);
156 function BoxRect(ALeft
, ATop
, ARight
, ABottom
: Longint): TRect
;
157 procedure Paint(DC
: HDC
);
158 procedure KeyDown(var Key
: Integer);
159 procedure MouseDown({Button: TMouseButton; Shift: TShiftState;} X
, Y
: Integer);
160 procedure MouseMove({Shift: TShiftState;} X
, Y
: Integer);
161 procedure MouseUp({Button: TMouseButton; Shift: TShiftState;} X
, Y
: Integer);
162 procedure WheelDown
{(Shift: TShiftState; MousePos: TPoint): Boolean};
163 procedure WheelUp
{(Shift: TShiftState; MousePos: TPoint): Boolean};
164 procedure TimedScroll(Direction
: TGridScrollDirection
);
165 procedure ScrollData(DX
, DY
: Integer);
166 function SelectCell(ACol
, ARow
: Longint): Boolean;
167 procedure MoveColumn(FromIndex
, ToIndex
: Longint);
168 procedure MoveRow(FromIndex
, ToIndex
: Longint);
169 procedure TopLeftMoved(const OldTopLeft
: TGridCoord
);
170 function GetRows(Index
: Integer): pStrList
;
171 procedure SetRows(Index
: Integer; const Value
: pStrList
);
172 function GetOnSelectCell
: TSelectCellEvent
;
173 procedure SetOnSelectCell(const Value
: TSelectCellEvent
);
175 // property MyEvent: TMyEvent read GetMyEvent write SetMyEvent;
176 property OnDrawCell
: TDrawCellEvent read GetOnDrawCell write SetOnDrawCell
;
177 property OnSelectCell
: TSelectCellEvent read GetOnSelectCell write SetOnSelectCell
;
179 // property OnLVData: Boolean read FNotAvailable;
180 property Col
: Longint read GetCol write SetCol
;
182 property ColCount
: Longint read GetColCount write SetColCount
;
183 property ColWidths
[Index
: Longint]: Integer read GetColWidths write SetColWidths
;
184 property DefaultColWidth
: Integer read GetDefaultColWidth write SetDefaultColWidth
;
185 property DefaultDrawing
: Boolean read GetDefaultDrawing write SetDefaultDrawing
;
186 property DefaultRowHeight
: Integer read GetDefaultRowHeight write SetDefaultRowHeight
;
187 property FixedCols
: Integer read GetFixedCols write SetFixedCols
;
188 property FixedRows
: Integer read GetFixedRows write SetFixedRows
;
189 property GridHeight
: Integer read GetGridHeight
;
190 property GridWidth
: Integer read GetGridWidth
;
191 property HitTest
: TPoint read GetHitTest
;
192 property LeftCol
: Longint read GetLeftCol write SetLeftCol
;
193 property Options
: TGridOptions read GetOptions write SetOptions
;
194 property Row
: Longint read GetRow write SetRow
;
195 property RowCount
: Longint read GetRowCount write SetRowCount
;
196 property RowHeights
[Index
: Longint]: Integer read GetRowHeights write SetRowHeights
;
197 property Rows
[Index
: Longint]: pStrList read GetRows write SetRows
;
198 property ScrollBars
: TScrollStyle read GetScrollBars write SetScrollBars
;
199 property Selection
: TGridRect read GetSelection write SetSelection
;
200 // property TabStops[Index: Longint]: Boolean read GetTabStops write SetTabStops;
201 property TopRow
: Longint read GetTopRow write SetTopRow
;
202 property VisibleColCount
: Integer read GetVisibleColCount
;
203 property VisibleRowCount
: Integer read GetVisibleRowCount
;
205 property Cells
[ACol
,ARow
: Longint]: string read GetCells write SetCells
;
210 TXorRects
= array[0..3] of TRect
;
215 function NewStGrd(Sender
: PControl
;CCount
,RCount
,FCols
,FRows
,DefCW
,DefRH
: Longint; Options
: TGridOptions
; DefDraw
,c3D
,hasBrdr
: Boolean; sBars
: TScrollStyle
): PStGrd
;
217 function PointInGridRect(Col
, Row
: Longint; const Rect
: TGridRect
): Boolean;
218 procedure XorRects(const R1
, R2
: TRect
; var XorRects
: TXorRects
);
227 IDC_HSPLIT
= PChar(32765);
228 IDC_VSPLIT
= PChar(32764);
230 { ÄÀÍÍÛÅ ÄËß ÍÀØÅÃÎ ÎÁÚÅÊÒÀ (ÑÂÎÉÑÒÂÀ È ÎÁÐÀÁÎÒ×ÈÊÈ) }
232 PStGrdData
= ^TStGrdData
;
233 TStGrdData
= object(TObj
)
236 fOnDrawCell
: TDrawCellEvent
;
237 fOnSelectCell
: TSelectCellEvent
;
243 // fTabStops: Pointer;
244 fCurrent
: TGridCoord
;
245 fDefaultColWidth
: Integer;
246 fDefaultRowHeight
: Integer;
249 fOptions
: TGridOptions
;
251 fRowHeights
: Pointer;
252 fScrollBars
: TScrollStyle
;
253 fTopLeft
: TGridCoord
;
254 fSizingIndex
: Longint;
255 fSizingPos
, fSizingOfs
: Integer;
256 fMoveIndex
, fMovePos
: Longint;
259 fDefaultDrawing
: Boolean;
260 fGridState
: TGridState
;
261 fSaveCellExtents
: Boolean;
265 destructor Destroy
; virtual;
268 { Allocate a section and set all its items to nil. Returns: Pointer to start of
270 function MakeSec(SecIndex
: Integer; SectionSize
: Word): Pointer;
275 Size
:= SectionSize
* SizeOf(Pointer);
277 FillChar(secP
^, size
, 0);
282 function GridRect(Coord1
, Coord2
: TGridCoord
): TGridRect
;
287 if Coord1
.X
< Coord2
.X
then Left
:= Coord1
.X
;
289 if Coord1
.X
< Coord2
.X
then Right
:= Coord2
.X
;
291 if Coord1
.Y
< Coord2
.Y
then Top
:= Coord1
.Y
;
293 if Coord1
.Y
< Coord2
.Y
then Bottom
:= Coord2
.Y
;
297 function PointInGridRect(Col
, Row
: Longint; const Rect
: TGridRect
): Boolean;
299 Result
:= (Col
>= Rect
.Left
) and (Col
<= Rect
.Right
) and (Row
>= Rect
.Top
)
300 and (Row
<= Rect
.Bottom
);
303 procedure XorRects(const R1
, R2
: TRect
; var XorRects
: TXorRects
);
305 Intersect
, Union
: TRect
;
307 function PtInRect(X
, Y
: Integer; const Rect
: TRect
): Boolean;
309 with Rect
do Result
:= (X
>= Left
) and (X
<= Right
) and (Y
>= Top
) and
313 function Includes(const P1
: TPoint
; var P2
: TPoint
): Boolean;
317 Result
:= PtInRect(X
, Y
, R1
) or PtInRect(X
, Y
, R2
);
318 if Result
then P2
:= P1
;
322 function Build(var R
: TRect
; const P1
, P2
, P3
: TPoint
): Boolean;
326 if Includes(P1
, TopLeft
) then
328 if not Includes(P3
, BottomRight
) then BottomRight
:= P2
;
330 else if Includes(P2
, TopLeft
) then BottomRight
:= P3
335 FillChar(XorRects
, SizeOf(XorRects
), 0);
336 if not Bool(IntersectRect(Intersect
, R1
, R2
)) then
338 { Don't intersect so its simple }
344 UnionRect(Union
, R1
, R2
);
345 if Build(XorRects
[0],
346 MakePoint(Union
.Left
, Union
.Top
),
347 MakePoint(Union
.Left
, Intersect
.Top
),
348 MakePoint(Union
.Left
, Intersect
.Bottom
)) then
349 XorRects
[0].Right
:= Intersect
.Left
;
350 if Build(XorRects
[1],
351 MakePoint(Intersect
.Left
, Union
.Top
),
352 MakePoint(Intersect
.Right
, Union
.Top
),
353 MakePoint(Union
.Right
, Union
.Top
)) then
354 XorRects
[1].Bottom
:= Intersect
.Top
;
355 if Build(XorRects
[2],
356 MakePoint(Union
.Right
, Intersect
.Top
),
357 MakePoint(Union
.Right
, Intersect
.Bottom
),
358 MakePoint(Union
.Right
, Union
.Bottom
)) then
359 XorRects
[2].Left
:= Intersect
.Right
;
360 if Build(XorRects
[3],
361 MakePoint(Union
.Left
, Union
.Bottom
),
362 MakePoint(Intersect
.Left
, Union
.Bottom
),
363 MakePoint(Intersect
.Right
, Union
.Bottom
)) then
364 XorRects
[3].Top
:= Intersect
.Bottom
;
368 procedure ModifyExtents(var Extents
: Pointer; Index
, Amount
: Longint;
371 LongSize
, OldSize
: LongInt;
377 if not Assigned(Extents
)
379 else OldSize
:= PIntArray(Extents
)^[0];
380 if (Index
< 0) or (OldSize
< Index
) then exit
;//InvalidOp(SIndexOutOfRange);
381 LongSize
:= OldSize
+ Amount
;
383 then exit
//InvalidOp(STooManyDeleted)
384 else if LongSize
>= MaxCustomExtents
- 1 then exit
;//InvalidOp(SGridTooLarge);
385 NewSize
:= Cardinal(LongSize
);
386 if NewSize
> 0 then Inc(NewSize
);
387 ReallocMem(Extents
, NewSize
* SizeOf(Integer));
388 if Assigned(Extents
) then begin
390 while I
< NewSize
do begin
391 PIntArray(Extents
)^[I
] := Default
;
394 PIntArray(Extents
)^[0] := NewSize
-1;
399 procedure UpdateExtents(var Extents
: Pointer; NewSize
: Longint;
405 if Assigned(Extents
) then OldSize
:= PIntArray(Extents
)^[0];
406 ModifyExtents(Extents
, OldSize
, NewSize
- OldSize
, Default
);
409 procedure MoveExtent(var Extents
: Pointer; FromIndex
, ToIndex
: Longint);
413 if Assigned(Extents
) then
415 Extent
:= PIntArray(Extents
)^[FromIndex
];
416 if FromIndex
< ToIndex
then
417 Move(PIntArray(Extents
)^[FromIndex
+ 1], PIntArray(Extents
)^[FromIndex
],
418 (ToIndex
- FromIndex
) * SizeOf(Integer))
419 else if FromIndex
> ToIndex
then
420 Move(PIntArray(Extents
)^[ToIndex
], PIntArray(Extents
)^[ToIndex
+ 1],
421 (FromIndex
- ToIndex
) * SizeOf(Integer));
422 PIntArray(Extents
)^[ToIndex
] := Extent
;
426 function CompareExtents(E1
, E2
: Pointer): Boolean;
435 for I
:= 0 to PIntArray(E1
)^[0] do
436 if PIntArray(E1
)^[I
] <> PIntArray(E2
)^[I
] then Exit
;
440 else Result
:= E2
= nil;
443 function LongMulDiv(Mult1
, Mult2
, Div1
: Longint): Longint; stdcall;
444 external 'kernel32.dll' name
'MulDiv';
446 procedure KillMessage(Wnd
: HWnd
; Msg
: Integer);
451 if PeekMessage(M
, Wnd
, Msg
, Msg
, pm_Remove
) and (M
.Message = WM_QUIT
) then
452 PostQuitMessage(M
.wparam
);
455 {-------------------------}
456 { Destructor ÍÀØÈÕ ÄÀÍÍÛÕ }
457 {-------------------------}
458 destructor TStGrdData
.Destroy
;
461 // All Strings := '';
462 // Free_And_Nil(All PObj);
463 for i
:= fColCount
-1 downto 0 do
464 PStrListArray(fCells
)^[i
].Free
;
465 SetLength(PStrListArray(fCells
)^,0);
466 Dispose(PStrListArray(fCells
));
470 FreeMem(fRowHeights
);
471 // FreeMem(fTabStops);
473 ////////////////////////////////////////////////////////////////////////////////
475 {--------------------}
476 { ÎÁÐÀÁÎÒ×ÈÊ ÎÁÚÅÊÒÀ }
477 {--------------------}
478 function WndProcStGrd(Ctl
: PControl
; var Msg
: TMsg
; var Rslt
: Integer): Boolean;
488 D
:= Pointer(S
.CustomObj
);
491 with S
^,Msg
do case Msg
.message of
492 WM_KEYDOWN
: KeyDown(wParam
);
493 WM_LBUTTONDOWN
: begin MouseDown(LOWORD(lParam
),HIWORD(lParam
)); SetCapture(Handle
); end;
494 WM_LBUTTONUP
: begin MouseUp(LoWord(lParam
),HiWord(lParam
)); ReleaseCapture
; end;
497 GetWindowRect(Handle
,r
);
498 InflateRect(r
,-2,-2);
499 if PtInRect(r
,p
) then MouseMove(LOWORD(lParam
),HIWORD(lParam
));
501 WM_SIZE
: UpdateScrollRange
;
503 Rslt
:= DLGC_WANTARROWS
;
504 if goRowSelect
in D
.fOptions
then Exit
;
505 if goTabs
in D
.fOptions
then Rslt
:= Rslt
or DLGC_WANTTAB
;
506 if goEditing
in D
.fOptions
then Rslt
:= Rslt
or DLGC_WANTCHARS
;
508 WM_KILLFOCUS
: InvalidateRect(Selection
);
509 WM_SETFOCUS
: InvalidateRect(Selection
);
510 WM_NCHITTEST
: D
.fHitTest
:= Screen2Client(MakePoint(LOWORD(lParam
),HIWORD(lParam
)));
513 t_dc
:= GetDC(Handle
);
515 ReleaseDC(Handle
,t_dc
);
517 WM_VSCROLL
: ModifyScrollBar(SB_VERT
, LOWORD(wParam
), HIWORD(wParam
), True);
518 WM_HSCROLL
: ModifyScrollBar(SB_HORZ
, LOWORD(wParam
), HIWORD(wParam
), True);
519 WM_MOUSEWHEEL
: if smallint(HIWORD(wParam
)) > 0 then WheelUp
else WheelDown
;
520 WM_SETCURSOR
: WMSetCursor(LOWORD(lParam
));
521 WM_CANCELMODE
: CancelMode
;
522 // Åñëè Result := TRUE, òî äàëüøå ñîîáùåíèå êîíòðîëó íå ïåðåäàåòñÿ.
525 ////////////////////////////////////////////////////////////////////////////////
527 {-----------------------------}
528 { ÊÎÍÑÒÐÓÊÒÎÐ ÄËß KOL ÎÁÚÅÊÒÀ }
529 {-----------------------------}
536 i
:= WS_CHILD
{or WS_CLIPCHILDREN or WS_CLIPSIBLINGS} or WS_TABSTOP
or WS_VISIBLE
;
537 if (sBars
in [ssVertical
,ssBoth
]) then i
:= i
or WS_VSCROLL
;
538 if (sBars
in [ssHorizontal
,ssBoth
]) then i
:= i
or WS_HSCROLL
;
540 Result
:= PStGrd(_NewControl(Sender
,'TStGrd',i
,false,nil));
542 Result
.ExStyle
:= Result
.ExStyle
and not WS_EX_CLIENTEDGE
;
543 Result
.Style
:= Result
.Style
and not WS_BORDER
;
545 if c3D
then Result
.ExStyle
:= Result
.ExStyle
or WS_EX_CLIENTEDGE
546 else Result
.Style
:= Result
.Style
or WS_BORDER
;
548 Result
.CustomObj
:= D
;
549 D
.fControl
:= Result
;
551 D
.fDefaultColWidth
:= DefCW
;
552 D
.fDefaultRowHeight
:= DefRH
;
553 D
.fDefaultDrawing
:= DefDraw
;
554 D
.fSaveCellExtents
:= True;
555 D
.fColCount
:= CCount
;
556 D
.fRowCount
:= RCount
;
557 D
.fFixedCols
:= FCols
;
558 D
.fFixedRows
:= FRows
;
559 D
.fTopLeft
.X
:= D
.fFixedCols
;
560 D
.fTopLeft
.Y
:= D
.fFixedRows
;
561 D
.fCurrent
:= D
.fTopLeft
;
562 D
.fAnchor
:= D
.fCurrent
;
563 D
.fOptions
:= Options
;
564 if goRowSelect
in D
.fOptions
then D
.fAnchor
.X
:= D
.fColCount
- 1;
565 D
.fScrollBars
:= sBars
;
566 D
.fGridState
:= gsNormal
;
569 New(PStrListArray(D
.fCells
));//,D.fColCount*D.fRowCount*SizeOf(PAnsiString));
570 SetLength(PStrListArray(D
.fCells
)^,D
.fColCount
);
571 for i
:= 0 to D
.fColCount
-1 do begin
572 PStrListArray(D
.fCells
)^[i
] := NewStrList
;//.Create;
573 for j
:= 0 to D
.fRowCount
-1 do
574 PStrListArray(D
.fCells
)^[i
].Add('');
577 // Result.TabStop := True;
581 { Óñòàíîâêà îáðàáîò÷èêîâ }
582 Result
.AttachProc(WndProcStGrd
);
584 { Óñòàíîâêà íîâîãî îáðàáîò÷èêà }
585 // Result.SetOnLVData(Result.OnNewLVData);
587 ////////////////////////////////////////////////////////////////////////////////
589 {--------------------}
590 { ÎÁÐÀÁÎÒ×ÈÊ MyEvent }
591 {--------------------}
592 { procedure TStGrd.SetMyEvent;
595 D := Pointer(CustomObj);
599 function TStGrd.GetMyEvent;
602 D := Pointer(CustomObj);
608 function TStGrd
.BoxRect(ALeft
, ATop
, ARight
, ABottom
: Integer): TRect
;
612 GridRect
.Left
:= ALeft
;
613 GridRect
.Right
:= ARight
;
614 GridRect
.Top
:= ATop
;
615 GridRect
.Bottom
:= ABottom
;
616 GridRectToScreenRect(GridRect
, Result
, False);
619 function TStGrd
.CalcCoordFromPoint(X
, Y
: Integer; const DrawInfo
: TGridDrawInfo
): TGridCoord
;
621 function DoCalc(const AxisInfo
: TGridAxisDrawInfo
; N
: Integer): Integer;
623 I
, Start
, Stop
: Longint;
628 if N
< FixedBoundary
then
631 Stop
:= FixedCellCount
- 1;
636 Start
:= FirstGridCell
;
637 Stop
:= GridCellCount
- 1;
638 Line
:= FixedBoundary
;
641 for I
:= Start
to Stop
do
643 Inc(Line
, GetExtent(I
) + EffectiveLineWidth
);
653 function DoCalcRightToLeft(const AxisInfo
: TGridAxisDrawInfo
; N
: Integer): Integer;
655 I
, Start
, Stop
: Longint;
658 N
:= ClientWidth
- N
;
661 if N
< FixedBoundary
then
664 Stop
:= FixedCellCount
- 1;
669 Start
:= FirstGridCell
;
670 Stop
:= GridCellCount
- 1;
671 Line
:= FixedBoundary
;
674 for I
:= Start
to Stop
do
676 Inc(Line
, GetExtent(I
) + EffectiveLineWidth
);
687 // if not UseRightToLeftAlignment then
688 Result
.X
:= DoCalc(DrawInfo
.Horz
, X
);
690 // Result.X := DoCalcRightToLeft(DrawInfo.Horz, X);
691 Result
.Y
:= DoCalc(DrawInfo
.Vert
, Y
);
694 procedure TStGrd
.CalcDrawInfo(var DrawInfo
: TGridDrawInfo
);
696 CalcDrawInfoXY(DrawInfo
, ClientWidth
, ClientHeight
);
699 procedure TStGrd
.CalcDrawInfoXY(var DrawInfo
: TGridDrawInfo
; UseWidth
, UseHeight
: Integer);
701 procedure CalcAxis(var AxisInfo
: TGridAxisDrawInfo
; UseExtent
: Integer);
704 with AxisInfo
do begin
705 GridExtent
:= UseExtent
;
706 GridBoundary
:= FixedBoundary
;
707 FullVisBoundary
:= FixedBoundary
;
708 LastFullVisibleCell
:= FirstGridCell
;
709 for I
:= FirstGridCell
to GridCellCount
- 1 do begin
710 Inc(GridBoundary
, GetExtent(I
) + EffectiveLineWidth
);
711 if GridBoundary
> GridExtent
+ EffectiveLineWidth
then begin
712 GridBoundary
:= GridExtent
;
715 LastFullVisibleCell
:= I
;
716 FullVisBoundary
:= GridBoundary
;
722 CalcFixedInfo(DrawInfo
);
723 CalcAxis(DrawInfo
.Horz
, UseWidth
);
724 CalcAxis(DrawInfo
.Vert
, UseHeight
);
727 procedure TStGrd
.CalcFixedInfo(var DrawInfo
: TGridDrawInfo
);
729 procedure CalcFixedAxis(var Axis
: TGridAxisDrawInfo
; LineOptions
: TGridOptions
; FixedCount
, FirstCell
, CellCount
: Integer; GetExtentFunc
: TGetExtentsFunc
);
733 if LineOptions
* Options
= []
734 then EffectiveLineWidth
:= 0
735 else EffectiveLineWidth
:= GridLineWidth
;
738 for I
:= 0 to FixedCount
- 1 do
739 Inc(FixedBoundary
, GetExtentFunc(I
) + EffectiveLineWidth
);
741 FixedCellCount
:= FixedCount
;
742 FirstGridCell
:= FirstCell
;
743 GridCellCount
:= CellCount
;
744 GetExtent
:= GetExtentFunc
;
750 D
:= Pointer(CustomObj
);
751 CalcFixedAxis(DrawInfo
.Horz
, [goFixedVertLine
, goVertLine
], D
.fFixedCols
, D
.fTopLeft
.X
, D
.fColCount
, GetColWidths
);
752 CalcFixedAxis(DrawInfo
.Vert
, [goFixedHorzLine
, goHorzLine
], D
.fFixedRows
, D
.fTopLeft
.Y
, D
.fRowCount
, GetRowHeights
);
755 function TStGrd
.CalcMaxTopLeft(const Coord
: TGridCoord
; const DrawInfo
: TGridDrawInfo
): TGridCoord
;
757 function CalcMaxCell(const Axis
: TGridAxisDrawInfo
; Start
: Integer): Integer;
765 Line
:= GridExtent
+ EffectiveLineWidth
;
766 for I
:= Start
downto FixedCellCount
do
768 Extent
:= GetExtent(I
);
772 Dec(Line
, EffectiveLineWidth
);
773 if Line
< FixedBoundary
then
775 if (Result
= Start
) and (GetExtent(Start
) <= 0) then
786 Result
.X
:= CalcMaxCell(DrawInfo
.Horz
, Coord
.X
);
787 Result
.Y
:= CalcMaxCell(DrawInfo
.Vert
, Coord
.Y
);
790 procedure TStGrd
.CalcSizingState(X
, Y
: Integer; var State
: TGridState
; var Index
, SizingPos
, SizingOfs
: Integer; var FixedInfo
: TGridDrawInfo
);
792 procedure CalcAxisState(const AxisInfo
: TGridAxisDrawInfo
; Pos
: Integer; NewState
: TGridState
);
793 var I
, Line
, Back
, Range
: Integer;
795 // if (NewState = gsColSizing) and UseRightToLeftAlignment then
796 // Pos := ClientWidth - Pos;
797 with AxisInfo
do begin
798 Line
:= FixedBoundary
;
799 Range
:= EffectiveLineWidth
;
801 if Range
< 7 then begin
803 Back
:= (Range
- EffectiveLineWidth
) shr 1;
805 for I
:= FirstGridCell
to GridCellCount
- 1 do begin
806 Inc(Line
, GetExtent(I
));
807 if Line
> GridBoundary
then Break
;
808 if (Pos
>= Line
- Back
) and (Pos
<= Line
- Back
+ Range
) then begin
811 SizingOfs
:= Line
- Pos
;
815 Inc(Line
, EffectiveLineWidth
);
817 if (GridBoundary
= GridExtent
) and (Pos
>= GridExtent
- Back
) and (Pos
<= GridExtent
) then begin
819 SizingPos
:= GridExtent
;
820 SizingOfs
:= GridExtent
- Pos
;
821 Index
:= LastFullVisibleCell
+ 1;
826 function XOutsideHorzFixedBoundary
: Boolean;
829 // if not UseRightToLeftAlignment then
830 Result
:= X
> Horz
.FixedBoundary
832 // Result := X < ClientWidth - Horz.FixedBoundary;
835 function XOutsideOrEqualHorzFixedBoundary
: Boolean;
838 // if not UseRightToLeftAlignment then
839 Result
:= X
>= Horz
.FixedBoundary
841 // Result := X <= ClientWidth - Horz.FixedBoundary;
846 EffectiveOptions
: TGridOptions
;
849 D
:= Pointer(CustomObj
);
852 EffectiveOptions
:= D
.fOptions
;
853 // if csDesigning in ComponentState then
854 // EffectiveOptions := EffectiveOptions + DesignOptionsBoost;
855 if [goColSizing
, goRowSizing
] * EffectiveOptions
<> [] then
856 with FixedInfo
do begin
857 Vert
.GridExtent
:= ClientHeight
;
858 Horz
.GridExtent
:= ClientWidth
;
859 if (XOutsideHorzFixedBoundary
) and (goColSizing
in EffectiveOptions
) then begin
860 if Y
>= Vert
.FixedBoundary
then Exit
;
861 CalcAxisState(Horz
, X
, gsColSizing
);
862 end else if (Y
> Vert
.FixedBoundary
) and (goRowSizing
in EffectiveOptions
) then begin
863 if XOutsideOrEqualHorzFixedBoundary
then Exit
;
864 CalcAxisState(Vert
, Y
, gsRowSizing
);
869 procedure TStGrd
.CancelMode
;
871 DrawInfo
: TGridDrawInfo
;
874 D
:= Pointer(CustomObj
);
878 KillTimer(Handle
, 1);
879 gsRowSizing
, gsColSizing
:
881 CalcDrawInfo(DrawInfo
);
882 DrawSizingLine(DrawInfo
);
884 gsColMoving
, gsRowMoving
:
887 KillTimer(Handle
, 1);
891 D
.fGridState
:= gsNormal
;
895 procedure TStGrd
.ChangeSize(NewColCount
, NewRowCount
: Integer);
897 OldColCount
, OldRowCount
: Longint;
898 OldDrawInfo
: TGridDrawInfo
;
901 procedure MinRedraw(const OldInfo
, NewInfo
: TGridAxisDrawInfo
; Axis
: Integer);
906 First
:= Min(OldInfo
.LastFullVisibleCell
, NewInfo
.LastFullVisibleCell
);
907 // Get the rectangle around the leftmost or topmost cell in the target range.
908 R
:= BoxRect(First
and not Axis
, First
and Axis
,First
and not Axis
, First
and Axis
);
911 Windows
.InvalidateRect(Handle
, @R
, False);
917 NewDrawInfo
: TGridDrawInfo
;
919 if D
.fColWidths
<> nil then
920 UpdateExtents(D
.fColWidths
, D
.fColCount
, D
.fDefaultColWidth
);
921 { if D.fTabStops <> nil then
922 UpdateExtents(D.fTabStops, D.fColCount, Integer(True));}
923 if D
.fRowHeights
<> nil then
924 UpdateExtents(D
.fRowHeights
, D
.fRowCount
, D
.fDefaultRowHeight
);
926 if Row
>= D
.fRowCount
then Coord
.Y
:= D
.fRowCount
- 1;
927 if Col
>= D
.fColCount
then Coord
.X
:= D
.fColCount
- 1;
928 if (D
.fCurrent
.X
<> Coord
.X
) or (D
.fCurrent
.Y
<> Coord
.Y
) then
929 MoveCurrent(Coord
.X
, Coord
.Y
, True, True);
930 if (D
.fAnchor
.X
<> Coord
.X
) or (D
.fAnchor
.Y
<> Coord
.Y
) then
933 (LeftCol
<> OldDrawInfo
.Horz
.FirstGridCell
) or
934 (TopRow
<> OldDrawInfo
.Vert
.FirstGridCell
) then
937 CalcDrawInfo(NewDrawInfo
);
938 MinRedraw(OldDrawInfo
.Horz
, NewDrawInfo
.Horz
, 0);
939 MinRedraw(OldDrawInfo
.Vert
, NewDrawInfo
.Vert
, -1);
942 // SizeChanged(OldColCount, OldRowCount);
946 D
:= Pointer(CustomObj
);
947 CalcDrawInfo(OldDrawInfo
);
948 OldColCount
:= D
.fColCount
;
949 OldRowCount
:= D
.fRowCount
;
950 D
.fColCount
:= NewColCount
;
951 D
.fRowCount
:= NewRowCount
;
952 if D
.fFixedCols
> NewColCount
then D
.fFixedCols
:= NewColCount
- 1;
953 if D
.fFixedRows
> NewRowCount
then D
.fFixedRows
:= NewRowCount
- 1;
957 { Could not change size so try to clean up by setting the size back }
958 D
.fColCount
:= OldColCount
;
959 D
.fRowCount
:= OldRowCount
;
966 procedure TStGrd
.ClampInView(const Coord
: TGridCoord
);
968 DrawInfo
: TGridDrawInfo
;
969 MaxTopLeft
: TGridCoord
;
970 OldTopLeft
: TGridCoord
;
973 CalcDrawInfo(DrawInfo
);
974 with DrawInfo
, Coord
do begin
975 if (X
> Horz
.LastFullVisibleCell
) or
976 (Y
> Vert
.LastFullVisibleCell
) or (X
< LeftCol
) or (Y
< TopRow
) then begin
977 D
:= Pointer(CustomObj
);
978 OldTopLeft
:= d
.fTopLeft
;
979 MaxTopLeft
:= CalcMaxTopLeft(Coord
, DrawInfo
);
981 if X
< LeftCol
then d
.fTopLeft
.X
:= X
982 else if X
> Horz
.LastFullVisibleCell
then d
.fTopLeft
.X
:= MaxTopLeft
.X
;
983 if Y
< TopRow
then d
.fTopLeft
.Y
:= Y
984 else if Y
> Vert
.LastFullVisibleCell
then d
.fTopLeft
.Y
:= MaxTopLeft
.Y
;
985 TopLeftMoved(OldTopLeft
);
990 procedure TStGrd
.DrawCell(Cnv
: PCanvas
; ACol
, ARow
: Integer; ARect
: TRect
; AState
: TGridDrawState
);
993 D
:= Pointer(CustomObj
);
994 if Assigned(D
.fOnDrawCell
) and (not D
.fDefaultDrawing
)
995 then D
.fOnDrawCell(@Self
,Cnv
,ACol
,ARow
,ARect
,AState
);
996 { else if D.fDefaultDrawing then begin
997 InflateRect(ARect,-2,-2);
998 Cnv.TextRect(ARect,ARect.Left,ARect.Top,Cells[ACol,ARow]);
1002 procedure TStGrd
.DrawMove
;
1004 OldPen
: PGraphicTool
;
1010 D
:= Pointer(CustomObj
);
1012 with Canvas
^ do begin
1015 Pen
.PenStyle
:= psDot
;
1016 Pen
.PenMode
:= pmXor
;
1017 Pen
.Color
:= $0FFFF00;
1019 if D
.fGridState
= gsRowMoving
then begin
1020 R
:= BoxRect(0, D
.fMovePos
, 0, D
.fMovePos
);
1021 if D
.fMovePos
> D
.fMoveIndex
then
1022 Pos
:= R
.Bottom
else
1025 LineTo(ClientWidth
, Pos
);
1027 R
:= BoxRect(D
.fMovePos
, 0, D
.fMovePos
, 0);
1028 if D
.fMovePos
> D
.fMoveIndex
1029 then {if not UseRightToLeftAlignment
1030 then} Pos
:= R
.Right
1031 //else Pos := R.Left
1032 else {if not UseRightToLeftAlignment
1033 then} Pos
:= R
.Left
- 1;
1034 //else Pos := R.Right;
1036 LineTo(Pos
, ClientHeight
);
1047 procedure TStGrd
.DrawSizingLine(const DrawInfo
: TGridDrawInfo
);
1049 OldPen
: PGraphicTool
;
1052 D
:= Pointer(CustomObj
);
1055 with Canvas
^, DrawInfo
do begin
1057 Pen
.PenStyle
:= psSolid
;
1058 Pen
.PenMode
:= pmXor
;
1059 Pen
.Color
:= $0FFFF00;
1062 if D
.fGridState
= gsRowSizing
then begin
1063 { if UseRightToLeftAlignment then
1065 MoveTo(Horz.GridExtent, FSizingPos);
1066 LineTo(Horz.GridExtent - Horz.GridBoundary, FSizingPos);
1070 MoveTo(0, D
.fSizingPos
);
1071 LineTo(Horz
.GridBoundary
, D
.fSizingPos
);
1074 MoveTo(D
.fSizingPos
, 0);
1075 LineTo(D
.fSizingPos
, Vert
.GridBoundary
);
1086 procedure TStGrd
.FocusCell(ACol
, ARow
: Integer; _MoveAnchor
: Boolean);
1088 MoveCurrent(ACol
, ARow
, _MoveAnchor
, True);
1092 function TStGrd
.GetCells(ACol
, ARow
: Integer): string;
1095 D
:= Pointer(CustomObj
);
1096 if (ACol
< 0) or (ARow
< 0) or (ACol
> D
.fColCount
-1) or (ARow
> D
.fRowCount
- 1) then exit
;
1097 { if PStrArray(D.fCells)^[ACol,ARow] = nil
1099 else Result := PStrArray(D.fCells)^[ACol,ARow];}
1100 Result
:= PStrListArray(D
.fCells
)^[ACol
].Items
[ARow
];
1103 function TStGrd
.GetCol
: Longint;
1106 D
:= Pointer(CustomObj
);
1107 Result
:= D
.fCurrent
.X
;
1110 function TStGrd
.GetColCount
: Longint;
1113 D
:= Pointer(CustomObj
);
1114 Result
:= D
.fColCount
;
1117 function TStGrd
.GetColWidths(Index
: Integer): Integer;
1120 D
:= Pointer(CustomObj
);
1121 if (D
.fColWidths
= nil) or (Index
>= D
.fColCount
) then
1122 Result
:= D
.fDefaultColWidth
1124 Result
:= PIntArray(D
.fColWidths
)^[Index
+ 1];
1127 function TStGrd
.GetDefaultColWidth
: Integer;
1130 D
:= Pointer(CustomObj
);
1131 Result
:= D
.fDefaultColWidth
;
1134 function TStGrd
.GetDefaultDrawing
: Boolean;
1137 D
:= Pointer(CustomObj
);
1138 Result
:= D
.fDefaultDrawing
;
1141 function TStGrd
.GetDefaultRowHeight
: Integer;
1144 D
:= Pointer(CustomObj
);
1145 Result
:= D
.fDefaultRowHeight
;
1148 function TStGrd
.GetFixedCols
: Integer;
1151 D
:= Pointer(CustomObj
);
1152 Result
:= D
.fFixedCols
;
1155 function TStGrd
.GetFixedRows
: Integer;
1158 D
:= Pointer(CustomObj
);
1159 Result
:= D
.fFixedRows
;
1162 function TStGrd
.GetGridHeight
: Integer;
1164 DrawInfo
: TGridDrawInfo
;
1166 CalcDrawInfo(DrawInfo
);
1167 Result
:= DrawInfo
.Vert
.GridBoundary
;
1170 function TStGrd
.GetGridWidth
: Integer;
1172 DrawInfo
: TGridDrawInfo
;
1174 CalcDrawInfo(DrawInfo
);
1175 Result
:= DrawInfo
.Horz
.GridBoundary
;
1178 function TStGrd
.GetHitTest
: TPoint
;
1181 D
:= Pointer(CustomObj
);
1182 Result
:= D
.fHitTest
;
1185 function TStGrd
.GetLeftCol
: Longint;
1188 D
:= Pointer(CustomObj
);
1189 Result
:= D
.fTopLeft
.X
;
1192 function TStGrd
.GetOnDrawCell
: TDrawCellEvent
;
1195 D
:= Pointer(CustomObj
);
1196 Result
:= D
.fOnDrawCell
;
1199 function TStGrd
.GetOnSelectCell
: TSelectCellEvent
;
1202 D
:= Pointer(CustomObj
);
1203 Result
:= D
.fOnSelectCell
;
1206 function TStGrd
.GetOptions
: TGridOptions
;
1209 D
:= Pointer(CustomObj
);
1210 Result
:= D
.fOptions
;
1213 function TStGrd
.GetRow
: Longint;
1216 D
:= Pointer(CustomObj
);
1217 Result
:= D
.fCurrent
.Y
;
1220 function TStGrd
.GetRowCount
: Longint;
1223 D
:= Pointer(CustomObj
);
1224 Result
:= D
.fRowCount
;
1227 function TStGrd
.GetRowHeights(Index
: Integer): Integer;
1230 D
:= Pointer(CustomObj
);
1231 if (d
.fRowHeights
= nil) or (Index
>= d
.fRowCount
)
1232 then Result
:= D
.fDefaultRowHeight
1233 else Result
:= PIntArray(d
.fRowHeights
)^[Index
+ 1];
1236 function TStGrd
.GetRows(Index
: Integer): pStrList
;
1240 Result
:= NewStrList
;
1241 D
:= Pointer(CustomObj
);
1242 for i
:= 0 to D
.fColCount
-1 do
1243 Result
.Add(PStrListArray(D
.fCells
)^[i
].Items
[Index
])
1246 function TStGrd
.GetScrollBars
: TScrollStyle
;
1249 D
:= Pointer(CustomObj
);
1250 Result
:= D
.fScrollBars
;
1253 function TStGrd
.GetSelection
: TGridRect
;
1256 D
:= Pointer(CustomObj
);
1257 Result
:= GridRect(D
.fCurrent
, D
.fAnchor
);
1260 function TStGrd.GetTabStops(Index: Integer): Boolean;
1263 D := Pointer(CustomObj);
1264 if D.fTabStops = nil then Result := True
1265 else Result := Boolean(PIntArray(D.fTabStops)^[Index + 1]);
1268 function TStGrd
.GetTopRow
: Longint;
1271 D
:= Pointer(CustomObj
);
1272 Result
:= D
.fTopLeft
.Y
;
1275 function TStGrd
.GetVisibleColCount
: Integer;
1277 DrawInfo
: TGridDrawInfo
;
1279 CalcDrawInfo(DrawInfo
);
1280 Result
:= DrawInfo
.Horz
.LastFullVisibleCell
- LeftCol
+ 1;
1283 function TStGrd
.GetVisibleRowCount
: Integer;
1285 DrawInfo
: TGridDrawInfo
;
1287 CalcDrawInfo(DrawInfo
);
1288 Result
:= DrawInfo
.Vert
.LastFullVisibleCell
- TopRow
+ 1;
1291 procedure TStGrd
.GridRectToScreenRect(GridRect
: TGridRect
; var ScreenRect
: TRect
; IncludeLine
: Boolean);
1293 function LinePos(const AxisInfo
: TGridAxisDrawInfo
; Line
: Integer): Integer;
1297 with AxisInfo
do begin
1299 if Line
< FixedCellCount
1302 if Line
>= FirstGridCell
then
1303 Result
:= FixedBoundary
;
1304 Start
:= FirstGridCell
;
1306 for I
:= Start
to Line
- 1 do begin
1307 Inc(Result
, GetExtent(I
) + EffectiveLineWidth
);
1308 if Result
> GridExtent
then begin
1316 function CalcAxis(const AxisInfo
: TGridAxisDrawInfo
;
1317 GridRectMin
, GridRectMax
: Integer;
1318 var ScreenRectMin
, ScreenRectMax
: Integer): Boolean;
1321 with AxisInfo
do begin
1322 if (GridRectMin
>= FixedCellCount
) and (GridRectMin
< FirstGridCell
) then
1323 if GridRectMax
< FirstGridCell
then begin
1324 FillChar(ScreenRect
, SizeOf(ScreenRect
), 0); { erase partial results }
1327 GridRectMin
:= FirstGridCell
;
1328 if GridRectMax
> LastFullVisibleCell
then begin
1329 GridRectMax
:= LastFullVisibleCell
;
1330 if GridRectMax
< GridCellCount
- 1 then Inc(GridRectMax
);
1331 if LinePos(AxisInfo
, GridRectMax
) = 0 then
1335 ScreenRectMin
:= LinePos(AxisInfo
, GridRectMin
);
1336 ScreenRectMax
:= LinePos(AxisInfo
, GridRectMax
);
1337 if ScreenRectMax
= 0
1338 then ScreenRectMax
:= ScreenRectMin
+ GetExtent(GridRectMin
)
1339 else Inc(ScreenRectMax
, GetExtent(GridRectMax
));
1340 if ScreenRectMax
> GridExtent
then ScreenRectMax
:= GridExtent
;
1341 if IncludeLine
then Inc(ScreenRectMax
, EffectiveLineWidth
);
1347 DrawInfo
: TGridDrawInfo
;
1350 FillChar(ScreenRect
, SizeOf(ScreenRect
), 0);
1351 if (GridRect
.Left
> GridRect
.Right
) or (GridRect
.Top
> GridRect
.Bottom
) then Exit
;
1352 CalcDrawInfo(DrawInfo
);
1353 with DrawInfo
do begin
1354 if GridRect
.Left
> Horz
.LastFullVisibleCell
+ 1 then Exit
;
1355 if GridRect
.Top
> Vert
.LastFullVisibleCell
+ 1 then Exit
;
1357 if CalcAxis(Horz
, GridRect
.Left
, GridRect
.Right
, ScreenRect
.Left
, ScreenRect
.Right
) then
1358 CalcAxis(Vert
, GridRect
.Top
, GridRect
.Bottom
, ScreenRect
.Top
, ScreenRect
.Bottom
);
1361 { if UseRightToLeftAlignment and (Canvas.CanvasOrientation = coLeftToRight) then
1363 Hold := ScreenRect.Left;
1364 ScreenRect.Left := ClientWidth - ScreenRect.Right;
1365 ScreenRect.Right := ClientWidth - Hold;
1369 procedure TStGrd
.InvalidateCell(ACol
, ARow
: Integer);
1375 Rect
.Bottom
:= ARow
;
1377 InvalidateRect(Rect
);
1380 procedure TStGrd
.InvalidateRect(ARect
: TGridRect
);
1384 GridRectToScreenRect(ARect
, InvalidRect
, True);
1385 Windows
.InvalidateRect(Handle
, @InvalidRect
, False);
1388 function TStGrd
.IsActiveControl
: Boolean;
1394 PForm
:= ParentForm
;
1395 if Assigned(PForm
) then begin
1396 if (PForm
.ActiveControl
= @Self
) then
1400 while IsWindow(H
) and (Result
= False) do begin
1403 else H
:= GetParent(H
);
1408 procedure FillDWord(var Dest
; Count
, Value
: Integer); register;
1418 function StackAlloc(Size
: Integer): Pointer; register;
1420 POP ECX { return address }
1423 AND EAX, not 3 // round up to keep
ESP dword aligned
1428 PUSH EAX { make sure we touch guard page, to grow stack }
1434 MOV EAX, ESP { function result = low memory address of block }
1435 PUSH EDX { save original SP, for cleanup }
1438 PUSH EDX { save current SP, for sanity check (sp = [sp]) }
1439 PUSH ECX { return to caller }
1442 procedure StackFree(P
: Pointer); register;
1444 POP ECX { return address }
1445 MOV EDX, DWORD PTR [ESP]
1447 CMP EDX, ESP { sanity check #1 (SP = [SP]) }
1449 CMP EDX, EAX { sanity check #2 (P = this stack block) }
1451 MOV ESP, DWORD PTR [ESP+4] { restore previous SP }
1453 PUSH ECX { return to caller }
1456 procedure TStGrd
.KeyDown(var Key
: Integer);
1458 NewTopLeft
, NewCurrent
, MaxTopLeft
: TGridCoord
;
1459 DrawInfo
: TGridDrawInfo
;
1460 PageWidth
, PageHeight
: Integer;
1461 // RTLFactor: Integer;
1462 // NeedsInvalidating: Boolean;
1465 procedure CalcPageExtents
;
1467 CalcDrawInfo(DrawInfo
);
1468 PageWidth
:= DrawInfo
.Horz
.LastFullVisibleCell
- LeftCol
;
1469 if PageWidth
< 1 then PageWidth
:= 1;
1470 PageHeight
:= DrawInfo
.Vert
.LastFullVisibleCell
- TopRow
;
1471 if PageHeight
< 1 then PageHeight
:= 1;
1474 procedure Restrict(var Coord
: TGridCoord
; MinX
, MinY
, MaxX
, MaxY
: Longint);
1478 if X
> MaxX
then X
:= MaxX
1479 else if X
< MinX
then X
:= MinX
;
1480 if Y
> MaxY
then Y
:= MaxY
1481 else if Y
< MinY
then Y
:= MinY
;
1486 D
:= Pointer(CustomObj
);
1487 // NeedsInvalidating := False;
1488 // if not CanGridAcceptKey(Key, Shift) then Key := 0;
1489 { if not UseRightToLeftAlignment then
1493 NewCurrent
:= D
.fCurrent
;
1494 NewTopLeft
:= D
.fTopLeft
;
1496 if (GetAsyncKeyState(vk_Control
) < 0) then //ssCtrl in Shift then
1498 VK_UP
: Dec(NewTopLeft
.Y
);
1499 VK_DOWN
: Inc(NewTopLeft
.Y
);
1501 if not (goRowSelect
in Options
) then
1503 Dec(NewCurrent
.X
, PageWidth
);
1504 Dec(NewTopLeft
.X
, PageWidth
);
1507 if not (goRowSelect
in Options
) then
1509 Inc(NewCurrent
.X
, PageWidth
);
1510 Inc(NewTopLeft
.X
, PageWidth
);
1512 VK_PRIOR
: NewCurrent
.Y
:= TopRow
;
1513 VK_NEXT
: NewCurrent
.Y
:= DrawInfo
.Vert
.LastFullVisibleCell
;
1516 NewCurrent
.X
:= FixedCols
;
1517 NewCurrent
.Y
:= FixedRows
;
1521 NewCurrent
.X
:= ColCount
- 1;
1522 NewCurrent
.Y
:= RowCount
- 1;
1527 VK_UP
: Dec(NewCurrent
.Y
);
1528 VK_DOWN
: Inc(NewCurrent
.Y
);
1530 if goRowSelect
in D
.fOptions
then
1531 Dec(NewCurrent
.Y
) else
1534 if goRowSelect
in D
.fOptions
then
1535 Inc(NewCurrent
.Y
) else
1539 Inc(NewCurrent
.Y
, PageHeight
);
1540 Inc(NewTopLeft
.Y
, PageHeight
);
1544 Dec(NewCurrent
.Y
, PageHeight
);
1545 Dec(NewTopLeft
.Y
, PageHeight
);
1548 if goRowSelect
in D
.fOptions
then
1549 NewCurrent
.Y
:= D
.fFixedRows
else
1550 NewCurrent
.X
:= D
.fFixedCols
;
1552 if goRowSelect
in D
.fOptions
then
1553 NewCurrent
.Y
:= D
.fRowCount
- 1 else
1554 NewCurrent
.X
:= D
.fColCount
- 1;
1556 if not (ssAlt in Shift) then
1558 if ssShift in Shift then
1561 if NewCurrent.X < FixedCols then
1563 NewCurrent.X := ColCount - 1;
1565 if NewCurrent.Y < FixedRows then NewCurrent.Y := RowCount - 1;
1572 if NewCurrent.X >= D.fColCount then
1574 NewCurrent.X := D.fFixedCols;
1576 if NewCurrent.Y >= RowCount then NewCurrent.Y := D.fFixedRows;
1579 until TabStops[NewCurrent.X] or (NewCurrent.X = D.fCurrent.X);}
1580 // VK_F2: EditorMode := True;
1582 MaxTopLeft
.X
:= D
.fColCount
- 1;
1583 MaxTopLeft
.Y
:= D
.fRowCount
- 1;
1584 MaxTopLeft
:= CalcMaxTopLeft(MaxTopLeft
, DrawInfo
);
1585 Restrict(NewTopLeft
, D
.fFixedCols
, D
.fFixedRows
, MaxTopLeft
.X
, MaxTopLeft
.Y
);
1586 if (NewTopLeft
.X
<> LeftCol
) or (NewTopLeft
.Y
<> TopRow
) then
1587 MoveTopLeft(NewTopLeft
.X
, NewTopLeft
.Y
);
1588 Restrict(NewCurrent
, D
.fFixedCols
, D
.fFixedRows
, D
.fColCount
- 1, D
.fRowCount
- 1);
1589 if (NewCurrent
.X
<> D
.fCurrent
.X
) or (NewCurrent
.Y
<> D
.fCurrent
.Y
) then
1590 FocusCell(NewCurrent
.X
, NewCurrent
.Y
, not (GetAsyncKeyState(vk_Shift
) < 0){(ssShift in Shift)});
1591 // if NeedsInvalidating then Invalidate;
1594 procedure TStGrd
.ModifyScrollBar(ScrollBar
, ScrollCode
, Pos
: Cardinal; UseRightToLeft
: Boolean);
1596 NewTopLeft
, MaxTopLeft
: TGridCoord
;
1597 DrawInfo
: TGridDrawInfo
;
1598 // RTLFactor: Integer;
1601 function Min
: Longint;
1603 if ScrollBar
= SB_HORZ
then Result
:= FixedCols
1604 else Result
:= FixedRows
;
1607 function Max
: Longint;
1609 if ScrollBar
= SB_HORZ
then Result
:= MaxTopLeft
.X
1610 else Result
:= MaxTopLeft
.Y
;
1613 function PageUp
: Longint;
1615 MaxTopLeft
: TGridCoord
;
1617 MaxTopLeft
:= CalcMaxTopLeft(D
.fTopLeft
, DrawInfo
);
1618 if ScrollBar
= SB_HORZ
then
1619 Result
:= D
.fTopLeft
.X
- MaxTopLeft
.X
else
1620 Result
:= D
.fTopLeft
.Y
- MaxTopLeft
.Y
;
1621 if Result
< 1 then Result
:= 1;
1624 function PageDown
: Longint;
1626 DrawInfo
: TGridDrawInfo
;
1628 CalcDrawInfo(DrawInfo
);
1630 if ScrollBar
= SB_HORZ
then
1631 Result
:= Horz
.LastFullVisibleCell
- D
.fTopLeft
.X
else
1632 Result
:= Vert
.LastFullVisibleCell
- D
.fTopLeft
.Y
;
1633 if Result
< 1 then Result
:= 1;
1636 function CalcScrollBar(Value
{, ARTLFactor}: Longint): Longint;
1641 Dec(Result
{, ARTLFactor});
1643 Inc(Result
{, ARTLFactor});
1645 Dec(Result
, PageUp
{ * ARTLFactor});
1647 Inc(Result
, PageDown
{ * ARTLFactor});
1648 SB_THUMBPOSITION
, SB_THUMBTRACK
:
1649 if (goThumbTracking
in Options
) or (ScrollCode
= SB_THUMBPOSITION
) then
1651 // if (not UseRightToLeftAlignment) or (ARTLFactor = 1) then
1652 Result
:= Min
+ LongMulDiv(Pos
, Max
- Min
, MaxShortInt
)
1654 // Result := Max - LongMulDiv(Pos, Max - Min, MaxShortInt);
1663 procedure ModifyPixelScrollBar(Code
, Pos
: Cardinal);
1668 GridSpace
, ColWidth
: Integer;
1670 NewOffset
:= D
.fColOffset
;
1671 ColWidth
:= ColWidths
[DrawInfo
.Horz
.FirstGridCell
];
1672 GridSpace
:= ClientWidth
- DrawInfo
.Horz
.FixedBoundary
;
1674 SB_LINEUP
: Dec(NewOffset
, Canvas
.TextWidth('0') {* RTLFactor});
1675 SB_LINEDOWN
: Inc(NewOffset
, Canvas
.TextWidth('0') {* RTLFactor});
1676 SB_PAGEUP
: Dec(NewOffset
, GridSpace
{* RTLFactor});
1677 SB_PAGEDOWN
: Inc(NewOffset
, GridSpace
{* RTLFactor});
1680 if (goThumbTracking
in Options
) or (Code
= SB_THUMBPOSITION
) then
1682 // if not UseRightToLeftAlignment then
1685 // NewOffset := Max - Integer(Pos);
1687 SB_BOTTOM
: NewOffset
:= 0;
1688 SB_TOP
: NewOffset
:= ColWidth
- GridSpace
;
1690 if NewOffset
< 0 then
1692 else if NewOffset
>= ColWidth
- GridSpace
then
1693 NewOffset
:= ColWidth
- GridSpace
;
1694 if NewOffset
<> D
.fColOffset
then
1696 OldOffset
:= D
.fColOffset
;
1697 D
.fColOffset
:= NewOffset
;
1698 ScrollData(OldOffset
- NewOffset
, 0);
1699 FillChar(R
, SizeOf(R
), 0);
1700 R
.Bottom
:= FixedRows
;
1710 D
:= Pointer(CustomObj
);
1711 // if (not UseRightToLeftAlignment) or (not UseRightToLeft) then
1715 if Visible
and {CanFocus and} TabStop
{and not (csDesigning in ComponentState)} then
1717 CalcDrawInfo(DrawInfo
);
1718 if (ScrollBar
= SB_HORZ
) and (ColCount
= 1) then
1720 ModifyPixelScrollBar(ScrollCode
, Pos
);
1723 MaxTopLeft
.X
:= ColCount
- 1;
1724 MaxTopLeft
.Y
:= RowCount
- 1;
1725 MaxTopLeft
:= CalcMaxTopLeft(MaxTopLeft
, DrawInfo
);
1726 NewTopLeft
:= D
.fTopLeft
;
1727 if ScrollBar
= SB_HORZ
then
1729 Temp
:= NewTopLeft
.X
;
1730 NewTopLeft
.X
:= CalcScrollBar(NewTopLeft
.X
{, RTLFactor});
1731 until (NewTopLeft
.X
<= D
.fFixedCols
) or (NewTopLeft
.X
>= MaxTopLeft
.X
)
1732 or (ColWidths
[NewTopLeft
.X
] > 0) or (Temp
= NewTopLeft
.X
)
1735 Temp
:= NewTopLeft
.Y
;
1736 NewTopLeft
.Y
:= CalcScrollBar(NewTopLeft
.Y
{, 1});
1737 until (NewTopLeft
.Y
<= D
.fFixedRows
) or (NewTopLeft
.Y
>= MaxTopLeft
.Y
)
1738 or (RowHeights
[NewTopLeft
.Y
] > 0) or (Temp
= NewTopLeft
.Y
);
1739 NewTopLeft
.X
:= KOLMath
.Max(D
.fFixedCols
, KOLMath
.Min(MaxTopLeft
.X
, NewTopLeft
.X
));
1740 NewTopLeft
.Y
:= KOLMath
.Max(D
.fFixedRows
, KOLMath
.Min(MaxTopLeft
.Y
, NewTopLeft
.Y
));
1741 if (NewTopLeft
.X
<> D
.fTopLeft
.X
) or (NewTopLeft
.Y
<> D
.fTopLeft
.Y
) then
1742 MoveTopLeft(NewTopLeft
.X
, NewTopLeft
.Y
);
1745 procedure TStGrd
.MouseDown(X
, Y
: Integer);
1747 CellHit
: TGridCoord
;
1748 DrawInfo
: TGridDrawInfo
;
1749 // MoveDrawn: Boolean;
1752 D
:= Pointer(CustomObj
);
1753 // MoveDrawn := False;
1755 // if not (csDesigning in ComponentState) and
1756 // (CanFocus or (GetParentForm(Self) = nil)) then
1759 // if not IsActiveControl then
1761 // MouseCapture := False;
1765 // if (Button = mbLeft) and (ssDouble in Shift) then
1767 // else if Button = mbLeft then
1769 CalcDrawInfo(DrawInfo
);
1770 { Check grid sizing }
1771 CalcSizingState(X
, Y
, D
.fGridState
, D
.fSizingIndex
, D
.fSizingPos
, D
.fSizingOfs
, DrawInfo
);
1772 if D
.fGridState
<> gsNormal
then
1774 // if (D.fGridState = gsColSizing) and UseRightToLeftAlignment then
1775 // FSizingPos := ClientWidth - FSizingPos;
1776 DrawSizingLine(DrawInfo
);
1779 CellHit
:= CalcCoordFromPoint(X
, Y
, DrawInfo
);
1780 if (CellHit
.X
>= D
.fFixedCols
) and (CellHit
.Y
>= D
.fFixedRows
) then begin
1781 if goEditing
in Options
then begin
1782 if (CellHit
.X
= D
.fCurrent
.X
) and (CellHit
.Y
= D
.fCurrent
.Y
) then
1785 MoveCurrent(CellHit
.X
, CellHit
.Y
, True, True);
1790 D
.fGridState
:= gsSelecting
;
1791 SetTimer(Handle
, 1, 60, nil);
1792 if (GetAsyncKeyState(vk_Shift
) < 0) then
1795 MoveCurrent(CellHit
.X
, CellHit
.Y
, True, True);
1797 end else if (goRowMoving
in D
.fOptions
) and (CellHit
.X
>= 0) and
1798 (CellHit
.X
< D
.fFixedCols
) and (CellHit
.Y
>= D
.fFixedRows
) then begin
1799 D
.fMoveIndex
:= CellHit
.Y
;
1800 D
.fMovePos
:= D
.fMoveIndex
;
1801 // if BeginRowDrag(FMoveIndex, FMovePos, Point(X,Y)) then
1803 D
.fGridState
:= gsRowMoving
;
1806 // MoveDrawn := True;
1807 SetTimer(Handle
, 1, 60, nil);
1809 end else if (goColMoving
in D
.fOptions
) and (CellHit
.Y
>= 0) and
1810 (CellHit
.Y
< D
.fFixedRows
) and (CellHit
.X
>= D
.fFixedCols
) then begin
1811 D
.fMoveIndex
:= CellHit
.X
;
1812 D
.fMovePos
:= D
.fMoveIndex
;
1813 // if BeginColumnDrag(FMoveIndex, FMovePos, Point(X,Y)) then
1815 D
.fGridState
:= gsColMoving
;
1818 // MoveDrawn := True;
1819 SetTimer(Handle
, 1, 60, nil);
1824 // inherited MouseDown(Button, Shift, X, Y);
1826 // if MoveDrawn then DrawMove;
1830 procedure TStGrd
.MouseMove(X
, Y
: Integer);
1832 DrawInfo
: TGridDrawInfo
;
1833 CellHit
: TGridCoord
;
1836 D
:= Pointer(CustomObj
);
1837 CalcDrawInfo(DrawInfo
);
1838 case D
.fGridState
of
1839 gsSelecting
, gsColMoving
, gsRowMoving
:
1841 CellHit
:= CalcCoordFromPoint(X
, Y
, DrawInfo
);
1842 if (CellHit
.X
>= D
.fFixedCols
) and (CellHit
.Y
>= D
.fFixedRows
) and
1843 (CellHit
.X
<= DrawInfo
.Horz
.LastFullVisibleCell
+1) and
1844 (CellHit
.Y
<= DrawInfo
.Vert
.LastFullVisibleCell
+1) then
1845 case D
.fGridState
of
1847 if ((CellHit
.X
<> D
.fAnchor
.X
) or (CellHit
.Y
<> D
.fAnchor
.Y
)) then
1848 MoveAnchor(CellHit
);
1850 MoveAndScroll(X
, CellHit
.X
, DrawInfo
, DrawInfo
.Horz
, SB_HORZ
, MakePoint(X
,Y
));
1852 MoveAndScroll(Y
, CellHit
.Y
, DrawInfo
, DrawInfo
.Vert
, SB_VERT
, MakePoint(X
,Y
));
1855 gsRowSizing
, gsColSizing
:
1857 DrawSizingLine(DrawInfo
); { XOR it out }
1858 if D
.fGridState
= gsRowSizing
then
1859 D
.fSizingPos
:= Y
+ D
.fSizingOfs
else
1860 D
.fSizingPos
:= X
+ D
.fSizingOfs
;
1861 DrawSizingLine(DrawInfo
); { XOR it back in }
1864 // inherited MouseMove(Shift, X, Y);
1867 procedure TStGrd
.MouseUp(X
, Y
: Integer);
1869 DrawInfo
: TGridDrawInfo
;
1873 function ResizeLine(const AxisInfo
: TGridAxisDrawInfo
): Integer;
1879 Result
:= FixedBoundary
;
1880 for I
:= FirstGridCell
to D
.fSizingIndex
- 1 do
1881 Inc(Result
, GetExtent(I
) + EffectiveLineWidth
);
1882 Result
:= D
.fSizingPos
- Result
;
1887 D
:= Pointer(CustomObj
);
1889 case D
.fGridState
of
1892 MouseMove({Shift,} X
, Y
);
1893 KillTimer(Handle
, 1);
1895 if Assigned(OnClick
) then OnClick(@self
);
1897 gsRowSizing
, gsColSizing
:
1899 CalcDrawInfo(DrawInfo
);
1900 DrawSizingLine(DrawInfo
);
1901 // if (D.fGridState = gsColSizing) and UseRightToLeftAlignment then
1902 // D.fSizingPos := ClientWidth - D.fSizingPos;
1903 if D
.fGridState
= gsColSizing
then begin
1904 NewSize
:= ResizeLine(DrawInfo
.Horz
);
1905 if (NewSize
> 1) then ColWidths
[D
.fSizingIndex
] := NewSize
;
1907 NewSize
:= ResizeLine(DrawInfo
.Vert
);
1908 if (NewSize
> 1) then RowHeights
[D
.fSizingIndex
] := NewSize
;
1914 KillTimer(Handle
, 1);
1915 if //EndColumnDrag(FMoveIndex, FMovePos, Point(X,Y)) and
1916 (D
.fMoveIndex
<> D
.fMovePos
) then
1918 MoveColumn(D
.fMoveIndex
, D
.fMovePos
);
1926 KillTimer(Handle
, 1);
1927 if //EndRowDrag(FMoveIndex, FMovePos, Point(X,Y)) and
1928 (D
.fMoveIndex
<> D
.fMovePos
) then
1930 MoveRow(D
.fMoveIndex
, D
.fMovePos
);
1938 // inherited MouseUp(Button, Shift, X, Y);
1940 D
.fGridState
:= gsNormal
;
1945 procedure TStGrd
.MoveAdjust(var CellPos
: Integer; FromIndex
, ToIndex
: Integer);
1949 if CellPos
= FromIndex
then CellPos
:= ToIndex
1954 if FromIndex
> ToIndex
then
1959 if (CellPos
>= Min
) and (CellPos
<= Max
) then
1960 if FromIndex
> ToIndex
then
1966 procedure TStGrd
.MoveAnchor(const NewAnchor
: TGridCoord
);
1971 D
:= Pointer(CustomObj
);
1972 if [goRangeSelect
, goEditing
] * D
.fOptions
= [goRangeSelect
] then begin
1973 OldSel
:= Selection
;
1974 D
.fAnchor
:= NewAnchor
;
1975 if goRowSelect
in D
.fOptions
then D
.fAnchor
.X
:= D
.fColCount
- 1;
1976 ClampInView(NewAnchor
);
1977 SelectionMoved(OldSel
);
1979 else MoveCurrent(NewAnchor
.X
, NewAnchor
.Y
, True, True);
1982 procedure TStGrd
.MoveAndScroll(Mouse
, CellHit
: Integer; var DrawInfo
: TGridDrawInfo
;
1983 var Axis
: TGridAxisDrawInfo
; Scrollbar
: Integer; const MousePt
: TPoint
);
1986 D
:= Pointer(CustomObj
);
1987 // if UseRightToLeftAlignment and (ScrollBar = SB_HORZ) then
1988 // Mouse := ClientWidth - Mouse;
1989 if (CellHit
<> D
.fMovePos
) and
1990 not((D
.fMovePos
= Axis
.FixedCellCount
) and (Mouse
< Axis
.FixedBoundary
)) and
1991 not((D
.fMovePos
= Axis
.GridCellCount
-1) and (Mouse
> Axis
.GridBoundary
)) then
1994 if (Mouse
< Axis
.FixedBoundary
) then
1996 if (D
.fMovePos
> Axis
.FixedCellCount
) then
1998 ModifyScrollbar(ScrollBar
, SB_LINEUP
, 0, False);
2000 CalcDrawInfo(DrawInfo
);
2002 CellHit
:= Axis
.FirstGridCell
;
2004 else if (Mouse
>= Axis
.FullVisBoundary
) then
2006 if (D
.fMovePos
= Axis
.LastFullVisibleCell
) and
2007 (D
.fMovePos
< Axis
.GridCellCount
-1) then
2009 ModifyScrollBar(Scrollbar
, SB_LINEDOWN
, 0, False);
2011 CalcDrawInfo(DrawInfo
);
2013 CellHit
:= Axis
.LastFullVisibleCell
;
2015 else if CellHit
< 0 then CellHit
:= D
.fMovePos
;
2016 if {(}(D
.fGridState
= gsColMoving
) {and CheckColumnDrag(D.fMoveIndex, CellHit, MousePt))}
2017 or {(}(D
.fGridState
= gsRowMoving
) {and CheckRowDrag(D.fMoveIndex, CellHit, MousePt))} then
2018 D
.fMovePos
:= CellHit
;
2023 procedure TStGrd
.MoveColumn(FromIndex
, ToIndex
: Integer);
2030 if FromIndex
= ToIndex
then Exit
;
2031 D
:= Pointer(CustomObj
);
2032 if Assigned(D
.fColWidths
) then
2034 MoveExtent(D
.fColWidths
, FromIndex
+ 1, ToIndex
+ 1);
2035 // MoveExtent(D.fTabStops, FromIndex + 1, ToIndex + 1);
2037 MoveAdjust(D
.fCurrent
.X
, FromIndex
, ToIndex
);
2038 MoveAdjust(D
.fAnchor
.X
, FromIndex
, ToIndex
);
2039 // MoveAdjust(FInplaceCol, FromIndex, ToIndex);
2041 Rect
.Bottom
:= VisibleRowCount
;
2042 if FromIndex
< ToIndex
then
2044 Rect
.Left
:= FromIndex
;
2045 Rect
.Right
:= ToIndex
;
2049 Rect
.Left
:= ToIndex
;
2050 Rect
.Right
:= FromIndex
;
2054 S
.Assign(PStrListArray(D
.fCells
)^[FromIndex
]);
2055 if FromIndex
< ToIndex
2056 then for i
:= FromIndex
to ToIndex
-1 do PStrListArray(D
.fCells
)^[i
].Assign(PStrListArray(D
.fCells
)^[i
+1])
2057 else for i
:= FromIndex
downto ToIndex
+1 do PStrListArray(D
.fCells
)^[i
].Assign(PStrListArray(D
.fCells
)^[i
-1]);
2058 PStrListArray(D
.fCells
)^[ToIndex
].Assign(S
);
2061 InvalidateRect(Rect
);
2062 // ColumnMoved(FromIndex, ToIndex);
2063 if Assigned(D
.fColWidths
) then
2064 UpdateScrollRange
;//ColWidthsChanged;
2068 procedure TStGrd
.MoveCurrent(ACol
, ARow
: Integer; _MoveAnchor
, _Show
: Boolean);
2071 OldCurrent
: TGridCoord
;
2074 D
:= Pointer(CustomObj
);
2075 if (ACol
< 0) or (ARow
< 0) or (ACol
>= d
.fColCount
) or (ARow
>= d
.fRowCount
) then
2076 exit
;//InvalidOp(SIndexOutOfRange);
2077 if SelectCell(ACol
, ARow
) then begin
2078 OldSel
:= Selection
;
2079 OldCurrent
:= d
.fCurrent
;
2080 d
.fCurrent
.X
:= ACol
;
2081 d
.fCurrent
.Y
:= ARow
;
2082 // if not (goAlwaysShowEditor in d.fOptions) then HideEditor;
2083 if _MoveAnchor
or not (goRangeSelect
in d
.fOptions
) then begin
2084 d
.fAnchor
:= d
.fCurrent
;
2085 if goRowSelect
in d
.fOptions
then d
.fAnchor
.X
:= d
.fColCount
- 1;
2087 if goRowSelect
in d
.fOptions
then d
.fCurrent
.X
:= d
.fFixedCols
;
2088 if _Show
then ClampInView(d
.fCurrent
);
2089 SelectionMoved(OldSel
);
2090 with OldCurrent
do InvalidateCell(X
,Y
);
2091 with d
.fCurrent
do InvalidateCell(X
,Y
);
2095 procedure TStGrd
.MoveRow(FromIndex
, ToIndex
: Integer);
2096 var Rect
: tGridRect
;
2101 D
:= Pointer(CustomObj
);
2102 if Assigned(D
.fRowHeights
) then
2103 MoveExtent(D
.fRowHeights
, FromIndex
+ 1, ToIndex
+ 1);
2104 MoveAdjust(D
.fCurrent
.Y
, FromIndex
, ToIndex
);
2105 MoveAdjust(D
.fAnchor
.Y
, FromIndex
, ToIndex
);
2109 for i
:= 0 to D
.fColCount
-1 do S
.Add(PStrListArray(D
.fCells
)^[i
].Items
[FromIndex
]);
2110 if FromIndex
< ToIndex
2111 then for i
:= FromIndex
to ToIndex
-1 do
2112 for j
:= 0 to D
.fColCount
-1 do PStrListArray(D
.fCells
)^[j
].Items
[i
] := PStrListArray(D
.fCells
)^[j
].Items
[i
+1]
2113 else for i
:= FromIndex
downto ToIndex
+1 do
2114 for j
:= 0 to D
.fColCount
-1 do PStrListArray(D
.fCells
)^[j
].Items
[i
] := PStrListArray(D
.fCells
)^[j
].Items
[i
-1];
2115 for i
:= 0 to D
.fColCount
-1 do PStrListArray(D
.fCells
)^[i
].Items
[ToIndex
] := S
.Items
[i
];
2119 Rect
.Right
:= VisibleColCount
;
2120 if FromIndex
< ToIndex
then begin
2121 Rect
.Top
:= FromIndex
;
2122 Rect
.Bottom
:= ToIndex
;
2124 Rect
.Top
:= ToIndex
;
2125 Rect
.Bottom
:= FromIndex
;
2128 InvalidateRect(Rect
);
2129 // MoveAdjust(D.fInplaceRow, FromIndex, ToIndex);
2130 // RowMoved(FromIndex, ToIndex);
2131 if Assigned(D
.fRowHeights
) then
2132 UpdateScrollRange
;//RowHeightsChanged;
2136 procedure TStGrd
.MoveTopLeft(ALeft
, ATop
: Integer);
2138 OldTopLeft
: TGridCoord
;
2141 D
:= PStGrdData(CustomObj
);
2142 if (ALeft
= D
.fTopLeft
.X
) and (ATop
= D
.fTopLeft
.Y
) then Exit
;
2144 OldTopLeft
:= D
.fTopLeft
;
2145 D
.fTopLeft
.X
:= ALeft
;
2146 D
.fTopLeft
.Y
:= ATop
;
2147 TopLeftMoved(OldTopLeft
);
2150 procedure TStGrd
.Paint(DC
: HDC
);
2153 DrawInfo
: TGridDrawInfo
;
2156 {AFocRect,} FocRect
: TRect
;
2157 PointsList
: PIntArray
;
2158 StrokeList
: PIntArray
;
2160 FrameFlags1
, FrameFlags2
: DWORD
;
2164 tmDC
, tmBmp
, tmObj
: Cardinal;
2167 procedure DrawLines(DoHorz
, DoVert
: Boolean; Col
, Row
: Longint; const CellBounds
: array of Integer; OnColor
, OffColor
: TColor
);
2169 // FlatPenStyle = PS_Geometric or PS_Solid or PS_EndCap_Flat or PS_Join_Miter;
2171 procedure DrawAxisLines(const AxisInfo
: TGridAxisDrawInfo
; Cell
, MajorIndex
: Integer; UseOnColor
: Boolean);
2174 // LogBrush: TLOGBRUSH;
2177 StopMajor
, StartMinor
, StopMinor
, StopIndex
: Integer;
2180 with c
^, AxisInfo
do begin
2181 if (EffectiveLineWidth
<> 0) then begin
2182 Pen
.PenWidth
:= GridLineWidth
;
2184 Pen
.Color
:= OnColor
2186 Pen
.Color
:= OffColor
;
2187 MoveTo(0,0); LineTo(0,0);
2188 { if Pen.Width > 1 then
2190 LogBrush.lbStyle := BS_Solid;
2191 LogBrush.lbColor := Pen.Color;
2192 LogBrush.lbHatch := 0;
2193 Pen.Handle := ExtCreatePen(FlatPenStyle, Pen.Width, LogBrush, 0, nil);
2195 Points
:= PointsList
;
2196 Line
:= CellBounds
[MajorIndex
] + EffectiveLineWidth
shr 1 + GetExtent(Cell
);
2197 //!!! ??? Line needs to be incremented for RightToLeftAlignment ???
2198 // if UseRightToLeftAlignment and (MajorIndex = 0) then Inc(Line);
2199 StartMinor
:= CellBounds
[MajorIndex
xor 1];
2200 StopMinor
:= CellBounds
[2 + (MajorIndex
xor 1)];
2201 StopMajor
:= CellBounds
[2 + MajorIndex
] + EffectiveLineWidth
;
2202 StopIndex
:= MaxStroke
* 4;
2205 Points
^[Index
+ MajorIndex
] := Line
; { MoveTo }
2206 Points
^[Index
+ (MajorIndex
xor 1)] := StartMinor
;
2208 Points
^[Index
+ MajorIndex
] := Line
; { LineTo }
2209 Points
^[Index
+ (MajorIndex
xor 1)] := StopMinor
;
2211 // Skip hidden columns/rows. We don't have stroke slots for them
2212 // A column/row with an extent of -EffectiveLineWidth is hidden
2215 LineIncr
:= GetExtent(Cell
) + EffectiveLineWidth
;
2216 until (LineIncr
> 0) or (Cell
> LastFullVisibleCell
);
2217 Inc(Line
, LineIncr
);
2218 until (Line
> StopMajor
) or (Cell
> LastFullVisibleCell
) or (Index
> StopIndex
);
2219 { 2 integers per point, 2 points per line -> Index div 4 }
2220 PolyPolyLine(Handle
, Points
^, StrokeList
^, Index
shr 2);
2226 if (CellBounds
[0] = CellBounds
[2]) or (CellBounds
[1] = CellBounds
[3]) then Exit
;
2227 if not DoHorz
then begin
2228 DrawAxisLines(DrawInfo
.Vert
, Row
, 1, DoHorz
);
2229 DrawAxisLines(DrawInfo
.Horz
, Col
, 0, DoVert
);
2231 DrawAxisLines(DrawInfo
.Horz
, Col
, 0, DoVert
);
2232 DrawAxisLines(DrawInfo
.Vert
, Row
, 1, DoHorz
);
2236 procedure DrawCells(ACol
, ARow
: Longint; StartX
, StartY
, StopX
, StopY
: Integer; Color
: TColor
; IncludeDrawState
: TGridDrawState
);
2238 CurCol
, CurRow
: Longint;
2239 {AWhere,} Where
, TempRect
: TRect
;
2240 DrawState
: TGridDrawState
;
2245 Where
.Top
:= StartY
;
2246 while (Where
.Top
< StopY
) and (CurRow
< d
.fRowCount
) do begin
2248 Where
.Left
:= StartX
;
2249 Where
.Bottom
:= Where
.Top
+ RowHeights
[CurRow
];
2250 while (Where
.Left
< StopX
) and (CurCol
< ColCount
) do begin
2251 Where
.Right
:= Where
.Left
+ ColWidths
[CurCol
];
2252 if (Where
.Right
> Where
.Left
) and RectVisible(c
.Handle
, Where
) then begin
2253 DrawState
:= IncludeDrawState
;
2254 Focused
:= IsActiveControl
;
2255 if Focused
and (CurRow
= Row
) and (CurCol
= Col
) then
2256 Include(DrawState
, gdFocused
);
2257 if PointInGridRect(CurCol
, CurRow
, Sel
) then
2258 Include(DrawState
, gdSelected
);
2259 // if not (gdFocused in DrawState) or not (goEditing in Options) {or not FEditorMode} then begin
2260 if d
.fDefaultDrawing
then with c
^ do begin
2261 Font
.Assign(Self
.Font
);
2262 if (gdSelected
in DrawState
) and
2263 (not (gdFocused
in DrawState
) or
2264 ([goDrawFocusSelected
, goRowSelect
] * d
.fOptions
<> [])) then
2266 Brush
.Color
:= clHighlight
;
2267 Font
.Color
:= clHighlightText
;
2269 Brush
.Color
:= Color
;
2273 InflateRect(TempRect
,-2,-2);
2274 s
:= Cells
[CurCol
,CurRow
];
2275 if (s
<> '') and (TempRect
.Right
-TempRect
.Left
> 4) and (TempRect
.Bottom
-TempRect
.Top
> 4) then begin
2276 SelectObject(c
.Handle
,Font
.Handle
);
2277 Windows
.DrawText(c
.Handle
,pChar(s
),length(s
),TempRect
,dt_SingleLine
);
2279 // TempRect := Where;
2280 // InflateRect(TempRect,-2,-2);
2281 // if () and () then
2282 // TextRect(TempRect,TempRect.Left,TempRect.Top,Cells[CurCol,CurRow]);
2284 DrawCell(c
, CurCol
, CurRow
, Where
, DrawState
);
2285 if d
.fDefaultDrawing
and (gdFixed
in DrawState
) and d
.fCtl3D
and
2286 ((FrameFlags1
or FrameFlags2
) <> 0) then
2289 if (FrameFlags1
and BF_RIGHT
) = 0
2290 then Inc(TempRect
.Right
, DrawInfo
.Horz
.EffectiveLineWidth
)
2291 else if (FrameFlags1
and BF_BOTTOM
) = 0
2292 then Inc(TempRect
.Bottom
, DrawInfo
.Vert
.EffectiveLineWidth
);
2293 DrawEdge(c
.Handle
, TempRect
, BDR_RAISEDINNER
, FrameFlags2
);
2294 DrawEdge(c
.Handle
, TempRect
, BDR_RAISEDINNER
, FrameFlags1
);
2297 if d
.fDefaultDrawing
and
2298 (gdFocused
in DrawState
)// and
2299 // ([goEditing, goAlwaysShowEditor] * d.fOptions <>
2300 // [goEditing, goAlwaysShowEditor])
2301 and not (goRowSelect
in d
.fOptions
) then
2302 c
.DrawFocusRect(Where
);// DrawFocusRect(c.Handle, Where)
2305 Where
.Left
:= Where
.Right
+ DrawInfo
.Horz
.EffectiveLineWidth
;
2308 Where
.Top
:= Where
.Bottom
+ DrawInfo
.Vert
.EffectiveLineWidth
;
2315 {GetClientRect(Handle,r); //}//r := MakeRect(0,0,ClientWidth,ClientHeight);
2316 UpdateRect
:= Canvas
.ClipRect
;
2318 tmDC
:= CreateCompatibleDC(DC
);
2319 tmBmp
:= CreateCompatibleBitmap(DC
,UpdateRect
.Right
,UpdateRect
.Bottom
);
2320 tmObj
:= SelectObject(tmDC
,tmBmp
);
2321 c
:= NewCanvas(tmDC
);
2323 // if UseRightToLeftAlignment then ChangeGridOrientation(True);
2325 D
:= Pointer(CustomObj
);
2326 CalcDrawInfo(DrawInfo
);
2327 with DrawInfo
do begin
2328 if (Horz
.EffectiveLineWidth
> 0) or (Vert
.EffectiveLineWidth
> 0) then begin
2329 LineColor
:= clSilver
;
2330 MaxStroke
:= Max(Horz
.LastFullVisibleCell
- d
.fTopLeft
.X
+ d
.fFixedCols
,
2331 Vert
.LastFullVisibleCell
- d
.fTopLeft
.Y
+ d
.fFixedRows
) + 3;
2332 PointsList
:= StackAlloc(MaxStroke
* sizeof(TPoint
) * 2);
2333 StrokeList
:= StackAlloc(MaxStroke
* sizeof(Integer));
2334 FillDWord(StrokeList
^, MaxStroke
, 2);
2336 if Color2RGB(Color
) = clSilver
then LineColor
:= clGray
;
2337 DrawLines(goFixedHorzLine
in d
.fOptions
, goFixedVertLine
in d
.fOptions
,
2338 0, 0, [0, 0, Horz
.FixedBoundary
, Vert
.FixedBoundary
], clBlack
, clBtnFace
);
2339 DrawLines(goFixedHorzLine
in d
.fOptions
, goFixedVertLine
in d
.fOptions
,
2340 d
.fTopLeft
.X
, 0, [Horz
.FixedBoundary
, 0, Horz
.GridBoundary
,
2341 Vert
.FixedBoundary
], clBlack
, clBtnFace
);
2342 DrawLines(goFixedHorzLine
in d
.fOptions
, goFixedVertLine
in d
.fOptions
,
2343 0, d
.fTopLeft
.Y
, [0, Vert
.FixedBoundary
, Horz
.FixedBoundary
,
2344 Vert
.GridBoundary
], clBlack
, clBtnFace
);
2345 DrawLines(goHorzLine
in d
.fOptions
, goVertLine
in d
.fOptions
,
2346 d
.fTopLeft
.X
, d
.fTopLeft
.Y
, [Horz
.FixedBoundary
, Vert
.FixedBoundary
, Horz
.GridBoundary
,
2347 Vert
.GridBoundary
], LineColor
, clWindow
);
2349 StackFree(StrokeList
);
2350 StackFree(PointsList
);
2351 end; {FixedColor = clBtnFace}
2353 { Draw the cells in the four areas }
2357 if goFixedVertLine
in d
.fOptions
then begin
2358 FrameFlags1
:= BF_RIGHT
;
2359 FrameFlags2
:= BF_LEFT
;
2361 if goFixedHorzLine
in d
.fOptions
then begin
2362 FrameFlags1
:= FrameFlags1
or BF_BOTTOM
;
2363 FrameFlags2
:= FrameFlags2
or BF_TOP
;
2365 DrawCells(0, 0, 0, 0, Horz
.FixedBoundary
, Vert
.FixedBoundary
, clBtnFace
{FixedColor},
2367 DrawCells(d
.fTopLeft
.X
, 0, Horz
.FixedBoundary
- d
.fColOffset
, 0, Horz
.GridBoundary
, //!! clip
2368 Vert
.FixedBoundary
, clBtnFace
{FixedColor}, [gdFixed
]);
2369 DrawCells(0, d
.fTopLeft
.Y
, 0, Vert
.FixedBoundary
, Horz
.FixedBoundary
,
2370 Vert
.GridBoundary
, clBtnFace
{FixedColor}, [gdFixed
]);
2371 DrawCells(d
.fTopLeft
.X
, d
.fTopLeft
.Y
, Horz
.FixedBoundary
- d
.fColOffset
, //!! clip
2372 Vert
.FixedBoundary
, Horz
.GridBoundary
, Vert
.GridBoundary
, clWindow
{Color}, []);
2374 if //not (csDesigning in ComponentState) and
2375 (goRowSelect
in d
.fOptions
) and d
.fDefaultDrawing
and Focused
then begin
2376 GridRectToScreenRect(GetSelection
, FocRect
, False);
2377 c
.DrawFocusRect(FocRect
);
2379 if Horz
.GridBoundary
< Horz
.GridExtent
then begin
2380 c
.Brush
.Color
:= Color
;
2381 c
.FillRect(MakeRect(Horz
.GridBoundary
, 0, Horz
.GridExtent
, Vert
.GridBoundary
));
2383 if Vert
.GridBoundary
< Vert
.GridExtent
then begin
2384 c
.Brush
.Color
:= Color
;
2385 c
.FillRect(MakeRect(0, Vert
.GridBoundary
, Horz
.GridExtent
, Vert
.GridExtent
));
2389 // BitBlt(Canvas.Handle,0,0,r.Right,r.Bottom,c.Handle,0,0,SrcCopy);
2390 BitBlt(Canvas
.Handle
,UpdateRect
.Left
,UpdateRect
.Top
,UpdateRect
.Right
,UpdateRect
.Bottom
,c
.Handle
,UpdateRect
.Left
,UpdateRect
.Top
,SrcCopy
);
2391 // Canvas.CopyRect(r,c,r);
2392 SelectObject(tmDC
,tmObj
);
2393 DeleteObject(tmBmp
);
2398 procedure TStGrd
.ScrollData(DX
, DY
: Integer);
2400 DrawInfo
: TGridDrawInfo
;
2402 CalcDrawInfo(DrawInfo
);
2403 ScrollDataInfo(DX
, DY
, DrawInfo
);
2406 procedure TStGrd
.ScrollDataInfo(DX
, DY
: Integer; var DrawInfo
: TGridDrawInfo
);
2409 ScrollFlags
: Integer;
2413 ScrollFlags
:= SW_INVALIDATE
;
2414 if not DefaultDrawing
then ScrollFlags
:= ScrollFlags
or SW_ERASE
;
2416 if DY
= 0 then begin
2417 { Scroll both the column titles and data area at the same time }
2418 // if not UseRightToLeftAlignment then
2419 ScrollArea
:= MakeRect(Horz
.FixedBoundary
, 0, Horz
.GridExtent
, Vert
.GridExtent
);
2422 ScrollArea := Rect(ClientWidth - Horz.GridExtent, 0, ClientWidth - Horz.FixedBoundary, Vert.GridExtent);
2425 ScrollWindowEx(Handle
, DX
, 0, @ScrollArea
, @ScrollArea
, 0, nil, ScrollFlags
);
2426 end else if DX
= 0 then begin
2427 ScrollArea
:= MakeRect(0, Vert
.FixedBoundary
, Horz
.GridExtent
, Vert
.GridExtent
);
2428 ScrollWindowEx(Handle
, 0, DY
, @ScrollArea
, @ScrollArea
, 0, nil, ScrollFlags
);
2430 ScrollArea
:= MakeRect(Horz
.FixedBoundary
, 0, Horz
.GridExtent
, Vert
.FixedBoundary
);
2431 ScrollWindowEx(Handle
, DX
, 0, @ScrollArea
, @ScrollArea
, 0, nil, ScrollFlags
);
2432 ScrollArea
:= MakeRect(0, Vert
.FixedBoundary
, Horz
.FixedBoundary
, Vert
.GridExtent
);
2433 ScrollWindowEx(Handle
, 0, DY
, @ScrollArea
, @ScrollArea
, 0, nil, ScrollFlags
);
2435 ScrollArea
:= MakeRect(Horz
.FixedBoundary
, Vert
.FixedBoundary
, Horz
.GridExtent
,
2437 ScrollWindowEx(Handle
, DX
, DY
, @ScrollArea
, @ScrollArea
, 0, nil, ScrollFlags
);
2440 if goRowSelect
in Options
then
2441 InvalidateRect(Selection
);
2444 function TStGrd
.SelectCell(ACol
, ARow
: Integer): Boolean;
2447 D
:= Pointer(CustomObj
);
2449 if Assigned(d
.fOnSelectCell
) then d
.fOnSelectCell(@Self
, ACol
, ARow
, Result
);
2452 procedure TStGrd
.SelectionMoved(const OldSel
: TGridRect
);
2454 OldRect
, NewRect
: TRect
;
2455 AXorRects
: TXorRects
;
2458 GridRectToScreenRect(OldSel
, OldRect
, True);
2459 GridRectToScreenRect(Selection
, NewRect
, True);
2460 XorRects(OldRect
, NewRect
, AXorRects
);
2461 for I
:= Low(AXorRects
) to High(AXorRects
) do
2462 Windows
.InvalidateRect(Handle
, @AXorRects
[I
], False);
2465 procedure TStGrd
.SetCells(ACol
, ARow
: Integer; const Value
: string);
2468 D
:= Pointer(CustomObj
);
2469 if (ACol
< 0) or (ARow
< 0) or (ACol
> D
.fColCount
-1) or (ARow
> D
.fRowCount
- 1) then exit
;
2470 PStrListArray(D
.fCells
)^[ACol
].Items
[ARow
] := Value
;
2471 InvalidateCell(ACol
,ARow
);
2474 procedure TStGrd
.SetCol(const Value
: Longint);
2476 FocusCell(Value
, Row
, True);
2479 procedure TStGrd
.SetColCount(Value
: Longint);
2483 D
:= Pointer(CustomObj
);
2484 if d
.fColCount
<> Value
then begin
2485 if Value
< 1 then Value
:= 1;
2486 if Value
<= d
.fFixedCols
then d
.fFixedCols
:= Value
- 1;
2488 ChangeSize(Value
, d
.fRowCount
);
2489 if goRowSelect
in d
.fOptions
then begin
2490 d
.fAnchor
.X
:= d
.fColCount
- 1;
2493 if old
> D
.fColCount
2494 then for i
:= old
- 1 downto D
.fColCount
do PStrListArray(D
.fCells
)^[i
].Free
2496 SetLength(PStrListArray(D
.fCells
)^,D
.fColCount
);
2497 for i
:= old
to D
.fColCount
- 1 do begin
2498 PStrListArray(D
.fCells
)^[i
] := NewStrList
;
2499 for j
:= 0 to D
.fRowCount
- 1 do
2500 PStrListArray(D
.fCells
)^[i
].Add('');
2506 procedure TStGrd
.SetColWidths(Index
: Integer; const Value
: Integer);
2509 D
:= Pointer(CustomObj
);
2510 if d
.fColWidths
= nil then
2511 UpdateExtents(d
.fColWidths
, d
.fColCount
, d
.fDefaultColWidth
);
2512 if Index
>= d
.fColCount
then exit
;//InvalidOp(SIndexOutOfRange);
2513 if Value
<> PIntArray(d
.fColWidths
)^[Index
+ 1] then
2515 invalidate
;//ResizeCol(Index, PIntArray(d.fColWidths)^[Index + 1], Value);
2516 PIntArray(d
.fColWidths
)^[Index
+ 1] := Value
;
2517 UpdateScrollRange
;//ColWidthsChanged;
2521 procedure TStGrd
.SetDefaultColWidth(const Value
: Integer);
2524 D
:= Pointer(CustomObj
);
2525 if D
.fColWidths
<> nil then UpdateExtents(D
.fColWidths
, 0, 0);
2526 D
.fDefaultColWidth
:= Value
;
2527 UpdateScrollRange
;//ColWidthsChanged;
2531 procedure TStGrd
.SetDefaultDrawing(const Value
: Boolean);
2534 D
:= Pointer(CustomObj
);
2535 D
.fDefaultDrawing
:= Value
;
2538 procedure TStGrd
.SetDefaultRowHeight(const Value
: Integer);
2541 D
:= Pointer(CustomObj
);
2542 if D
.fRowHeights
<> nil then UpdateExtents(D
.fRowHeights
, 0, 0);
2543 D
.fDefaultRowHeight
:= Value
;
2544 UpdateScrollRange
;//RowHeightsChanged;
2548 procedure TStGrd
.SetFixedCols(const Value
: Integer);
2551 D
:= Pointer(CustomObj
);
2552 if Value
< 0 then exit
;//InvalidOp(SIndexOutOfRange);
2553 if Value
>= D
.fColCount
then exit
;//InvalidOp(SFixedColTooBig);
2554 D
.fFixedCols
:= Value
;
2556 D
.fTopLeft
.X
:= D
.fFixedCols
;
2557 D
.fTopLeft
.Y
:= D
.fFixedRows
;
2558 D
.fCurrent
:= D
.fTopLeft
;
2559 D
.fAnchor
:= D
.fCurrent
;
2560 if goRowSelect
in D
.fOptions
then D
.fAnchor
.X
:= D
.fColCount
- 1;
2565 procedure TStGrd
.SetFixedRows(const Value
: Integer);
2568 D
:= Pointer(CustomObj
);
2569 if Value
< 0 then exit
;//InvalidOp(SIndexOutOfRange);
2570 if Value
>= D
.fRowCount
then exit
;//InvalidOp(SFixedRowTooBig);
2571 D
.fFixedRows
:= Value
;
2573 D
.fTopLeft
.X
:= D
.fFixedCols
;
2574 D
.fTopLeft
.Y
:= D
.fFixedRows
;
2575 D
.fCurrent
:= D
.fTopLeft
;
2576 D
.fAnchor
:= D
.fCurrent
;
2577 if goRowSelect
in D
.fOptions
then D
.fAnchor
.X
:= D
.fColCount
- 1;
2582 procedure TStGrd
.SetLeftCol(const Value
: Longint);
2584 MoveTopLeft(Value
, TopRow
);
2587 procedure TStGrd
.SetOnDrawCell(const Value
: TDrawCellEvent
);
2590 D
:= Pointer(CustomObj
);
2591 D
.fOnDrawCell
:= Value
;
2594 procedure TStGrd
.SetOnSelectCell(const Value
: TSelectCellEvent
);
2597 D
:= Pointer(CustomObj
);
2598 D
.fOnSelectCell
:= Value
;
2601 procedure TStGrd
.SetOptions(Value
: TGridOptions
);
2604 D
:= Pointer(CustomObj
);
2605 if goRowSelect
in Value
then
2606 Exclude(Value
, goAlwaysShowEditor
);
2607 D
.fOptions
:= Value
;
2608 // if not FEditorMode then
2609 // if goAlwaysShowEditor in Value then
2612 if goRowSelect
in Value
then MoveCurrent(Col
, Row
, True, False);
2616 procedure TStGrd
.SetRow(const Value
: Longint);
2618 FocusCell(Col
, Value
, True);
2621 procedure TStGrd
.SetRowCount(Value
: Longint);
2625 D
:= Pointer(CustomObj
);
2626 if Value
< 1 then Value
:= 1;
2627 if Value
<= D
.fFixedRows
then D
.fFixedRows
:= Value
- 1;
2629 ChangeSize(D
.fColCount
, Value
);
2630 if old
> D
.fRowCount
2631 then for i
:= 0 to D
.fColCount
- 1 do
2632 for j
:= old
- 1 downto D
.fRowCount
do
2633 PStrListArray(D
.fCells
)^[i
].Delete(j
)
2634 else for i
:= 0 to D
.fColCount
- 1 do
2635 for j
:= old
to D
.fRowCount
- 1 do
2636 PStrListArray(D
.fCells
)^[i
].Add('');
2639 procedure TStGrd
.SetRowHeights(Index
: Integer; const Value
: Integer);
2642 D
:= Pointer(CustomObj
);
2643 if D
.fRowHeights
= nil then
2644 UpdateExtents(d
.fRowHeights
, d
.fRowCount
, d
.fDefaultRowHeight
);
2645 if Index
>= d
.fRowCount
then exit
;//InvalidOp(SIndexOutOfRange);
2646 if Value
<> PIntArray(d
.fRowHeights
)^[Index
+ 1] then begin
2647 invalidate
;//ResizeRow(Index, PIntArray(D.fRowHeights)^[Index + 1], Value);
2648 PIntArray(d
.fRowHeights
)^[Index
+ 1] := Value
;
2649 UpdateScrollRange
;//RowHeightsChanged;
2653 procedure TStGrd
.SetRows(Index
: Integer; const Value
: pStrList
);
2657 D
:= Pointer(CustomObj
);
2658 if (Index
< 0) or (Index
> D
.fRowCount
- 1) then exit
;
2659 for i
:= 0 to Value
.Count
-1 do
2660 PStrListArray(D
.fCells
)^[i
].Items
[Index
] := Value
.Items
[i
];
2663 procedure TStGrd
.SetScrollBars(const Value
: TScrollStyle
);
2666 D
:= Pointer(CustomObj
);
2667 if D
.fScrollBars
<> Value
then begin
2668 D
.fScrollBars
:= Value
;
2669 ShowScrollBar(Handle
,sb_Vert
,Value
in [ssVertical
,ssBoth
]);
2670 ShowScrollBar(Handle
,sb_Horz
,Value
in [ssHorizontal
,ssBoth
]);
2674 procedure TStGrd
.SetSelection(const Value
: TGridRect
);
2679 D
:= Pointer(CustomObj
);
2680 OldSel
:= Selection
;
2681 D
.fAnchor
:= Value
.TopLeft
;
2682 D
.fCurrent
:= Value
.BottomRight
;
2683 SelectionMoved(OldSel
);
2686 procedure TStGrd.SetTabStops(Index: Integer; const Value: Boolean);
2689 D := Pointer(CustomObj);
2690 if D.fTabStops = nil then
2691 UpdateExtents(D.fTabStops, D.fColCount, Integer(True));
2692 if Index >= D.fColCount then exit;//InvalidOp(SIndexOutOfRange);
2693 PIntArray(D.fTabStops)^[Index + 1] := Integer(Value);
2696 procedure TStGrd
.SetTopRow(const Value
: Longint);
2698 MoveTopLeft(LeftCol
, Value
);
2701 procedure TStGrd
.TimedScroll(Direction
: TGridScrollDirection
);
2703 MaxAnchor
, NewAnchor
: TGridCoord
;
2706 D
:= Pointer(CustomObj
);
2707 NewAnchor
:= D
.fAnchor
;
2708 MaxAnchor
.X
:= D
.fColCount
- 1;
2709 MaxAnchor
.Y
:= D
.fRowCount
- 1;
2710 if (sdLeft
in Direction
) and (D
.fAnchor
.X
> D
.fFixedCols
) then Dec(NewAnchor
.X
);
2711 if (sdRight
in Direction
) and (D
.fAnchor
.X
< MaxAnchor
.X
) then Inc(NewAnchor
.X
);
2712 if (sdUp
in Direction
) and (D
.fAnchor
.Y
> D
.fFixedRows
) then Dec(NewAnchor
.Y
);
2713 if (sdDown
in Direction
) and (D
.fAnchor
.Y
< MaxAnchor
.Y
) then Inc(NewAnchor
.Y
);
2714 if (D
.fAnchor
.X
<> NewAnchor
.X
) or (D
.fAnchor
.Y
<> NewAnchor
.Y
) then
2715 MoveAnchor(NewAnchor
);
2718 procedure TStGrd
.TopLeftMoved(const OldTopLeft
: TGridCoord
);
2720 function CalcScroll(const AxisInfo
: TGridAxisDrawInfo
;
2721 OldPos
, CurrentPos
: Integer; var Amount
: Longint): Boolean;
2723 Start
, Stop
: Longint;
2727 with AxisInfo
do begin
2728 if OldPos
< CurrentPos
then begin
2732 Start
:= CurrentPos
;
2736 for I
:= Start
to Stop
- 1 do begin
2737 Inc(Amount
, GetExtent(I
) + EffectiveLineWidth
);
2738 if Amount
> (GridBoundary
- FixedBoundary
) then begin
2739 { Scroll amount too big, redraw the whole thing }
2744 if OldPos
< CurrentPos
then Amount
:= -Amount
;
2750 DrawInfo
: TGridDrawInfo
;
2754 D
:= Pointer(CustomObj
);
2756 CalcDrawInfo(DrawInfo
);
2757 if CalcScroll(DrawInfo
.Horz
, OldTopLeft
.X
, D
.fTopLeft
.X
, Delta
.X
) and
2758 CalcScroll(DrawInfo
.Vert
, OldTopLeft
.Y
, D
.fTopLeft
.Y
, Delta
.Y
) then
2759 ScrollDataInfo(Delta
.X
, Delta
.Y
, DrawInfo
);
2763 procedure TStGrd
.UpdateScrollPos
;
2765 DrawInfo
: TGridDrawInfo
;
2766 MaxTopLeft
: TGridCoord
;
2767 GridSpace
, ColWidth
: Integer;
2770 procedure SetScroll(Code
: Word; Value
: Integer);
2772 { if UseRightToLeftAlignment and (Code = SB_HORZ) then
2773 if ColCount <> 1 then Value := MaxShortInt - Value
2774 else Value := (ColWidth - GridSpace) - Value;}
2775 if GetScrollPos(Handle
, Code
) <> Value
then
2776 SetScrollPos(Handle
, Code
, Value
, True);
2780 D
:= Pointer(CustomObj
);
2781 if (ScrollBars
= ssNone
) then Exit
;
2782 CalcDrawInfo(DrawInfo
);
2783 MaxTopLeft
.X
:= ColCount
- 1;
2784 MaxTopLeft
.Y
:= RowCount
- 1;
2785 MaxTopLeft
:= CalcMaxTopLeft(MaxTopLeft
, DrawInfo
);
2786 if ScrollBars
in [ssHorizontal
, ssBoth
] then
2787 if ColCount
= 1 then
2789 ColWidth
:= ColWidths
[DrawInfo
.Horz
.FirstGridCell
];
2790 GridSpace
:= ClientWidth
- DrawInfo
.Horz
.FixedBoundary
;
2791 if (D
.fColOffset
> 0) and (GridSpace
> (ColWidth
- D
.fColOffset
)) then
2792 ModifyScrollbar(SB_HORZ
, SB_THUMBPOSITION
, ColWidth
- GridSpace
, True)
2794 SetScroll(SB_HORZ
, D
.fColOffset
)
2797 SetScroll(SB_HORZ
, LongMulDiv(D
.fTopLeft
.X
- D
.fFixedCols
, MaxShortInt
,
2798 MaxTopLeft
.X
- D
.fFixedCols
));
2799 if ScrollBars
in [ssVertical
, ssBoth
] then
2800 SetScroll(SB_VERT
, LongMulDiv(D
.fTopLeft
.Y
- D
.fFixedRows
, MaxShortInt
,
2801 MaxTopLeft
.Y
- D
.fFixedRows
));
2804 procedure TStGrd
.UpdateScrollRange
;
2806 MaxTopLeft
, OldTopLeft
: TGridCoord
;
2807 DrawInfo
: TGridDrawInfo
;
2808 OldScrollBars
: TScrollStyle
;
2821 function ScrollBarVisible(Code
: Word): Boolean;
2826 if (ScrollBars
= ssBoth
) or
2827 ((Code
= SB_HORZ
) and (ScrollBars
= ssHorizontal
)) or
2828 ((Code
= SB_VERT
) and (ScrollBars
= ssVertical
)) then
2830 GetScrollRange(Handle
, Code
, Min
, Max
);
2831 Result
:= Min
<> Max
;
2835 procedure CalcSizeInfo
;
2837 CalcDrawInfoXY(DrawInfo
, DrawInfo
.Horz
.GridExtent
, DrawInfo
.Vert
.GridExtent
);
2838 MaxTopLeft
.X
:= ColCount
- 1;
2839 MaxTopLeft
.Y
:= RowCount
- 1;
2840 MaxTopLeft
:= CalcMaxTopLeft(MaxTopLeft
, DrawInfo
);
2843 procedure SetAxisRange(var Max
, Old
, Current
: Longint; Code
: Word;
2847 if Fixeds
< Max
then
2848 SetScrollRange(Handle
, Code
, 0, MaxShortInt
, True)
2850 SetScrollRange(Handle
, Code
, 0, 0, True);
2858 procedure SetHorzRange
;
2862 if OldScrollBars
in [ssHorizontal
, ssBoth
] then
2863 if ColCount
= 1 then
2865 Range
:= ColWidths
[0] - ClientWidth
;
2866 if Range
< 0 then Range
:= 0;
2867 SetScrollRange(Handle
, SB_HORZ
, 0, Range
, True);
2870 SetAxisRange(MaxTopLeft
.X
, OldTopLeft
.X
, D
.fTopLeft
.X
, SB_HORZ
, D
.fFixedCols
);
2873 procedure SetVertRange
;
2875 if OldScrollBars
in [ssVertical
, ssBoth
] then
2876 SetAxisRange(MaxTopLeft
.Y
, OldTopLeft
.Y
, D
.fTopLeft
.Y
, SB_VERT
, D
.fFixedRows
);
2880 if (ScrollBars
= ssNone
) {or not Showing} then Exit
;
2881 D
:= Pointer(CustomObj
);
2884 Horz
.GridExtent
:= ClientWidth
;
2885 Vert
.GridExtent
:= ClientHeight
;
2886 { Ignore scroll bars for initial calculation }
2887 if ScrollBarVisible(SB_HORZ
) then
2888 Inc(Vert
.GridExtent
, GetSystemMetrics(SM_CYHSCROLL
));
2889 if ScrollBarVisible(SB_VERT
) then
2890 Inc(Horz
.GridExtent
, GetSystemMetrics(SM_CXVSCROLL
));
2892 OldTopLeft
:= D
.fTopLeft
;
2893 { Temporarily mark us as not having scroll bars to avoid recursion }
2894 OldScrollBars
:= D
.fScrollBars
;
2895 D
.fScrollBars
:= ssNone
;
2898 { Update scrollbars }
2900 DrawInfo
.Vert
.GridExtent
:= ClientHeight
;
2902 if DrawInfo
.Horz
.GridExtent
<> ClientWidth
then
2904 DrawInfo
.Horz
.GridExtent
:= ClientWidth
;
2908 D
.fScrollBars
:= OldScrollBars
;
2911 if (D
.fTopLeft
.X
<> OldTopLeft
.X
) or (D
.fTopLeft
.Y
<> OldTopLeft
.Y
) then
2912 TopLeftMoved(OldTopLeft
);
2915 procedure TStGrd
.WheelDown
{(Shift: TShiftState; MousePos: TPoint): Boolean};
2917 // Result := inherited DoMouseWheelDown(Shift, MousePos);
2918 // if not Result then
2920 if Row
< RowCount
- 1 then Row
:= Row
+ 1;
2925 procedure TStGrd
.WheelUp
{(Shift: TShiftState; MousePos: TPoint): Boolean};
2927 // Result := inherited DoMouseWheelUp(Shift, MousePos);
2928 // if not Result then
2930 if Row
> FixedRows
then Row
:= Row
- 1;
2935 procedure TStGrd
.WMSetCursor(_HitTest
: Word);
2937 DrawInfo
: TGridDrawInfo
;
2944 if _HitTest
= HTCLIENT
then begin
2945 D
:= Pointer(CustomObj
);
2946 if D
.fGridState
= gsNormal
then begin
2947 CalcDrawInfo(DrawInfo
);
2948 CalcSizingState(D
.fHitTest
.X
, D
.fHitTest
.Y
, State
, Index
, Pos
, Ofs
, DrawInfo
);
2949 end else State
:= D
.fGridState
;
2951 gsRowSizing
: Cur
:= LoadCursor(hInstance
,IDC_VSPLIT
); //LoadCursor(0,IDC_SIZENS);
2952 gsColSizing
: Cur
:= LoadCursor(hInstance
,IDC_HSPLIT
); //LoadCursor(0,IDC_SIZEWE);
2954 Cur
:= LoadCursor(0,IDC_ARROW
);
2956 { if State = gsRowSizing
2957 then Cur := LoadCursor(0,IDC_SIZENS) //Screen.Cursors[crVSplit]
2958 else if State = gsColSizing
2959 then Cur := LoadCursor(0,IDC_SIZEWE); //Screen.Cursors[crHSplit]}
2960 DestroyCursor(Cursor
);
2967 procedure TStGrd
.WMTimer
;
2970 DrawInfo
: TGridDrawInfo
;
2971 ScrollDirection
: TGridScrollDirection
;
2972 CellHit
: TGridCoord
;
2973 // LeftSide: Integer;
2974 // RightSide: Integer;
2977 D
:= Pointer(CustomObj
);
2978 if not (D
.fGridState
in [gsSelecting
, gsRowMoving
, gsColMoving
]) then Exit
;
2979 GetCursorPos(Point
);
2980 Point
:= Screen2Client(Point
);
2981 CalcDrawInfo(DrawInfo
);
2982 ScrollDirection
:= [];
2985 CellHit
:= CalcCoordFromPoint(Point
.X
, Point
.Y
, DrawInfo
);
2986 case D
.fGridState
of
2988 MoveAndScroll(Point
.X
, CellHit
.X
, DrawInfo
, Horz
, SB_HORZ
, Point
);
2990 MoveAndScroll(Point
.Y
, CellHit
.Y
, DrawInfo
, Vert
, SB_VERT
, Point
);
2993 // if not UseRightToLeftAlignment then
2995 if Point
.X
< Horz
.FixedBoundary
then Include(ScrollDirection
, sdLeft
)
2996 else if Point
.X
> Horz
.FullVisBoundary
then Include(ScrollDirection
, sdRight
);
3000 LeftSide := ClientWidth - Horz.FullVisBoundary;
3001 RightSide := ClientWidth - Horz.FixedBoundary;
3002 if Point.X < LeftSide then Include(ScrollDirection, sdRight)
3003 else if Point.X > RightSide then Include(ScrollDirection, sdLeft);
3005 if Point
.Y
< Vert
.FixedBoundary
then Include(ScrollDirection
, sdUp
)
3006 else if Point
.Y
> Vert
.FullVisBoundary
then Include(ScrollDirection
, sdDown
);
3007 if ScrollDirection
<> [] then TimedScroll(ScrollDirection
);