📄 ehgrids.pas
字号:
function CalcMaxCell(const Axis: TGridAxisDrawInfo; Start: Integer): Integer;
var
Line: Integer;
I, Extent: Longint;
begin
Result := Start;
with Axis do
begin
Line := GridExtent + EffectiveLineWidth;
for I := Start downto FixedCellCount do
begin
Extent := GetExtent(I);
if Extent > 0 then
begin
Dec(Line, Extent);
Dec(Line, EffectiveLineWidth);
if Line < FixedBoundary then
begin
if (Result = Start) and (GetExtent(Start) <= 0) then
Result := I;
Break;
end;
Result := I;
end;
end;
end;
end;
begin
Result.X := CalcMaxCell(DrawInfo.Horz, Coord.X);
Result.Y := CalcMaxCell(DrawInfo.Vert, Coord.Y);
end;
procedure TCustomGridEh.CalcSizingState(X, Y: Integer; var State: TGridState;
var Index: Longint; var SizingPos, SizingOfs: Integer;
var FixedInfo: TGridDrawInfo);
procedure CalcAxisState(const AxisInfo: TGridAxisDrawInfo; Pos: Integer;
NewState: TGridState);
var
I, Line, Back, Range: Integer;
begin
if UseRightToLeftAlignment then
Pos := ClientWidth - Pos;
with AxisInfo do
begin
Line := FixedBoundary;
Range := EffectiveLineWidth;
Back := 0;
if Range < 7 then
begin
Range := 7;
Back := (Range - EffectiveLineWidth) shr 1;
end;
for I := FirstGridCell to GridCellCount - 1 do
begin
Inc(Line, GetExtent(I));
if Line > GridBoundary then Break;
if (Pos >= Line - Back) and (Pos <= Line - Back + Range) then
begin
State := NewState;
SizingPos := Line;
SizingOfs := Line - Pos;
Index := I;
Exit;
end;
Inc(Line, EffectiveLineWidth);
end;
if (GridBoundary = GridExtent) and (Pos >= GridExtent - Back)
and (Pos <= GridExtent) then
begin
State := NewState;
SizingPos := GridExtent;
SizingOfs := GridExtent - Pos;
Index := LastFullVisibleCell + 1;
end;
end;
end;
function XOutsideHorzFixedBoundary: Boolean;
begin
with FixedInfo do
if not UseRightToLeftAlignment then
Result := X > Horz.FixedBoundary
else
Result := X < ClientWidth - Horz.FixedBoundary;
end;
function XOutsideOrEqualHorzFixedBoundary: Boolean;
begin
with FixedInfo do
if not UseRightToLeftAlignment then
Result := X >= Horz.FixedBoundary
else
Result := X <= ClientWidth - Horz.FixedBoundary;
end;
var
EffectiveOptions: TGridOptions;
begin
State := gsNormal;
Index := -1;
EffectiveOptions := Options;
if csDesigning in ComponentState then
EffectiveOptions := EffectiveOptions + DesignOptionsBoost;
if [goColSizing, goRowSizing] * EffectiveOptions <> [] then
with FixedInfo do
begin
Vert.GridExtent := ClientHeight;
Horz.GridExtent := ClientWidth;
if (XOutsideHorzFixedBoundary) and (goColSizing in EffectiveOptions) then
begin
if Y >= Vert.FixedBoundary then Exit;
CalcAxisState(Horz, X, gsColSizing);
end
else if (Y > Vert.FixedBoundary) and (goRowSizing in EffectiveOptions) then
begin
if XOutsideOrEqualHorzFixedBoundary then Exit;
CalcAxisState(Vert, Y, gsRowSizing);
end;
end;
end;
procedure TCustomGridEh.ChangeGridOrientation(RightToLeftOrientation: Boolean);
var
Org: TPoint;
Ext: TPoint;
begin
if RightToLeftOrientation then
begin
Org := Point(ClientWidth,0);
Ext := Point(-1,1);
SetMapMode(Canvas.Handle, mm_Anisotropic);
SetWindowOrgEx(Canvas.Handle, Org.X, Org.Y, nil);
SetViewportExtEx(Canvas.Handle, ClientWidth, ClientHeight, nil);
SetWindowExtEx(Canvas.Handle, Ext.X*ClientWidth, Ext.Y*ClientHeight, nil);
end
else
begin
Org := Point(0,0);
Ext := Point(1,1);
SetMapMode(Canvas.Handle, mm_Anisotropic);
SetWindowOrgEx(Canvas.Handle, Org.X, Org.Y, nil);
SetViewportExtEx(Canvas.Handle, ClientWidth, ClientHeight, nil);
SetWindowExtEx(Canvas.Handle, Ext.X*ClientWidth, Ext.Y*ClientHeight, nil);
end;
end;
procedure TCustomGridEh.ChangeSize(NewColCount, NewRowCount: Longint);
var
OldColCount, OldRowCount: Longint;
OldDrawInfo: TGridDrawInfo;
procedure MinRedraw(const OldInfo, NewInfo: TGridAxisDrawInfo; Axis: Integer);
var
R: TRect;
First: Integer;
begin
First := Min(OldInfo.LastFullVisibleCell, NewInfo.LastFullVisibleCell);
// Get the rectangle around the leftmost or topmost cell in the target range.
R := CellRect(First and not Axis, First and Axis);
R.Bottom := Height;
R.Right := Width;
Windows.InvalidateRect(Handle, @R, False);
end;
procedure DoChange;
var
Coord: TGridCoord;
NewDrawInfo: TGridDrawInfo;
begin
if FColWidths <> nil then
UpdateExtents(FColWidths, ColCount, DefaultColWidth);
if FTabStops <> nil then
UpdateExtents(FTabStops, ColCount, Integer(True));
if FRowHeights <> nil then
UpdateExtents(FRowHeights, RowCount, DefaultRowHeight);
Coord := FCurrent;
if Row >= RowCount then Coord.Y := RowCount - 1;
if Col >= ColCount then Coord.X := ColCount - 1;
if (FCurrent.X <> Coord.X) or (FCurrent.Y <> Coord.Y) then
MoveCurrent(Coord.X, Coord.Y, True, True);
if (FAnchor.X <> Coord.X) or (FAnchor.Y <> Coord.Y) then
MoveAnchor(Coord);
if VirtualView or
(LeftCol <> OldDrawInfo.Horz.FirstGridCell) or
(TopRow <> OldDrawInfo.Vert.FirstGridCell) then
InvalidateGrid
else if HandleAllocated then
begin
CalcDrawInfo(NewDrawInfo);
MinRedraw(OldDrawInfo.Horz, NewDrawInfo.Horz, 0);
MinRedraw(OldDrawInfo.Vert, NewDrawInfo.Vert, -1);
end;
UpdateScrollRange;
SizeChanged(OldColCount, OldRowCount);
end;
begin
if HandleAllocated then
CalcDrawInfo(OldDrawInfo);
OldColCount := FColCount;
OldRowCount := FRowCount;
FColCount := NewColCount;
FRowCount := NewRowCount;
if FixedCols > NewColCount then FFixedCols := NewColCount - 1;
if FixedRows > NewRowCount then FFixedRows := NewRowCount - 1;
try
DoChange;
except
{ Could not change size so try to clean up by setting the size back }
FColCount := OldColCount;
FRowCount := OldRowCount;
DoChange;
InvalidateGrid;
raise;
end;
end;
{ Will move TopLeft so that Coord is in view }
procedure TCustomGridEh.ClampInView(const Coord: TGridCoord);
var
DrawInfo: TGridDrawInfo;
MaxTopLeft: TGridCoord;
OldTopLeft: TGridCoord;
begin
if not HandleAllocated then Exit;
CalcDrawInfo(DrawInfo);
with DrawInfo, Coord do
begin
if (X > Horz.LastFullVisibleCell) or
(Y > Vert.LastFullVisibleCell) or (X < LeftCol) or (Y < TopRow) then
begin
OldTopLeft := FTopLeft;
MaxTopLeft := CalcMaxTopLeft(Coord, DrawInfo);
Update;
if X < LeftCol then FTopLeft.X := X
else if X > Horz.LastFullVisibleCell then FTopLeft.X := MaxTopLeft.X;
if Y < TopRow then FTopLeft.Y := Y
else if Y > Vert.LastFullVisibleCell then FTopLeft.Y := MaxTopLeft.Y;
TopLeftMoved(OldTopLeft);
end;
end;
end;
procedure TCustomGridEh.DrawSizingLine(const DrawInfo: TGridDrawInfo);
var
OldPen: TPen;
begin
OldPen := TPen.Create;
try
with Canvas, DrawInfo do
begin
OldPen.Assign(Pen);
Pen.Style := psDot;
Pen.Mode := pmXor;
Pen.Width := 1;
try
if FGridState = gsRowSizing then
begin
MoveTo(0, FSizingPos);
LineTo(Horz.GridBoundary, FSizingPos);
end
else
begin
MoveTo(FSizingPos, 0);
LineTo(FSizingPos, Vert.GridBoundary);
end;
finally
Pen := OldPen;
end;
end;
finally
OldPen.Free;
end;
end;
procedure TCustomGridEh.DrawMove;
var
OldPen: TPen;
Pos: Integer;
R: TRect;
begin
OldPen := TPen.Create;
try
with Canvas do
begin
OldPen.Assign(Pen);
try
Pen.Style := psDot;
Pen.Mode := pmXor;
Pen.Width := 5;
if FGridState = gsRowMoving then
begin
R := CellRect(0, FMovePos);
if FMovePos > FMoveIndex then
Pos := R.Bottom else
Pos := R.Top;
MoveTo(0, Pos);
LineTo(ClientWidth, Pos);
end
else
begin
R := CellRect(FMovePos, 0);
if FMovePos > FMoveIndex then
if not UseRightToLeftAlignment then
Pos := R.Right
else
Pos := R.Left
else
if not UseRightToLeftAlignment then
Pos := R.Left
else
Pos := R.Right;
MoveTo(Pos, 0);
LineTo(Pos, ClientHeight);
end;
finally
Canvas.Pen := OldPen;
end;
end;
finally
OldPen.Free;
end;
end;
procedure TCustomGridEh.FocusCell(ACol, ARow: Longint; MoveAnchor: Boolean);
begin
MoveCurrent(ACol, ARow, MoveAnchor, True);
UpdateEdit;
Click;
end;
procedure TCustomGridEh.GridRectToScreenRect(GridRect: TGridRect;
var ScreenRect: TRect; IncludeLine: Boolean);
function LinePos(const AxisInfo: TGridAxisDrawInfo; Line: Integer): Integer;
var
Start, I: Longint;
begin
with AxisInfo do
begin
Result := 0;
if Line < FixedCellCount then
Start := 0
else
begin
if Line >= FirstGridCell then
Result := FixedBoundary;
Start := FirstGridCell;
end;
for I := Start to Line - 1 do
begin
Inc(Result, GetExtent(I) + EffectiveLineWidth);
if Result > GridExtent then
begin
Result := 0;
Exit;
end;
end;
end;
end;
function CalcAxis(const AxisInfo: TGridAxisDrawInfo;
GridRectMin, GridRectMax: Integer;
var ScreenRectMin, ScreenRectMax: Integer): Boolean;
begin
Result := False;
with AxisInfo do
begin
if (GridRectMin >= FixedCellCount) and (GridRectMin < FirstGridCell) then
if GridRectMax < FirstGridCell then
begin
FillChar(ScreenRect, SizeOf(ScreenRect), 0); { erase partial results }
Exit;
end
else
GridRectMin := FirstGridCell;
if GridRectMax > LastFullVisibleCell then
begin
GridRectMax := LastFullVisibleCell;
if GridRectMax < GridCellCount - 1 then Inc(GridRectMax);
if LinePos(AxisInfo, GridRectMax) = 0 then
Dec(GridRectMax);
end;
ScreenRectMin := LinePos(AxisInfo, GridRectMin);
ScreenRectMax := LinePos(AxisInfo, GridRectMax);
if ScreenRectMax = 0 then
ScreenRectMax := ScreenRectMin + GetExtent(GridRectMin)
else
Inc(ScreenRectMax, GetExtent(GridRectMax));
if ScreenRectMax > GridExtent then
ScreenRectMax := GridExtent;
if IncludeLine then Inc(ScreenRectMax, EffectiveLineWidth);
end;
Result := True;
end;
var
DrawInfo: TGridDrawInfo;
Hold: Integer;
begin
FillChar(ScreenRect, SizeOf(ScreenRect), 0);
if (GridRect.Left > GridRect.Right) or (GridRect.Top > GridRect.Bottom) then
Exit;
CalcDrawInfo(DrawInfo);
with DrawInfo do
begin
if GridRect.Left > Horz.LastFullVisibleCell + 1 then Exit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -