📄 ehgrids.pas
字号:
NewSize: Integer;
I: Integer;
begin
if Amount <> 0 then
begin
if not Assigned(Extents) then OldSize := 0
else OldSize := PIntArray(Extents)^[0];
if (Index < 0) or (OldSize < Index) then InvalidOp(SIndexOutOfRange);
LongSize := OldSize + Amount;
if LongSize < 0 then InvalidOp(STooManyDeleted)
else if LongSize >= MaxListSize - 1 then InvalidOp(SGridTooLarge);
NewSize := Cardinal(LongSize);
if NewSize > 0 then Inc(NewSize);
ReallocMem(Extents, NewSize * SizeOf(Integer));
if Assigned(Extents) then
begin
I := Index + 1;
while I < NewSize do
begin
PIntArray(Extents)^[I] := Default;
Inc(I);
end;
PIntArray(Extents)^[0] := NewSize-1;
end;
end;
end;
procedure UpdateExtents(var Extents: Pointer; NewSize: Longint;
Default: Integer);
var
OldSize: Integer;
begin
OldSize := 0;
if Assigned(Extents) then OldSize := PIntArray(Extents)^[0];
ModifyExtents(Extents, OldSize, NewSize - OldSize, Default);
end;
procedure MoveExtent(var Extents: Pointer; FromIndex, ToIndex: Longint);
var
Extent: Integer;
begin
if Assigned(Extents) then
begin
Extent := PIntArray(Extents)^[FromIndex];
if FromIndex < ToIndex then
Move(PIntArray(Extents)^[FromIndex + 1], PIntArray(Extents)^[FromIndex],
(ToIndex - FromIndex) * SizeOf(Integer))
else if FromIndex > ToIndex then
Move(PIntArray(Extents)^[ToIndex], PIntArray(Extents)^[ToIndex + 1],
(FromIndex - ToIndex) * SizeOf(Integer));
PIntArray(Extents)^[ToIndex] := Extent;
end;
end;
function CompareExtents(E1, E2: Pointer): Boolean;
var
I: Integer;
begin
Result := False;
if E1 <> nil then
begin
if E2 <> nil then
begin
for I := 0 to PIntArray(E1)^[0] do
if PIntArray(E1)^[I] <> PIntArray(E2)^[I] then Exit;
Result := True;
end
end
else Result := E2 = nil;
end;
{ Private. LongMulDiv multiplys the first two arguments and then
divides by the third. This is used so that real number
(floating point) arithmetic is not necessary. This routine saves
the possible 64-bit value in a temp before doing the divide. Does
not do error checking like divide by zero. Also assumes that the
result is in the 32-bit range (Actually 31-bit, since this algorithm
is for unsigned). }
function LongMulDiv(Mult1, Mult2, Div1: Longint): Longint; stdcall;
external 'kernel32.dll' name 'MulDiv';
type
TSelection = record
StartPos, EndPos: Integer;
end;
constructor TInplaceEditEh.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ParentCtl3D := False;
Ctl3D := False;
TabStop := False;
BorderStyle := bsNone;
DoubleBuffered := False;
end;
procedure TInplaceEditEh.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style or ES_MULTILINE;
end;
procedure TInplaceEditEh.SetGrid(Value: TCustomGridEh);
begin
FGrid := Value;
end;
procedure TInplaceEditEh.CMShowingChanged(var Message: TMessage);
begin
{ Ignore showing using the Visible property }
end;
procedure TInplaceEditEh.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
inherited;
if goTabs in Grid.Options then
Message.Result := Message.Result or DLGC_WANTTAB;
end;
procedure TInplaceEditEh.WMPaste(var Message);
begin
if not EditCanModify then Exit;
inherited
end;
procedure TInplaceEditEh.WMClear(var Message);
begin
if not EditCanModify then Exit;
inherited;
end;
procedure TInplaceEditEh.WMCut(var Message);
begin
if not EditCanModify then Exit;
inherited;
end;
procedure TInplaceEditEh.DblClick;
begin
Grid.DblClick;
end;
function TInplaceEditEh.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
MousePos: TPoint): Boolean;
begin
Result := Grid.DoMouseWheel(Shift, WheelDelta, MousePos);
end;
function TInplaceEditEh.EditCanModify: Boolean;
begin
Result := Grid.CanEditModify;
end;
procedure TInplaceEditEh.KeyDown(var Key: Word; Shift: TShiftState);
procedure SendToParent;
begin
Grid.KeyDown(Key, Shift);
Key := 0;
end;
procedure ParentEvent;
var
GridKeyDown: TKeyEvent;
begin
GridKeyDown := Grid.OnKeyDown;
if Assigned(GridKeyDown) then GridKeyDown(Grid, Key, Shift);
end;
function ForwardMovement: Boolean;
begin
Result := goAlwaysShowEditor in Grid.Options;
end;
function Ctrl: Boolean;
begin
Result := ssCtrl in Shift;
end;
function Selection: TSelection;
begin
SendMessage(Handle, EM_GETSEL, Longint(@Result.StartPos), Longint(@Result.EndPos));
end;
function RightSide: Boolean;
begin
with Selection do
Result := ((StartPos = 0) or (EndPos = StartPos)) and
(EndPos = GetTextLen);
end;
function LeftSide: Boolean;
begin
with Selection do
Result := (StartPos = 0) and ((EndPos = 0) or (EndPos = GetTextLen));
end;
begin
case Key of
VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, VK_ESCAPE: SendToParent;
VK_INSERT:
if Shift = [] then SendToParent
else if (Shift = [ssShift]) and not Grid.CanEditModify then Key := 0;
VK_LEFT: if ForwardMovement and (Ctrl or LeftSide) then SendToParent;
VK_RIGHT: if ForwardMovement and (Ctrl or RightSide) then SendToParent;
VK_HOME: if ForwardMovement and (Ctrl or LeftSide) then SendToParent;
VK_END: if ForwardMovement and (Ctrl or RightSide) then SendToParent;
VK_F2:
begin
ParentEvent;
if Key = VK_F2 then
begin
Deselect;
Exit;
end;
end;
VK_TAB: if not (ssAlt in Shift) then SendToParent;
end;
if (Key = VK_DELETE) and not Grid.CanEditModify then Key := 0;
if Key <> 0 then
begin
ParentEvent;
inherited KeyDown(Key, Shift);
end;
end;
procedure TInplaceEditEh.KeyPress(var Key: Char);
var
Selection: TSelection;
begin
Grid.KeyPress(Key);
if (Key in [#32..#255]) and not Grid.CanEditAcceptKey(Key) then
begin
Key := #0;
MessageBeep(0);
end;
case Key of
#9, #27: Key := #0;
#13:
begin
SendMessage(Handle, EM_GETSEL, Longint(@Selection.StartPos), Longint(@Selection.EndPos));
if (Selection.StartPos = 0) and (Selection.EndPos = GetTextLen) then
Deselect else
SelectAll;
Key := #0;
end;
^H, ^V, ^X, #32..#255:
if not Grid.CanEditModify then Key := #0;
end;
if Key <> #0 then inherited KeyPress(Key);
end;
procedure TInplaceEditEh.KeyUp(var Key: Word; Shift: TShiftState);
begin
Grid.KeyUp(Key, Shift);
end;
procedure TInplaceEditEh.WndProc(var Message: TMessage);
begin
case Message.Msg of
WM_SETFOCUS:
begin
if (GetParentForm(Self) = nil) or GetParentForm(Self).SetFocusedControl(Grid) then Dispatch(Message);
Exit;
end;
WM_LBUTTONDOWN:
begin
if UINT(GetMessageTime - FClickTime) < GetDoubleClickTime then
Message.Msg := WM_LBUTTONDBLCLK;
FClickTime := 0;
end;
end;
inherited WndProc(Message);
end;
procedure TInplaceEditEh.Deselect;
begin
SendMessage(Handle, EM_SETSEL, $7FFFFFFF, Longint($FFFFFFFF));
end;
procedure TInplaceEditEh.Invalidate;
var
Cur: TRect;
begin
ValidateRect(Handle, nil);
InvalidateRect(Handle, nil, True);
Windows.GetClientRect(Handle, Cur);
MapWindowPoints(Handle, Grid.Handle, Cur, 2);
ValidateRect(Grid.Handle, @Cur);
InvalidateRect(Grid.Handle, @Cur, False);
end;
procedure TInplaceEditEh.Hide;
begin
if HandleAllocated and IsWindowVisible(Handle) then
begin
Invalidate;
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_HIDEWINDOW or SWP_NOZORDER or
SWP_NOREDRAW);
if Focused then Windows.SetFocus(Grid.Handle);
end;
end;
function TInplaceEditEh.PosEqual(const Rect: TRect): Boolean;
var
Cur: TRect;
begin
GetWindowRect(Handle, Cur);
MapWindowPoints(HWND_DESKTOP, Grid.Handle, Cur, 2);
Result := EqualRect(Rect, Cur);
end;
procedure TInplaceEditEh.InternalMove(const Loc: TRect; Redraw: Boolean);
begin
if IsRectEmpty(Loc) then Hide
else
begin
CreateHandle;
Redraw := Redraw or not IsWindowVisible(Handle);
Invalidate;
with Loc do
SetWindowPos(Handle, HWND_TOP, Left, Top, Right - Left, Bottom - Top,
SWP_SHOWWINDOW or SWP_NOREDRAW);
BoundsChanged;
if Redraw then Invalidate;
if Grid.Focused then
Windows.SetFocus(Handle);
end;
end;
procedure TInplaceEditEh.BoundsChanged;
var
R: TRect;
begin
R := Rect(2, 2, Width - 2, Height);
SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@R));
SendMessage(Handle, EM_SCROLLCARET, 0, 0);
end;
procedure TInplaceEditEh.UpdateLoc(const Loc: TRect);
begin
InternalMove(Loc, False);
end;
function TInplaceEditEh.Visible: Boolean;
begin
Result := IsWindowVisible(Handle);
end;
procedure TInplaceEditEh.Move(const Loc: TRect);
begin
InternalMove(Loc, True);
end;
procedure TInplaceEditEh.SetFocus;
begin
if IsWindowVisible(Handle) then
Windows.SetFocus(Handle);
end;
procedure TInplaceEditEh.UpdateContents;
begin
Text := '';
EditMask := Grid.GetEditMask(Grid.Col, Grid.Row);
Text := Grid.GetEditText(Grid.Col, Grid.Row);
MaxLength := Grid.GetEditLimit;
end;
{ TCustomGridEh }
constructor TCustomGridEh.Create(AOwner: TComponent);
const
GridStyle = [csCaptureMouse, csOpaque, csDoubleClicks];
begin
inherited Create(AOwner);
if NewStyleControls then
ControlStyle := GridStyle else
ControlStyle := GridStyle + [csFramed];
FCanEditModify := True;
FColCount := 5;
FRowCount := 5;
FFixedCols := 1;
FFixedRows := 1;
FGridLineWidth := 1;
FOptions := [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine,
goRangeSelect];
DesignOptionsBoost := [goColSizing, goRowSizing];
FFixedColor := clBtnFace;
FScrollBars := ssBoth;
FBorderStyle := bsSingle;
FDefaultColWidth := 64;
FDefaultRowHeight := 24;
FDefaultDrawing := True;
FSaveCellExtents := True;
FEditorMode := False;
Color := clWindow;
FLineColor := clBlack;
FSelectedColor:=clHighLight;
FSelectedFontColor:=clHighLightText;
ParentColor := False;
TabStop := True;
SetBounds(Left, Top, FColCount * FDefaultColWidth,
FRowCount * FDefaultRowHeight);
Initialize;
end;
destructor TCustomGridEh.Destroy;
begin
FInplaceEdit.Free;
inherited Destroy;
FreeMem(FColWidths);
FreeMem(FRowHeights);
FreeMem(FTabStops);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -