我用了一个具有排序功能的LISTVIEW 控件,是继承自 LISTVIEW 的, 我想让这个自定义的控件也能具有XP风格,就是利用 DELPHI 自带的 XPMAN 时,有XP效果,但总是报错,请各位大侠帮忙看看吧,不胜感激!错误信息: raised exception class EStackOverFlow with message 'Stack OverFlow';出错的地方提示是:ComCtrls 的 Result := CallWindowProc(FDefHeaderProc, FHeaderHandle, Msg, WParam, LParam);我的代码:
-----------------------------------------------------------------------------------------
unit SortListView;
interface
uses
Windows, SysUtils, Messages, Classes, Graphics, Controls, ComCtrls, CommCtrl;type
TSortListView = class; TSortListView = class(TListView)
private
FaToz :Boolean;
FoldCol :Integer;
FPicture :TPicture;
procedure DrawHeaderItem(pDS:PDrawItemStruct);
procedure SetHeaderStyle(phd:PHDNotify);
procedure SetPicture(Value: TPicture);
procedure PictureChanged(Sender: TObject);
procedure LCustomDraw(Sender: TCustomListView; const ARect: TRect; var DefaultDraw: Boolean);//virtual;
procedure DrawBack;
protected
procedure WndProc(var Message : TMessage); override;
public
constructor Create(AOwner: TComponent); override;
procedure CreateWnd; override;
destructor Destroy; override;
procedure SortColumn(Column: TListColumn);
published
property BackPicture: TPicture read FPicture write SetPicture;
end;procedure Register;implementationprocedure Register;
begin
RegisterComponents('SortListView', [TSortListView]);
end;constructor TSortListView.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPicture:=TPicture.Create;
FPicture.OnChange:=PictureChanged;
OnCustomDraw:=LCustomDraw;
end;
procedure TSortListView.CreateWnd;
begin
inherited CreateWnd;
if HandleAllocated then HandleNeeded;
end;destructor TSortListView.Destroy;
begin
FPicture.Free;
inherited Destroy;
end;procedure TSortListView.SetPicture(Value: TPicture);
begin
FPicture.Assign(Value);
end;procedure TSortListView.PictureChanged(Sender: TObject);
begin
Invalidate;
end;procedure TSortListView.LCustomDraw(Sender: TCustomListView; const ARect: TRect; var DefaultDraw: Boolean);begin
if (FPicture.Graphic<>nil)then begin
DrawBack;
SetBkMode(Canvas.Handle,TRANSPARENT);
ListView_SetTextBKColor(Handle,CLR_NONE);
end;
end;procedure TSortListView.DrawBack;
var x,y,dx: Integer;
begin
x:=0;
y:=0;
if Items.Count>0 then begin
if ViewStyle = vsReport then x:=TopItem.DisplayRect(drBounds).Left
else x:=Items[0].DisplayRect(drBounds).Left;
y:=Items[0].DisplayRect(drBounds).Top - 2;
end;
if X>0 then x:=0;
dx:=x;
while y<=ClientHeight do begin
while x<=ClientWidth do begin
Canvas.Draw(x,y,FPicture.Graphic);
inc(x,FPicture.Graphic.Width);
end;
inc(y,FPicture.Graphic.Height);
x:=dx;
end;
end;
//==================================================================
procedure TSortListView.WndProc(var Message : TMessage);
var pDS :PDrawItemStruct;
phd :PHDNotify;
begin
inherited WndProc(Message);
with Message do
case Msg of
WM_DRAWITEM :
begin
pDS := PDrawItemStruct(Message.lParam);
if pDS.CtlType<>ODT_MENU then begin
DrawHeaderItem(pDS);
Result := 1;
end;
end;
WM_NOTIFY:
begin
phd := PHDNotify(Message.lParam);
if (phd.Hdr.hwndFrom = GetDlgItem(Handle, 0)) then
Case phd.Hdr.code of
HDN_ITEMCLICK,HDN_ITEMCLICKW:
begin
SortColumn(Columns.Items[phd.item]);
InvalidateRect(GetDlgItem(Handle, 0), nil, true);
end;
HDN_ENDTRACK,HDN_ENDTRACKW,HDN_ITEMCHANGED:
Begin
SetHeaderStyle(phd);
end;
end;
end;
end;
end;//=====================================================================
var AtoZOrder: Boolean;
function CustomSortProc(Item1, Item2: TListItem; ParamSort: Integer): Integer; stdcall;
begin
case ParamSort of
0:
if AtoZOrder then
Result := lstrcmp(PChar(TListItem(Item1).Caption), PChar(TListItem(Item2).Caption))
else
Result := -lstrcmp(PChar(TListItem(Item1).Caption), PChar(TListItem(Item2).Caption));
else
if(AtoZOrder) then
Result := lstrcmp(PChar(TListItem(Item1).SubItems[ParamSort-1]), PChar(TListItem(Item2).SubItems[ParamSort-1]))
else
Result := -lstrcmp(PChar(TListItem(Item1).SubItems[ParamSort-1]), PChar(TListItem(Item2).SubItems[ParamSort-1]));
end;
end;procedure TSortListView.SortColumn(Column: TListColumn);
begin
if FOldCol = Column.Index then
FaToz := not FAtoZ
else
FOldCol := Column.Index;
AtoZOrder := FaToz;
CustomSort(@CustomSortProc, Column.Index);
end;
//=====================================================================procedure TSortListView.DrawHeaderItem(pDS :PDrawItemStruct);
var
tmpCanvas :TCanvas;
tmpLeft :Integer;
begin
tmpCanvas := TCanvas.Create;
tmpCanvas.Handle:=pDS.hDC;
tmpCanvas.Brush.Style:=bsClear;
tmpCanvas.TextOut(pDS^.rcItem.Left+6,pDS^.rcItem.Top+2,Columns[pDS^.itemID].Caption);
if (abs(pDS^.itemID) <> FOldCol) then Exit;
with tmpCanvas do
with pDS^.rcItem do
begin
tmpLeft := TextWidth(Columns[pDS^.itemID].Caption) + Left + 16;
if FAtoZ then
begin
Pen.Color := clBtnHighlight;
MoveTo(tmpLeft, Bottom - 5);
LineTo(tmpLeft + 8, Bottom - 5);
Pen.Color := clBtnHighlight;
LineTo(tmpLeft + 4, Top + 5);
Pen.Color := clBtnShadow;
LineTo(tmpLeft, Bottom - 5);
end else
begin
Pen.Color := clBtnShadow;
MoveTo(tmpLeft, Top + 5);
LineTo(tmpLeft + 8, Top + 5);
Pen.Color := clBtnHighlight;
LineTo(tmpLeft + 4, Bottom - 5);
Pen.Color := clBtnShadow;
LineTo(tmpLeft, Top + 5);
end;
end;
tmpCanvas.Free;
end;procedure TSortListView.SetHeaderStyle(phd:PHDNotify);
var
i :integer;
hdi :THDItem;
begin
for i := 0 to Columns.Count - 1 do
begin
hdi.Mask:= HDF_STRING or HDI_FORMAT;
hdi.fmt := HDF_STRING or HDF_OWNERDRAW;
Header_SetItem(phd.Hdr.hwndFrom, i, hdi);
end;
end;
//=====================================================================
end.
-----------------------------------------------------------------------------------------
unit SortListView;
interface
uses
Windows, SysUtils, Messages, Classes, Graphics, Controls, ComCtrls, CommCtrl;type
TSortListView = class; TSortListView = class(TListView)
private
FaToz :Boolean;
FoldCol :Integer;
FPicture :TPicture;
procedure DrawHeaderItem(pDS:PDrawItemStruct);
procedure SetHeaderStyle(phd:PHDNotify);
procedure SetPicture(Value: TPicture);
procedure PictureChanged(Sender: TObject);
procedure LCustomDraw(Sender: TCustomListView; const ARect: TRect; var DefaultDraw: Boolean);//virtual;
procedure DrawBack;
protected
procedure WndProc(var Message : TMessage); override;
public
constructor Create(AOwner: TComponent); override;
procedure CreateWnd; override;
destructor Destroy; override;
procedure SortColumn(Column: TListColumn);
published
property BackPicture: TPicture read FPicture write SetPicture;
end;procedure Register;implementationprocedure Register;
begin
RegisterComponents('SortListView', [TSortListView]);
end;constructor TSortListView.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPicture:=TPicture.Create;
FPicture.OnChange:=PictureChanged;
OnCustomDraw:=LCustomDraw;
end;
procedure TSortListView.CreateWnd;
begin
inherited CreateWnd;
if HandleAllocated then HandleNeeded;
end;destructor TSortListView.Destroy;
begin
FPicture.Free;
inherited Destroy;
end;procedure TSortListView.SetPicture(Value: TPicture);
begin
FPicture.Assign(Value);
end;procedure TSortListView.PictureChanged(Sender: TObject);
begin
Invalidate;
end;procedure TSortListView.LCustomDraw(Sender: TCustomListView; const ARect: TRect; var DefaultDraw: Boolean);begin
if (FPicture.Graphic<>nil)then begin
DrawBack;
SetBkMode(Canvas.Handle,TRANSPARENT);
ListView_SetTextBKColor(Handle,CLR_NONE);
end;
end;procedure TSortListView.DrawBack;
var x,y,dx: Integer;
begin
x:=0;
y:=0;
if Items.Count>0 then begin
if ViewStyle = vsReport then x:=TopItem.DisplayRect(drBounds).Left
else x:=Items[0].DisplayRect(drBounds).Left;
y:=Items[0].DisplayRect(drBounds).Top - 2;
end;
if X>0 then x:=0;
dx:=x;
while y<=ClientHeight do begin
while x<=ClientWidth do begin
Canvas.Draw(x,y,FPicture.Graphic);
inc(x,FPicture.Graphic.Width);
end;
inc(y,FPicture.Graphic.Height);
x:=dx;
end;
end;
//==================================================================
procedure TSortListView.WndProc(var Message : TMessage);
var pDS :PDrawItemStruct;
phd :PHDNotify;
begin
inherited WndProc(Message);
with Message do
case Msg of
WM_DRAWITEM :
begin
pDS := PDrawItemStruct(Message.lParam);
if pDS.CtlType<>ODT_MENU then begin
DrawHeaderItem(pDS);
Result := 1;
end;
end;
WM_NOTIFY:
begin
phd := PHDNotify(Message.lParam);
if (phd.Hdr.hwndFrom = GetDlgItem(Handle, 0)) then
Case phd.Hdr.code of
HDN_ITEMCLICK,HDN_ITEMCLICKW:
begin
SortColumn(Columns.Items[phd.item]);
InvalidateRect(GetDlgItem(Handle, 0), nil, true);
end;
HDN_ENDTRACK,HDN_ENDTRACKW,HDN_ITEMCHANGED:
Begin
SetHeaderStyle(phd);
end;
end;
end;
end;
end;//=====================================================================
var AtoZOrder: Boolean;
function CustomSortProc(Item1, Item2: TListItem; ParamSort: Integer): Integer; stdcall;
begin
case ParamSort of
0:
if AtoZOrder then
Result := lstrcmp(PChar(TListItem(Item1).Caption), PChar(TListItem(Item2).Caption))
else
Result := -lstrcmp(PChar(TListItem(Item1).Caption), PChar(TListItem(Item2).Caption));
else
if(AtoZOrder) then
Result := lstrcmp(PChar(TListItem(Item1).SubItems[ParamSort-1]), PChar(TListItem(Item2).SubItems[ParamSort-1]))
else
Result := -lstrcmp(PChar(TListItem(Item1).SubItems[ParamSort-1]), PChar(TListItem(Item2).SubItems[ParamSort-1]));
end;
end;procedure TSortListView.SortColumn(Column: TListColumn);
begin
if FOldCol = Column.Index then
FaToz := not FAtoZ
else
FOldCol := Column.Index;
AtoZOrder := FaToz;
CustomSort(@CustomSortProc, Column.Index);
end;
//=====================================================================procedure TSortListView.DrawHeaderItem(pDS :PDrawItemStruct);
var
tmpCanvas :TCanvas;
tmpLeft :Integer;
begin
tmpCanvas := TCanvas.Create;
tmpCanvas.Handle:=pDS.hDC;
tmpCanvas.Brush.Style:=bsClear;
tmpCanvas.TextOut(pDS^.rcItem.Left+6,pDS^.rcItem.Top+2,Columns[pDS^.itemID].Caption);
if (abs(pDS^.itemID) <> FOldCol) then Exit;
with tmpCanvas do
with pDS^.rcItem do
begin
tmpLeft := TextWidth(Columns[pDS^.itemID].Caption) + Left + 16;
if FAtoZ then
begin
Pen.Color := clBtnHighlight;
MoveTo(tmpLeft, Bottom - 5);
LineTo(tmpLeft + 8, Bottom - 5);
Pen.Color := clBtnHighlight;
LineTo(tmpLeft + 4, Top + 5);
Pen.Color := clBtnShadow;
LineTo(tmpLeft, Bottom - 5);
end else
begin
Pen.Color := clBtnShadow;
MoveTo(tmpLeft, Top + 5);
LineTo(tmpLeft + 8, Top + 5);
Pen.Color := clBtnHighlight;
LineTo(tmpLeft + 4, Bottom - 5);
Pen.Color := clBtnShadow;
LineTo(tmpLeft, Top + 5);
end;
end;
tmpCanvas.Free;
end;procedure TSortListView.SetHeaderStyle(phd:PHDNotify);
var
i :integer;
hdi :THDItem;
begin
for i := 0 to Columns.Count - 1 do
begin
hdi.Mask:= HDF_STRING or HDI_FORMAT;
hdi.fmt := HDF_STRING or HDF_OWNERDRAW;
Header_SetItem(phd.Hdr.hwndFrom, i, hdi);
end;
end;
//=====================================================================
end.
解决方案 »
- 为何把FormStyle改成Normal后这个Form一被创建便会自动弹出?
- fastReport实用问题,在线特等......
- 各位知道哪里有MARC数据生成源码??delphi的
- 我的数据库连接代码为什么不能跨网连接?是因为防火墙吗?
- 如何实现使combobox.text的内容是combobox.items.text?
- ★★关于拷贝目录树的问题?
- paradox配置的数据库出了问题
- 哪位高手能帮我一下
- 如何让不规则窗体拖动时,不显示原窗体的边框?
- 请问cxgrid中如何可设置成象EXCLE那样可计算?
- 我客戶端是ado2.8,服務器上是SQL2000,ado2.7,是否對客戶端有什麼影響?
- 与大家分享权限管理模块的设计,并希望得到改进。。。sorry,没分了
摘自别处:
type
PSortInfo = ^TSortInfo;
TSortInfo = record
Col : Integer;
Style : TSortStyle;
Asc : Boolean;
end;function ListViewCompare(I1, I2: TListItem; Data: Integer): Integer; stdcall;
var
V1, V2: string; function Sign(Val: Extended): Integer;
begin
if Val < 0 then
Result := -1
else if Val > 0 then
Result := 1
else
Result := 0;
end; function ExtractNum(const S: string): string;
var
i, j: Integer;
begin
j := 0;
for i := 1 to Length(S) do
if S[i] in ['0'..'9'] then
Inc(j)
else
Break;
if j = 0 then
Result := '0'
else
Result := Copy(S,1,j);
end;
begin
with PSortInfo(Data)^ do
begin if Col = 0 then
begin
V1 := I1.Caption;
V2 := I2.Caption;
end
else
begin
V1 := I1.SubItems[Col-1];
V2 := I2.SubItems[Col-1];
end; case Style of
ssAlpha : Result := AnsiCompareText(V1,V2);
ssNumeric : Result := Sign(StrToFloat(ExtractNum(V1))-StrToFloat(ExtractNum(V2)));
ssDateTime : Result := Sign(StrToDateTime(V1) - StrToDateTime(V2));
else
Result := 0;
end; if not Asc then
Result := -Result;
end;
end;procedure SortListView(ListView:TListView; ColumnIndex:Integer;
Style: TSortStyle; Ascending: Boolean=True);
{排序ListView,ColumnIndex:排序列索引号,
Style 排序方式:按字符,按数值,按日期(日期格式为
SysUtils.ShortDataTimeFmt,缺省为YY-MM-DD);
Ascending:=True按升序,否则按降序}
var
FSortInfo:TSortInfo;
begin
FSortInfo.Col := ColumnIndex;
FSortInfo.Style := Style;
FSortInfo.Asc := Ascending;
ListView.CustomSort(@ListViewCompare,LongInt(@FSortInfo));
end;