`
javasogo
  • 浏览: 1779292 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

ListView扩展

阅读更多

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

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

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

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

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

unit ListviewEx;

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

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

* autor: linzhenqun

* date: <chsdate w:st="on" isrocdate="False" islunardate="False" day="14" month="8" year="2005">2005-8-14</chsdate>

* 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.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics