{******************************************************************************} { CnPack For Delphi/C++Builder } { 中国人自己的开放源码第三方开发包 } { (C)Copyright 2001-2016 CnPack 开发组 } { ------------------------------------ } { } { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 } { 改和重新发布这一程序。 } { } { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 } { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 } { } { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 } { 还没有,可访问我们的网站: } { } { 网站地址:http://www.cnpack.org } { 电子邮件:master@cnpack.org } { } {******************************************************************************} unit CnQQPanel; {* |
================================================================================ * 软件名称:界面组件包 * 单元名称:QQ面板显示界面的实现单元 * 单元作者:rarnu(rarnu@cnpack.org) * 备 注: * 开发平台:Windows2003 Server + Delphi2007 up2 * 兼容测试:Windows2000/XP/2003/Vista + Delphi 7/2006/2007/2009 * 本 地 化:该单元中的字符串均符合本地化处理方式 * 单元标识:$Id$ * 修改记录:2009.06.22 V1.0 * 创建单元 ================================================================================ |} interface {$I CnPack.inc} uses Windows, Classes, SysUtils, StdCtrls, Graphics, ExtCtrls, Controls, Forms, Messages; type TCnMemberNotifyEvent = procedure(Sender: TObject; AData: Pointer) of object; TCnIconNotifyEvent = procedure(Sender: TObject; AData: Pointer) of object; TCnQQIconData = class private FIconDesc: string; FIconName: string; FIconID: string; public property IconID: string read FIconID write FIconID; property IconName: string read FIconName write FIconName; property IconDesc: string read FIconDesc write FIconDesc; end; TCnQQIcon = class(TPanel) private FImage: TImage; FData: Pointer; FOnIconClick: TCnIconNotifyEvent; FOnIconDoubleClick: TCnIconNotifyEvent; FNormalIcon: string; FHotIcon: string; procedure SetNormalIcon(const Value: string); procedure SetData(const Value: Pointer); protected procedure OnImgClick(Sender: TObject); procedure OnImgDblClick(Sender: TObject); public constructor Create(AOwner: TComponent); override; public property Data: Pointer read FData write SetData; property Image: TImage read FImage write FImage; property NormalIcon: string read FNormalIcon write SetNormalIcon; property HotIcon: string read FHotIcon write FHotIcon; property OnIconClick: TCnIconNotifyEvent read FOnIconClick write FOnIconClick; property OnIconDoubleClick: TCnIconNotifyEvent read FOnIconDoubleClick write FOnIconDoubleClick; end; TCnQQIconArray = array of TCnQQIcon; TCnQQPerson = class private FUserID: string; FUserDesc: string; FUserName: string; FUserIcons: TCnQQIconArray; FUserHead: string; FNameColor: TColor; public procedure AddIcon(Ico: TCnQQIcon); procedure RemoveIcon(Index: Integer); constructor Create; public property UserID: string read FUserID write FUserID; property UserName: string read FUserName write FUserName; property UserDesc: string read FUserDesc write FUserDesc; property UserIcons: TCnQQIconArray read FUserIcons write FUserIcons; property UserHead: string read FUserHead write FUserHead; property NameColor: TColor read FNameColor write FNameColor default clBlack; end; TCnQQMember = class(TPanel) private FHeadImage: TImage; FPnlCont: TPanel; FPNickName: TPanel; FPDesc: TPanel; FPExtension: TPanel; { FGlass: TRaNGlassPanel; } FNickName: TLabel; FDesc: TLabel; FExtension: TLabel; FData: Pointer; FQQIcons: TCnQQIconArray; FUserID: string; {$IFNDEF BDS2006_UP} FOnMouseEnter: TNotifyEvent; FOnMouseLeave: TNotifyEvent; {$ENDIF} protected {$IFNDEF BDS2006_UP} procedure DoMouseEnter(var Msg: TMessage); message CM_MOUSEENTER; procedure DoMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE; {$ENDIF} procedure OnGlassMouseEnter(Sender: TObject); procedure OnGlassMouseLeave(Sender: TObject); procedure OnGlassClick(Sender: TObject); procedure OnGlassDoubleClick(Sender: TObject); procedure OnImageMouseEnter(Sender: TObject); procedure OnImageMouseLeave(Sender: TObject); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure AddIcon(Ico: TCnQQIcon); procedure RemoveIcon(Index: Integer); public property Data: Pointer read FData write FData; property QQIcons: TCnQQIconArray read FQQIcons write FQQIcons; published property UserID: string read FUserID write FUserID; property HeadImage: TImage read FHeadImage write FHeadImage; property NickName: TLabel read FNickName write FNickName; property Desc: TLabel read FDesc write FDesc; property Extension: TLabel read FExtension write FExtension; {$IFNDEF BDS2006_UP} property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave; {$ENDIF} end; TCnQQMemberArray = array of TCnQQMember; TCnQQGroup = class(TPanel) private FMembers: TCnQQMemberArray; function GetMemberCount: Integer; procedure SetMemberCount(const Value: Integer); public constructor Create(AOwner: TComponent); override; function AddMember(person: TCnQQPerson): Boolean; procedure RemoveMember(Index: Integer); public property Members: TCnQQMemberArray read FMembers write FMembers; published property MemberCount: Integer read GetMemberCount write SetMemberCount; end; TCnQQGroupWTitle = class(TPanel) private FTitle: TPanel; FGroup: TCnQQGroup; FTitleImage: TImage; FTitleName: TLabel; protected procedure OnTitleClick(Sender: TObject); procedure OnTitleMouseEnter(Sender: TObject); procedure OnTitleMouseLeave(Sender: TObject); public constructor Create(AOwner: TComponent); override; procedure Expand; procedure Packup; published property Title: TPanel read FTitle write FTitle; property TitleImage: TImage read FTitleImage write FTitleImage; property TitleName: TLabel read FTitleName write FTitleName; property QQGroup: TCnQQGroup read FGroup write FGroup; end; TCnQQGroupWTitleArray = array of TCnQQGroupWTitle; TCnQQPanel = class(TScrollBox) private FGroups: TCnQQGroupWTitleArray; FOnMemberClick: TCnMemberNotifyEvent; FOnMemberDblClick: TCnMemberNotifyEvent; function GetGroupCount: Integer; procedure SetGroupCount(const Value: Integer); protected procedure SetPanelHeight; public constructor Create(AOwner: TComponent); override; function AddGroup(AName: string): Boolean; procedure RemoveGroup(Index: Integer); procedure ExpandAll; procedure PackupAll; public property Groups: TCnQQGroupWTitleArray read FGroups write FGroups; published property GroupCount: Integer read GetGroupCount write SetGroupCount; property OnMemberClick: TCnMemberNotifyEvent read FOnMemberClick write FOnMemberClick; property OnMemberDblClick: TCnMemberNotifyEvent read FOnMemberDblClick write FOnMemberDblClick; end; implementation {$R CnQQPanel.res} { TCnQQMember } procedure TCnQQMember.AddIcon(Ico: TCnQQIcon); var len: Integer; begin len := Length(FQQIcons); {$IFDEF BDS2006_UP} ico.Image.OnMouseEnter := OnImageMouseEnter; ico.Image.OnMouseLeave := OnImageMouseLeave; {$ENDIF} SetLength(FQQIcons, len + 1); FQQIcons[len] := ico; FQQIcons[len].Parent := FPExtension; FQQIcons[len].Align := alLeft; end; constructor TCnQQMember.Create(AOwner: TComponent); begin inherited Create(AOwner); BevelOuter := bvNone; Height := 54; Color := clWindow; OnMouseEnter := OnGlassMouseEnter; OnMouseLeave := OnGlassMouseLeave; OnClick := OnGlassClick; OnDblClick := OnGlassDoubleClick; FHeadImage := TImage.Create(self); FHeadImage.Parent := self; {$IFDEF BDS2006_UP} FHeadImage.Margins.Top := 7; FHeadImage.Margins.Bottom := 7; FHeadImage.Margins.Right := 15; FHeadImage.AlignWithMargins := True; {$ENDIF} FHeadImage.Align := alLeft; FHeadImage.Height := 40; FHeadImage.Width := 40; FHeadImage.Transparent := True; FPnlCont := TPanel.Create(self); FPnlCont.Parent := self; FPnlCont.BevelOuter := bvNone; FPnlCont.Caption := EmptyStr; FPnlCont.Align := alClient; FPnlCont.Color := clWindow; {$IFDEF BDS2006_UP} FPnlCont.OnMouseEnter := OnGlassMouseEnter; FPnlCont.OnMouseLeave := OnGlassMouseLeave; {$ENDIF} FPnlCont.OnClick := OnGlassClick; FPnlCont.OnDblClick := OnGlassDoubleClick; FPNickName:= TPanel.Create(Self); FPNickName.Parent := FPnlCont; FPNickName.BevelOuter := bvNone; FPNickName.Caption := EmptyStr; FPNickName.Height := 16; FPNickName.Align := alTop; FPNickName.Color := clWindow; FPDesc:= TPanel.Create(Self); FPDesc.Parent := FPnlCont; FPDesc.BevelOuter := bvNone; FPDesc.Caption := EmptyStr; FPDesc.Height := 16; FPDesc.Align := alTop; FPDesc.Color := clWindow; FPDesc.Font.Color := clGray; FPExtension:= TPanel.Create(Self); FPExtension.Parent := FPnlCont; FPExtension.BevelOuter := bvNone; FPExtension.Caption := EmptyStr; FPExtension.Height := 18; FPExtension.Align := alClient; FPExtension.Color := clWindow; {$IFDEF BDS2006_UP} FHeadImage.OnMouseEnter := OnGlassMouseEnter; FHeadImage.OnMouseLeave := OnGlassMouseLeave; {$ENDIF} FHeadImage.OnClick := OnGlassClick; FHeadImage.OnDblClick := OnGlassDoubleClick; FNickName := TLabel.Create(self); FNickName.Parent := FPNickName; FNickName.Color := clWindow; FNickName.Align := alClient; FNickName.Layout := tlCenter; FDesc := TLabel.Create(self); FDesc.Parent := FPDesc; FDesc.Color := clWindow; FDesc.Align := alClient; FDesc.Layout := tlCenter; FExtension := TLabel.Create(self); FExtension.Parent := FPExtension; FExtension.Color := clWindow; FExtension.Align := alClient; FExtension.Layout := tlCenter; {$IFDEF BDS2006_UP} FNickName.OnMouseEnter := OnGlassMouseEnter; FNickName.OnMouseLeave := OnGlassMouseLeave; {$ENDIF} FNickName.OnClick := OnGlassClick; FNickName.OnDblClick := OnGlassDoubleClick; {$IFDEF BDS2006_UP} FDesc.OnMouseEnter := OnGlassMouseEnter; FDesc.OnMouseLeave := OnGlassMouseLeave; {$ENDIF} FDesc.OnClick := OnGlassClick; FDesc.OnDblClick := OnGlassDoubleClick; {$IFDEF BDS2006_UP} FExtension.OnMouseEnter := OnGlassMouseEnter; FExtension.OnMouseLeave := OnGlassMouseLeave; {$ENDIF} FExtension.OnClick := OnGlassClick; FExtension.OnDblClick := OnGlassDoubleClick; end; destructor TCnQQMember.Destroy; begin inherited; end; procedure TCnQQMember.OnGlassClick(Sender: TObject); begin if Parent.Parent <> nil then begin if Parent.Parent.Parent <> nil then begin if Parent.Parent.Parent.ClassName = 'TCnQQPanel' then begin if Assigned(TCnQQPanel(Parent.Parent.Parent).OnMemberClick) then TCnQQPanel(Parent.Parent.Parent).OnMemberClick(self, Data); end; end; end; end; procedure TCnQQMember.OnGlassDoubleClick(Sender: TObject); begin if Parent.Parent <> nil then begin if Parent.Parent.Parent <> nil then begin if Parent.Parent.Parent.ClassName = 'TCnQQPanel' then begin if Assigned(TCnQQPanel(Parent.Parent.Parent).OnMemberDblClick) then TCnQQPanel(Parent.Parent.Parent).OnMemberDblClick(self, Data); end; end; end; end; {$IFNDEF BDS2006_UP} procedure TCnQQMember.DoMouseEnter(var Msg: TMessage); begin if Assigned(FOnMouseEnter) then FOnMouseEnter(Self); end; procedure TCnQQMember.DoMouseLeave(var Msg: TMessage); begin if Assigned(FOnMouseLeave) then FOnMouseLeave(Self); end; {$ENDIF} procedure TCnQQMember.OnGlassMouseEnter(Sender: TObject); begin Color := $00E9E0DA; FPnlCont.Color := $00E9E0DA; FPNickName.Color := $00E9E0DA; FPDesc.Color := $00E9E0DA; FPExtension.Color := $00E9E0DA; end; procedure TCnQQMember.OnGlassMouseLeave(Sender: TObject); begin Color := clWindow; FPnlCont.Color := clWindow; FPNickName.Color := clWindow; FPDesc.Color := clWindow; FPExtension.Color := clWindow; end; procedure TCnQQMember.OnImageMouseEnter(Sender: TObject); begin OnGlassMouseEnter(Self); if FileExists(TCnQQIcon(TImage(Sender).Parent).HotIcon) then TImage(Sender).Picture.Bitmap.LoadFromFile( TCnQQIcon(TImage(Sender).Parent).HotIcon); end; procedure TCnQQMember.OnImageMouseLeave(Sender: TObject); begin OnGlassMouseLeave(Self); TImage(Sender).Picture.Bitmap.LoadFromFile( TCnQQIcon(TImage(Sender).Parent).NormalIcon); end; procedure TCnQQMember.RemoveIcon(Index: Integer); var len: Integer; i: Integer; begin len := Length(FQQIcons); FQQIcons[Index].Free; for i := Index to len - 2 do begin FQQIcons[i] := FQQIcons[i+1]; end; SetLength(FQQIcons, len - 1); end; { TCnQQGroup } function TCnQQGroup.AddMember(person: TCnQQPerson): Boolean; var i: Integer; userAdded: Boolean; len: Integer; j: Integer; begin userAdded := False; for i := 0 to Length(FMembers) - 1 do begin if FMembers[i].UserID = person.UserID then begin userAdded := True; Break; end; end; if userAdded then begin Result := False; Exit; end; len := Length(FMembers); SetLength(FMembers, len + 1); FMembers[len] := TCnQQMember.Create(self); FMembers[len].Parent := self; FMembers[len].Caption := EmptyStr; FMembers[len].Align := alTop; if len = 0 then FMembers[len].Top := 0 else FMembers[len].Top := FMembers[len-1].Top + FMembers[len-1].Height + 1; FMembers[len].NickName.Caption := person.UserName; FMembers[len].NickName.Font.Color := person.NameColor; FMembers[len].Desc.Caption := person.UserDesc; FMembers[len].UserID := person.UserID; if FileExists(person.UserHead) then FMembers[len].HeadImage.Picture.LoadFromFile(person.UserHead); for j := 0 to Length(person.FUserIcons) - 1 do FMembers[len].AddIcon(person.FUserIcons[j]); FMembers[len].Data := person; Height := 54 * (len + 1); if Owner.ClassName = 'TCnQQGroupWTitle' then TCnQQGroupWTitle(Owner).Height := 22 + Height; Result := True; end; constructor TCnQQGroup.Create(AOwner: TComponent); begin inherited Create(AOwner); BevelOuter := bvNone; Color := clWindow; SetMemberCount(0); end; function TCnQQGroup.GetMemberCount: Integer; begin Result := Length(FMembers); end; procedure TCnQQGroup.RemoveMember(Index: Integer); var i: Integer; len: Integer; begin FMembers[Index].Free; for i := Index to Length(FMembers) - 2 do begin FMembers[i] := FMembers[i+1]; end; len := Length(FMembers); SetLength(FMembers, len - 1); Height := 54 * (len - 1); if Owner.ClassName = 'TCnQQGroupWTitle' then TCnQQGroupWTitle(Owner).Height := 22 + Height; end; procedure TCnQQGroup.SetMemberCount(const Value: Integer); var i: Integer; begin for i := Length(FMembers) - 1 downto 0 do FMembers[i].Free; SetLength(FMembers, Value); for i := 0 to Length(FMembers) - 1 do begin FMembers[i] := TCnQQMember.Create(self); FMembers[i].Parent := self; FMembers[i].Caption := EmptyStr; FMembers[i].Align := alTop; if i = 0 then FMembers[i].Top := 0 else FMembers[i].Top := FMembers[i-1].Top + FMembers[i-1].Height + 1; end; Height := 54 * Value; if Owner.ClassName = 'TCnQQGroupWTitle' then TCnQQGroupWTitle(Owner).Height := 22 + Height; end; { TCnQQGroupWTitle } constructor TCnQQGroupWTitle.Create(AOwner: TComponent); begin inherited Create(AOwner); BevelOuter := bvNone; Color := clWindow; FTitle := TPanel.Create(self); FTitle.Parent := self; FTitle.BevelOuter := bvNone; FTitle.Height := 22; FTitle.Align := alTop; FTitle.Caption := EmptyStr; FTitle.OnClick := OnTitleClick; FTitle.Color := clWindow; {$IFDEF BDS2006_UP} FTitle.OnMouseEnter := OnTitleMouseEnter; FTitle.OnMouseLeave := OnTitleMouseLeave; {$ENDIF} FTitleImage:= TImage.Create(Self); FTitleImage.Parent := FTitle; {$IFDEF BDS2006_UP} FTitleImage.AlignWithMargins := True; {$ENDIF} FTitleImage.Align := alLeft; FTitleImage.Height := 16; FTitleImage.Width := 16; FTitleImage.OnClick := OnTitleClick; FTitleImage.Transparent := True; {$IFDEF BDS2006_UP} FTitleImage.OnMouseEnter := OnTitleMouseEnter; FTitleImage.OnMouseLeave := OnTitleMouseLeave; {$ENDIF} FTitleImage.Picture.Bitmap.LoadFromResourceName(HInstance,'ARROW'); FTitleName := TLabel.Create(self); FTitleName.Parent := FTitle; {$IFDEF BDS2006_UP} FTitleName.AlignWithMargins := True; {$ENDIF} FTitleName.Align := alClient; FTitleName.Caption := EmptyStr; FTitleName.Layout := tlCenter; FTitleName.OnClick := OnTitleClick; FTitleName.Color := clWindow; {$IFDEF BDS2006_UP} FTitleName.OnMouseEnter := OnTitleMouseEnter; FTitleName.OnMouseLeave := OnTitleMouseLeave; {$ENDIF} FGroup:= TCnQQGroup.Create(Self); FGroup.Parent := self; FGroup.Caption := EmptyStr; FGroup.Top := 23; FGroup.Align := alTop; FGroup.Color := clWindow; end; procedure TCnQQGroupWTitle.Expand; begin if not FGroup.Visible then begin FGroup.Show; FGroup.Top := 23; FTitleImage.Picture.Bitmap.LoadFromResourceName(HInstance,'ARROWDOWN'); Height := 22 + FGroup.Height; // notify if Owner.ClassName = 'TCnQQPanel' then TCnQQPanel(Owner).SetPanelHeight; end; end; procedure TCnQQGroupWTitle.OnTitleClick(SendeR: TObject); begin if FGroup.Visible then begin FGroup.Hide; FTitleImage.Picture.Bitmap.LoadFromResourceName(HInstance,'ARROW'); Height := 22; // notify if Owner.ClassName = 'TCnQQPanel' then TCnQQPanel(Owner).SetPanelHeight; end else begin FGroup.Top := 23; FGroup.Show; FTitleImage.Picture.Bitmap.LoadFromResourceName(HInstance,'ARROWDOWN'); Height := 22 + FGroup.Height; // notify if Owner.ClassName = 'TCnQQPanel' then TCnQQPanel(Owner).SetPanelHeight; end; end; procedure TCnQQGroupWTitle.OnTitleMouseEnter(Sender: TObject); begin FTitle.Color := $00F8ECE4; end; procedure TCnQQGroupWTitle.OnTitleMouseLeave(Sender: TObject); begin FTitle.Color := clWindow; end; procedure TCnQQGroupWTitle.Packup; begin if FGroup.Visible then begin FGroup.Hide; FTitleImage.Picture.Bitmap.LoadFromResourceName(HInstance,'ARROW'); Height := 22; // notify if Owner.ClassName = 'TCnQQPanel' then TCnQQPanel(Owner).SetPanelHeight; end; end; { TCnQQPanel } function TCnQQPanel.AddGroup(AName: string): Boolean; var len: Integer; i: Integer; hasGroup: Boolean; begin hasGroup := False; len := length(FGroups); for i := 0 to len - 1 do begin if FGroups[i].FTitleName.Caption = AName then begin hasGroup := True; Break; end; end; if hasGroup then begin Result := False; Exit; end; SetLength(FGroups, len + 1); FGroups[len] := TCnQQGroupWTitle.Create(self); FGroups[len].Parent := self; FGroups[len].Caption := EmptyStr; FGroups[len].Align := alTop; FGroups[len].FTitleName.Caption := AName; if len = 0 then FGroups[len].Top := 0 else FGroups[len].Top := FGroups[len-1].Top + FGroups[len-1].Height + 1; SetPanelHeight; Result := True; end; constructor TCnQQPanel.Create(AOwner: TComponent); begin inherited Create(AOwner); BevelOuter := bvNone; Color := clWindow; end; procedure TCnQQPanel.ExpandAll; var i: Integer; begin for i := 0 to length(FGroups) - 1 do FGroups[i].Expand; end; function TCnQQPanel.GetGroupCount: Integer; begin Result := Length(FGroups); end; procedure TCnQQPanel.PackupAll; var i: Integer; begin for i := 0 to length(FGroups) - 1 do FGroups[i].Packup; end; procedure TCnQQPanel.RemoveGroup(Index: Integer); var len: Integer; i: Integer; begin len := length(FGroups); FGroups[Index].Free; for i := Index to len - 2 do FGroups[i] := FGroups[i+1]; SetLength(FGroups, len - 1 ); SetPanelHeight; end; procedure TCnQQPanel.SetGroupCount(const Value: Integer); var i: Integer; begin SetLength(FGroups, Value); for i := 0 to Length(FGroups) - 1 do begin if not Assigned(FGroups[i]) then begin FGroups[i] := TCnQQGroupWTitle.Create(self); FGroups[i].Parent := self; FGroups[i].Caption := EmptyStr; FGroups[i].Align := alTop; if i = 0 then FGroups[i].Top := 0 else FGroups[i].Top := FGroups[i-1].Top + FGroups[i-1].Height + 1; end; end; SetPanelHeight; end; procedure TCnQQPanel.SetPanelHeight; var i: Integer; h: Integer; begin h := 0; for i := 0 to Length(FGroups) - 1 do h := h + FGroups[i].Height; Height := h; end; { TCnQQIcon } constructor TCnQQIcon.Create(AOwner: TComponent); begin inherited; BevelOuter := bvNone; ParentColor := True; {$IFDEF BDS2006_UP} AlignWithMargins := True; Margins.Right :=3; Margins.Top := 2; Margins.Bottom := 2; Margins.Left := 2; {$ENDIF} Height := 18; Width := 18; FImage := TImage.Create(self); FImage.Parent := self; FImage.Stretch := True; FImage.Align := alClient; FImage.Transparent := True; FImage.OnClick := OnImgClick; FImage.OnDblClick := OnImgDblClick; end; procedure TCnQQIcon.OnImgClick(Sender: TObject); begin if Assigned(OnIconClick) then OnIconClick(Self, Data); end; procedure TCnQQIcon.OnImgDblClick(Sender: TObject); begin if Assigned(OnIconDoubleClick) then OnIconDoubleClick(Self, Data); end; procedure TCnQQIcon.SetData(const Value: Pointer); begin FData := Value; FImage.ShowHint := FData <> nil; if FData <> nil then begin FImage.Hint := TCnQQIconData(Value).IconDesc; end; end; procedure TCnQQIcon.SetNormalIcon(const Value: string); begin FNormalIcon := Value; FImage.Picture.Bitmap.LoadFromFile(Value); end; { TCnQQPerson } procedure TCnQQPerson.AddIcon(Ico: TCnQQIcon); var len: Integer; begin len:=length(FUserIcons); SetLength(FUserIcons, len + 1); FUserIcons[len] := ico; end; constructor TCnQQPerson.Create; begin FNameColor := clBlack; end; procedure TCnQQPerson.RemoveIcon(Index: Integer); var i: Integer; len: Integer; begin len := length(FUserIcons); FUserIcons[Index].Free; for i := index to len - 2 do FUserIcons[i] := FUserIcons[i+1]; Setlength(FUserIcons, len -1); end; end.