gpt4 book ai didi

Delphi Windows 7 控制面板组件

转载 作者:行者123 更新时间:2023-12-03 14:56:07 26 4
gpt4 key购买 nike

我正在寻找一个delphi组件,当您“按类别查看”时,它的外观和功能类似于Windows 7控制面板按钮。有人知道这样的东西是否已经存在吗?

alt text

最佳答案

我刚刚创建了一个看起来像你想要的那样的小组件。它是双缓冲的,因此完全无闪烁,并且可以在启用和禁用视觉主题的情况下工作。

unit TaskButton;

interface

uses
SysUtils, Forms, Messages, Windows, Graphics, Classes, Controls, UxTheme,
ImgList, PNGImage;

type
TIconSource = (isImageList, isPNGImage);

TTaskButtonLinkClickEvent = procedure(Sender: TObject; LinkIndex: integer) of object;

TTaskButton = class(TCustomControl)
private
{ Private declarations }
FCaption: TCaption;
FHeaderRect: TRect;
FImageSpacing: integer;
FLinks: TStrings;
FHeaderHeight: integer;
FLinkHeight: integer;
FLinkSpacing: integer;
FHeaderSpacing: integer;
FLinkRects: array of TRect;
FPrevMouseHoverIndex: integer;
FMouseHoverIndex: integer;
FImages: TImageList;
FImageIndex: TImageIndex;
FIconSource: TIconSource;
FImage: TPngImage;
FBuffer: TBitmap;
FOnLinkClick: TTaskButtonLinkClickEvent;
procedure UpdateMetrics;
procedure SetCaption(const Caption: TCaption);
procedure SetImageSpacing(ImageSpacing: integer);
procedure SetLinkSpacing(LinkSpacing: integer);
procedure SetHeaderSpacing(HeaderSpacing: integer);
procedure SetLinks(Links: TStrings);
procedure SetImages(Images: TImageList);
procedure SetImageIndex(ImageIndex: TImageIndex);
procedure SetIconSource(IconSource: TIconSource);
procedure SetImage(Image: TPngImage);
procedure SwapBuffers;
function ImageWidth: integer;
function ImageHeight: integer;
procedure SetNonThemedHeaderFont;
procedure SetNonThemedLinkFont(Hovering: boolean = false);
protected
{ Protected declarations }
procedure Paint; override;
procedure WndProc(var Message: TMessage); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X: Integer; Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property Caption: TCaption read FCaption write SetCaption;
property Links: TStrings read FLinks write SetLinks;
property ImageSpacing: integer read FImageSpacing write SetImageSpacing default 16;
property HeaderSpacing: integer read FHeaderSpacing write SetHeaderSpacing default 2;
property LinkSpacing: integer read FLinkSpacing write SetLinkSpacing default 2;
property Images: TImageList read FImages write SetImages;
property ImageIndex: TImageIndex read FImageIndex write SetImageIndex;
property Image: TPngImage read FImage write SetImage;
property IconSource: TIconSource read FIconSource write SetIconSource default isPNGImage;
property OnLinkClick: TTaskButtonLinkClickEvent read FOnLinkClick write FOnLinkClick;
end;

procedure Register;

implementation

uses Math;

procedure Register;
begin
RegisterComponents('Rejbrand 2009', [TTaskButton]);
end;

function IsIntInInterval(x, xmin, xmax: integer): boolean; inline;
begin
IsIntInInterval := (xmin <= x) and (x <= xmax);
end;

function PointInRect(const Point: TPoint; const Rect: TRect): boolean; inline;
begin
PointInRect := IsIntInInterval(Point.X, Rect.Left, Rect.Right) and
IsIntInInterval(Point.Y, Rect.Top, Rect.Bottom);
end;

{ TTaskButton }

constructor TTaskButton.Create(AOwner: TComponent);
begin
inherited;
InitThemeLibrary;
FBuffer := TBitmap.Create;
FLinks := TStringList.Create;
FImage := TPngImage.Create;
FImageSpacing := 16;
FHeaderSpacing := 2;
FLinkSpacing := 2;
FPrevMouseHoverIndex := -1;
FMouseHoverIndex := -1;
FIconSource := isPNGImage;
end;

destructor TTaskButton.Destroy;
begin
FLinkRects := nil;
FImage.Free;
FLinks.Free;
FBuffer.Free;
inherited;
end;

function TTaskButton.ImageHeight: integer;
begin

result := 0;
case FIconSource of
isImageList:
if Assigned(FImages) then
result := FImages.Height;
isPNGImage:
if Assigned(FImage) then
result := FImage.Height;
end;

end;

function TTaskButton.ImageWidth: integer;
begin

result := 0;
case FIconSource of
isImageList:
if Assigned(FImages) then
result := FImages.Width;
isPNGImage:
if Assigned(FImage) then
result := FImage.Width;
end;

end;

procedure TTaskButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
inherited;
Paint;
end;

procedure TTaskButton.MouseMove(Shift: TShiftState; X, Y: Integer);
var
i: Integer;
begin
inherited;
FMouseHoverIndex := -1;
for i := 0 to high(FLinkRects) do
if PointInRect(point(X, Y), FLinkRects[i]) then
begin
FMouseHoverIndex := i;
break;
end;

if FMouseHoverIndex <> FPrevMouseHoverIndex then
begin
Cursor := IfThen(FMouseHoverIndex <> -1, crHandPoint, crDefault);
Paint;
end;

FPrevMouseHoverIndex := FMouseHoverIndex;
end;

procedure TTaskButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
inherited;
Paint;
if (FMouseHoverIndex <> -1) and Assigned(FOnLinkClick) then
FOnLinkClick(Self, FMouseHoverIndex);
end;

procedure TTaskButton.Paint;
var
theme: HTHEME;
i: Integer;
pnt: TPoint;
r: PRect;
begin
inherited;

if FLinks.Count <> length(FLinkRects) then
UpdateMetrics;

FBuffer.Canvas.Brush.Color := Color;
FBuffer.Canvas.FillRect(ClientRect);


if GetCursorPos(pnt) then
if PointInRect(Self.ScreenToClient(pnt), ClientRect) then
begin

if UxTheme.UseThemes then
begin

theme := OpenThemeData(Handle, 'BUTTON');
if theme <> 0 then
try
DrawThemeBackground(theme,
FBuffer.Canvas.Handle,
BP_COMMANDLINK,
CMDLS_HOT,
ClientRect,
nil);
finally
CloseThemeData(theme);
end;

end
else
begin

New(r);
try
r^ := ClientRect;
DrawEdge(FBuffer.Canvas.Handle, r^, EDGE_RAISED, BF_RECT);
finally
Dispose(r);
end;

end;

end;

case FIconSource of
isImageList:
if Assigned(FImages) then
FImages.Draw(FBuffer.Canvas, 14, 16, FImageIndex);
isPNGImage:
if Assigned(FImage) then
FBuffer.Canvas.Draw(14, 16, FImage);
end;

if UxTheme.UseThemes then
begin

theme := OpenThemeData(Handle, 'CONTROLPANEL');

if theme <> 0 then
try

DrawThemeText(theme,
FBuffer.Canvas.Handle,
CPANEL_SECTIONTITLELINK,
CPSTL_NORMAL,
PChar(Caption),
length(Caption),
DT_LEFT or DT_END_ELLIPSIS or DT_TOP or DT_SINGLELINE,
0,
FHeaderRect);

for i := 0 to FLinks.Count - 1 do
DrawThemeText(theme,
FBuffer.Canvas.Handle,
CPANEL_CONTENTLINK,
IfThen(FMouseHoverIndex = i, IfThen(csLButtonDown in ControlState, CPCL_PRESSED, CPCL_HOT), CPCL_NORMAL),
PChar(FLinks[i]),
length(FLinks[i]),
DT_LEFT or DT_END_ELLIPSIS or DT_TOP or DT_SINGLELINE,
0,
FLinkRects[i]
);

finally
CloseThemeData(theme);
end;

end
else
begin

SetNonThemedHeaderFont;
DrawText(FBuffer.Canvas.Handle,
PChar(Caption),
-1,
FHeaderRect,
DT_LEFT or DT_END_ELLIPSIS or DT_TOP or DT_SINGLELINE);

for i := 0 to FLinks.Count - 1 do
begin
SetNonThemedLinkFont(FMouseHoverIndex = i);
DrawText(FBuffer.Canvas.Handle,
PChar(FLinks[i]),
-1,
FLinkRects[i],
DT_LEFT or DT_END_ELLIPSIS or DT_TOP or DT_SINGLELINE);
end;

end;

SwapBuffers;
end;

procedure TTaskButton.SetCaption(const Caption: TCaption);
begin
if not SameStr(FCaption, Caption) then
begin
FCaption := Caption;
UpdateMetrics;
Paint;
end;
end;

procedure TTaskButton.SetHeaderSpacing(HeaderSpacing: integer);
begin
if FHeaderSpacing <> HeaderSpacing then
begin
FHeaderSpacing := HeaderSpacing;
UpdateMetrics;
Paint;
end;
end;

procedure TTaskButton.SetIconSource(IconSource: TIconSource);
begin
if FIconSource <> IconSource then
begin
FIconSource := IconSource;
UpdateMetrics;
Paint;
end;
end;

procedure TTaskButton.SetImage(Image: TPngImage);
begin
FImage.Assign(Image);
UpdateMetrics;
Paint;
end;

procedure TTaskButton.SetImageIndex(ImageIndex: TImageIndex);
begin
if FImageIndex <> ImageIndex then
begin
FImageIndex := ImageIndex;
UpdateMetrics;
Paint;
end;
end;

procedure TTaskButton.SetImages(Images: TImageList);
begin
FImages := Images;
UpdateMetrics;
Paint;
end;

procedure TTaskButton.SetImageSpacing(ImageSpacing: integer);
begin
if FImageSpacing <> ImageSpacing then
begin
FImageSpacing := ImageSpacing;
UpdateMetrics;
Paint;
end;
end;

procedure TTaskButton.SetLinks(Links: TStrings);
begin
FLinks.Assign(Links);
UpdateMetrics;
Paint;
end;

procedure TTaskButton.SetLinkSpacing(LinkSpacing: integer);
begin
if FLinkSpacing <> LinkSpacing then
begin
FLinkSpacing := LinkSpacing;
UpdateMetrics;
Paint;
end;
end;

procedure TTaskButton.SwapBuffers;
begin
BitBlt(Canvas.Handle, 0, 0, Width, Height, FBuffer.Canvas.Handle, 0, 0, SRCCOPY);
end;

procedure TTaskButton.WndProc(var Message: TMessage);
begin
inherited;
case Message.Msg of
WM_SIZE:
UpdateMetrics;
CM_MOUSEENTER:
Paint;
CM_MOUSELEAVE:
Paint;
WM_ERASEBKGND:
Message.Result := 1;
end;
end;


procedure TTaskButton.UpdateMetrics;
var
theme: HTHEME;
cr, r: TRect;
i, y: Integer;
begin

FBuffer.SetSize(Width, Height);
SetLength(FLinkRects, FLinks.Count);

if UxTheme.UseThemes then
begin

theme := OpenThemeData(Handle, 'CONTROLPANEL');

if theme <> 0 then
try

with cr do
begin
Top := 10;
Left := ImageWidth + FImageSpacing;
Right := Width - 4;
Bottom := Self.Height;
end;

GetThemeTextExtent(theme,
FBuffer.Canvas.Handle,
CPANEL_SECTIONTITLELINK,
CPSTL_NORMAL,
PChar(Caption),
-1,
DT_LEFT or DT_END_ELLIPSIS or DT_TOP or DT_SINGLELINE,
@cr,
r);

FHeaderHeight := r.Bottom - r.Top;

with FHeaderRect do
begin
Top := 10;
Left := 14 + ImageWidth + FImageSpacing;
Right := Width - 4;
Bottom := Top + FHeaderHeight;
end;

with cr do
begin
Top := 4;
Left := 14 + ImageWidth + FImageSpacing;
Right := Width - 4;
Bottom := Self.Height;
end;

y := FHeaderRect.Bottom + FHeaderSpacing;
for i := 0 to high(FLinkRects) do
begin

GetThemeTextExtent(theme,
FBuffer.Canvas.Handle,
CPANEL_CONTENTLINK,
CPCL_NORMAL,
PChar(FLinks[i]),
-1,
DT_LEFT or DT_END_ELLIPSIS or DT_TOP or DT_SINGLELINE,
@cr,
r);

FLinkHeight := r.Bottom - r.Top;

FLinkRects[i].Left := FHeaderRect.Left;
FLinkRects[i].Top := y;
FLinkRects[i].Right := FLinkRects[i].Left + r.Right - r.Left;
FLinkRects[i].Bottom := FLinkRects[i].Top + FLinkHeight + FLinkSpacing;

inc(y, FLinkHeight + FLinkSpacing);
end;

finally
CloseThemeData(theme);
end;
end
else
begin

SetNonThemedHeaderFont;

FHeaderHeight := FBuffer.Canvas.TextHeight(FCaption);

with FHeaderRect do
begin
Top := 10;
Left := 14 + ImageWidth + FImageSpacing;
Right := Width - 4;
Bottom := Top + FHeaderHeight;
end;

SetNonThemedLinkFont;

y := FHeaderRect.Bottom + FHeaderSpacing;
for i := 0 to high(FLinkRects) do
with FBuffer.Canvas.TextExtent(FLinks[i]) do
begin

FLinkHeight := cy;

FLinkRects[i].Left := FHeaderRect.Left;
FLinkRects[i].Top := y;
FLinkRects[i].Right := FLinkRects[i].Left + cx;
FLinkRects[i].Bottom := FLinkRects[i].Top + FLinkHeight + FLinkSpacing;

inc(y, FLinkHeight + FLinkSpacing);
end;

end;

end;

procedure TTaskButton.SetNonThemedHeaderFont;
begin
with FBuffer.Canvas.Font do
begin
Color := clNavy;
Style := [];
Size := 14;
end;
end;

procedure TTaskButton.SetNonThemedLinkFont(Hovering: boolean = false);
begin
with FBuffer.Canvas.Font do
begin
Color := clNavy;
if Hovering then
Style := [fsUnderline]
else
Style := [];
Size := 10;
end;
end;

initialization
// Override Delphi's ugly hand cursor with the nice Windows hand cursor
Screen.Cursors[crHandPoint] := LoadCursor(0, IDC_HAND);


end.

截图:

Image of TTaskButton

Image of TTaskButton (unthemed)

如果我有时间,我会为其添加一个键盘接口(interface)。

关于Delphi Windows 7 控制面板组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3986067/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com