📄 zproplst.~pas
字号:
Invalidate;
FInplaceEdit.UpdateLoc(GetEditRect);
UpdateScrollRange;
end;
procedure TZPropList.ModifyScrollBar(ScrollCode: Integer);
var
OldPos, NewPos, MaxPos: Integer;
si: TScrollInfo;
begin
OldPos := FTopRow;
NewPos := OldPos;
with si do
begin
cbSize := SizeOf(TScrollInfo);
fMask := SIF_ALL;
{$IFDEF Prior4}
GetScrollInfo(Handle, SB_VERT, si);
{$ELSE}
FlatSB_GetScrollInfo(Handle, SB_VERT, si);
{$ENDIF}
MaxPos := nMax - Integer(nPage) + 1;
case ScrollCode of
SB_LINEUP: Dec(NewPos);
SB_LINEDOWN: Inc(NewPos);
SB_PAGEUP: Dec(NewPos, nPage);
SB_PAGEDOWN: Inc(NewPos, nPage);
SB_THUMBPOSITION, SB_THUMBTRACK: NewPos := nTrackPos;
SB_TOP: NewPos := nMin;
SB_BOTTOM: NewPos := MaxPos;
else Exit;
end;
{ if NewPos < 0 then NewPos := 0;
if NewPos > MaxPos then NewPos := MaxPos;}
MoveTop(NewPos);
end;
end;
procedure TZPropList.WMVScroll(var Msg: TWMVScroll);
begin
ModifyScrollBar(Msg.ScrollCode);
end;
procedure TZPropList.MoveTop(NewTop: Integer);
var
VertCount, ShiftY: Integer;
ScrollArea: TRect;
begin
if NewTop < 0 then NewTop := 0;
VertCount := VisibleRowCount;
if NewTop + VertCount > FPropCount then
NewTop := FPropCount - VertCount;
if NewTop = FTopRow then Exit;
ShiftY := (FTopRow - NewTop) * FRowHeight;
FTopRow := NewTop;
ScrollArea := ClientRect;
{$IFDEF Prior4}
SetScrollPos(Handle, SB_VERT, NewTop, True);
{$ELSE}
FlatSB_SetScrollPos(Handle, SB_VERT, NewTop, True);
{$ENDIF}
if Abs(ShiftY) >= VertCount * FRowHeight then
InvalidateRect(Handle, @ScrollArea, True)
else
ScrollWindowEx(Handle, 0, ShiftY,
@ScrollArea, @ScrollArea, 0, nil, SW_INVALIDATE);
FInplaceEdit.Move(GetEditRect);
end;
function TZPropList.GetValueRect(ARow: Integer): TRect;
var
RowStart: Integer;
begin
RowStart := (ARow - FTopRow) * FRowHeight;
Result := Rect(FVertLine + 1, RowStart, ClientWidth, RowStart + FRowHeight - 1);
end;
function TZPropList.GetEditRect: TRect;
begin
Result := GetValueRect(FCurrent);
end;
procedure TZPropList.Paint;
{ procedure DrawValue(const S: string; R: TRect; XOfs: Integer);
begin
ExtTextOut(Canvas.Handle, R.Left + XOfs, R.Top + 1,
ETO_CLIPPED or ETO_OPAQUE, @R, PChar(S), Length(S), nil);
end;}
procedure DrawName(Index: Integer; R: TRect; XOfs: Integer);
var
S: string;
E: PZEditor;
BColor, PColor: TColor;
YOfs: Integer;
begin
if FNewButtons then
begin
E := FEditors[Index];
S := E.peEditor.GetName;
Inc(XOfs, R.Left + E.peIdent * 10);
ExtTextOut(Canvas.Handle, XOfs + 11, R.Top + 1,
ETO_CLIPPED or ETO_OPAQUE, @R, PChar(S), Length(S), nil);
if E.peNode then
with Canvas do
begin
BColor := Brush.Color;
PColor := Pen.Color;
Brush.Color := clWindow;
Pen.Color := Font.Color;
YOfs := R.Top + (FRowHeight - 9) shr 1;
Rectangle(XOfs, YOfs, XOfs + 9, YOfs + 9);
PolyLine([Point(XOfs + 2, YOfs + 4), Point(XOfs + 7, YOfs + 4)]);
if not E.peExpanded then
PolyLine([Point(XOfs + 4, YOfs + 2), Point(XOfs + 4, YOfs + 7)]);
Brush.Color := BColor;
Pen.Color := PColor;
end;
end
else
begin
Canvas.TextRect(R, R.Left + XOfs, R.Top + 1, GetName(Index));
end;
end;
function GetPenColor(Color: Integer): Integer;
type
TRGB = record
R, G, B, A: Byte;
end;
begin
// produce slightly darker color
if Color < 0 then Color := GetSysColor(Color and $FFFFFF);
Dec(TRGB(Color).R, EMin(TRGB(Color).R, $10));
Dec(TRGB(Color).G, EMin(TRGB(Color).G, $10));
Dec(TRGB(Color).B, EMin(TRGB(Color).B, $10));
Result := Color;
end;
var
RedrawRect, NameRect, ValueRect, CurRect: TRect;
FirstRow, LastRow, Y, RowIdx, CW, Offset: Integer;
NameColor: TColor;
DrawCurrent: Boolean;
begin
if FRowHeight < 1 then Exit;
FInplaceEdit.Move(GetEditRect);
with Canvas do
begin
RedrawRect := ClipRect;
FirstRow := RedrawRect.Top div FRowHeight;
LastRow := EMin(FPropCount - FTopRow - 1, (RedrawRect.Bottom - 1) div FRowHeight);
if LastRow + FTopRow = Pred(FCurrent) then Inc(LastRow); // Selection occupies 2 rows
{with RedrawRect do
Form1.p1.Caption := Format('%d, %d, %d, %d: %d-%d',
[Left, Top, Right, Bottom, FirstRow, LastRow]);}
NameRect := Bounds(0, FirstRow * FRowHeight, FVertLine, FRowHeight - 1);
ValueRect := NameRect;
ValueRect.Left := FVertLine + 2;
CW := ClientWidth;
ValueRect.Right := CW;
Brush.Color := Self.Color;
Pen.Color := GetPenColor(Self.Color);
Font := Self.Font;
NameColor := Font.Color;
DrawCurrent := False;
for Y := FirstRow to LastRow do
begin
RowIdx := Y + FTopRow;
Font.Color := NameColor;
if RowIdx = FCurrent then
begin
CurRect := Rect(0, NameRect.Top - 2, CW, NameRect.Bottom + 1);
DrawCurrent := True;
Inc(NameRect.Left); // Space for DrawEdge
DrawName(RowIdx, NameRect, 1);
Dec(NameRect.Left);
end
else
begin
if RowIdx <> Pred(FCurrent) then
begin
Offset := 0;
PolyLine([Point(0, NameRect.Bottom), Point(CW, NameRect.Bottom)]);
end
else
Offset := 1;
Dec(NameRect.Bottom, Offset);
DrawName(RowIdx, NameRect, 2);
Inc(NameRect.Bottom, Offset);
Font.Color := FPropColor;
{$IFDEF Delphi5}
FEditors[RowIdx].peEditor.PropDrawValue(Self.Canvas, ValueRect, False);
{$ELSE}
Dec(ValueRect.Bottom, Offset);
TextRect(ValueRect, ValueRect.Left + 1, ValueRect.Top + 1,
GetPrintableValue(RowIdx));
Inc(ValueRect.Bottom, Offset);
{$ENDIF}
end;
OffsetRect(NameRect, 0, FRowHeight);
OffsetRect(ValueRect, 0, FRowHeight);
end;
Dec(NameRect.Bottom, FRowHeight - 1);
NameRect.Right := CW;
ValueRect := Rect(FVertLine, RedrawRect.Top, 10, NameRect.Bottom - 1);
DrawEdge(Handle, ValueRect, EDGE_ETCHED, BF_LEFT);
if DrawCurrent then
begin
DrawEdge(Handle, CurRect, BDR_SUNKENOUTER, BF_LEFT + BF_BOTTOM + BF_RIGHT);
DrawEdge(Handle, CurRect, EDGE_SUNKEN, BF_TOP);
end;
if NameRect.Bottom < RedrawRect.Bottom then
begin
Brush.Color := Self.Color;
RedrawRect.Top := NameRect.Bottom;
FillRect(RedrawRect);
end;
end;
end;
procedure TZPropList.WMGetDlgCode(var Msg: TWMGetDlgCode);
begin
Msg.Result := DLGC_WANTARROWS;
end;
procedure TZPropList.KeyDown(var Key: Word; Shift: TShiftState);
var
PageHeight, NewCurrent: Integer;
begin
inherited KeyDown(Key, Shift);
NewCurrent := FCurrent;
PageHeight := VisibleRowCount - 1;
case Key of
VK_UP: Dec(NewCurrent);
VK_DOWN: Inc(NewCurrent);
VK_NEXT: Inc(NewCurrent, PageHeight);
VK_PRIOR: Dec(NewCurrent, PageHeight);
else Exit;
end;
MoveCurrent(NewCurrent);
end;
procedure TZPropList.InvalidateSelection;
var
R: TRect;
RowStart: Integer;
begin
RowStart := (FCurrent - FTopRow) * FRowHeight;
R := Rect(0, RowStart - 2, ClientWidth, RowStart + FRowHeight + 1);
InvalidateRect(Handle, @R, True);
end;
function TZPropList.MoveCurrent(NewCur: Integer): Boolean;
var
NewTop, VertCount: Integer;
begin
Result := UpdateText(True);
if not Result then Exit;
if NewCur < 0 then NewCur := 0;
if NewCur >= FPropCount then NewCur := FPropCount - 1;
if NewCur = FCurrent then Exit;
InvalidateSelection;
FCurrent := NewCur;
InvalidateSelection;
NewTop := FTopRow;
VertCount := VisibleRowCount;
if NewCur < NewTop then NewTop := NewCur;
if NewCur >= NewTop + VertCount then NewTop := NewCur - VertCount + 1;
FInplaceEdit.Move(GetEditRect);
UpdateEditor(True);
MoveTop(NewTop);
end;
procedure TZPropList.MarkModified;
begin
FModified := True;
end;
procedure TZPropList.ClearModified;
begin
FModified := False;
end;
procedure TZPropList.Synchronize;
begin
MarkModified;
Invalidate;
UpdateEditor(False);
end;
procedure TZPropList.UpdateEditor(CallActivate: Boolean);
var
Attr: TPropertyAttributes;
begin
if Assigned(FInplaceEdit) and (FCurrent >= 0) then
with FInplaceEdit, Editor do
begin
if CallActivate then Activate;
MaxLength := GetEditLimit;
Attr := GetAttributes;
ReadOnly := paReadOnly in Attr;
FAutoUpdate := paAutoUpdate in Attr;
Text := GetPrintableValue(FCurrent);
SelectAll;
Modified := False;
end;
end;
function TZPropList.UpdateText(Exiting: Boolean): Boolean;
begin
Result := True;
if not FInUpdate and Assigned(FInplaceEdit) and
(FCurrent >= 0) and (FInplaceEdit.Modified) then
begin
FInUpdate := True;
try
SetValue(FCurrent, FInplaceEdit.Text);
except
Result := False;
FTracking := False;
Application.ShowException(Exception(ExceptObject));
end;
if Exiting then UpdateEditor(False);
Invalidate; // repaint all dependent properties
FInUpdate := False;
end;
end;
procedure TZPropList.WMNCHitTest(var Msg: TWMNCHitTest);
begin
inherited;
FHitTest := ScreenToClient(SmallPointToPoint(Msg.Pos));
end;
function TZPropList.VertLineHit(X: Integer): Boolean;
begin
Result := Abs(X - FVertLine) < 3;
end;
function TZPropList.ButtonHit(X: Integer): Boolean;
begin
// whether we hit collapse/expand button next to property with subproperties
if FCurrent >= 0 then
begin
Dec(X, FEditors[FCurrent].peIdent * 10);
Result := (X > 0) and (X < 12);
end
else
Result := False;
end;
procedure TZPropList.SetBorderStyle(Value: TBorderStyle);
begin
if FBorderStyle <> Value then
begin
FBorderStyle := Value;
RecreateWnd;
end;
end;
procedure TZPropList.WMSetCursor(var Msg: TWMSetCursor);
var
Cur: HCURSOR;
begin
Cur := 0;
if (Msg.HitTest = HTCLIENT) and VertLineHit(FHitTest.X) then
Cur := Screen.Cursors[crHSplit];
if Cur <> 0 then SetCursor(Cur) else inherited;
end;
procedure TZPropList.CMDesignHitTest(var Msg: TCMDesignHitTest);
begin
Msg.Result := Integer(FDividerHit or VertLineHit(Msg.XPos));
end;
function TZPropList.YToRow(Y: Integer): Integer;
begin
Result := FTopRow + Y div FRowHeight;
end;
procedure TZPropList.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
if not (csDesigning in ComponentState) and
(CanFocus or (GetParentForm(Self) = nil)) then SetFocus;
if ssDouble in Shift then DblClick
else
begin
FDividerHit := VertLineHit(X) and (Button = mbLeft);
if not FDividerHit and (Button = mbLeft) then
begin
if not MoveCurrent(YToRow(Y)) then Exit;
if FNewButtons and ButtonHit(X) then NodeClicked
else
begin
FTracking := True;
FInplaceEdit.FClickTime := GetMessageTime;
end;
end;
end;
inherited;
end;
procedure TZPropList.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
if FDividerHit then SizeColumn(X)
else
if FTracking and (ssLeft in Shift) then MoveCurrent(YToRow(Y));
inherited;
end;
procedure TZPropList.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
FDividerHit := False;
FTracking := False;
inherited;
end;
function TZPropList.ColumnSized(X: Integer): Boolean;
var
NewSizingPos: Integer;
begin
NewSizingPos := EMax(MINCOLSIZE, EMin(X, ClientWidth - MINCOLSIZE));
Result := NewSizingPos <> FVertLine;
FVertLine := NewSizingPos
end;
procedure TZPropList.SizeColumn(X: Integer);
begin
if ColumnSized(X) then
begin
Invalidate;
FInplaceEdit.UpdateLoc(GetEditRect);
end;
end;
procedure TZPropList.CMCancelMode(var Msg: TMessage);
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -