2

当 ListView 开始垂直滚动并结束它时,有什么方法可以捕获事件?
首先,我试图捕捉 LVN_BEGINSCROLL 和 LVN_ENDSCROLL 通知,但结果并不符合我的预期。也许我试图处理这些通知是错误的(在父表单中我处理了 WM_NOTIFY 消息,在它的处理程序中我检查了 Msg.NMHdr.code)。
我还尝试处理 ListView 的 WM_VSCROLL 消息并检查了 ScrollCode = SB_ENDSCROLL。但是如何检测 BeginScroll 事件呢?
当我通过鼠标滚轮滚动 ListView 时,WM_VSCROLL 没有出现。WM_MOUSEWHEEL 消息来代替。如何使用 WM_MOUSEWHEEL 消息检测和处理我需要的事件?是否可以通过检查 delta,即 WM_MOUSEWHEEL 消息的 wParam 中的高位词?

或者我能做什么?
谢谢。

4

1 回答 1

4

LVN_BEGINSCROLL并且LVN_ENDSCROLL当我尝试它们时对我来说工作正常,前提是该应用程序启用了 XP 主题,因为它们仅适用于 ComCtrl32 v6。但是他们的时间与您的预期不同,这可能会让您感到困惑。

WM_VSCROLL它本身会更好地满足您的需求,并且它不依赖于 ComCtl32 v6。它还将处理鼠标滚轮滚动,尽管滚轮开始/结束滚动通知的时间将更像LVN_BEGINSCROLLLVN_ENDSCROLL通知,因为滚轮不知道下一次移动何时发生,因此滚轮的每个滴答声都是独立处理的。

使用时WM_VSCROLL,您可以使用布尔变量来跟踪滚动状态,以便您可以检测到 BeginScroll,然后消息会通知您 EndScroll。

尝试这个:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, ComCtrls;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    IsScrolling: Boolean;
    PreviousWndProc: TWndMethod;
    procedure ListViewWndProc(var Message: TMessage);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  Commctrl;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  PreviousWndProc := ListView1.WindowProc;
  ListView1.WindowProc := ListViewWndProc;
end;

procedure TForm1.ListViewWndProc(var Message: TMessage);
{
type
  NMLVSCROLL = record
    hdr: NMHDR;
    dx: Integer;
    dy: Integer;
  end;
  LPNMLVSCROLL = ^NMLVSCROLL;
}
begin
  PreviousWndProc(Message);
  case Message.Msg of
    {
    CN_NOTIFY:
    begin
      case TWMNotify(Message).NMHdr^.code of
        LVN_BEGINSCROLL:
        begin
          if not IsScrolling then
          begin
            IsScrolling := True;
            // do something...
            // use LPNMLVSCROLL(Message.LParam) if needed...
          end;
        end;
        LVN_ENDSCROLL:
        begin
          if IsScrolling then
          begin
            IsScrolling := False;
            // do something...
            // use LPNMLVSCROLL(Message.LParam) if needed...
          end;
        end;
      end;
    end;
    }
    WM_VSCROLL:
    begin
      if TWMVScroll(Message).ScrollCode = SB_ENDSCROLL then
      begin
        if IsScrolling then
        begin
          IsScrolling := False;
          // do something...
        end;
      end
      else if not IsScrolling then
      begin
        IsScrolling := True;
        // do something...
      end;
    end;
  end;
end;

end.
于 2012-09-06T17:59:34.770 回答