📄 spcategorybuttons.pas
字号:
GetObject(Canvas.Font.Handle, SizeOf(F), @F);
F.lfEscapement := round(0);
Buffer.Canvas.Font.Handle := CreateFontIndirect(F);
end;
if (spboBoldCaptions in ButtonOptions) then
Buffer.Canvas.Font.Style := Canvas.Font.Style - [fsBold];
if not Category.Collapsed then
begin
{ Draw the buttons }
if (FButtonFlow = bscbfVertical) and (spboFullSize in ButtonOptions) then
ActualWidth := ClientWidth - FSideBufferSize - GetScrollSize - 5
else
ActualWidth := FButtonWidth;
ButtonStart := ButtonBounds.Left;
ButtonTop := ButtonBounds.Top;
ButtonLeft := ButtonStart;
for I := 0 to Category.Items.Count - 1 do
begin
{ Don't waste time painting clipped things }
if (FButtonFlow = bscbfVertical) and (ButtonTop > ClientHeight) then
Break; { Done drawing }
{ Don't waste time drawing what is offscreen }
ButtonBottom := ButtonTop + FButtonHeight;
ButtonRight := ButtonLeft + ActualWidth;
if (ButtonBottom >= 0) and (ButtonRight >= 0) then
begin
ButtonRect := Rect(ButtonLeft, ButtonTop, ButtonRight, ButtonBottom);
Button := Category.Items[I];
DrawState := [];
if Button = FHotButton then
begin
Include(DrawState, spbdsHot);
if Button = FDownButton then
Include(DrawState, spbdsDown);
end;
if Button = FSelectedItem then
Include(DrawState, spbdsSelected)
else if (Button = FFocusedItem) and Focused and (FDownButton = nil) then
Include(DrawState, spbdsFocused);
if Button = FInsertTop then
Include(DrawState, spbdsInsertTop)
else if Button = FInsertBottom then
Include(DrawState, spbdsInsertBottom)
else if Button = FInsertRight then
Include(DrawState, spbdsInsertRight)
else if Button = FInsertLeft then
Include(DrawState, spbdsInsertLeft);
BR := ButtonRect;
OffsetRect(BR, -CategoryRealBounds.Left, -CategoryRealBounds.Top);
DrawButton(Button, Buffer.Canvas, BR, DrawState);
end;
Inc(ButtonLeft, ActualWidth);
if (ButtonLeft + ActualWidth) > ButtonBounds.Right then
begin
ButtonLeft := ButtonStart;
Inc(ButtonTop, FButtonHeight);
end;
end;
end;
Canvas.Draw(CategoryRealBounds.Left, CategoryRealBounds.Top, Buffer);
Buffer.Free;
end;
procedure TspSkinCategoryButtons.Paint;
procedure DrawSkinBGRect(R: TRect);
var
PanelData: TspDataSkinPanelControl;
w, h, X, Y, XCnt, YCnt: Integer;
Buffer, Buffer2: TBitMap;
FSkinPicture: TBitMap;
begin
if (RectWidth(R) <= 0) or (RectHeight(R) <= 0) then Exit;
PanelData := TspDataSkinPanelControl(SkinData.CtrlList[SkinData.GetControlIndex('panel')]);
Buffer := TBitMap.Create;
with PanelData do
begin
FSkinPicture := TBitMap(SkinData.FActivePictures.Items[PictureIndex]);
Buffer.Width := RectWidth(ClRect);
Buffer.Height := RectHeight(ClRect);
Buffer.Canvas.CopyRect(Rect(0, 0, Buffer.Width, Buffer.Height),
FSkinPicture.Canvas,
Rect(SkinRect.Left + ClRect.Left, SkinRect.Top + ClRect.Top,
SkinRect.Left + ClRect.Right,
SkinRect.Top + ClRect.Bottom));
w := RectWidth(ClRect);
h := RectHeight(ClRect);
XCnt := RectWidth(R) div w;
YCnt := RectHeight(R) div h;
if StretchEffect
then
begin
case StretchType of
spstFull:
Canvas.StretchDraw(R, Buffer);
spstHorz:
begin
Buffer2 := TBitMap.Create;
Buffer2.Width := Buffer.Width;
Buffer2.Height := RectHeight(R);
Buffer2.Canvas.StretchDraw(Rect(0, 0, Buffer2.Width, Buffer2.Height), Buffer);
XCnt := Width div Buffer2.Width;
for X := 0 to XCnt do
Canvas.Draw(R.Left + X * Buffer2.Width, R.Top, Buffer2);
Buffer2.Free;
end;
spstVert:
begin
Buffer2 := TBitMap.Create;
Buffer2.Width := RectWidth(R);
Buffer2.Height := Buffer.Height;
Buffer2.Canvas.StretchDraw(Rect(0, 0, Buffer2.Width, Buffer2.Height), Buffer);
YCnt := RectHeight(R) div Buffer2.Height;
for Y := 0 to YCnt do
Canvas.Draw(R.Left, R.Top + Y * Buffer2.Height, Buffer2);
Buffer2.Free;
end;
end;
end
else
for X := 0 to XCnt do
for Y := 0 to YCnt do
Canvas.Draw(X * w + R.Left, Y * h + R.Top, Buffer);
end;
Buffer.Free;
end;
var
TopCategory: Integer;
CatIndex: Integer;
StartingPos: Integer;
EndingPos: Integer;
Category: TspButtonCategory;
DrawRect: TRect;
begin
StartingPos := 0;
TopCategory := GetIndexOfFirstCategory;
if (TopCategory > -1) and (TopCategory < FButtonCategories.Count) then
begin
{ Calculate the virtual position and ending position }
StartingPos := FButtonCategories[TopCategory].FStart - GetScrollOffset;
if FButtonFlow = bscbfVertical then
EndingPos := ClientHeight
else
EndingPos := ClientWidth;
for CatIndex := TopCategory to FButtonCategories.Count - 1 do
begin
Category := FButtonCategories[CatIndex];
DrawCategory(Category, Canvas, StartingPos);
StartingPos := StartingPos + Category.FEnd - Category.FStart;
{ Stop drawing early, if we can }
if StartingPos > EndingPos then
Break;
end;
end;
//
Canvas.Brush.Color := clBtnFace;
//
if (FButtonFlow = bscbfVertical) and
(StartingPos < ClientHeight)
then
begin
DrawRect := Rect(0, StartingPos, ClientWidth,
ClientHeight);
if (SkinData <> nil) and (not Skindata.Empty) and
(SkinData.GetControlIndex('panel') <> -1)
then
DrawSkinBGRect(DrawRect)
else
Canvas.FillRect(DrawRect);
end
else
if (FButtonFlow = bscbfHorizontal) and
(StartingPos < ClientWidth)
then
begin
DrawRect := Rect(StartingPos, 0, ClientWidth,
ClientHeight);
if (SkinData <> nil) and (not Skindata.Empty) and
(SkinData.GetControlIndex('panel') <> -1)
then
DrawSkinBGRect(DrawRect)
else
Canvas.FillRect(DrawRect);
end
end;
function TspSkinCategoryButtons.CalcButtonsPerRow: Integer;
begin
if spboFullSize in ButtonOptions
then
Result := 1
else
begin
Result := (ClientWidth - GetScrollSize - FSideBufferSize - 1) div FButtonWidth;
if Result * FButtonWidth > ClientWidth - GetScrollSize - FSideBufferSize - 1
then
Dec(Result)
else
if (Result + 1) * FButtonWidth < ClientWidth - GetScrollSize - FSideBufferSize - 1
then
Inc(Result);
if Result <= 0 then Result := 1;
end;
end;
function TspSkinCategoryButtons.CalcButtonsPerCol: Integer;
begin
Result := (ClientHeight - FSideBufferSize - GetScrollSize - 1) div FButtonHeight;
if Result * FButtonHeight > ClientHeight - FSideBufferSize - GetScrollSize
then
Dec(Result)
else
if (Result + 1) * FButtonHeight < ClientHeight - FSideBufferSize - GetScrollSize
then
Inc(Result);
if Result = 0 then
Result := 1;
end;
const
cScrollBarKind: array[TspCatButtonFlow] of Integer = (SB_VERT, SB_HORZ);
procedure TspSkinCategoryButtons.Resize;
function CalcCategoryHeights: Integer;
var
I: Integer;
Category: TspButtonCategory;
Y: Integer;
ButtonsPerRow: Integer;
begin
ButtonsPerRow := CalcButtonsPerRow;
Y := 0;
for I := 0 to FButtonCategories.Count - 1 do
begin
Category := FButtonCategories[I];
Category.FStart := Y;
Category.FEnd := Y + CalcCategoryHeight(Category, ButtonsPerRow);
Y := Category.FEnd;
end;
Result := Y;
end;
function CalcCategoryWidths: Integer;
var
I: Integer;
Category: TspButtonCategory;
X: Integer;
ButtonsPerCol: Integer;
begin
ButtonsPerCol := CalcButtonsPerCol;
X := 0;
for I := 0 to FButtonCategories.Count - 1 do
begin
Category := FButtonCategories[I];
Category.FStart := X;
Category.FEnd := X + CalcCategoryWidth(Category, ButtonsPerCol);
X := Category.FEnd;
end;
Result := X;
end;
var
ScrollInfo: TScrollInfo;
TotalAmount: Integer;
AmountSeen: Integer;
begin
inherited;
if (not HandleAllocated) or (FGutterSize = 0) then
Exit;
if FButtonFlow = bscbfVertical then
begin
TotalAmount := CalcCategoryHeights;
AmountSeen := ClientHeight;
end
else
begin
TotalAmount := CalcCategoryWidths;
AmountSeen := ClientWidth;
end;
{ Do we have to take the scrollbar into consideration? }
if (TotalAmount > AmountSeen) then
begin
{ The max size is the number of "rows of buttons" that are hidden }
FScrollBarMax := TotalAmount div FGutterSize;
ScrollInfo.nMax := FScrollBarMax;
AmountSeen := AmountSeen div FGutterSize;
if FScrollBarMax > AmountSeen then
FPageAmount := AmountSeen
else
FPageAmount := FScrollBarMax;
{ Adjust the max to NOT contain the page amount }
FScrollBarMax := FScrollBarMax - FPageAmount + 1;
if FScrollBarPos > FScrollBarMax then
FScrollBarPos := FScrollBarMax;
ScrollInfo.cbSize := SizeOf(TScrollInfo);
ScrollInfo.fMask := SIF_RANGE or SIF_POS or SIF_PAGE;
ScrollInfo.nMin := 0;
ScrollInfo.nPos := FScrollBarPos;
ScrollInfo.nPage := FPageAmount;
if FSkinScrollBar = nil
then
begin
ShowSkinScrollBar(True);
end;
FSkinScrollBar.SetRange(ScrollInfo.nMin, ScrollInfo.nMax,
FScrollBarPos, ScrollInfo.nPage);
end
else
begin
FScrollBarPos := 0;
FScrollBarMax := 0;
if FSkinScrollBar <> nil
then
begin
ShowSkinScrollBar(False);
end;
end;
end;
procedure TspSkinCategoryButtons.SetButtonHeight(const Value: Integer);
begin
if FButtonHeight <> Value then
begin
FButtonHeight := Value;
Resize;
UpdateAllButtons;
end;
end;
procedure TspSkinCategoryButtons.SetButtonCategories(const Value: TspButtonCategories);
begin
FButtonCategories.Assign(Value);
end;
procedure TspSkinCategoryButtons.SetCatButtonOptions(const Value: TspCatButtonOptions);
begin
if FButtonOptions <> Value then
begin
FButtonOptions := Value;
CalcBufferSizes;
Resize;
UpdateAllButtons;
end;
end;
procedure TspSkinCategoryButtons.SetButtonWidth(const Value: Integer);
begin
if FButtonWidth <> Value then
begin
FButtonWidth := Value;
Resize;
UpdateAllButtons;
end;
end;
procedure TspSkinCategoryButtons.SBChange(Sender: TObject);
var
ScrollCode: TScrollCode;
begin
ScrollCode := scPosition;
ScrollPosChanged(TScrollCode(ScrollCode), FSkinScrollBar.Position);
end;
procedure TspSkinCategoryButt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -