📄 jvspeedbutton.pas
字号:
begin
Result := AllocateIndex;
Replace(Result, Image, Mask);
Inc(FCount);
end;
function TJvGlyphList.AddMasked(Image: TBitmap; MaskColor: TColor): Integer;
begin
Result := AllocateIndex;
ReplaceMasked(Result, Image, MaskColor);
Inc(FCount);
end;
function TJvGlyphList.AllocateIndex: Integer;
begin
Result := FUsed.OpenBit;
if Result >= FUsed.Size then
begin
Result := inherited Add(nil, nil);
FUsed.Size := Result + 1;
end;
FUsed[Result] := True;
end;
constructor TJvGlyphList.CreateSize(AWidth, AHeight: Integer);
begin
inherited CreateSize(AWidth, AHeight);
FUsed := TBits.Create;
end;
procedure TJvGlyphList.Delete(Index: Integer);
begin
if FUsed[Index] then
begin
Dec(FCount);
FUsed[Index] := False;
end;
end;
destructor TJvGlyphList.Destroy;
begin
FUsed.Free;
inherited Destroy;
end;
//=== { TJvImageSpeedButton } ================================================
procedure TJvImageSpeedButton.ActionChange(Sender: TObject;
CheckDefaults: Boolean);
begin
inherited ActionChange(Sender, CheckDefaults);
if Sender is TCustomAction then
with TCustomAction(Sender) do
begin
if (not CheckDefaults or (Self.Images = nil)) and (ActionList <> nil) then
Self.Images := ActionList.Images;
if not CheckDefaults or (Self.ImageIndex = -1) then
Self.ImageIndex := ImageIndex;
end;
end;
constructor TJvImageSpeedButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FImageChangeLink := TChangeLink.Create;
FImageChangeLink.OnChange := ImageListChange;
FImageIndex := -1;
end;
destructor TJvImageSpeedButton.Destroy;
begin
FreeAndNil(FImageChangeLink);
inherited Destroy;
end;
function TJvImageSpeedButton.GetActionLinkClass: TControlActionLinkClass;
begin
Result := TJvImageSpeedButtonActionLink;
end;
procedure TJvImageSpeedButton.ImageListChange(Sender: TObject);
begin
InvalidateImage;
end;
procedure TJvImageSpeedButton.InvalidateImage;
begin
Invalidate;
end;
function TJvImageSpeedButton.IsImageVisible: Boolean;
begin
Result := {FImageVisible and} Assigned(FImages) and (FImageIndex >= 0)
end;
procedure TJvImageSpeedButton.PaintImage(Canvas: TCanvas; ARect: TRect;
const Offset: TPoint; AState: TJvButtonState; DrawMark: Boolean);
var
LImageIndex: TImageIndex;
begin
if (MouseOver or FDragging) and HotTrack and (HotTrackImageIndex <> -1) then
LImageIndex := HotTrackImageIndex
else
LImageIndex := ImageIndex;
TJvxButtonGlyph(FGlyph).DrawEx(Canvas, ARect, Offset, Caption, FLayout,
FMargin, FSpacing, DrawMark, Images, LImageIndex, AState, DrawTextBiDiModeFlags(Alignments[Alignment]));
end;
procedure TJvImageSpeedButton.SetHotTrackImageIndex(
const Value: TImageIndex);
begin
if FHotTrackImageIndex <> Value then
begin
FHotTrackImageIndex := Value;
{ Only invalidate when hot }
if (MouseOver or FDragging) and HotTrack then
InvalidateImage;
end;
end;
procedure TJvImageSpeedButton.SetImageIndex(const Value: TImageIndex);
begin
if FImageIndex <> Value then
begin
FImageIndex := Value;
{ Only invalidate when not hot }
if not (MouseOver or FDragging) or not HotTrack then
InvalidateImage;
end;
end;
procedure TJvImageSpeedButton.SetImages(const Value: TCustomImageList);
begin
if FImages <> nil then
FImages.UnRegisterChanges(FImageChangeLink);
FImages := Value;
if FImages <> nil then
begin
FImages.RegisterChanges(FImageChangeLink);
FImages.FreeNotification(Self);
end
else
SetImageIndex(-1);
InvalidateImage;
end;
//=== { TJvImageSpeedButtonActionLink } ======================================
procedure TJvImageSpeedButtonActionLink.AssignClient(AClient: TObject);
begin
inherited AssignClient(AClient);
FClient := AClient as TJvImageSpeedButton;
end;
function TJvImageSpeedButtonActionLink.IsCheckedLinked: Boolean;
begin
Result := inherited IsCheckedLinked and (FClient.GroupIndex <> 0) and
FClient.AllowAllUp and (FClient.Down = (Action as TCustomAction).Checked);
end;
{$IFDEF COMPILER6_UP}
{$IFDEF VCL}
function TJvImageSpeedButtonActionLink.IsGroupIndexLinked: Boolean;
begin
{ (rb) This will fail in D7 due to a bug in TCustomAction.SetGroupIndex }
Result := (FClient is TJvCustomSpeedButton) and
(FClient.GroupIndex = (Action as TCustomAction).GroupIndex);
end;
procedure TJvImageSpeedButtonActionLink.SetGroupIndex(Value: Integer);
begin
if IsGroupIndexLinked then
FClient.GroupIndex := Value;
end;
{$ENDIF VCL}
{$ENDIF COMPILER6_UP}
function TJvImageSpeedButtonActionLink.IsImageIndexLinked: Boolean;
begin
Result := inherited IsImageIndexLinked and
(FClient.ImageIndex = (Action as TCustomAction).ImageIndex);
end;
procedure TJvImageSpeedButtonActionLink.SetChecked(Value: Boolean);
begin
if IsCheckedLinked then
FClient.Down := Value;
end;
procedure TJvImageSpeedButtonActionLink.SetImageIndex(Value: Integer);
begin
if IsImageIndexLinked then
FClient.ImageIndex := Value;
end;
//=== { TJvSpeedButton } =====================================================
procedure TJvSpeedButton.ActionChange(Sender: TObject; CheckDefaults: Boolean);
procedure CopyImage(ImageList: TCustomImageList; Index: Integer);
begin
with Glyph do
begin
Width := ImageList.Width;
Height := ImageList.Height;
Canvas.Brush.Color := clFuchsia;
Canvas.FillRect(Rect(0, 0, Width, Height));
ImageList.Draw(Canvas, 0, 0, Index);
TransparentColor := clFuchsia;
end;
end;
begin
inherited ActionChange(Sender, CheckDefaults);
if Sender is TCustomAction then
with TCustomAction(Sender) do
begin
if CheckDefaults or (Self.GroupIndex = 0) then
Self.GroupIndex := GroupIndex;
{ Copy image from action's imagelist }
if (Glyph.Empty) and (ActionList <> nil) and (ActionList.Images <> nil) and
(ImageIndex >= 0) and (ImageIndex < ActionList.Images.Count) then
CopyImage(ActionList.Images, ImageIndex);
end;
end;
constructor TJvSpeedButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
TJvxButtonGlyph(FGlyph).OnChange := GlyphChanged;
FHotTrackGlyph := TJvxButtonGlyph.Create;
TJvxButtonGlyph(FHotTrackGlyph).OnChange := HotTrackGlyphChanged;
end;
destructor TJvSpeedButton.Destroy;
begin
TJvxButtonGlyph(FHotTrackGlyph).Free;
inherited Destroy;
end;
function TJvSpeedButton.GetActionLinkClass: TControlActionLinkClass;
begin
Result := TJvSpeedButtonActionLink;
end;
function TJvSpeedButton.GetGlyph: TBitmap;
begin
Result := TJvxButtonGlyph(FGlyph).Glyph;
end;
function TJvSpeedButton.GetHotTrackGlyph: TBitmap;
begin
Result := TJvxButtonGlyph(FHotTrackGlyph).Glyph;
end;
function TJvSpeedButton.GetNumGlyphs: TJvNumGlyphs;
begin
Result := TJvxButtonGlyph(FGlyph).NumGlyphs;
end;
{$IFDEF VCL}
function TJvSpeedButton.GetPalette: HPALETTE;
begin
Result := Glyph.Palette;
end;
{$ENDIF VCL}
procedure TJvSpeedButton.GlyphChanged(Sender: TObject);
begin
Invalidate;
end;
procedure TJvSpeedButton.HotTrackGlyphChanged(Sender: TObject);
begin
Invalidate;
end;
procedure TJvSpeedButton.PaintImage(Canvas: TCanvas; ARect: TRect; const Offset: TPoint;
AState: TJvButtonState; DrawMark: Boolean);
begin
if (MouseOver or FDragging) and HotTrack and not HotTrackGlyph.Empty then
begin
SyncHotGlyph;
TJvxButtonGlyph(FHotTrackGlyph).Draw(Canvas, ARect, Offset, Caption, FLayout,
FMargin, FSpacing, DrawMark, AState, DrawTextBiDiModeFlags(Alignments[Alignment]));
end
else
TJvxButtonGlyph(FGlyph).Draw(Canvas, ARect, Offset, Caption, FLayout,
FMargin, FSpacing, DrawMark, AState, DrawTextBiDiModeFlags(Alignments[Alignment]));
end;
procedure TJvSpeedButton.SetGlyph(Value: TBitmap);
begin
TJvxButtonGlyph(FGlyph).Glyph := Value;
Invalidate;
end;
procedure TJvSpeedButton.SetHotTrackGlyph(const Value: TBitmap);
begin
TJvxButtonGlyph(FHotTrackGlyph).Glyph := Value;
Invalidate;
end;
procedure TJvSpeedButton.SetNumGlyphs(Value: TJvNumGlyphs);
begin
if Value < 0 then
Value := 1
else
if Value > Ord(High(TJvButtonState)) + 1 then
Value := Ord(High(TJvButtonState)) + 1;
if Value <> TJvxButtonGlyph(FGlyph).NumGlyphs then
begin
TJvxButtonGlyph(FGlyph).NumGlyphs := Value;
Invalidate;
end;
end;
procedure TJvSpeedButton.SyncHotGlyph;
begin
with TJvxButtonGlyph(FHotTrackGlyph) do
begin
OnChange := nil;
try
Alignment := TJvxButtonGlyph(FGlyph).Alignment;
GrayNewStyle := TJvxButtonGlyph(FGlyph).GrayNewStyle;
NumGlyphs := TJvxButtonGlyph(FGlyph).NumGlyphs;
WordWrap := TJvxButtonGlyph(FGlyph).WordWrap;
finally
OnChange := HotTrackGlyphChanged;
end;
end;
end;
//=== { TJvSpeedButtonActionLink } ===========================================
procedure TJvSpeedButtonActionLink.AssignClient(AClient: TObject);
begin
inherited AssignClient(AClient);
FClient := AClient as TJvSpeedButton;
end;
function TJvSpeedButtonActionLink.IsCheckedLinked: Boolean;
begin
Result := inherited IsCheckedLinked and (FClient.GroupIndex <> 0) and
FClient.AllowAllUp and (FClient.Down = (Action as TCustomAction).Checked);
end;
{$IFDEF COMPILER6_UP}
{$IFDEF VCL}
function TJvSpeedButtonActionLink.IsGroupIndexLinked: Boolean;
begin
Result := (FClient is TJvSpeedButton) and
(TJvSpeedButton(FClient).GroupIndex = (Action as TCustomAction).GroupIndex);
end;
procedure TJvSpeedButtonActionLink.SetGroupIndex(Value: Integer);
begin
if IsGroupIndexLinked then
TJvSpeedButton(FClient).GroupIndex := Value;
end;
{$ENDIF VCL}
{$ENDIF COMPILER6_UP}
procedure TJvSpeedButtonActionLink.SetChecked(Value: Boolean);
begin
if IsCheckedLinked then
TJvSpeedButton(FClient).Down := Value;
end;
//=== { TJvxButtonGlyph } ====================================================
procedure TJvxButtonGlyph.CalcButtonLayout(Canvas: TCanvas; const Client: TRect; const Offset: TPoint;
var Caption: string; Layout: TButtonLayout; Margin, Spacing: Integer;
PopupMark: Boolean; var GlyphPos: TPoint; var TextBounds: TRect;
Flags: Word; Images: TCustomImageList; ImageIndex: Integer);
var
TextPos: TPoint;
MaxSize, ClientSize, GlyphSize, TextSize: TPoint;
TotalSize: TPoint;
{ Parameter nCount of DrawText specifies the length of the string. For the
ANSI function it is a BYTE count }
CString: array [0..255] of Char;
begin
{ calculate the item sizes }
ClientSize := Point(Client.Right - Client.Left, Client.Bottom - Client.Top);
if Assigned(Images) and (Images.Width > 0) and (ImageIndex >= 0) and
(ImageIndex < Images.Count) then
GlyphSize := Point(Images.Width, Images.Height)
else
if FOriginal <> nil then
GlyphSize := Point(FOriginal.Width div FNumGlyphs, FOriginal.Height)
else
GlyphSize := Point(0, 0);
if Layout in [blGlyphLeft, blGlyphRight] then
begin
MaxSize.X := ClientSize.X - GlyphSize.X;
if Margin <> -1 then
Dec(MaxSize.X, Margin);
if Spacing <> -1 then
Dec(MaxSize.X, Spacing);
if PopupMark then
Dec(MaxSize.X, 9);
MaxSize.Y := ClientSize.Y;
end
else { blGlyphTop, blGlyphBottom }
begin
MaxSize.X := ClientSize.X;
MaxSize.Y := ClientSize.Y - GlyphSize.Y;
if Margin <> -1 then
Dec(MaxSize.Y, Margin);
if Spacing <> -1 then
Dec(MaxSize.Y, Spacing);
end;
MaxSize.X := Max(0, MaxSize.X);
MaxSize.Y := Max(0, MaxSize.Y);
MinimizeCaption(Canvas, Caption, CString, SizeOf(CString) - 1, MaxSize.X);
Caption := StrPas(CString);
if Length(Caption) > 0 then
begin
TextBounds := Rect(0, 0, MaxSize.X, 0);
DrawText(Canvas, CString, -1, TextBounds, DT_CALCRECT or DT_CENTER or
DT_VCENTER or WordWraps[FWordWrap] or Flags);
end
else
TextBounds := Rect(0, 0, 0, 0);
TextBounds.Bottom := Max(TextBounds.Top, TextBounds.Top +
Min(MaxSize.Y, RectHeight(TextBounds)));
TextBounds.Right := Max(TextBounds.Left, TextBounds.Left +
Min(MaxSize.X, RectWidth(TextBounds)));
TextSize := Point(TextBounds.Right - TextBounds.Left, TextBounds.Bottom -
TextBounds.Top);
if PopupMark then
if ((GlyphSize.X = 0) or (GlyphSize.Y = 0)) or (Layout = blGlyphLeft) then
Inc(TextSize.X, 9)
else
if GlyphSize.X > 0 then
Inc(GlyphSize.X, 6);
{ If the layout has the glyph on the right or the left, then both the
text and the glyph are centered vertica
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -