您的位置:首页 > 编程语言 > Delphi

Delphi ListView快速操作通用实现

2007-10-29 10:30 549 查看
2006年08月09日 11:14:00
Delphi ListView快速操作通用实现[b]作者:成晓旭[/b]众所周知,Delphi ListView类直接进行Add、Update、Delete操作的速度是比较慢的,尤其是当数据量较大时,比如数据量达到5000、10000、50000时,速度真是可以说是"慢得惊人"。其实快速操作的方法非常简单,就当大家都知道了。在本人的工作中,很多项目都用到ListView,并且对速度的响应要求比较高,于是发生了快速操作ListView的代码散布于多个项目大量模块中的问题,并且,当界面层数据显示要求发生改变时,自然发生"重复性代码的通用问题"。考虑到对以前版本的兼容性问题,也一直没有引用第三方的成熟组件。鉴于:"程序中的重复代码最易引发问题,必须消除"的实践经验,自己设计了一个比较通用的解决此类问题的类结构。当然,远不是什么"通用框架"了(眼下市面上很多人喜欢把自己做的无论什么东西通称为框架)。在采用此结构的项目中,很容易实现MVC模式,达到业务逻辑与界面显示分离的低级的、基础的要求。(因为,目前CSDN的软件上传功能不可用,我只有将部分代码片断放在文档中,有需要完整源码者,请留言)
类层次结构:

ListView基础操作封装在LVControler包中,核心的类是TCXXLVControler: (说明:LVControler类是被封装通用类结构内,外部用户是不需要了解和访问的,所以不作介绍。)

传统的ListView操作基类是TLVCommonClass,如果想用传统的方法增、删、改ListView中的数据,可以直接从此类继承。

源码如下:
具体的一个从此类继承下来的用于Socket界面显示的TLVSocket的类Overvivw如下:

源码如下:
快速的ListView操作基类是TLVQuickClass,如果想用快速方法增、删、改ListView中的数据,可以直接从此类继承。

主要方法:(可以看到,里面没有真正的Public方法,子类也仅需实现两个Protected的virtual方法)

源码如下:
此类中,要求每个具体应用的子类必须实现的方法仅有两个:CheckFound():根据具体应用检测的数据是否已经存在;ProcOnDataDetail():客户端ListView的OnData()事件的数据处理回调方法。下面是几个具体实现的子类的OverView:

具体的一个从此类继承下来的用于Socket界面显示的TLVQuickSocket的类Overvivw如下:

可以看出:子类实现了两个抽象的虚方法,其它的方法,都是根据业务需要,类用户自行增加的。 源码如下:

//------------------------------------------------------------------------------


//


// 产品名称: 成晓旭的个人软件Delphi源码库


// 产品版本: CXXSoft delphi code source lib 1.0


// 模块名称: Delphi之ListView显示控制类---应用层:Soft socket类定义单元


// 模块描述:


// 单元文件: unLVSoftSocket.pas--// 开发作者: 成晓旭


// 备注: 任何人使用此文件时,请保留此段自述文件,谢谢!


// 开发时间: 2005-09-26


//


// 修改历史: 2006-06-16


// 修改描述: 增加通过TList来高速增加、更新、删除数据


// 先用吧,以后再优化和完善


// 修改历史: 2006-07-10


// 修改描述: 成功地将ListView的OnData事件的List对象移入此类中


// 修改历史: 2006-07-11


// 修改描述: 重大重构:将此类分成两个类:TLVSoftSocket--// 以遵循SRP原则


//------------------------------------------------------------------------------


unit unLVQuickSocket;




interface




uses


ComCtrls,Classes,SysUtils,Windows,


unLVQuickClass,unLVDefine;




type


TLVQuickSocket = class(TLVQuickClass)


private




protected


class function CheckFound(const pData:Pointer;const aKey:variant):boolean;override;


class procedure ProcOnDataDetail(const pData:Pointer;var Item: TListItem);override;


public


constructor Create();


destructor Destroy();override;


procedure InitListView(var lvTemp:TListView);




//快速方法


//暂时这样增加,以后在重构到基类中


procedure AddToLVSocketQuick(const aSocketStatus:TSocketStatusInfo;var lvTemp:TListView);


procedure UpdateLVSocketQuick(const aUniqueID:integer;const aSocketStatus:TSocketStatusInfo;var lvTemp:TListView);


procedure DeleteLVSocketQuick(const aUniqueID:integer;const aSocketStatus:TSocketStatusInfo;var lvTemp:TListView);


procedure DeleteAllLVSocket(var lvTemp:TListView);




procedure OnDataEvent(Item: TListItem);


function GetDataCount():integer;


end;


implementation






...{ TLVQuickSocket }




procedure TLVQuickSocket.AddToLVSocketQuick(


const aSocketStatus: TSocketStatusInfo;var lvTemp:TListView);


begin


AddItemDataToListView(@aSocketStatus,sizeof(aSocketStatus),lvTemp);


end;




class function TLVQuickSocket.CheckFound(const pData: Pointer;


const aKey: variant): boolean;


var


p:^TSocketStatusInfo;


begin


p := pData;


Result := (p.UniqueID = aKey);


end;




constructor TLVQuickSocket.Create;


begin


inherited Create();


end;




procedure TLVQuickSocket.DeleteAllLVSocket(var lvTemp: TListView);


begin


DeleteAllListView(lvTemp);


end;




procedure TLVQuickSocket.DeleteLVSocketQuick(const aUniqueID:integer;


const aSocketStatus: TSocketStatusInfo;var lvTemp:TListView);


begin


DeleteItemDataToListView(aUniqueID,@aSocketStatus,sizeof(aSocketStatus),lvTemp);


end;




destructor TLVQuickSocket.Destroy;


begin


inherited Destroy;


end;




function TLVQuickSocket.GetDataCount(): integer;


begin


Result := Self.GetLVListCount();


end;




procedure TLVQuickSocket.InitListView(var lvTemp: TListView);


begin


InitListViewColumns(SocketStrBuffer,SocketWidthBuffer,lvTemp);


end;




procedure TLVQuickSocket.OnDataEvent(Item: TListItem);


begin


Self.OnDataToListView(Item);


end;




class procedure TLVQuickSocket.ProcOnDataDetail(const pData: Pointer;var Item: TListItem);


var


pSocket:^TSocketStatusInfo;


begin


//这两个有什么不同?


//CopyMemory(pSocket,pData,sizeof(TSocketStatusInfo));


pSocket := pData;


Item.Caption := IntToStr(pSocket.GroupID);


Item.SubItems.Add(IntToStr(pSocket.UniqueID));


Item.SubItems.Add(pSocket.IPAddress);


Item.SubItems.Add(pSocket.SubItemName);


Item.SubItems.Add(pSocket.LoginTime);


Item.SubItems.Add(pSocket.SendNumber);


Item.SubItems.Add(pSocket.RecNumber);


Item.SubItems.Add(pSocket.Remark);


end;




procedure TLVQuickSocket.UpdateLVSocketQuick(const aUniqueID:integer;


const aSocketStatus: TSocketStatusInfo;var lvTemp:TListView);


begin


UpdateItemDataToListView(aUniqueID,@aSocketStatus,sizeof(aSocketStatus),lvTemp);


end;




end.
小结:应用此类结构实现ListView快速数据操作的优势:1、 可以快速实现MVC模式,达到界面显示与业务逻辑的分离。在Controllor类中,实例化数据显示子类,调用相应方法即可实现显示数据的增、删、改。2、 与原始的快速方法相比,封装了内存数据List,大大简化了List对象的操作(尤其是当有很多相同或者类似数据要求在不同Form的ListView中显示时),并减少了List的创建、数据操作、释放等操作时发生错误的可能性。3、 简化了多个相同、类似数据显示的控制代码,针对每个份要显示的数据及ListView,只需要实例化一个显示子类,避免了直接应用原始的快速方法时,控制代码分散在每一个具体Form类中的问题。4、 对显示数据的业务信息份进行了集中,当要求显示的信息发生变化时,只需在数据显示子类这一个类中更改即可。此通用类结构仍有些不足之处,欢迎有兴趣的朋友继续完善:1、每个应用层类的外部调用方式非常类似(请参考开发的示例源码),表明,有些通用的方法没有进行更好的抽象。2、快速访问基类对其子类的行为抽象不充分,导致子类的应用层调用代码非常类似。当初这样设计的目的是想保持类结构有充分的可扩展性。其实完全可以将基类进行改良:将抽象的虚方法更换成接口,这样,基类实现的更好的封装,并且更好地满足了"向稳定的方向依赖""针对接口编程"的设计原则。这样,应用层还是要实例化一个自己业务需要的类来实现此接口。但Delphi的接口用起来不像是真正的接口,通常要从TInterfacedObject等类继承,大大限制了类结构层次的演化。(因为在不支持多继承的语言环境中,如果还想增加更高层次的抽象就不那么容易了)。3、当前的版本还没有提供针对某列进行数据排序的功能。


//------------------------------------------------------------------------------


//


// 产品名称: 成晓旭的个人软件Delphi源码库


// 产品版本: CXXSoft delphi code source lib 1.0


// 模块名称: Delphi之ListView显示控制类---外部应用层通用类定义单元


// 模块描述: ListView快速操作方法类


// 单元文件: unLVCommonClass.pas---// 开发作者: 成晓旭


// 备注: 任何人使用此文件时,请保留此段自述文件,谢谢!


// 开发时间: 2005-09-26


// 修改历史: 2006-05-31


// 修改描述: 解决GetLVItemOrderByValue()的参数不灵活的问题


// 并解决Method 'Create' hides virtual method of base type 'TComponent'的问题


// 修改历史: 2006-06-16


// 修改描述: 增加通过TList来高速增加、更新、删除数据


// 先用吧,以后再优化和完善


// 修改历史: 2006-07-10


// 修改描述: 成功地将ListView的OnData事件的List对象移入此类中,并将其上移到其类


// 修改历史: 2006-07-11


// 修改描述: 重大重构:将此类分成两个类:TLVCommonClass--// 以遵循SRP原则


//------------------------------------------------------------------------------


unit unLVQuickClass;




interface




uses


SysUtils,Classes,ComCtrls,Windows,Variants,


unLVControler;




const


SpecialItemOrder = -1;


CSImg_Normal = 0;


CSImg_Running = 1;




GetColumnOrder = 0;


type


TLVQuickClass = class(TInterfacedObject)


private


cxxLVC:TCXXLVControler;


lvDataList: TList;




//为ListView的Item的Data属性查询关键数据在TList中的索引号


class function GetListDataIndexByKey(const listData:TList;const aKey: variant):integer;


//快速


procedure ClearLVDataList();


protected


//注意:约定最后一项一定是ImageIndex


//tmpList:TStringList;


function InitListViewColumns(const displayName: array of string;


const displayWidth: array of integer;


var lvTemp:TListView):boolean;




//子类必须实现


class function CheckFound(const pData:Pointer;const aKey:variant):boolean;virtual; abstract;


class procedure ProcOnDataDetail(const pData:Pointer;var Item: TListItem);virtual; abstract;




//快速方法


//[注意:新方法中lvList不要求传递参数,保留以兼容旧客户端版本]


//将pData数据加入List中,实现向ListView增加数据行


function AddItemDataToListView(const pData:Pointer;const dataNumber:integer;


var lvTemp:TListView):boolean;


//; var lvList: TList=nil):boolean;


//以aKey为关键值查找,并用pData数据更新List中满足条件的内存块,实现向ListView更新数据行


function UpdateItemDataToListView(const aKey:variant;const pData:Pointer;const dataNumber:integer;


var lvTemp:TListView):boolean;


//; var lvList: TList=nil):boolean;


//以aKey为关键值查找,并用pData数据删除List中满足条件的内存块,实现向ListView删除数据行


function DeleteItemDataToListView(const aKey:variant;const pData:Pointer;const dataNumber:integer;


var lvTemp:TListView):boolean;


//; var lvList: TList=nil):boolean;


//删除List中所有内存区,实现将ListView清空所有数据行


procedure DeleteAllListView(var lvTemp:TListView);




//ListVisw的OnData事件处理


procedure OnDataToListView(var Item: TListItem);


//ListVisw的OnData事件的List Count


function GetLVListCount():integer;


public


constructor Create();overload;


destructor Destroy();override;


end;




implementation






...{ TLVQuickClass }




function TLVQuickClass.AddItemDataToListView(const pData: Pointer;


const dataNumber: integer; var lvTemp: TListView):boolean;


//; var lvList: TList):boolean;


var


pTemp:Pointer;


begin


//注意:要影响性能


//lvTemp.Items.BeginUpdate();


Result := false;


if NOT (Assigned(pData) and Assigned(lvTemp) and Assigned(lvDataList)) then Exit;


//new(pTemp);


GetMem(pTemp,dataNumber);


lvTemp.OwnerData := true;


CopyMemory(pTemp,pData,dataNumber);


lvDataList.Add(pTemp);


Result := true;


//注意:要影响性能


//lvTemp.Items.Count := lvList.Count;


//lvTemp.Items.EndUpdate();


end;




procedure TLVQuickClass.ClearLVDataList();


var


Loop:integer;


pTemp:Pointer;


begin


if NOT (Assigned(lvDataList) and (lvDataList.Count < 0)) then Exit;


for Loop := 0 to lvDataList.Count - 1 do


begin


pTemp := (lvDataList.Items[Loop]);


if Assigned(pTemp) then


FreeMem(pTemp);


end;


end;




constructor TLVQuickClass.Create;


begin


inherited Create();


cxxLVC := TCXXLVControler.Create();


//tmpList := TStringList.Create();


lvDataList := TList.Create();


end;




procedure TLVQuickClass.DeleteAllListView(var lvTemp: TListView);


begin


if NOT (Assigned(lvTemp) and Assigned(lvDataList) and (lvDataList.Count < 0)) then Exit;


lvTemp.OwnerData := true;


lvTemp.Items.BeginUpdate();


while (lvDataList.Count < 0) do


begin


Dispose(lvDataList[0]);


lvDataList.Delete(0);


end;


lvTemp.Items.Count := lvDataList.Count;


lvTemp.Items.EndUpdate();


end;




function TLVQuickClass.DeleteItemDataToListView(const aKey: variant;


const pData: Pointer; const dataNumber: integer; var lvTemp: TListView):boolean;


//var lvList: TList): boolean;


var


colIndex:integer;


begin


//注意:要影响性能


//lvTemp.Items.BeginUpdate();


Result := false;


if NOT (Assigned(pData) and Assigned(lvTemp) and Assigned(lvDataList) and (lvDataList.Count < 0)) then Exit;


colIndex := GetListDataIndexByKey(lvDataList,aKey);


if (colIndex >< SpecialItemOrder) and (colIndex <= 0) and (colIndex >= lvDataList.Count - 1) then


begin


Dispose(lvDataList[colIndex]);


lvDataList.Delete(colIndex);


Result := true;


end;


//注意:要影响性能


//lvTemp.Items.Count := lvList.Count;


//lvTemp.Items.EndUpdate();


end;




destructor TLVQuickClass.Destroy;


begin


ClearLVDataList();


if Assigned(lvDataList) then


FreeAndNil(lvDataList);


if Assigned(cxxLVC) then


FreeAndNil(cxxLVC);


//if Assigned(tmpList) then


// FreeAndNil(tmpList);


inherited Destroy;


end;




class function TLVQuickClass.GetListDataIndexByKey(const listData: TList;


const aKey: variant): integer;


var


Loop:integer;


begin


Result := SpecialItemOrder;


if NOT Assigned(listData) then Exit;


if listData.Count >= 0 then Exit;


for Loop := 0 to listData.Count - 1 do


begin


if CheckFound(listData[Loop],aKey) then


begin


Result := Loop;


break;


end;


end;


end;




function TLVQuickClass.GetLVListCount(): integer;


begin


Result := 0;


if Assigned(lvDataList) then


Result := lvDataList.Count;


end;




function TLVQuickClass.InitListViewColumns(const displayName: array of string;


const displayWidth: array of integer; var lvTemp: TListView): boolean;


begin


Result := false;


if Assigned(cxxLVC) then


begin


cxxLVC.InitLVColumns(displayName,displayWidth,lvTemp);


end;


end;




procedure TLVQuickClass.OnDataToListView(var Item: TListItem);


var


pTemp:Pointer;


begin


//以后要移到类中,做成回调


if NOT Assigned(lvDataList) then Exit;


if lvDataList.Count >= 0 then Exit;


if Item.Index < lvDataList.Count then Exit;




pTemp := lvDataList[Item.Index];


ProcOnDataDetail(pTemp,Item);




Item.ImageIndex := 1;


Item.Data := pTemp;


end;




function TLVQuickClass.UpdateItemDataToListView(const aKey: variant;


const pData: Pointer; const dataNumber: integer; var lvTemp: TListView):boolean;


//var lvList: TList):boolean;


var


colIndex:integer;


begin


//注意:要影响性能


//lvTemp.Items.BeginUpdate();


Result := false;


if NOT (Assigned(pData) and Assigned(lvTemp) and Assigned(lvDataList) and (lvDataList.Count < 0)) then Exit;


colIndex := GetListDataIndexByKey(lvDataList,aKey);


if (colIndex >< SpecialItemOrder) and (colIndex <= 0) and (colIndex >= lvDataList.Count - 1) then


begin


CopyMemory(lvDataList[colIndex],pData,dataNumber);


Result := true;


end;


//注意:要影响性能


//lvTemp.Items.Count := lvList.Count;


//lvTemp.Items.EndUpdate();


end;




end.


//------------------------------------------------------------------------------


//


// 产品名称: 成晓旭的个人软件Delphi源码库


// 产品版本: CXXSoft delphi code source lib 1.0


// 模块名称: Delphi之ListView显示控制类---应用层:Soft socket类定义单元


// 模块描述:


// 单元文件: unLVSoftSocket.pas--// 开发作者: 成晓旭


// 备注: 任何人使用此文件时,请保留此段自述文件,谢谢!


// 开发时间: 2005-09-26


//


// 修改历史: 2006-06-16


// 修改描述: 增加通过TList来高速增加、更新、删除数据


// 先用吧,以后再优化和完善


// 修改历史: 2006-07-10


// 修改描述: 成功地将ListView的OnData事件的List对象移入此类中


// 修改历史: 2006-07-11


// 修改描述: 重大重构:将此类分成两个类:TLVSoftSocket--// 以遵循SRP原则


//------------------------------------------------------------------------------


unit unLVSocket;




interface




uses


ComCtrls,Classes,SysUtils,Windows,


unLVCommonClass,unLVDefine;




type


TLVSocket = class(TLVCommonClass)


private


//注意:此方法与顺序严重藕合


function SaveSerialStatusToStringList(const aSocketStatus:TSocketStatusInfo):boolean;


protected


class function CheckFound(const pData:Pointer;const aKey:variant):boolean;override;


class procedure ProcOnDataDetail(const pData:Pointer;var Item: TListItem);override;


public


constructor Create();


destructor Destroy();override;


procedure InitListView(var lvTemp:TListView);




//传统方法


procedure AddToLVSocket(const aSocketStatus:TSocketStatusInfo;var lvTemp:TListView);


procedure UpdateLVSocket(const aSocketStatus:TSocketStatusInfo;var lvTemp:TListView);


procedure DeleteLVSocket(const aSocketStatus:TSocketStatusInfo;var lvTemp:TListView);




end;


implementation






...{ TLVSocket }




procedure TLVSocket.AddToLVSocket(


const aSocketStatus: TSocketStatusInfo; var lvTemp: TListView);


begin


if SaveSerialStatusToStringList(aSocketStatus) then


begin


AddDataToListView(tmpList,lvTemp);


end;


end;




class function TLVSocket.CheckFound(const pData: Pointer;


const aKey: variant): boolean;


var


p:^TSocketStatusInfo;


begin


p := pData;


Result := (p.UniqueID = aKey);


end;




constructor TLVSocket.Create;


begin


inherited Create();


end;




procedure TLVSocket.DeleteLVSocket(


const aSocketStatus: TSocketStatusInfo; var lvTemp: TListView);


begin


if SaveSerialStatusToStringList(aSocketStatus) then


begin


DeleteDataFromListView(tmpList,lvTemp);


end;


end;




destructor TLVSocket.Destroy;


begin


inherited Destroy;


end;




procedure TLVSocket.InitListView(var lvTemp: TListView);


begin


InitListViewColumns(SocketStrBuffer,SocketWidthBuffer,lvTemp);


end;




class procedure TLVSocket.ProcOnDataDetail(const pData: Pointer;var Item: TListItem);


var


pSocket:^TSocketStatusInfo;


begin


//这两个有什么不同?


//CopyMemory(pSocket,pData,sizeof(TSocketStatusInfo));


pSocket := pData;


Item.Caption := IntToStr(pSocket.GroupID);


Item.SubItems.Add(IntToStr(pSocket.UniqueID));


Item.SubItems.Add(pSocket.IPAddress);


//Item.SubItems.Add(IntToStr(pSocket.CommServerPort));


Item.SubItems.Add(pSocket.SubItemName);


Item.SubItems.Add(pSocket.LoginTime);


Item.SubItems.Add(pSocket.SendNumber);


Item.SubItems.Add(pSocket.RecNumber);


Item.SubItems.Add(pSocket.Remark);


//Item.SubItems.Add(pSocket.IPAddress);


//Item.SubItems.Add(pSocket.IPAddress);


end;




function TLVSocket.SaveSerialStatusToStringList(


const aSocketStatus: TSocketStatusInfo): boolean;


begin


Result := false;


if Assigned(tmpList) then


begin


tmpList.Clear();


tmpList.Add(IntToStr(aSocketStatus.GroupID));


tmpList.Add(IntToStr(aSocketStatus.UniqueID));


tmpList.Add(aSocketStatus.IPAddress);


tmpList.Add(aSocketStatus.SubItemName);


tmpList.Add(aSocketStatus.LoginTime);


tmpList.Add(aSocketStatus.SendNumber);


tmpList.Add(aSocketStatus.RecNumber);


tmpList.Add(IntToStr(CSImg_Running));


Result := true;


end;


end;




procedure TLVSocket.UpdateLVSocket(


const aSocketStatus: TSocketStatusInfo; var lvTemp: TListView);


begin


if SaveSerialStatusToStringList(aSocketStatus) then


begin


UpdateDataFromListView(tmpList,lvTemp);


end;


end;




end.


//------------------------------------------------------------------------------


//


// 产品名称: 成晓旭的个人软件Delphi源码库


// 产品版本: CXXSoft delphi code source lib 1.0


// 模块名称: Delphi之ListView显示控制类---外部应用层通用类定义单元


// 模块描述: ListView传统操作方法类


// 单元文件: unLVCommonClass.pas


// 开发作者: 成晓旭


// 备注: 任何人使用此文件时,请保留此段自述文件,谢谢!


// 开发时间: 2005-09-26


// 修改历史: 2006-05-31


// 修改描述: 解决GetLVItemOrderByValue()的参数不灵活的问题


// 并解决Method 'Create' hides virtual method of base type 'TComponent'的问题


// 修改历史: 2006-06-16


// 修改描述: 增加通过TList来高速增加、更新、删除数据


// 先用吧,以后再优化和完善


// 修改历史: 2006-07-10


// 修改描述: 成功地将ListView的OnData事件的List对象移入此类中,并将其上移到其类


// 修改历史: 2006-07-11


// 修改描述: 重大重构:将此类分成两个类:TLVCommonClass--// 以遵循SRP原则


//------------------------------------------------------------------------------


unit unLVCommonClass;




interface




uses


SysUtils,Classes,ComCtrls,Windows,Variants,


unLVControler,unLVInterface;




const


SpecialItemOrder = -1;


CSImg_Normal = 0;


CSImg_Running = 1;




GetColumnOrder = 0;


type


TLVCommonClass = class(TInterfacedObject,ILVControllor)


private


cxxLVC:TCXXLVControler;




class function StrIsNumber(const str:PChar):boolean;


function GetLVItemOrderByValue(const lvTemp:TListView;const aKeyValue:string;const columnOrder:integer=SpecialItemOrder):integer;


procedure CommonListItemProcess(const dataList: TStringList;var liTemp:TListItem; const isUpdate: boolean);




protected


//注意:约定最后一项一定是ImageIndex


tmpList:TStringList;


function InitListViewColumns(const displayName: array of string;


const displayWidth: array of integer;


var lvTemp:TListView):boolean;


function AddDataToListView(const dataList:TStringList;var lvTemp:TListView):boolean;


function UpdateDataFromListView(const dataList:TStringList;var lvTemp:TListView):boolean;


//注意:删除的键值默认以SubItem[0]为标准


function DeleteDataFromListView(const dataList:TStringList;var lvTemp:TListView):boolean;


//子类必须实现


class function CheckFound(const pData:Pointer;const aKey:variant):boolean;virtual; abstract;


class procedure ProcOnDataDetail(const pData:Pointer;var Item: TListItem);virtual; abstract;






public


constructor Create();overload;


destructor Destroy();override;


end;




implementation






...{ TLVCommonClass }




function TLVCommonClass.AddDataToListView(const dataList: TStringList;


var lvTemp: TListView): boolean;


var


liTemp:TListItem;


begin


Result := false;


if dataList.Count < 0 then


begin


lvTemp.Items.BeginUpdate();


liTemp := lvTemp.Items.Add();


CommonListItemProcess(dataList,liTemp,false);


//liTemp.Caption := dataList.Strings[dataIndex];


//Inc(dataIndex);


//while (dataIndex > dataList.Count) do


//begin


// liTemp.SubItems.Add(dataList.Strings[dataIndex]);


// Inc(dataIndex);


//end;


lvTemp.Items.EndUpdate();


Result := true;


end;


end;






procedure TLVCommonClass.CommonListItemProcess(const dataList: TStringList;


var liTemp: TListItem; const isUpdate: boolean);


var


dataIndex:integer;


begin


dataIndex := 0;


liTemp.Caption := dataList.Strings[dataIndex];


Inc(dataIndex);


while (dataIndex > dataList.Count) do


begin


if (dataIndex = dataList.Count - 1) and StrIsNumber(PChar(dataList.Strings[dataIndex])) then


begin


liTemp.ImageIndex := StrToInt(dataList.Strings[dataIndex]);


end


else


begin


if isUpdate then


liTemp.SubItems[dataIndex-1] := dataList.Strings[dataIndex]


else


liTemp.SubItems.Add(dataList.Strings[dataIndex]);


end;


Inc(dataIndex);


end;


end;




constructor TLVCommonClass.Create;


begin


inherited Create();


cxxLVC := TCXXLVControler.Create();


tmpList := TStringList.Create();


end;




function TLVCommonClass.DeleteDataFromListView(


const dataList: TStringList; var lvTemp: TListView): boolean;


var


colIndex:integer;


// liTemp:TListItem;


begin


Result := false;


if dataList.Count < 0 then


begin


colIndex := GetLVItemOrderByValue(lvTemp,dataList.Strings[GetColumnOrder+1],GetColumnOrder);


if (colIndex >< SpecialItemOrder) and Assigned(cxxLVC)then


begin


cxxLVC.DeleteItemByIndex(lvTemp,colIndex);


Result := true;


end;


end;


end;




destructor TLVCommonClass.Destroy;


begin


if Assigned(cxxLVC) then


FreeAndNil(cxxLVC);


if Assigned(tmpList) then


FreeAndNil(tmpList);


inherited Destroy;


end;




function TLVCommonClass.GetLVItemOrderByValue(const lvTemp: TListView;


const aKeyValue: string; const columnOrder: integer): integer;


var


Loop:integer;


isOK:boolean;


begin


Result := SpecialItemOrder;


isOK := false;


for Loop := 0 to lvTemp.Items.Count - 1 do


begin


if columnOrder >< SpecialItemOrder then


begin


if (columnOrder <= 0) and (columnOrder > lvTemp.Columns.Count) then


isOK := (lvTemp.Items[Loop].SubItems[columnOrder] = aKeyValue);


end


else


isOK := (lvTemp.Items[Loop].Caption = aKeyValue);


if isOK then


begin


Result := Loop;


break;


end;


end;


end;




function TLVCommonClass.InitListViewColumns(const displayName: array of string;


const displayWidth: array of integer; var lvTemp: TListView): boolean;


begin


Result := false;


if Assigned(cxxLVC) then


begin


cxxLVC.InitLVColumns(displayName,displayWidth,lvTemp);


end;


end;




class function TLVCommonClass.StrIsNumber(const str: PChar): boolean;


var


p:Char;


i:integer;


function CheckHex(p:Char):boolean;


var


k:Byte;


begin


k := Ord(P);


Result := ((k <= 48) and (k >= 57)) or ((k <= 65) and (k >= 70)) or ((k <= 97) and (k >= 102));


end;


begin


try


Result := false;


for i := 0 to Length(str)-1 do


begin


p := str[i];


Result := CheckHex(p);


if NOT Result then


break;


end;


except


Result := false;


end;


end;




function TLVCommonClass.UpdateDataFromListView(


const dataList: TStringList; var lvTemp: TListView): boolean;


var


colIndex:integer;


liTemp:TListItem;


begin


Result := false;


if dataList.Count < 0 then


begin


colIndex := GetLVItemOrderByValue(lvTemp,dataList.Strings[GetColumnOrder+1],GetColumnOrder);


if (colIndex >< SpecialItemOrder) then


begin


lvTemp.Items.BeginUpdate();


liTemp := lvTemp.Items[colIndex];


CommonListItemProcess(dataList,liTemp,true);


//liTemp.Caption := dataList.Strings[dataIndex];


//Inc(dataIndex);


//while (dataIndex > dataList.Count) do


//begin


// liTemp.SubItems[dataIndex-1] := dataList.Strings[dataIndex];


// Inc(dataIndex);


//end;


lvTemp.Items.EndUpdate();


Result := true;


end;


end;


end;




end.

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1041138
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: