📄 bsbuttongroup.pas
字号:
end;
procedure TbsSkinButtonGroup.DoStartDrag(var DragObject: TDragObject);
var
ButtonRect: TRect;
State: TbsButtonDrawState;
DragImage: TBitmap;
begin
inherited DoStartDrag(DragObject);
if FDragIndex <> -1 then
begin
DragImage := TBitmap.Create;
try
ButtonRect := GetButtonRect(FDragIndex);
DragImage.Width := ButtonRect.Right - ButtonRect.Left;
DragImage.Height := ButtonRect.Bottom - ButtonRect.Top;
State := [bsbdsDragged];
if FItemIndex = FDragIndex then
State := State + [bsbdsSelected];
DrawButton(FDragIndex, DragImage.Canvas,
Rect(0, 0, DragImage.Width, DragImage.Height), State);
FDragImageList.Clear;
FDragImageList.Width := DragImage.Width;
FDragImageList.Height := DragImage.Height;
FDragImageList.Add(DragImage, nil);
{ with FDragImageList.DragHotspot do
begin
X := FDragStartPos.X - ButtonRect.Left - Mouse.DragThreshold;
Y := FDragStartPos.Y - ButtonRect.Top - Mouse.DragThreshold;
end;}
finally
DragImage.Free;
end;
end
else
FDragImageList.Clear; { No drag image }
end;
function TbsSkinButtonGroup.GetDragImages: TDragImageList;
begin
Result := FDragImageList;
end;
procedure TbsSkinButtonGroup.RemoveInsertionPoints;
procedure ClearSelection(var Index: Integer);
var
OldIndex: Integer;
begin
if Index <> -1 then
begin
OldIndex := Index;
Index := -1;
UpdateButton(OldIndex);
end;
end;
begin
ClearSelection(FInsertTop);
ClearSelection(FInsertLeft);
ClearSelection(FInsertRight);
ClearSelection(FInsertBottom);
end;
procedure TbsSkinButtonGroup.DoReorderButton(const OldIndex, NewIndex: Integer);
var
OldIndexID: Integer;
begin
FIgnoreUpdate := True;
try
if FItemIndex <> -1 then
OldIndexID := Items[FItemIndex].ID
else
OldIndexID := -1;
FButtonItems.Items[OldIndex].Index := NewIndex;
if OldIndexID <> -1 then
FItemIndex := Items.FindItemID(OldIndexID).Index;
finally
FIgnoreUpdate := False;
end;
Invalidate;
if Assigned(FOnReorderButton) then
FOnReorderButton(Self, OldIndex, NewIndex);
end;
procedure TbsSkinButtonGroup.AutoScroll(ScrollCode: TScrollCode);
function ShouldContinue(out Delay: Integer): Boolean;
const
cMaxDelay = 500;
begin
{ Are we autoscrolling up or down? }
if ScrollCode = scLineDown then
begin
Result := FHiddenItems < FScrollBarMax;
if Result then
begin
{ Is the mouse still in position? }
with ScreenToClient(Mouse.CursorPos) do
begin
if (X < 0) or (X > Width) or
(Y > Height) or (Y < Height - cScrollBuffer) then
Result := False
else if Y < (Height - cScrollBuffer div 2) then
Delay := cMaxDelay
else
Delay := cMaxDelay div 2; { A little faster }
end
end;
end
else
begin
Result := FHiddenItems > 0;
if Result then
begin
with ScreenToClient(Mouse.CursorPos) do
if (X < 0) or (X > Width) or
(Y < 0) or (Y > cScrollBuffer) then
Result := False
else if Y > (cScrollBuffer div 2) then
Delay := cMaxDelay
else
Delay := cMaxDelay div 2;
end;
end;
end;
var
CurrentTime, StartTime, ElapsedTime: Longint;
Delay: Integer;
begin
FDragImageList.HideDragImage;
RemoveInsertionPoints;
FDragImageList.ShowDragImage;
CurrentTime := 0;
while (ShouldContinue(Delay)) do
begin
StartTime := GetCurrentTime;
ElapsedTime := StartTime - CurrentTime;
if ElapsedTime < Delay then
Sleep(Delay - ElapsedTime);
CurrentTime := StartTime;
FDragImageList.HideDragImage;
ScrollPosChanged(ScrollCode, 0{ Ignored});
UpdateWindow(Handle);
FDragImageList.ShowDragImage;
end;
end;
function TbsSkinButtonGroup.TargetIndexAt(const X, Y: Integer): Integer;
var
ButtonRect: TRect;
LastRect: TRect;
begin
Result := IndexOfButtonAt(X, Y);
if Result = -1 then
begin
LastRect := GetButtonRect(Items.Count);
if (Y >= LastRect.Bottom) then
Result := Items.Count
else if (Y >= LastRect.Top) then
if (bsgboFullSize in FButtonOptions) or (X >= LastRect.Left) then
Result := Items.Count; { After the last item }
end;
if (Result > -1) and (Result < Items.Count) then
begin
{ Before the index, or after it? }
ButtonRect := GetButtonRect(Result);
if CalcButtonsPerRow = 1 then
begin
if Y > (ButtonRect.Top + (ButtonRect.Bottom - ButtonRect.Top) div 2) then
Inc(Result); { Insert above the item below it (after the index) }
end
else
if X > (ButtonRect.Left + (ButtonRect.Right - ButtonRect.Left) div 2) then
Inc(Result)
end;
end;
procedure TbsSkinButtonGroup.DoMouseLeave;
begin
if Assigned(FOnMouseLeave) then
FOnMouseLeave(Self);
end;
procedure TbsSkinButtonGroup.CNKeydown(var Message: TWMKeyDown);
var
IncAmount: Integer;
procedure FixIncAmount(const StartValue: Integer);
begin
{ Keep it within the bounds }
if StartValue + IncAmount >= FButtonItems.Count then
IncAmount := FButtonItems.Count - StartValue - 1
else if StartValue + IncAmount < 0 then
IncAmount := 0 - StartValue;
end;
var
NewIndex: Integer;
begin
IncAmount := 0;
if Message.CharCode = VK_DOWN then
IncAmount := CalcButtonsPerRow
else if Message.CharCode = VK_UP then
IncAmount := -1*CalcButtonsPerRow
else if Message.CharCode = VK_LEFT then
IncAmount := -1
else if Message.CharCode = VK_RIGHT then
IncAmount := 1
else if Message.CharCode = VK_NEXT then
IncAmount := CalcRowsSeen
else if Message.CharCode = VK_PRIOR then
IncAmount := -1*CalcRowsSeen
else if Message.CharCode = VK_HOME then
begin
if bsgboGroupStyle in ButtonOptions then
IncAmount := -1*FItemIndex
else
IncAmount := -1*FFocusIndex;
end
else if Message.CharCode = VK_END then
begin
if bsgboGroupStyle in ButtonOptions then
IncAmount := FButtonItems.Count - FItemIndex
else
IncAmount := FButtonItems.Count - FFocusIndex;
end
else if (Message.CharCode = VK_RETURN) or (Message.CharCode = VK_SPACE) then
begin
if (bsgboGroupStyle in ButtonOptions) and (FItemIndex <> -1) then
DoItemClicked(FItemIndex) { Click the current item index }
else if (bsgboGroupStyle in ButtonOptions) and
(FFocusIndex >= 0) and (FFocusIndex < FButtonItems.Count) then
DoItemClicked(FFocusIndex) { Click the focused index }
else
inherited;
end
else
inherited;
if IncAmount <> 0 then
begin
if bsgboGroupStyle in ButtonOptions then
FixIncAmount(FItemIndex)
else
FixIncAmount(FFocusIndex);
if IncAmount <> 0 then
begin
{ Do the actual scrolling work }
if bsgboGroupStyle in ButtonOptions then
begin
NewIndex := ItemIndex + IncAmount;
ScrollIntoView(NewIndex);
ItemIndex := NewIndex;
end
else
begin
NewIndex := FFocusIndex+ IncAmount;
ScrollIntoView(NewIndex);
UpdateButton(FFocusIndex);
FFocusIndex := NewIndex;
UpdateButton(FFocusIndex);
end;
end;
end;
end;
procedure TbsSkinButtonGroup.WMKillFocus(var Message: TWMKillFocus);
begin
inherited;
UpdateButton(FFocusIndex)
end;
procedure TbsSkinButtonGroup.WMSetFocus(var Message: TWMSetFocus);
begin
inherited;
if (FFocusIndex = -1) and (FButtonItems.Count > 0) then
FFocusIndex := 0; { Focus the first item }
UpdateButton(FFocusIndex)
end;
procedure TbsSkinButtonGroup.ScrollIntoView(const Index: Integer);
var
RowsSeen, ButtonsPerRow, HiddenCount, VisibleCount: Integer;
begin
if (Index >= 0) and (Index < FButtonItems.Count) then
begin
ButtonsPerRow := CalcButtonsPerRow;
HiddenCount := FHiddenItems*ButtonsPerRow;
if Index < HiddenCount then
begin
{ We have to scroll above to get the item insight }
while (Index <= HiddenCount) and (FHiddenItems > 0) do
begin
ScrollPosChanged(scLineUp, 0);
HiddenCount := FHiddenItems*ButtonsPerRow;
end;
end
else
begin
RowsSeen := CalcRowsSeen;
VisibleCount := RowsSeen*ButtonsPerRow;
{ Do we have to scroll down to see the item? }
while Index >= (HiddenCount + VisibleCount) do
begin
ScrollPosChanged(scLineDown, 0);
HiddenCount := FHiddenItems*ButtonsPerRow;
end;
end;
end;
end;
procedure TbsSkinButtonGroup.CMHintShow(var Message: TCMHintShow);
var
ItemIndex: Integer;
begin
Message.Result := 1; { Don't show the hint }
if Message.HintInfo.HintControl = Self then
begin
ItemIndex := IndexOfButtonAt(Message.HintInfo.CursorPos.X, Message.HintInfo.CursorPos.Y);
if (ItemIndex >= 0) and (ItemIndex < Items.Count) then
begin
{ Only show the hint if the item's text is truncated }
if Items[ItemIndex].Hint <> '' then
Message.HintInfo.HintStr := Items[ItemIndex].Hint
else
begin
// corbin - finish..
// Canvas.TextRect(TextRect, Items[ItemIndex].Caption, [tfEndEllipsis]);
Message.HintInfo.HintStr := Items[ItemIndex].Caption;
end;
if (Items[ItemIndex].ActionLink <> nil) then
Items[ItemIndex].ActionLink.DoShowHint(Message.HintInfo.HintStr);
Message.HintInfo.CursorRect := GetButtonRect(ItemIndex);
Message.Result := 0; { Show the hint }
end;
end;
end;
procedure TbsSkinButtonGroup.Assign(Source: TPersistent);
begin
if Source is TbsSkinButtonGroup then
begin
Items := TbsSkinButtonGroup(Source).Items;
ButtonHeight := TbsSkinButtonGroup(Source).ButtonHeight;
ButtonWidth := TbsSkinButtonGroup(Source).ButtonWidth;
ButtonOptions := TbsSkinButtonGroup(Source).ButtonOptions;
end
else
inherited;
end;
procedure TbsSkinButtonGroup.SetInsertionPoints(const InsertionIndex: Integer);
begin
if FInsertTop <> InsertionIndex then
begin
RemoveInsertionPoints;
if CalcButtonsPerRow = 1 then
begin
FInsertTop := InsertionIndex;
FInsertBottom := InsertionIndex - 1;
end
else
begin
{ More than one button per row, so use Left/Right separators }
FInsertLeft := InsertionIndex;
FInsertRight := InsertionIndex - 1;
end;
UpdateButton(FInsertTop);
UpdateButton(FInsertLeft);
UpdateButton(FInsertBottom);
UpdateButton(FInsertRight);
UpdateWindow(Handle);
end;
end;
procedure TbsSkinButtonGroup.DoEndDrag(Target: TObject; X, Y: Integer);
begin
inherited;
FDragIndex := -1;
RemoveInsertionPoints;
end;
procedure TbsSkinButtonGroup.SetDragIndex(const Value: Integer);
begin
FDragIndex := Value;
FDragStarted := True;
end;
function TbsSkinButtonGroup.DoMouseWheelDown(Shift: TShiftState;
MousePos: TPoint): Boolean;
begin
Result := inherited DoMouseWheelDown(Shift, MousePos);
if not Result then
begin
UpdateButton(FHotIndex);
FHotIndex := -1;
Result := True;
if (FScrollBarMax > 0) and (Shift = []) then
ScrollPosChanged(scLineDown, 0)
else if (FScrollBarMax > 0) and (ssCtrl in Shift) then
ScrollPosChanged(scPageDown, 0)
{ else if ssShift in Shift then
begin
NextButton := GetNextButton(SelectedItem, True);
if NextButton <> nil then
SelectedItem := NextButton;
end;
}
end;
end;
function TbsSkinButtonGroup.DoMouseWheelUp(Shift: TShiftState;
MousePos: TPoint): Boolean;
begin
Result := inherited DoMouseWheelUp(Shift, MousePos);
if not Result then
begin
UpdateButton(FHotIndex);
FHotIndex := -1;
Result := True;
if (FScrollBarMax > 0) and (Shift = []) then
ScrollPosChanged(scLineUp, 0)
else if (FScrollBarMax > 0) and (ssCtrl in Shift) then
ScrollPosChanged(scPageUp, 0)
{ else if ssShift in Shift then
begin
NextButton := GetNextButton(Selecte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -