📄 generatormessagesgrid.pas
字号:
begin
CalcDrawInfo(DrawInfo); //calculate current view
Result := DrawInfo.Vert.GridBoundary; //return used vertical height
end;
{Calculates the visible coordinates of a single cell.
~param ACol, ARow the cell whose coordinates should be calculated
~result the coordinates of the rectangle of the cell }
function TGMGrid.CellRect(ACol, ARow: Integer): TRect;
begin
Result := BoxRect(ACol, ARow, ACol, ARow); //treat the cell as a rectangle
end;
{Calculates the visible coordinates of a rectangle of cells.
~param ALeft, ATop, ARight, ABottom the positions of the cells spanning the
rectangle
~result the coordinates of the rectangle containing the cells }
function TGMGrid.BoxRect(ALeft, ATop, ARight, ABottom: Integer): TRect;
var GridRect :TGMGridRect; //the rectangle as a rectangle
begin
GridRect.Left := ALeft; //assign to rectangle structure
GridRect.Right := ARight;
GridRect.Top := ATop;
GridRect.Bottom := ABottom;
GridRectToClientRect(GridRect, Result, False); //calculate position
end;
{Calculates the client rectangle of a rectangle of cells.
~param GridRect the rectangle of cells to calculate the visible rectangle of
~param ClientRect out: the coordinates of the visible rectangle containing all
cells in the rectangle
~param IncludeLine whether the lower and right border lines of the cells should
be included in the resulting rectangle }
procedure TGMGrid.GridRectToClientRect(GridRect: TGMGridRect;
var ClientRect: TRect;
IncludeLine: Boolean);
{Returns the client position of a line (column or row) inside the grid.
~param AxisInfo the information about the axis of the line to calculate the
position with
~param CellLine the line (column or row) of the grid whose position should
be calculated
~result the position of the line or 0 }
function LinePos(const AxisInfo: TGridAxisDrawInfo;
CellLine: Integer): Integer;
var Start :Integer; //first cell to count through
i :Integer; //counter through cells
begin
Result := 0; //position starts at beginning
if CellLine < AxisInfo.FixedCellCount then //is a fixed cell?
Start := 0 //start at first fixed cell
else
begin
//start at first non-fixed and visible cell (FLeftTop.x/y)
Start := AxisInfo.FirstGridCell;
if CellLine >= Start then //the line is visible?
Result := AxisInfo.FixedBoundary; //position after fixed cells
end;
//add space of all visible lines before the line
i := Start;
while (i < CellLine) and (Result <= AxisInfo.GridExtent) do
begin
Inc(Result, AxisInfo.GetExtent(i) + AxisInfo.EffectiveLineWidth);
Inc(i);
end;
if Result > AxisInfo.GridExtent then //line not visible anymore?
Result := 0; //return "invalid" position
end;
{Calculates the position of the rectangle on one of the axes.
~param AxisInfo the information about the axis
~param GridRectMin the smaller edge of the rectangle (Left or Top)
~param GridRectMax the bigger edge of the rectangle (Right or Bottom)
~param ClientRectMin out: position of smaller edge
~param ClientRectMax out: position of bigger edge
~result whether the rectangle is visible on this axis }
function CalcAxis(const AxisInfo: TGridAxisDrawInfo;
GridRectMin, GridRectMax: Integer;
var ClientRectMin, ClientRectMax: Integer): Boolean;
begin
//smaller edge may be visible?
Result := (GridRectMin < AxisInfo.FixedCellCount) or
(GridRectMin >= AxisInfo.FirstGridCell);
if not Result then //smaller edge not visible?
begin
//bigger edge is visible or selection spans visible part?
Result := GridRectMax >= AxisInfo.FirstGridCell;
if Result then
//use the first visible cell as the smaller edge instead of
GridRectMin := AxisInfo.FirstGridCell; //the invisible one
end;
if Result then //rectangle is visible?
begin
//bigger edge is not visible?
if GridRectMax > AxisInfo.LastFullVisibleCell then
begin
GridRectMax := AxisInfo.LastFullVisibleCell; //restrict to visible part
if GridRectMax < AxisInfo.GridCellCount - 1 then //not the last cell?
//include the following only partly visible cell
Inc(GridRectMax);
if LinePos(AxisInfo, GridRectMax) = 0 then //bigger edge not visible?
Dec(GridRectMax); //use the previous one
end;
//calculate the positions of both edges
ClientRectMin := LinePos(AxisInfo, GridRectMin);
ClientRectMax := LinePos(AxisInfo, GridRectMax);
if ClientRectMax = 0 then //bigger edge not visible?
//only use rectangle including the cells of the smaller edge
ClientRectMax := ClientRectMin + AxisInfo.GetExtent(GridRectMin)
else
//extend the rectangle to include the cells of the bigger edge
Inc(ClientRectMax, AxisInfo.GetExtent(GridRectMax));
if ClientRectMax > AxisInfo.GridExtent then //extends beyond client size?
ClientRectMax := AxisInfo.GridExtent; //limit to it
if IncludeLine then //should include border line?
Inc(ClientRectMax, AxisInfo.EffectiveLineWidth); //add it
end;
end;
var DrawInfo :TGridDrawInfo; //information about the view of the grid
TempX :Integer; //to swap coordinates horizontally
begin
FillChar(ClientRect, SizeOf(ClientRect), 0); //clear the resulting rectangle
if (GridRect.Left <= GridRect.Right) and //is a valid rectangle?
(GridRect.Top <= GridRect.Bottom) then
begin
CalcDrawInfo(DrawInfo); //calculate current view
//rectangle is not scrolled out of view (too far left or down)?
if (GridRect.Left <= DrawInfo.Horz.LastFullVisibleCell + 1) and
(GridRect.Top <= DrawInfo.Vert.LastFullVisibleCell + 1) then
begin
//calculate right and left client coordinates
if CalcAxis(DrawInfo.Horz, GridRect.Left, GridRect.Right,
ClientRect.Left, ClientRect.Right) then
//calculate upper and lower client coordinates
if not CalcAxis(DrawInfo.Vert, GridRect.Top, GridRect.Bottom,
ClientRect.Top, ClientRect.Bottom) then //not visible?
begin
ClientRect.Left := 0; //clear rectangle again
ClientRect.Right := 0;
end
else
if UseRightToLeftAlignment and //has to be mirrored horizontally?
(Canvas.CanvasOrientation = coLeftToRight) then
begin
TempX := ClientRect.Left; //mirror it
ClientRect.Left := ClientWidth - ClientRect.Right;
ClientRect.Right := ClientWidth - TempX;
end;
end;
end;
end;
{Calculates the cell at the specified client coordinate.
~param X, Y the client coordinate to search the cell at
~param DrawInfo information about the view of the grid
~result the cell located at the position, an axis may be -1 if not in a cell }
function TGMGrid.CalcCellFromPoint(X, Y: Integer;
const DrawInfo: TGridDrawInfo): TGMGridCoord;
{Calculate the row or column at the position.
~param AxisInfo the information about the axis of the line to calculate the
cell with
~param N the position within the axis to calculate the cell with
~result the cell (column or row) at the position }
function DoCalc(const AxisInfo: TGridAxisDrawInfo; N: Integer): Integer;
var Stop :Integer; //the last cell to check
Line :Integer; //position of the cell
begin
if N < AxisInfo.FixedBoundary then //is on the fixed cells?
begin
Result := 0; //start with the first (fixed) cell
Stop := AxisInfo.FixedCellCount - 1; //to the last fixed cell
Line := 0; //fixed cell starts at the beginning
end
else
begin
Result := AxisInfo.FirstGridCell; //start with first shown cell
Stop := AxisInfo.GridCellCount - 1; //up to the last cell
Line := AxisInfo.FixedBoundary; //cell starts after the fixed cells
end;
//run through all the cells until position in it
while (Result <= Stop) and (Line < N) do
begin //move line to the next cell
Inc(Line, AxisInfo.GetExtent(Result) + AxisInfo.EffectiveLineWidth);
Inc(Result); //and resume with the next cell
end;
if Line < N then //not on a cell?
Result := -1 //return invalid index
else
Dec(Result); //restore matching index
end;
{Calculate the column at the position.
~param AxisInfo the information about the horizontal axis to calculate the
column with
~param N the position within the axis to calculate the cell with
~result the column at the position }
function DoCalcRightToLeft(const AxisInfo: TGridAxisDrawInfo;
N: Integer): Integer;
var Stop :Integer; //the last cell to check
Line :Integer; //position of the cell
begin
N := ClientWidth - N; //mirror the position
Result := AxisInfo.FirstGridCell; //start with first shown cell
Stop := AxisInfo.GridCellCount - 1; //up to the last cell
Line := 0; //cell starts at the beginning
//run through all the cells until position in it
while (Result <= Stop) and (Line < N) do
begin //move line to the next cell
Inc(Line, AxisInfo.GetExtent(Result) + AxisInfo.EffectiveLineWidth);
Inc(Result); //and resume with the next cell
end;
if Line < N then //not on a cell?
Result := -1 //return invalid index
else
Dec(Result); //restore matching index
end;
begin
if UseRightToLeftAlignment then //is horizonatally mirrored?
Result.X := DoCalcRightToLeft(DrawInfo.Horz, X) //calculate column mirrored
else
Result.X := DoCalc(DrawInfo.Horz, X); //calculate column at the position
Result.Y := DoCalc(DrawInfo.Vert, Y); //calculate row at the position
end;
{Calculates the information about the current view of the grid.
~param DrawInfo out: information about the view of the grid }
procedure TGMGrid.CalcDrawInfo(var DrawInfo: TGridDrawInfo);
begin
CalcDrawInfoXY(DrawInfo, ClientWidth, ClientHeight);
end;
{Calculates and sets the information about the currently shown cells.
~param DrawInfo out: information about the view of the grid
~param UseWidth, UseHeight the size of the visible area
(i.e. ClientWidth and ClientHeight) }
procedure TGMGrid.CalcDrawInfoXY(var DrawInfo: TGridDrawInfo;
UseWidth, UseHeight: Integer);
{Calculates the information about the currently shown cells on one axis.
~param AxisInfo out: the information about the axis
~param UseExtend the size of the area to use }
procedure CalcAxis(var AxisInfo: TGridAxisDrawInfo; UseExtent: Integer);
var i :Integer; //counter through columns/rows
begin
AxisInfo.GridExtent := UseExtent; //set available space
AxisInfo.GridBoundary := AxisInfo.FixedBoundary; //initialize used space
i := AxisInfo.FirstGridCell;
while (i < AxisInfo.GridCellCount) and //add up all cells
(AxisInfo.GridBoundary <= //until space filled
AxisInfo.GridExtent + AxisInfo.EffectiveLineWidth) do
begin
Inc(AxisInfo.GridBoundary, AxisInfo.GetExtent(i)); //add the used spaces
Inc(AxisInfo.GridBoundary, AxisInfo.EffectiveLineWidth);
Inc(i); //next cell
end;
if i <> AxisInfo.FirstGridCell then //cells available and fit?
begin
Dec(i); //the last cell didn't fit
AxisInfo.LastFullVisibleCell := i; //set last fitting cell
AxisInfo.FullVisBoundary := AxisInfo.GridBoundary; //and used space
if AxisInfo.GridBoundary > //last cell didn't fit?
AxisInfo.GridExtent + AxisInfo.EffectiveLineWidth then
begin
AxisInfo.GridBoundary := AxisInfo.GridExtent; //use maximum space
//remove space of last cell again
Dec(AxisInfo.FullVisBoundary, AxisInfo.GetExtent(i));
Dec(AxisInfo.FullVisBoundary, AxisInfo.EffectiveLineWidth);
Dec(AxisInfo.LastFullVisibleCell); //last cell not fully visible
end;
end
else
begin
//only the first cell fits (although that's probably not true)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -