ListView扩展

博客内容讲述了如何扩展Delphi的ListView控件,使其能够响应列表头移动事件。作者通过获取列表头的句柄并替换其窗口过程,创建了一个新的TListviewEx类,包含了OnHeadMoved事件,该事件在列表头移动完成后触发。文章还提供了相关代码实现。
摘要由CSDN通过智能技术生成

在论坛上看一个贴,问能不能在ListView的列表头移动时响应事件,随翻查了ListView的事件,发现竟没有。于是自己动手来写一个。

其实要响应这个事件也不算难,关键是了解ListView的结构,ListView的列头其实也是一个窗口,不信用Spy看一下。我们只要获得了这个头的句柄,那它的一举一动便逃不过程序的眼睛了(^ ^)。

获得了句柄,再用一个新的窗口过程代替旧的窗口过程,当然这个新的窗口过程最后得成一个类的成员,这个用DelphiMakeObjectInstance可以轻松完成。这样就可以在新的窗口过程中操纵列表头。

理论已经具备,接下来就是动手,想了一想,该功能还是挺常用的,不如扩展到控件去,造福他人,岂不是快哉!

于是就有了下面的控件,可以装上去,用起来更方便,OnHeadMoved事件,处理这个事件即可。不过先声明,这个事件可是等你移动完成之后才触发的:

unit ListviewEx;

 

{*******************************************

 * brief: 一个可以响应列表头移动事件的ListView

 * autor: linzhenqun

 * date: 2005-8-14

 * email: linzhengqun@163.com

 * blog: http://blog.csdn.net/linzhengqun

********************************************}

 

interface

 

uses

  Windows, Messages, SysUtils, Classes, Controls, ComCtrls, CommCtrl;

 

type

  TListviewEx = class(TListView)

  private

    FHeaderHandle: THandle;

    FHeaderInst: Pointer;

    FOldHeaderProc: Pointer;

    FOnHeaderMoved: TNotifyEvent;

 

    FDown: Boolean;

    FColsWidth: array of Integer;

    procedure SaveColumnsWidth;

    function ColumnsWidthChange: Boolean;

  protected

    procedure CreateWnd; override;

    procedure NewHeaderProc(var Message: TMessage);

  public

    destructor Destroy; override;

  published

    property OnHeadMoved: TNotifyEvent read FOnHeaderMoved

      write FOnHeaderMoved;

  end;

 

procedure Register;

 

implementation

 

procedure Register;

begin

  RegisterComponents('Samples', [TListviewEx]);

end;

 

{ TListviewEx }

 

function TListviewEx.ColumnsWidthChange: Boolean;

var

  i, C: Integer;

begin

  Result := False;

  if Length(FColsWidth) > Columns.Count then

    C := Columns.Count

  else

    C := Length(FColsWidth);

  for i := 0 to C - 1 do

    if FColsWidth[i] <> Columns[i].Width then

    begin

      Result := True;

      break;

    end;

end;

 

procedure TListviewEx.CreateWnd;

begin

  inherited;

  FDown := False;

  FHeaderHandle := ListView_GetHeader(Handle);

  if FHeaderHandle <> 0 then

  begin

    FHeaderInst := MakeObjectInstance(NewHeaderProc);

    FOldHeaderProc := Pointer(GetWindowLong(FHeaderHandle, GWL_WNDPROC));

    SetWindowLong(FHeaderHandle, GWL_WNDPROC, Longint(FHeaderInst));

  end;

end;

 

destructor TListviewEx.Destroy;

begin

  if FHeaderHandle <> 0 then

  begin

    SetWindowLong(FHeaderHandle, GWL_WNDPROC, Longint(FOldHeaderProc));

    FreeObjectInstance(FHeaderInst);

  end;

  inherited;

end;

 

procedure TListviewEx.NewHeaderProc(var Message: TMessage);

begin

  Message.Result := CallWindowProc(FOldHeaderProc, FHeaderHandle,

    Message.Msg, Message.WPARAM, Message.LPARAM);

  if not (csDesigning  in ComponentState) then

    if Message.Msg = WM_LBUTTONDOWN then

    begin

      FDown := True;

      SaveColumnsWidth;

    end

    else if Message.Msg = WM_LBUTTONUP then

    begin

      if FDown and ColumnsWidthChange then

        if Assigned(FOnHeaderMoved) then

          FOnHeaderMoved(Self);

      FDown := False;

    end

    else if Message.Msg = WM_LBUTTONDBLCLK then

    begin

      if ColumnsWidthChange then

        if Assigned(FOnHeaderMoved) then

          FOnHeaderMoved(Self);

      FDown := False;

    end;

end;

 

procedure TListviewEx.SaveColumnsWidth;

var

  i: Integer;

begin

  FColsWidth := nil;

  SetLength(FColsWidth, Columns.Count);

  for i:= 0 to Columns.Count - 1 do

    FColsWidth[i] := Columns[i].Width;

end;

 

end.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值