📄 generatormessagesgrid.pas
字号:
AxisInfo.LastFullVisibleCell := AxisInfo.FirstGridCell;
//only fixed cells fit (maybe not even they)
AxisInfo.FullVisBoundary := AxisInfo.FixedBoundary;
if AxisInfo.GridBoundary > //fixed cells don't fit?
AxisInfo.GridExtent + AxisInfo.EffectiveLineWidth then
AxisInfo.GridBoundary := AxisInfo.GridExtent; //use maximum space
end;
end;
begin
CalcFixedInfo(DrawInfo); //calculate information about fixed cells
CalcAxis(DrawInfo.Horz, UseWidth); //and of both axes
CalcAxis(DrawInfo.Vert, UseHeight);
end;
{Calculates the information about the always visible parts of the grid.
~param DrawInfo out: information about always visible parts of the grid }
procedure TGMGrid.CalcFixedInfo(var DrawInfo: TGridDrawInfo);
{Calculates the information about the always visible parts of an axis.
~param Axis out: information about always visible parts of the axis
~param LineOptions option pertaining this axis that may be set
~param FirstCell the first visible (non-fixed) cell
~param CellCount the total number of cells in this axis
~param GetExtendFunc the function to get the used space of cells
~param Row whether it is the horizontal axis (along the rows) }
procedure CalcFixedAxis(var Axis: TGridAxisDrawInfo;
LineOptions: TGMGridOption;
FirstCell, CellCount: Integer;
GetExtentFunc: TGetExtentsFunc; Row: Boolean);
begin
if FirstCell < 0 then //make sure the value of the first cell is valid
FirstCell := 0;
if LineOptions in Options then //set width of the line between the cells
Axis.EffectiveLineWidth := 1
else
Axis.EffectiveLineWidth := 0;
if Row or (GetFixedRows = 0) then //no fixed cells used for the axis?
begin
Axis.FixedBoundary := 0; //they use not space
Axis.FixedCellCount := 0; //no fixed cells
end
else
begin
Axis.FixedBoundary := FTitleHeight; //set height of title bar
Axis.FixedCellCount := 1; //the title bar is only one row
if FirstCell = 0 then //make sure the value of the first cell is valid
FirstCell := 1;
end;
Axis.FirstGridCell := FirstCell; //set the first visible (non-fixed) cell
Axis.GridCellCount := CellCount; //the number of cells and
Axis.GetExtent := GetExtentFunc; //the function to get the size of cells
end;
begin
//calculate the information about the always visible parts of both axes
CalcFixedAxis(DrawInfo.Horz, goVertLine, LeftCol, ColCount, GetWidthOfCol,
True);
CalcFixedAxis(DrawInfo.Vert, goHorzLine, TopRow, RowCount, GetRowHeights,
False);
end;
{Checks whether the size of a column can be changed at the position.
~param X, Y the position of the mouse pointer within the component
~param State out: gsColSizing if a column can be resized at the
position or gsNormal if that is not the case
~param Index out: index of the column to be resized
~param SizingOrgSize out: the position of the of the separator that can be used
to resize the column
~param SizingOfs out: the offset (difference) of the mouse pointer from the
separator
~param FixedInfo information about the view of the grid }
procedure TGMGrid.CalcSizingState(X, Y: Integer; var State: TGMGridState;
var Index: Integer;
var SizingOrgSize, SizingOfs: Integer;
const FixedInfo: TGridDrawInfo);
{Checks whether the size of a column can be changed.
~param AxisInfo the information about the axis to check for resizing
~param Pos the position on the axis }
procedure CalcAxisState(const AxisInfo: TGridAxisDrawInfo; Pos: Integer);
var Range :Integer; //the range forward to check
Back :Integer; //the range backward to check
Line :Integer; //the position of the sizing line
i :Integer; //counter through columns
begin
if UseRightToLeftAlignment then //grid is mirrored left to right?
Pos := ClientWidth - Pos; //correct position
Range := AxisInfo.EffectiveLineWidth; //widths of lines to resize columns
if Range < 5 then //range is too small?
begin
Range := 5; //use this minimal width
Back := (Range - AxisInfo.EffectiveLineWidth) div 2 +
AxisInfo.EffectiveLineWidth; //this means this far backward
end
else
//line width will be added before comparing, so adjust backward range
Back := AxisInfo.EffectiveLineWidth;
Dec(Range, Back); //decrease forward by backward
Line := AxisInfo.FixedBoundary; //start at the first cell
i := AxisInfo.FirstGridCell;
if i < AxisInfo.GridCellCount then //some cells available?
begin
repeat
Inc(Line, AxisInfo.GetExtent(i)); //calculate end of the column
Inc(Line, AxisInfo.EffectiveLineWidth);
Inc(i); //resume with next column
//last column reached, end of grid reached or on end of column?
until (i = AxisInfo.GridCellCount) or (Line > AxisInfo.GridBoundary) or
((Pos >= Line - Back) and (Pos <= Line + Range));
if Line > AxisInfo.GridBoundary then //end of the grid reached?
begin
Line := AxisInfo.GridExtent; //compare with its end
i := AxisInfo.LastFullVisibleCell + 1 + 1; //last column will be resized
end;
//is at the end of a column (between two columns)?
if (Pos >= Line - Back) and (Pos <= Line + Range) then
begin
Index := i - 1; //return column to be resized
SizingOrgSize := AxisInfo.GetExtent(i - 1); //set size of column
SizingOfs := Line - Pos; //offset of the pointer from it
State := gsColSizing; //column can be resized
end;
end;
end;
begin
State := gsNormal; //assume columns can not be resized at that position
Index := -1;
Assert(FixedInfo.Vert.GridExtent = ClientHeight);
Assert(FixedInfo.Horz.GridExtent = ClientWidth);
//is on the title bar and on a column?
if Y < FixedInfo.Vert.FixedBoundary then
CalcAxisState(FixedInfo.Horz, X); //check whether it is between two columns
end;
{Calculates the minimum ~[link FTopLeft] that will put the given Coord in view,
if the grid has to be scrolled right or down to make the cell visible.
~param Coord the coordinate to make visible
~param DrawInfo information about the view of the grid
~result the new scroll position to be used to show the specified cell }
function TGMGrid.CalcMinTopLeft(const Coord: TGMGridCoord;
const DrawInfo: TGridDrawInfo): TGMGridCoord;
{Calculates the new ~[link TopLeft] that will put the given Coord in view.
~param Axis the information about the axis to check for visibility of the
cell
~param Start the column or row to make visible
~result the new scroll position to be used to show the specified cell }
function CalcMaxCell(const Axis: TGridAxisDrawInfo; Start: Integer): Integer;
var Line :Integer; //position of edges of the cells
begin
Result := Start; //show the cell to be shown
if Result >= Axis.FixedCellCount then //cells before it?
begin
Line := Axis.GridExtent + Axis.EffectiveLineWidth; //get maximum size
repeat
Dec(Line, Axis.GetExtent(Result)); //reduce space by cell
Dec(Line, Axis.EffectiveLineWidth); //and width of line
Dec(Result); //check the previous cell
//first cell reached or no more cells fit?
until (Result < Axis.FixedCellCount) or (Line < Axis.FixedBoundary);
Inc(Result); //decremented one too far
//last cell does not fit and is not the cell in question?
if (Line < Axis.FixedBoundary) and (Result <> Start) then
Inc(Result); //scroll one cell farther
end;
end;
begin
//calculate position for both axes
Result.X := CalcMaxCell(DrawInfo.Horz, Coord.X);
Result.Y := CalcMaxCell(DrawInfo.Vert, Coord.Y);
end;
{Returns whether the grid is currently active, has the focus. This method will
also return true if a in-place editor of the content of a cell is currently
focused.
~result whether the grid is currently focused }
function TGMGrid.IsActiveControl: Boolean;
var ParentForm :TCustomForm; //the form the grid is on
H :Hwnd; //currently focused control
begin
ParentForm := GetParentForm(Self); //get form the grid is on
if Assigned(ParentForm) then //is on a (Delphi) form?
Result := ParentForm.ActiveControl = Self //return whether active control
else
begin
Result := False; //so far not determined as active
H := GetFocus; //get current control
//while not grid found and control focused or parent window known
while not Result and IsWindow(H) do
if H = WindowHandle then //is the grid?
Result := True //grid is active!
else
H := GetParent(H); //try parent of the control
end;
end;
{Cancels the current mode/state of the grid (selectings cells or moving or
resizing columns). }
procedure TGMGrid.CancelMode;
begin
try
case FGridState of //check whether in a state to be canceled?
gsSelecting: //currently selecting?
KillTimer(Handle, 1); //stop timer to scroll the grid
gsColSizing: //currently resizing a column?
begin //set original size of the column
ColWidths[FColumns[ExSizingIndex]] := ExSizingOrgSize;
UpdateDesigner;
end;
gsColMoving: //currently moving a column?
begin
KillTimer(Handle, 1); //stop timer to scroll the grid
if ExMoveIndex <> ExOrgMoveIndex then //column already moved?
begin
MoveColumn(ExMoveIndex, ExOrgMoveIndex); //move it back
UpdateDesigner;
end;
end;
end;
finally
FGridState := gsNormal; //reset the state of the grid
end;
end;
{Used during painting to temporarily change the orientation of the canvas.
~param RightToLeftOrientation whether the orientation should be set to mirror
the left and right sides or whether it should be
restored to the original setting }
procedure TGMGrid.ChangeGridOrientation(RightToLeftOrientation: Boolean);
var Org :TPoint; //new origin of the coordinate system of the canvas
Ext :TPoint; //direction of the axis of the coordinate system
begin
if RightToLeftOrientation then //canvas should mirror left and right?
begin
Org := Point(ClientWidth, 0); //start x-axis on the right
Ext := Point(-1,1); //and it extends to the left
end
else
begin
Org := Point(0,0); //start axes at top left corner
Ext := Point(1,1); //and extend them to the right lower corner
end;
//allow custom mapping of axes
SetMapMode(Canvas.Handle, mm_Anisotropic);
//set origin of the coordinate system
SetWindowOrgEx(Canvas.Handle, Org.X, Org.Y, nil);
//set size of the canvas
SetViewportExtEx(Canvas.Handle, ClientWidth, ClientHeight, nil);
//set direction of the axes
SetWindowExtEx(Canvas.Handle, Ext.X * ClientWidth, Ext.Y * ClientHeight, nil);
end;
{Changes the number of columns and/or rows of the grid.
~param NewColCount the new number of columns in the grid
~param NewRowCount the new number of rows in the grid }
procedure TGMGrid.ChangeSize(NewColCount, NewRowCount: Integer);
//information about the view of the grid before changing the number
var OldDrawInfo :TGridDrawInfo; //of cells
OldColCount :Integer; //previous number of columns in the grid
OldRowCount :Integer; //previous number of rows in the grid
{Calculates what part of the grid has to be redrawn for a changed axis.
~param OldI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -