【问题标题】:TListView scroll eventTListView 滚动事件
【发布时间】:2011-07-25 14:57:24
【问题描述】:

TListView 控件是否有一个在控件滚动时触发的事件?

我宁愿不必对 TListView 控件进行子类化。

【问题讨论】:

  • 我不明白这个问题。
  • @David Heffernan:是的,就是这样。
  • 你需要监听 WM_VSCROLL。

标签: delphi listview scroll scrollbar


【解决方案1】:

这很有效,但可能会违反您问题的限制。

在包含使用TListView 的表单的单元的interface 部分(在TForm 声明之前),添加

type
  TListView = class(ComCtrls.TListView)
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

然后,在同一单元的implementation部分,定义

procedure TListView.WndProc(var Message: TMessage);
begin
  inherited;
  case Message.Msg of
    WM_HSCROLL, WM_VSCROLL: beep;
  end;
end;

【讨论】:

  • 这个技巧有多安全/合法?由于 Delphi 期望控件是不同的 TListView 会不会有问题? (例如,表单设计器使用已注册的控件,而这个未注册)
【解决方案2】:

您可以在不编写后代类的情况下对窗口进行子类化,这在您期望更改的行为是一次性要求时很有用。像Andreas's answer 一样编写TWndMethod 函数,但可以将它写在你想要的任何类中,例如拥有列表视图的表单。将其分配给列表视图控件的WindowProc 属性。在执行此操作之前,请存储该属性的先前值,以便您可以将所有其他消息推迟到它。

type
  TNanikForm = class(TForm)
    ListView: TListView;
  private
    FPrevListViewProc: TWndMethod;
    procedure ListViewWndProc(var Msg: TMessage);
  public
    procedure Loaded; override;
  end;

procedure TNanikForm.ListViewWndProc(var Msg: TMessage);
begin
  case Msg.Message of
    wm_VScroll: ;
    else FPrevListViewProc(Msg);
  end;
end;

procedure TNanikForm.Loaded;
begin
  inherited;
  FPrevListViewProc := ListView.WindowProc;
  ListView.WindowProc := ListViewWndProc;
end;

【讨论】:

  • 我已经准备好发布一个几乎相同的答案来表达同样的观点。但是,我发现只听 WM_VSCROLL 是不够的。这适用于滚动条的操作,但如果您使用鼠标滚轮或键盘导航,则不会触发。我查看了似乎会有所帮助的 LVN_ENDSCROLL 通知消息,但我无法让我的代码捕获其中一次。
  • 其实我越看这个越绝望!也许 OnMessage hack 毕竟是最不邪恶的!
  • @David,通知消息被发送到控件的。然后德尔福父母在添加一个值后重新向指定的孩子发送通知 - 我认为是cm_Base。常见消息的名称上有C 前缀。尝试捕获 cm_Notify 而不是 wm_Notify
  • 其实是CN_NOTIFY。我可以得到那些,只是不是 LVN_ENDSCROLL。无论如何,从我读过的内容来看,键盘导航似乎根本没有发出任何通知,它是控件内部的。
【解决方案3】:

或者如果你只想捕获垂直滚动事件,你可以使用它。代码与 Andreas 发布的几乎相同...

type
  TListView = class(ComCtrls.TListView)
  protected
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  end;

procedure TListView.WMVScroll(var Message: TWMVScroll);
begin
  inherited;
  Beep;
end;

【讨论】:

    【解决方案4】:

    所有答案都很好:-),但我不会创建新的班级孩子。 感谢大家的帮助 :-)!


    我的解决方案: 我使用组件(在 Delphi 7 中)ApplicationEvents 并检查 ScrollBar 位置 的变化(GetScrollPos(ListView.Handle, SB_VERT))。

    【讨论】:

    • 其他解决方案要好得多。您只需在具有此组件的表单中包含单元中的代码。它被称为插入器。你为什么害怕子分类?这是一件非常正常的日常事情。每次消息队列中出现事件时调用 GetScrollPos 是一种浪费。
    • @Andreas OnMessage 更有可能。真是个坏主意。
    • @Nanik 我同意您不将标准组件子类化的偏好。当我能找到满足这种愿望的好解决方案时,我就会接受。然而,这是一个糟糕的解决方案,比子分类差得多。你应该更灵活。
    • 您能否明确告诉我们您正在处理哪个应用程序事件?甚至发布一些代码。请记住,如果这真的是最好的答案,那么您不仅仅是在为自己回答这个问题。您正在为所有未来访问此网站并提出类似问题的人回答,所以请尽力而为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    相关资源
    最近更新 更多