📄 jvnetscapesplitter.pas
字号:
end;
procedure TJvCustomNetscapeSplitter.SetButtonCursor(const Value: TCursor);
begin
FButtonCursor := Value;
end;
procedure TJvCustomNetscapeSplitter.SetButtonHighlightColor(const Value: TColor);
begin
if FButtonHighlightColor <> Value then
begin
FButtonHighlightColor := Value;
if (ButtonStyle = bsNetscape) and ShowButton then
Invalidate;
end;
end;
procedure TJvCustomNetscapeSplitter.SetButtonStyle(const Value: TJvButtonStyle);
begin
FButtonStyle := Value;
if ShowButton then
Invalidate;
end;
procedure TJvCustomNetscapeSplitter.SetButtonWidth(const Value: Integer);
begin
if Value <> FButtonWidth then
begin
FButtonWidth := Value;
if (ButtonWidthKind = btwPercentage) and (FButtonWidth > 100) then
FButtonWidth := 100;
if FButtonWidth < 0 then
FButtonWidth := 0;
if (ButtonStyle = bsNetscape) and ShowButton then
Invalidate;
end;
end;
procedure TJvCustomNetscapeSplitter.SetButtonWidthKind(const Value: TJvButtonWidthKind);
begin
if Value <> FButtonWidthKind then
begin
FButtonWidthKind := Value;
if (FButtonWidthKind = btwPercentage) and (ButtonWidth > 100) then
FButtonWidth := 100;
if (ButtonStyle = bsNetscape) and ShowButton then
Invalidate;
end;
end;
procedure TJvCustomNetscapeSplitter.SetMaximized(const Value: Boolean);
begin
if Value <> FMaximized then
begin
if csLoading in ComponentState then
begin
FMaximized := Value;
Exit;
end;
FindControl;
if FControl = nil then
Exit;
if Value then
begin
if FMinimized then
FMinimized := False
else
begin
case Align of
alLeft, alRight:
FRestorePos := FControl.Width;
alTop, alBottom:
FRestorePos := FControl.Height;
else
Exit;
end;
end;
if ButtonStyle = bsNetscape then
UpdateControlSize(-3000)
else
case Align of
alLeft, alBottom:
UpdateControlSize(3000);
alRight, alTop:
UpdateControlSize(-3000);
else
Exit;
end;
FMaximized := Value;
DoMaximize;
end
else
begin
UpdateControlSize(FRestorePos);
FMaximized := Value;
DoRestore;
end;
end;
end;
procedure TJvCustomNetscapeSplitter.SetMinimized(const Value: Boolean);
begin
if Value <> FMinimized then
begin
if csLoading in ComponentState then
begin
FMinimized := Value;
Exit;
end;
FindControl;
if FControl = nil then
Exit;
if Value then
begin
if FMaximized then
FMaximized := False
else
begin
case Align of
alLeft, alRight:
FRestorePos := FControl.Width;
alTop, alBottom:
FRestorePos := FControl.Height;
else
Exit;
end;
end;
FMinimized := Value;
// Just use something insanely large to get it to move to the other extreme
case Align of
alLeft, alBottom:
UpdateControlSize(-3000);
alRight, alTop:
UpdateControlSize(3000);
else
Exit;
end;
DoMinimize;
end
else
begin
FMinimized := Value;
UpdateControlSize(FRestorePos);
DoRestore;
end;
end;
end;
procedure TJvCustomNetscapeSplitter.SetShowButton(const Value: Boolean);
begin
if Value <> FShowButton then
begin
FShowButton := Value;
SetRectEmpty(FLastKnownButtonRect);
Invalidate;
end;
end;
procedure TJvCustomNetscapeSplitter.SetTextureColor1(const Value: TColor);
begin
if FTextureColor1 <> Value then
begin
FTextureColor1 := Value;
if (ButtonStyle = bsNetscape) and ShowButton then
Invalidate;
end;
end;
procedure TJvCustomNetscapeSplitter.SetTextureColor2(const Value: TColor);
begin
if FTextureColor2 <> Value then
begin
FTextureColor2 := Value;
if (ButtonStyle = bsNetscape) and ShowButton then
Invalidate;
end;
end;
procedure TJvCustomNetscapeSplitter.SetWindowsButtons(const Value: TJvWindowsButtons);
begin
FWindowsButtons := Value;
if (ButtonStyle = bsWindows) and ShowButton then
Invalidate;
end;
procedure TJvCustomNetscapeSplitter.StoreOtherProperties(Writer: TWriter);
begin
Writer.WriteInteger(RestorePos);
end;
procedure TJvCustomNetscapeSplitter.UpdateControlSize(NewSize: Integer);
procedure MoveViaMouse(FromPos, ToPos: Integer; Horizontal: Boolean);
begin
if Horizontal then
begin
MouseDown(mbLeft, [ssLeft], FromPos, 0);
MouseMove([ssLeft], ToPos, 0);
MouseUp(mbLeft, [ssLeft], ToPos, 0);
end
else
begin
MouseDown(mbLeft, [ssLeft], 0, FromPos);
MouseMove([ssLeft], 0, ToPos);
MouseUp(mbLeft, [ssLeft], 0, ToPos);
end;
end;
begin
if FControl <> nil then
begin
{ You'd think that using FControl directly would be the way to change it's
position (and thus the splitter's position), wouldn't you? But, TSplitter
has this nutty idea that the only way a control's size will change is if
the mouse moves the splitter. If you size the control manually, the
splitter has an internal variable (FOldSize) that will not get updated.
Because of this, if you try to then move the newly positioned splitter
back to the old position, it won't go there (NewSize <> OldSize must be
True). Now, what are the odds that the user will move the splitter back
to the exact same pixel it used to be on? Normally, extremely low. But,
if the splitter has been restored from it's minimized position, it then
becomes quite likely: i.e. they drag it back all the way to the min
position. What a pain. }
case Align of
alLeft:
MoveViaMouse(Left, FControl.Left + NewSize, True);
// alLeft: FControl.Width := NewSize;
alTop:
MoveViaMouse(Top, FControl.Top + NewSize, False);
// FControl.Height := NewSize;
alRight:
MoveViaMouse(Left, (FControl.Left + FControl.Width - Width) - NewSize, True);
{begin
Parent.DisableAlign;
try
FControl.Left := FControl.Left + (FControl.Width - NewSize);
FControl.Width := NewSize;
finally
Parent.EnableAlign;
end;
end;}
alBottom:
MoveViaMouse(Top, (FControl.Top + FControl.Height - Height) - NewSize, False);
{begin
Parent.DisableAlign;
try
FControl.Top := FControl.Top + (FControl.Height - NewSize);
FControl.Height := NewSize;
finally
Parent.EnableAlign;
end;
end;}
end;
Update;
end;
end;
function TJvCustomNetscapeSplitter.VisibleWinButtons: Integer;
var
X: TJvWindowsButton;
begin
Result := 0;
for X := Low(TJvWindowsButton) to High(TJvWindowsButton) do
if X in WindowsButtons then
Inc(Result);
end;
function TJvCustomNetscapeSplitter.WindowButtonHitTest(X, Y: Integer): TJvWindowsButton;
var
BtnRect: TRect;
I: Integer;
B: TJvWindowsButton;
WinButton: array [0..2] of TJvWindowsButton;
BW: Integer;
BRs: array [0..2] of TRect;
begin
Result := wbMin;
// Figure out which one was hit. This function assumes ButtonHitTest has
// been called and returned True.
BtnRect := ButtonRect; // So we don't repeatedly call GetButtonRect
I := 0;
if Align in [alLeft, alRight] then
begin
for B := High(TJvWindowsButton) downto Low(TJvWindowsButton) do
if B in WindowsButtons then
begin
WinButton[I] := B;
Inc(I);
end;
end
else
for B := Low(TJvWindowsButton) to High(TJvWindowsButton) do
if B in WindowsButtons then
begin
WinButton[I] := B;
Inc(I);
end;
if Align in [alLeft, alRight] then
BW := BtnRect.Right - BtnRect.Left
else
BW := BtnRect.Bottom - BtnRect.Top;
FillChar(BRs, SizeOf(BRs), 0);
for I := 0 to VisibleWinButtons - 1 do
if ((Align in [alLeft, alRight]) and PtInRect(Bounds(BtnRect.Left,
BtnRect.Top + (BW * I), BW, BW), Point(X, Y))) or ((Align in [alTop,
alBottom]) and PtInRect(Bounds(BtnRect.Left + (BW * I), BtnRect.Top, BW,
BW), Point(X, Y))) then
begin
Result := WinButton[I];
break;
end;
end;
procedure TJvCustomNetscapeSplitter.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
inherited SetBounds(ALeft, ATop, AWidth, AHeight);
if FRestorePos < 0 then
begin
FindControl;
if FControl <> nil then
case Align of
alLeft, alRight:
FRestorePos := FControl.Width;
alTop, alBottom:
FRestorePos := FControl.Height;
end;
end;
end;
{$IFDEF VCL}
procedure TJvCustomNetscapeSplitter.WMLButtonDown(var Msg: TWMLButtonDown);
begin
if Enabled then
begin
FGotMouseDown := ButtonHitTest(Msg.XPos, Msg.YPos);
if FGotMouseDown then
begin
FindControl;
FDownPos := ClientToScreen(Point(Msg.XPos, Msg.YPos));
end;
end;
if AllowDrag then
inherited // Let TSplitter have it.
else
// Bypass TSplitter and just let normal handling occur. Prevents drag painting.
DefaultHandler(Msg);
end;
procedure TJvCustomNetscapeSplitter.WMLButtonUp(var Msg: TWMLButtonUp);
var
CurPos: TPoint;
OldMax: Boolean;
begin
inherited;
if FGotMouseDown then
begin
if ButtonHitTest(Msg.XPos, Msg.YPos) then
begin
CurPos := ClientToScreen(Point(Msg.XPos, Msg.YPos));
// More than a little movement is not a click, but a regular resize.
if ((Align in [alLeft, alRight]) and
(Abs(FDownPos.X - CurPos.X) <= MOVEMENT_TOLERANCE)) or
((Align in [alTop, alBottom]) and
(Abs(FDownPos.Y - CurPos.Y) <= MOVEMENT_TOLERANCE)) then
begin
StopSizing;
if ButtonStyle = bsNetscape then
Maximized := not Maximized
else
case WindowButtonHitTest(Msg.XPos, Msg.YPos) of
wbMin:
Minimized := not Minimized;
wbMax:
Maximized := not Maximized;
wbClose:
DoClose;
end;
end;
end;
FGotMouseDown := False;
end
else
if AllowDrag then
begin
FindControl;
if FControl = nil then
Exit;
OldMax := FMaximized;
case Align of
alLeft, alRight:
FMaximized := FControl.Width <= MinSize;
alTop, alBottom:
FMaximized := FControl.Height <= MinSize;
end;
if FMaximized then
begin
UpdateControlSize(MinSize);
if not OldMax then
DoMaximize;
end
else
begin
case Align of
alLeft, alRight:
FRestorePos := FControl.Width;
alTop, alBottom:
FRestorePos := FControl.Height;
end;
if OldMax then
DoRestore;
end;
end;
Invalidate;
end;
procedure TJvCustomNetscapeSplitter.WMMouseMove(var Msg: TWMMouseMove);
begin
if AllowDrag then
begin
inherited;
// The order is important here. ButtonHitTest must be evaluated before
// the ButtonStyle because it will change the cursor (over button or not).
// If the order were reversed, the cursor would not get set for bsWindows
// style since short-circuit Boolean eval would stop it from ever being
// called in the first place.
if ButtonHitTest(Msg.XPos, Msg.YPos) and (ButtonStyle = bsNetscape) then
begin
if not FIsHighlighted then
PaintButton(True)
end
else
if FIsHighlighted then
PaintButton(False);
end
else
DefaultHandler(Msg); // Bypass TSplitter and just let normal handling occur.
end;
{$ENDIF VCL}
{$IFDEF UNITVERSIONING}
initialization
RegisterUnitVersion(HInstance, UnitVersioning);
finalization
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -