{*******************************************************} { } { ComponentName : SJListView } { Version : 2.2a } { Author : SJ(小笨苯) } { E_Mail : [email protected] } { Last Modified : 2002-5-15 } { History : } { 修改 : 2004-12-25 afan } { } {*******************************************************}unit SJListView;interfaceuses Windows, Messages, SysUtils, Classes, ComCtrls, Commctrl, WinSock, Controls;type TListView2 = class(TListView) private { Private declarations } ArrowUp : HBitMap; ArrowDown : HBitMap; CurColumn: integer; vHandle: HWND; procedure SetHeaderBitmap(Col: integer);//画Header protected { Protected declarations } //procedure WndProc(var Msg : TMessage); override; public { Public declarations } constructor Create(AOwner: TComponent); override; procedure CreateWnd; override; destructor Destroy; override; published { Published declarations } end;type TMainListview = class(TListview2) private FEnabledColumnSort: boolean; protected procedure WndProc(var Msg: TMessage); override; Public constructor Create(AOwner: TComponent); override; Published property EnabledColumnSort: boolean read FEnabledColumnSort write FEnabledColumnSort; end; type TMyListview = class(TListview2) protected procedure WndProc(var Msg: TMessage); override; end;procedure Register;const COLUMN_UP = 1; //向上 COLUMN_DOWN = -1; //向下 //COLUMN_SHOW = 2; //显示的列 COLUMN_HIDE = -2; //隐藏的列 implementation{$R SJListView.res} { 通用排序函数 } Function CustomSortProc( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall; begin Result:=0; if (Item1=nil) or (Item2=nil)then exit; if lParam = 0 then result := CompareText(Item1.Caption,Item2.Caption ) else if lparam > 0 then begin { 有的列可能是空的null,点击排序会raise exception } if (LParam > Item1.SubItems.Count) or (LParam > Item2.SubItems.Count) then exit; result := CompareText(Item1.SubItems[Lparam-1],Item2.SubItems[Lparam-1]); end; Result:= Result * Item1.ListView.Column[lParam].Tag ; end; function CustomSortProcMain( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall; var ip1,ip2:cardinal; a,b: integer; s1,s2:String; begin Result:=0; if (Item1 = nil)or(Item2 = nil)then exit; { 有的列可能是空的null,点击排序会raise exception } if LParam > 0 then begin if (LParam > Item1.SubItems.Count) then begin result:= -1; exit; end else if (LParam > Item2.SubItems.Count) then begin result:= 1; exit; end; end; if lParam = 0 then result := CompareText(Item1.Caption,Item2.Caption ) else if lparam =2 then begin //排序 ip 采用新算法 s1:=Item1.SubItems[1]; s2:=Item2.SubItems[1]; result:= CompareText(s1,s2); end else begin { 有图片的项目 } a:= Item1.SubItemImages[LParam-1]; b:= Item2.SubItemImages[LParam-1]; if a + b <> -2 then result:= a - b else result := CompareText(Item1.SubItems[Lparam-1],Item2.SubItems[Lparam-1]) ; end; Result:= Result * Item1.ListView.Column[lParam].Tag ; end;constructor TListview2.Create(AOwner: TComponent); begin inherited Create(AOwner); ArrowUp := LoadImage(hInstance, 'ArrowUp', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); ArrowDown := LoadImage(hInstance, 'ArrowDown', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); //SetHeaderBitmap; end;procedure TListview2.CreateWnd; begin inherited CreateWnd; if HandleAllocated then HandleNeeded; vHandle := ListView_GetHeader(Handle); end;destructor TListview2.Destroy; begin DeleteObject(ArrowUp); DeleteObject(ArrowDown); inherited Destroy; end;
procedure TListview2.SetHeaderBitmap(Col: integer); var HdItem : THdItem; begin FillChar(HdItem, SizeOf(HdItem), #0); HdItem.Mask := HDI_FORMAT; Header_GetItem(vHandle, Col, HdItem); HdItem.Mask := HDI_BITMAP or HDI_FORMAT; if Column[Col].Tag = COLUMN_DOWN then begin { 反向 } HdItem.fmt := HdItem.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT; HdItem.hbm := LoadImage(hInstance, 'ArrowDown', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); end else if Column[Col].Tag = COLUMN_UP then begin { 正向 } HdItem.fmt := HdItem.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT; HdItem.hbm := LoadImage(hInstance, 'ArrowUp', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); end else begin{ 消除箭头 } HdItem.fmt := HdItem.fmt and not (HDF_BITMAP or HDF_BITMAP_ON_RIGHT); HdItem.hbm := 0; end; Header_SetItem(vHandle, Col, HdItem); end;(* procedure TListview2.WndProc(var Msg : TMessage); var pHD : PHDNotify; i: integer; begin inherited WndProc(Msg); if Msg.Msg = WM_NOTIFY then //如果截获的消息是WM_NOTIFY begin pHD := PHDNotify(Msg.LParam); HwndFrom:= pHD.Hdr.hwndFrom ; if (hwndFrom = vHandle) and (vHandle <> 0) then begin wmCode:= 0; Case pHD.HDr.code of { 如果是点击Header } HDN_ITEMCLICK,HDN_ITEMCLICKW: begin CurColumn := Columns.Items[pHD.item].Index; wmCode:= pHD.Hdr.code ; { 做标记,正向或反向排序 } for i:= 0 to Columns.Count - 1 do begin if I = CurColumn then begin if Column[I].Tag = 0 then Column[I].Tag := 1 else Column[I].Tag := -1 * Column[I].Tag ; SetHeaderBitmap(I); end else begin if Column[I].Tag <> 0 then begin Column[I].Tag := 0; SetHeaderBitmap(I); end; end; end; {of FOR} { 排序 } //CustomSort(@CustomSortProc, CurColumn); end; { 拖动改变宽度时,ColumnItem <> 原来排序的列 } HDN_ENDTRACK,HDN_ENDTRACKW: Begin CurColumn:= Columns.Items[pHD.item].Index; if Columns[CurColumn].Tag <> 0 then SetHeaderBitmap(CurColumn); end; end; end; end; end; *)Procedure TMyListview.WndProc(var Msg: TMessage); var pHD : PHDNotify; i: integer; begin inherited WndProc(Msg); if Msg.Msg = WM_NOTIFY then //如果截获的消息是WM_NOTIFY begin pHD := PHDNotify(Msg.LParam); if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin Case pHD.HDr.code of { 如果是点击Header } HDN_ITEMCLICKA,HDN_ITEMCLICKW: begin CurColumn := Columns.Items[pHD.item].Index; { 做标记,正向或反向排序 } for i:= 0 to Columns.Count - 1 do begin if I = CurColumn then begin if Column[I].Tag = 0 then Column[I].Tag := COLUMN_UP else Column[I].Tag := -1 * Column[I].Tag ; SetHeaderBitmap(I); end else begin if Column[I].Tag <> 0 then begin Column[I].Tag := 0; SetHeaderBitmap(I); end; end; end; {of FOR} { 排序 } CustomSort(@CustomSortProc, CurColumn); end; { 拖动改变宽度时,ColumnItem <> 原来排序的列 } HDN_ENDTRACKA,HDN_ENDTRACKW,HDN_DIVIDERDBLCLICKA,HDN_DIVIDERDBLCLICKW: Begin CurColumn:= Columns.Items[pHD.item].Index; if Columns[CurColumn].Tag <> 0 then SetHeaderBitmap(CurColumn); end; end; end; end; end;{ 主窗口中的列表框 } constructor TMainListview.Create(AOwner: TComponent); begin inherited Create(AOwner); FEnabledColumnSort:= true; end;procedure TMainListview.WndProc(var Msg: TMessage); var pHD : PHDNotify; i: integer; begin { 如果截获的消息是WM_NOTIFY } if Msg.Msg = WM_NOTIFY then begin pHD := PHDNotify(Msg.LParam); Case pHD.HDr.code of HDN_BeginTrackA, HDN_BeginTrackW: if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin { 隐藏列 } if Columns.Items[pHD.item].Tag = COLUMN_HIDE then begin msg.Result := 1; exit; end; end; end; {of CASE} end; inherited WndProc(Msg); if Msg.Msg = WM_NOTIFY then begin pHD := PHDNotify(Msg.LParam); if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin Case pHD.HDr.code of { 如果是点击Header } HDN_ITEMCLICK,HDN_ITEMCLICKW: begin if not FEnabledColumnSort then exit; CurColumn := Columns.Items[pHD.item].Index; { 做标记,正向或反向排序 } for i:= 0 to Columns.Count - 1 do begin if I = CurColumn then begin if Column[I].Tag = 0 then Column[I].Tag := COLUMN_UP else Column[I].Tag := -1 * Column[I].Tag ; SetHeaderBitmap(I); end else begin if Column[I].Tag = COLUMN_HIDE then SetHeaderBitmap(I) { 对于隐藏的列,不要改变标记 } else if Column[I].Tag <> 0 then begin Column[I].Tag := 0; SetHeaderBitmap(I); end; end; end; {of FOR} { 排序 } CustomSort(@CustomSortProcMain, CurColumn); end; { 拖动改变宽度时,ColumnItem <> 原来排序的列 } HDN_ENDTRACKA,HDN_ENDTRACKW,HDN_DIVIDERDBLCLICKA,HDN_DIVIDERDBLCLICKW: Begin CurColumn:= Columns.Items[pHD.item].Index; if Columns[CurColumn].Tag <> 0 then SetHeaderBitmap(CurColumn); end; end; end; end; end; procedure Register; begin RegisterComponents('Win32', [TMainListView, TMyListview]); end; end.
{ }
{ ComponentName : SJListView }
{ Version : 2.2a }
{ Author : SJ(小笨苯) }
{ E_Mail : [email protected] }
{ Last Modified : 2002-5-15 }
{ History : }
{ 修改 : 2004-12-25 afan }
{ }
{*******************************************************}unit SJListView;interfaceuses
Windows, Messages, SysUtils, Classes, ComCtrls, Commctrl, WinSock, Controls;type
TListView2 = class(TListView)
private
{ Private declarations }
ArrowUp : HBitMap;
ArrowDown : HBitMap;
CurColumn: integer;
vHandle: HWND; procedure SetHeaderBitmap(Col: integer);//画Header
protected
{ Protected declarations }
//procedure WndProc(var Msg : TMessage); override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
procedure CreateWnd; override;
destructor Destroy; override;
published
{ Published declarations }
end;type
TMainListview = class(TListview2)
private
FEnabledColumnSort: boolean;
protected
procedure WndProc(var Msg: TMessage); override;
Public
constructor Create(AOwner: TComponent); override;
Published
property EnabledColumnSort: boolean read FEnabledColumnSort write FEnabledColumnSort;
end;
type
TMyListview = class(TListview2)
protected
procedure WndProc(var Msg: TMessage); override;
end;procedure Register;const
COLUMN_UP = 1; //向上
COLUMN_DOWN = -1; //向下
//COLUMN_SHOW = 2; //显示的列
COLUMN_HIDE = -2; //隐藏的列
implementation{$R SJListView.res}
{ 通用排序函数 }
Function CustomSortProc( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall;
begin
Result:=0;
if (Item1=nil) or (Item2=nil)then
exit;
if lParam = 0 then
result := CompareText(Item1.Caption,Item2.Caption )
else if lparam > 0 then begin
{ 有的列可能是空的null,点击排序会raise exception }
if (LParam > Item1.SubItems.Count) or (LParam > Item2.SubItems.Count) then
exit;
result := CompareText(Item1.SubItems[Lparam-1],Item2.SubItems[Lparam-1]);
end;
Result:= Result * Item1.ListView.Column[lParam].Tag ;
end;
function CustomSortProcMain( Item1, Item2 : TListItem; lParam : LongInt ) : Integer; stdcall;
var
ip1,ip2:cardinal;
a,b: integer;
s1,s2:String;
begin
Result:=0;
if (Item1 = nil)or(Item2 = nil)then
exit;
{ 有的列可能是空的null,点击排序会raise exception }
if LParam > 0 then begin
if (LParam > Item1.SubItems.Count) then begin
result:= -1;
exit;
end
else if (LParam > Item2.SubItems.Count) then begin
result:= 1;
exit;
end;
end; if lParam = 0 then
result := CompareText(Item1.Caption,Item2.Caption )
else if lparam =2 then begin //排序 ip 采用新算法
s1:=Item1.SubItems[1];
s2:=Item2.SubItems[1];
result:= CompareText(s1,s2);
end
else begin
{ 有图片的项目 }
a:= Item1.SubItemImages[LParam-1];
b:= Item2.SubItemImages[LParam-1];
if a + b <> -2 then
result:= a - b
else
result := CompareText(Item1.SubItems[Lparam-1],Item2.SubItems[Lparam-1]) ;
end; Result:= Result * Item1.ListView.Column[lParam].Tag ;
end;constructor TListview2.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ArrowUp := LoadImage(hInstance, 'ArrowUp', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
ArrowDown := LoadImage(hInstance, 'ArrowDown', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
//SetHeaderBitmap;
end;procedure TListview2.CreateWnd;
begin
inherited CreateWnd;
if HandleAllocated then HandleNeeded;
vHandle := ListView_GetHeader(Handle);
end;destructor TListview2.Destroy;
begin
DeleteObject(ArrowUp);
DeleteObject(ArrowDown);
inherited Destroy;
end;
procedure TListview2.SetHeaderBitmap(Col: integer);
var
HdItem : THdItem;
begin
FillChar(HdItem, SizeOf(HdItem), #0); HdItem.Mask := HDI_FORMAT;
Header_GetItem(vHandle, Col, HdItem);
HdItem.Mask := HDI_BITMAP or HDI_FORMAT; if Column[Col].Tag = COLUMN_DOWN then begin { 反向 }
HdItem.fmt := HdItem.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT;
HdItem.hbm := LoadImage(hInstance, 'ArrowDown', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
end
else if Column[Col].Tag = COLUMN_UP then begin { 正向 }
HdItem.fmt := HdItem.fmt or HDF_BITMAP or HDF_BITMAP_ON_RIGHT;
HdItem.hbm := LoadImage(hInstance, 'ArrowUp', IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
end
else begin{ 消除箭头 }
HdItem.fmt := HdItem.fmt and not (HDF_BITMAP or HDF_BITMAP_ON_RIGHT);
HdItem.hbm := 0;
end; Header_SetItem(vHandle, Col, HdItem);
end;(*
procedure TListview2.WndProc(var Msg : TMessage);
var
pHD : PHDNotify;
i: integer;
begin
inherited WndProc(Msg); if Msg.Msg = WM_NOTIFY then //如果截获的消息是WM_NOTIFY
begin
pHD := PHDNotify(Msg.LParam);
HwndFrom:= pHD.Hdr.hwndFrom ;
if (hwndFrom = vHandle) and (vHandle <> 0) then begin
wmCode:= 0;
Case pHD.HDr.code of
{ 如果是点击Header }
HDN_ITEMCLICK,HDN_ITEMCLICKW:
begin
CurColumn := Columns.Items[pHD.item].Index;
wmCode:= pHD.Hdr.code ;
{ 做标记,正向或反向排序 }
for i:= 0 to Columns.Count - 1 do begin
if I = CurColumn then begin
if Column[I].Tag = 0 then
Column[I].Tag := 1
else
Column[I].Tag := -1 * Column[I].Tag ;
SetHeaderBitmap(I);
end
else begin
if Column[I].Tag <> 0 then begin
Column[I].Tag := 0;
SetHeaderBitmap(I);
end;
end;
end; {of FOR} { 排序 }
//CustomSort(@CustomSortProc, CurColumn);
end; { 拖动改变宽度时,ColumnItem <> 原来排序的列 }
HDN_ENDTRACK,HDN_ENDTRACKW:
Begin
CurColumn:= Columns.Items[pHD.item].Index;
if Columns[CurColumn].Tag <> 0 then
SetHeaderBitmap(CurColumn);
end;
end;
end;
end;
end;
*)Procedure TMyListview.WndProc(var Msg: TMessage);
var
pHD : PHDNotify;
i: integer;
begin
inherited WndProc(Msg); if Msg.Msg = WM_NOTIFY then //如果截获的消息是WM_NOTIFY
begin
pHD := PHDNotify(Msg.LParam);
if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin
Case pHD.HDr.code of
{ 如果是点击Header }
HDN_ITEMCLICKA,HDN_ITEMCLICKW:
begin
CurColumn := Columns.Items[pHD.item].Index;
{ 做标记,正向或反向排序 }
for i:= 0 to Columns.Count - 1 do begin
if I = CurColumn then begin
if Column[I].Tag = 0 then
Column[I].Tag := COLUMN_UP
else
Column[I].Tag := -1 * Column[I].Tag ;
SetHeaderBitmap(I);
end
else begin
if Column[I].Tag <> 0 then begin
Column[I].Tag := 0;
SetHeaderBitmap(I);
end;
end;
end; {of FOR} { 排序 }
CustomSort(@CustomSortProc, CurColumn);
end; { 拖动改变宽度时,ColumnItem <> 原来排序的列 }
HDN_ENDTRACKA,HDN_ENDTRACKW,HDN_DIVIDERDBLCLICKA,HDN_DIVIDERDBLCLICKW:
Begin
CurColumn:= Columns.Items[pHD.item].Index;
if Columns[CurColumn].Tag <> 0 then
SetHeaderBitmap(CurColumn);
end;
end;
end;
end;
end;{ 主窗口中的列表框 }
constructor TMainListview.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEnabledColumnSort:= true;
end;procedure TMainListview.WndProc(var Msg: TMessage);
var
pHD : PHDNotify;
i: integer;
begin
{ 如果截获的消息是WM_NOTIFY }
if Msg.Msg = WM_NOTIFY then begin
pHD := PHDNotify(Msg.LParam);
Case pHD.HDr.code of
HDN_BeginTrackA, HDN_BeginTrackW:
if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin
{ 隐藏列 }
if Columns.Items[pHD.item].Tag = COLUMN_HIDE then begin
msg.Result := 1;
exit;
end;
end;
end; {of CASE}
end; inherited WndProc(Msg); if Msg.Msg = WM_NOTIFY then
begin
pHD := PHDNotify(Msg.LParam);
if (pHD.Hdr.hwndFrom = vHandle) and (vHandle <> 0) then begin
Case pHD.HDr.code of
{ 如果是点击Header }
HDN_ITEMCLICK,HDN_ITEMCLICKW:
begin
if not FEnabledColumnSort then exit;
CurColumn := Columns.Items[pHD.item].Index;
{ 做标记,正向或反向排序 }
for i:= 0 to Columns.Count - 1 do begin
if I = CurColumn then begin
if Column[I].Tag = 0 then
Column[I].Tag := COLUMN_UP
else
Column[I].Tag := -1 * Column[I].Tag ;
SetHeaderBitmap(I);
end
else begin
if Column[I].Tag = COLUMN_HIDE then
SetHeaderBitmap(I)
{ 对于隐藏的列,不要改变标记 }
else if Column[I].Tag <> 0 then begin
Column[I].Tag := 0;
SetHeaderBitmap(I);
end;
end;
end; {of FOR} { 排序 }
CustomSort(@CustomSortProcMain, CurColumn);
end; { 拖动改变宽度时,ColumnItem <> 原来排序的列 }
HDN_ENDTRACKA,HDN_ENDTRACKW,HDN_DIVIDERDBLCLICKA,HDN_DIVIDERDBLCLICKW:
Begin
CurColumn:= Columns.Items[pHD.item].Index;
if Columns[CurColumn].Tag <> 0 then
SetHeaderBitmap(CurColumn);
end;
end;
end;
end;
end;
procedure Register;
begin
RegisterComponents('Win32', [TMainListView, TMyListview]);
end;
end.