📄 emswidestringgrid.pas
字号:
begin
N := ClientWidth - N;
with AxisInfo do
begin
if N < FixedBoundary then
begin
Start := 0;
Stop := FixedCellCount - 1;
Line := ClientWidth;
end
else
begin
Start := FirstGridCell;
Stop := GridCellCount - 1;
Line := FixedBoundary;
end;
Result := -1;
for I := Start to Stop do
begin
Inc(Line, GetExtent(I) + EffectiveLineWidth);
if N < Line then
begin
Result := I;
Exit;
end;
end;
end;
end;
begin
if not UseRightToLeftAlignment then
Result.X := DoCalc(DrawInfo.Horz, X)
else
Result.X := DoCalcRightToLeft(DrawInfo.Horz, X);
Result.Y := DoCalc(DrawInfo.Vert, Y);
end;
procedure TEmsCustomGrid.CalcDrawInfo(var DrawInfo: TGridDrawInfo);
begin
CalcDrawInfoXY(DrawInfo, ClientWidth, ClientHeight);
end;
procedure TEmsCustomGrid.CalcDrawInfoXY(var DrawInfo: TGridDrawInfo;
UseWidth, UseHeight: Integer);
procedure CalcAxis(var AxisInfo: TGridAxisDrawInfo; UseExtent: Integer);
var
I: Integer;
begin
with AxisInfo do
begin
GridExtent := UseExtent;
GridBoundary := FixedBoundary;
FullVisBoundary := FixedBoundary;
LastFullVisibleCell := FirstGridCell;
for I := FirstGridCell to GridCellCount - 1 do
begin
Inc(GridBoundary, GetExtent(I) + EffectiveLineWidth);
if GridBoundary > GridExtent + EffectiveLineWidth then
begin
GridBoundary := GridExtent;
Break;
end;
LastFullVisibleCell := I;
FullVisBoundary := GridBoundary;
end;
end;
end;
begin
CalcFixedInfo(DrawInfo);
CalcAxis(DrawInfo.Horz, UseWidth);
CalcAxis(DrawInfo.Vert, UseHeight);
end;
procedure TEmsCustomGrid.CalcFixedInfo(var DrawInfo: TGridDrawInfo);
procedure CalcFixedAxis(var Axis: TGridAxisDrawInfo; LineOptions: TGridOptions;
FixedCount, FirstCell, CellCount: Integer; GetExtentFunc: TGetExtentsFunc);
var
I: Integer;
begin
with Axis do
begin
if LineOptions * Options = [] then
EffectiveLineWidth := 0
else
EffectiveLineWidth := GridLineWidth;
FixedBoundary := 0;
for I := 0 to FixedCount - 1 do
Inc(FixedBoundary, GetExtentFunc(I) + EffectiveLineWidth);
FixedCellCount := FixedCount;
FirstGridCell := FirstCell;
GridCellCount := CellCount;
GetExtent := GetExtentFunc;
end;
end;
begin
CalcFixedAxis(DrawInfo.Horz, [goFixedVertLine, goVertLine], FixedCols,
LeftCol, ColCount, GetColWidths);
CalcFixedAxis(DrawInfo.Vert, [goFixedHorzLine, goHorzLine], FixedRows,
TopRow, RowCount, GetRowHeights);
end;
function TEmsCustomGrid.CalcMaxTopLeft(const Coord: TGridCoord;
const DrawInfo: TGridDrawInfo): TGridCoord;
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 TEmsCustomGrid.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 TEmsCustomGrid.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 TEmsCustomGrid.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);
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
FColCount := OldColCount;
FRowCount := OldRowCount;
DoChange;
InvalidateGrid;
raise;
end;
end;
procedure TEmsCustomGrid.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 TEmsCustomGrid.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 TEmsCustomGrid.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 :=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -