风中之歌

我是世界的光

用户操作
[即时聊天] [发私信] [加为好友]
linzhenqunID:linzhengqun
84349次访问,排名1225,好友9人,关注者26人。
程序,设计,音乐,
linzhengqun的文章
原创 49 篇
翻译 0 篇
转载 0 篇
评论 119 篇
linzhenqun的公告

我们生的时候啊,
要像夏季的花一样灿烂;
而在死的时候,
须如秋天的叶一般静美!

seo sydney
seo sydney Counter

最近评论
linzhengqun:呵,不好意思我不是底层的开发人员,所以对Ring0的东西其实知之甚少。
不过作为一个优秀的程序员,应该有能力自学这些东西。
hzfch:看了你的文章和提供的代码对我帮助很大
谢谢了
希望你写一些ring0 hook的文章
wwp3321:只能说声谢谢了,谢谢楼主的共享精神
trytobegood:好东东!!!收藏了
yunhaisoft://你的这个版本中文乱码,我参考Cnpack的代码帮着你改了一下,你看看。经测试已经没有乱码了。
procedure TConvRTF.ChangeSpeString(var S: String);
var
Str: string;
i: Integer;
Len: Integer;
tmpWide, tmpStr:……
文章分类
收藏
相册
CodeGear纪念
GDI绘制
MFC文档视图
MFC消息分派
玻璃效果
汇编与高级语言
接口的实现
增量搜索
最简单的MFC程序
友情链接
Ari
天蝎蝴蝶的专栏
还猪哥哥
醉到天亮说晚安
风中之歌-非技术Blog
存档
软件项目交易
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 ListView扩展收藏

新一篇: 浅析Delphi Container库 | 旧一篇: Delphi的持久化

在论坛上看一个贴,问能不能在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.

发表于 @ 2005年10月18日 19:03:00|评论(loading...)|编辑

新一篇: 浅析Delphi Container库 | 旧一篇: Delphi的持久化

评论

#测试 发表于2005-10-29 19:18:00  IP: 211.100.21.*
测试测试
#me2 发表于2006-01-17 10:12:00  IP: 218.13.188.*
真是太好了,一直都在找有这样事件的控件
不知能否加一个点击标题栏自动排序的功能呢。
发表评论  


当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
Csdn Blog version 3.1a
Copyright © linzhenqun