在delphi的滚动框中滚动时如何查看组件是不是不在视图中?

Posted

技术标签:

【中文标题】在delphi的滚动框中滚动时如何查看组件是不是不在视图中?【英文标题】:How to see if a component is out of view when scrolling in a scrollbox in delphi?在delphi的滚动框中滚动时如何查看组件是否不在视图中? 【发布时间】:2020-10-11 14:16:36 【问题描述】:

我想在 TScrollBox 中滚动时更改面板的标题。我有一个滚动框,其中所有所有类别都列在彼此下方,并且随着每个类别的标题滚动过去,我希望顶部面板更改以显示我当前正在滚动浏览的类别。我该怎么做?

【问题讨论】:

我有这种感觉,你问错了你需要做什么的问题。因此,请编辑您的问题并提供一些背景信息,说明您首先需要更改名称的原因,以及为什么必须在面板看不见时进行更改。 @TomBrunberg 是对的。根据控件当前在滚动框中的可见性来更改控件的名称听起来非常很奇怪。很可能有更好的方法来解决您的实际问题。尽管如此,当控件由于滚动而变得可见/不可见时,响应是非常可行的,如我的 A 中所述。 所以你想改变面板的caption,而不是name @AndreasRejbrand 是的,对不起。 您要更改其标题的面板,该面板真的是滚动框的子项吗?因为如果是这样,这似乎是一个相当乏味的 Q,因为当面板不可见时,它有什么标题并不重要(因为你不会看到它!)。也许您的意思是您想在滚动滚动框时更改滚动框外某些面板的标题? 【参考方案1】:

要查看子控件ChildCtrl 的任何像素当前是否在名为ScrollBox 的父TScrollBox 控件中可见,请检查

ScrollBox.ClientRect.IntersectsWith(ChildCtrl.BoundsRect)

不过,这只是“未超出视野”的一种定义。如果您想检查 整个 控件是否可见,请检查

ScrollBox.ClientRect.Contains(ChildCtrl.BoundsRect)

要检测滚动,您会喜欢TScrollBox 的已发布OnScroll 属性,但不幸的是没有这样的属性。相反,您必须自己拦截滚动消息,详细说明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

【讨论】:

我已经添加了 system.types 单元,但仍然找不到 IntersectsWith 命令。 它可能还没有在 D2010 中引入。我不知道它是什么时候引入的。如果不存在,您始终可以使用简单的不等式:(C.Left &lt; SB.Right) and (C.Right &gt; SB.Left) and (C.Top &lt; SB.Bottom) and (C.Bottom &gt; SB.Top) 其中SB := ScrollBox.ClientRectC := ChildCtrl.BoundsRect 用于第一种情况。

以上是关于在delphi的滚动框中滚动时如何查看组件是不是不在视图中?的主要内容,如果未能解决你的问题,请参考以下文章

delphi中加个下拉滚动条,如果。现在是第九第十下面的显示不出来。请问如何加滚动条?

delphi如何判断RichEdit是不是显示到底部了?

如何使用 Selenium 在 Instagram 弹出框中向下滚动

Delphi Firemonkey Android TEdit滑动滚动不聚焦

delphi 谁知道如何让image自动有滚动条(当图片尺寸大于image尺寸时

delphi6 两个dbgrid如何实现水平滚动条同步滚动?