在 delphi 的滚动框中滚动时,如何查看组件是否超出视图?
How to see if a component is out of view when scrolling in a scrollbox in delphi?
我想在 TScrollBox 中滚动时更改不在视图中的面板的标题。我有一个滚动框,其中所有类别都在彼此下方列出,并且随着每个类别的标题滚动过去,我希望顶部面板更改以显示我当前正在滚动的类别。我该怎么做?
要查看子控件 ChildCtrl
的任何像素当前是否在名为 ScrollBox
的父 TScrollBox
控件中可见,请检查
ScrollBox.ClientRect.IntersectsWith(ChildCtrl.BoundsRect)
然而,这只是“不在视野之外”的一种定义。如果您想检查 entire 控件是否可见,请改为检查
ScrollBox.ClientRect.Contains(ChildCtrl.BoundsRect)
要检测滚动,您会喜欢已发布的 OnScroll
属性 of TScrollBox
,但不幸的是没有这样的 属性。相反,您必须自己拦截滚动消息,详见 in this Q&A.
这是一个完整的示例(只是简单粗暴地展示它是如何完成的——在真实的应用程序中,您将重构它):
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, StdCtrls;
type
TScrollBox = class(Vcl.Forms.TScrollBox)
procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
end;
TForm1 = class(TForm)
ScrollBox1: TScrollBox;
lblTitle: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FButtons: TArray<TButton>;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
const
N = 30;
var
i, y: Integer;
btn: TButton;
begin
// First, populate the scroll box with some sample buttons
SetLength(FButtons, N);
y := 10;
for i := 0 to N - 1 do
begin
btn := TButton.Create(ScrollBox1);
btn.Parent := ScrollBox1;
btn.Left := 10;
btn.Top := y;
btn.Caption := 'Button ' + (i + 1).ToString;
Inc(y, 3*btn.Height div 2);
FButtons[i] := btn;
end;
end;
{ TScrollBox }
procedure TScrollBox.WMVScroll(var Message: TWMVScroll);
var
i: Integer;
begin
inherited;
for i := 0 to High(Form1.FButtons) do
if Form1.ScrollBox1.ClientRect.Contains(Form1.FButtons[i].BoundsRect) then
begin
Form1.lblTitle.Caption := Form1.FButtons[i].Caption;
Break;
end;
end;
end.
不要忘记将TScrollBox.VertScrollBar.Tracking
设置为True
!
我想在 TScrollBox 中滚动时更改不在视图中的面板的标题。我有一个滚动框,其中所有类别都在彼此下方列出,并且随着每个类别的标题滚动过去,我希望顶部面板更改以显示我当前正在滚动的类别。我该怎么做?
要查看子控件 ChildCtrl
的任何像素当前是否在名为 ScrollBox
的父 TScrollBox
控件中可见,请检查
ScrollBox.ClientRect.IntersectsWith(ChildCtrl.BoundsRect)
然而,这只是“不在视野之外”的一种定义。如果您想检查 entire 控件是否可见,请改为检查
ScrollBox.ClientRect.Contains(ChildCtrl.BoundsRect)
要检测滚动,您会喜欢已发布的 OnScroll
属性 of TScrollBox
,但不幸的是没有这样的 属性。相反,您必须自己拦截滚动消息,详见 in this Q&A.
这是一个完整的示例(只是简单粗暴地展示它是如何完成的——在真实的应用程序中,您将重构它):
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, StdCtrls;
type
TScrollBox = class(Vcl.Forms.TScrollBox)
procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
end;
TForm1 = class(TForm)
ScrollBox1: TScrollBox;
lblTitle: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FButtons: TArray<TButton>;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
const
N = 30;
var
i, y: Integer;
btn: TButton;
begin
// First, populate the scroll box with some sample buttons
SetLength(FButtons, N);
y := 10;
for i := 0 to N - 1 do
begin
btn := TButton.Create(ScrollBox1);
btn.Parent := ScrollBox1;
btn.Left := 10;
btn.Top := y;
btn.Caption := 'Button ' + (i + 1).ToString;
Inc(y, 3*btn.Height div 2);
FButtons[i] := btn;
end;
end;
{ TScrollBox }
procedure TScrollBox.WMVScroll(var Message: TWMVScroll);
var
i: Integer;
begin
inherited;
for i := 0 to High(Form1.FButtons) do
if Form1.ScrollBox1.ClientRect.Contains(Form1.FButtons[i].BoundsRect) then
begin
Form1.lblTitle.Caption := Form1.FButtons[i].Caption;
Break;
end;
end;
end.
不要忘记将TScrollBox.VertScrollBar.Tracking
设置为True
!